Skip to content
SaasQuirk
Engage, by SaasQuirk

The CPaaS built for aggregators, not adapted for them

Developer-first, the way the global platforms are: one API for every channel, a webhook for every status, a log for every message, a rate card per channel. Then the layer none of them have: the pot. One prepaid balance that every brand you serve draws from, with one receipt, one invoice and one report.

One paymentlands on the pot once; receipt SQ-R/2627/0041THE POTOne prepaid balance$1,394.71remaining, one currency, one invoiceNorthwind Retail36% of the pot; own account, own ratesNorthwind Travel35% of the pot; own account, own ratesNorthwind Rewards29% of the pot; own account, own ratesOne report across all three, or any few
The pot. An aggregator pays in once; every brand it serves draws from the same balance with its own account and rate card; one invoice and one report cover them all. Demo data.

Everything a developer-first CPaaS gives you, and the layer built for the aggregator

A global platform is built for one brand that sends. An aggregator resells to many brands and ends up running their balances, their rates and their month end in spreadsheets around the platform. Engage puts that layer inside the platform.

What you expect

Developer-first, as any global platform

  • One API for every channel: WhatsApp Business, SMS, RCS, email, voice AI agents
  • A webhook for every status: accepted, sent, delivered, read, failed, inbound reply
  • A log for every message, down to the charge the ledger made for it
  • A rate card per channel and per account
  • Analytics for any period, by channel, in the customer's own time zone
  • Sign in with a six digit code, and roles that decide who sees what
What only Engage adds

Built for the aggregator

  • The pot: one prepaid balance that every brand you serve draws from
  • Every brand ranked by what it drew, with a fortnight of traffic beside each name
  • One payment, recorded once, with a numbered receipt, and one invoice on the pot, never on a brand
  • One Excel report across all the brands or any few, read from the same ledger as the bill
  • Each brand keeps its own account, users and rate card, and a pot leader sees them all
  • A staff console for onboarding, channels, rates and payments, and our routing layer in front of the provider

The left column is table stakes and we meet it. The right column is why an aggregator moves: the pot, the ranking, the receipt, the one report. None of it is a workaround outside the platform.

One prepaid balance, drawn by every brand the aggregator serves

An aggregator pays in once. Each brand it serves sends from its own account, with its own users, its own rate card and its own traffic, and draws from the shared pot.

The console ranks the brands by what each one used, shows a fortnight of traffic beside every name, and prepares one report for all of them or any few. Each brand still sees its own consumption; nobody adds up separate statements at month end.

The rules that make this safe are in the schema, not in a procedure. A pot holds one currency, and an account in a different currency cannot join it by any route. A payment is recorded on the pot once. A brand inside a pot is never invoiced or alerted on its own; the pot is.

Engage · the aggregator’s accounts · demo data
The Engage console: an aggregator's shared balance, flagged as running low, with paid in, used and today so far, and three brands ranked by what each has drawn
The shared pot: every brand under the aggregator, ranked by what it has drawn. Demo data.
The account model
Account
The tenant and the unit of billing, one per brand
Prepaid or postpaid
Per account. The balance is reported and flagged, traffic is never blocked
Currency
Exactly one per account and per pot, enforced in the schema
Rate card
Per channel, per account
Pot
One balance for several accounts, the payment lands on the pot once
Invoicing
On the pot, never on a member brand
Account manager
One per pot, covering every brand in it

Five channels behind one account and one routing layer

A rate card per channel, one statement, one sign in.

  • WhatsApp Business
  • SMS
  • RCS
  • Email
  • Voice AI agents
01The brand's systemOne call: POST /messages02EngageAccount, rate card, the pot03Our routing layerChooses the route04The providerOfficial Infobip partner05The channelsStatus reported back
One call in, every status back. The brand integrates with Engage once; the route behind it can change without the brand changing anything.

Our router moves traffic between providers without the customer changing anything

Infobip

SaasQuirk is an official Infobip partner. Messages still run through our own routing layer before they reach the provider, so when a route has to change, we change it there. The brand's integration with us stays exactly as it was.

Voice AI agents are offered alongside the messaging channels, from the same team that runs them.

One call to send, a webhook for every status, a log of every message

A brand's developers write to one API whatever the channel. Each status the channel reports comes back on the brand's webhook, and the log keeps the full path of every message, down to the charge the ledger made for it.

Send with one call, on any channelDemo data
POST /messages
{
  "channel": "whatsapp",
  "account": "northwind-retail",
  "to": "+91 98xxx xx412",
  "template": "order_shipped",
  "params": { "order": "48213", "day": "Thursday" }
}
202 Accepted { message_id: msg_01J9X4K7 }
Change the channel to sms, rcs or email. The rest of the call, and your integration, stays as it is. Demo data.
Your webhook hears every statusDemo data
POST https://api.northwind.example/engage
{
  "event": "message.delivered",
  "message_id": "msg_01J9X4K7",
  "channel": "whatsapp",
  "account": "northwind-retail",
  "at": "2026-10-28T09:41:09Z"
}
Eventsacceptedsentdeliveredreadfailedinbound reply
One event per status change, posted to the endpoint the brand registers. Demo data.
The log of one messageDemo data
  1. 09:41:07.212acceptedmsg_01J9X4K7 · whatsapp · northwind-retail · template order_shipped
  2. 09:41:07.230routedRoute chosen by our routing layer; the rate card for WhatsApp applied
  3. 09:41:07.618sentHanded to the provider; provider reference kept against the message
  4. 09:41:09.004deliveredWebhook posted to api.northwind.example, answered 200
  5. 09:43:51.110readWebhook posted, answered 200
  6. 00:00:00.000chargedNext morning: $0.0412 drawn from the shared balance, on the ledger line the invoice reads
Every message keeps its path: accepted, routed, sent, each status the channel reports, and the charge the ledger made for it. Demo data.

Three billing rules and a receipt on every payment

Balances settle each day from what was actually sent. The console shows how many days the balance lasts at the current rate, and flags it when it is running low, before anyone has to ask.

Every payment carries a numbered receipt, kept. Three rules hold the ledger together, and each one was paid for.

ledger · demo data
[02:15 UTC] USAGE_FETCH sent, delivered and failed counts fetched for every account, last four days
[03:15 UTC] USAGE_PRICED 2026-10-21 priced per account, per channel, from the sent count
[09:42 UTC] RECHARGE payment recorded on the pot; receipt SQ-R/2627/0041 issued
[10:05 UTC] DELIVERY delivery updates for 2026-10-21 applied; the priced day stands
[18:00 UTC] BALANCE pot lasts 3 days at the current rate; flagged running low
[18:03 UTC] REPORT workbook for 26 Aug to 24 Sep ready; kept for seven days
A day in the ledger, with the entry types the real system records. Demo data.
The three rules
Bill on what was sent
The sent count is the quantity that becomes money. What the provider charges us is a different question, and it never leaks into a customer's bill.
Two clocks
Sent settles when the UTC day closes. Delivered and failed keep moving for 48 hours. A priced day is never rewritten in full, but it takes the delivery updates.
A report reads charged from the ledger
Never sent multiplied by rate. A report that can disagree with the bill it explains is worse than no report.
Receipts
Numbering
Per billing company and year
Issued
When a payment is recorded
Kept
In object storage
Shown
On every payment row in the console

Workbooks and analytics that read the same ledger as the bill

A customer asks for a workbook for any range up to a year and downloads it a minute later. Its figures come from the same ledger as the bill, so what a report says was charged is what was charged.

Analytics answers the operational question: how much was sent, delivered and failed, for any period, by channel, in the customer's own time zone.

The workbook
Sheets
Dashboard with charts, then daily, weekly and monthly
Whole pot
Adds an accounts sheet and a tab per brand
Range
Any period up to a year, with presets for the last 30 days, last month, this month, this quarter
Ready
Within about a minute
Kept
Seven days, expired reports stay listed
Provisional
The last two days, while delivery reports still arrive
Engage · analytics · demo data
Engage analytics: sent, delivered, failed and delivery rate over 24 hours, with a line chart over time
Sent, delivered, failed and delivery rate for a 24 hour window, grouped automatically, in the customer's time zone. Demo data.

The console, screen by screen

Screens marked as image slots are being captured on demo data.

Customer

Overview

The balance as the headline: how much is left, how many days it lasts at the current rate, today so far. Traffic per channel with a chart and the last seven days.
Image slot: Overview: the balance, how many days it lasts, today so far, traffic per channel.
Overview: the balance, how many days it lasts, today so far, traffic per channel.
Customer

Payments and invoices

Payments grouped by month with a numbered receipt on every row. Consumption per billing day with a sparkline. Adjustments shown only when there are any.
Image slot: Payments and invoices: a numbered receipt on every row.
Payments and invoices: a numbered receipt on every row.
Customer

Reports

Ask for a workbook, watch it prepare, download it for seven days. Presets, which sheets, which accounts. A paginated history, expired reports still listed.
Image slot: Reports: prepare an Excel workbook for any range up to a year.
Reports: prepare an Excel workbook for any range up to a year.
Customer

Analytics

Sent, delivered, failed and delivery rate for any period from fifteen minutes to thirty days, or a custom range, by channel, in the customer's own time zone.
Engage console
Engage analytics: sent, delivered, failed and delivery rate over 24 hours, with a line chart over time
Traffic for any period, by channel, in the customer's own time zone. Demo data.
Pot leader

Your accounts

The pot's balance against its limit, every brand ranked by what it drew, a fortnight of traffic beside each name, and a report covering all of them or some.
Engage console
The Engage console: an aggregator's shared balance, flagged as running low, with paid in, used and today so far, and three brands ranked by what each has drawn
The shared pot: every brand under the aggregator, ranked by what it has drawn. Demo data.
Staff

The staff console

Onboard a client, switch channels on, set rates, record a payment, re fetch usage. Pots, billing companies, people. A root admin sees the estate's exceptions: a missing rate card, an undrawn receipt, a credit limit crossed.
Image slot: The staff console: accounts, channels, rates, payments, pots.
The staff console: accounts, channels, rates, payments, pots.

Provisioning, sessions, and who sees what

There is no demo password, and that is the point. An account manager creates the account; its owner finishes it through an emailed link and sets a password nobody else ever knows. Sign in asks for a six digit code; a trusted browser may be allowed to skip it.

Customer screens resolve the account from the session token and nothing else. No customer route accepts an account id, so there is no id to change.

Who sees what
Customer finance
Own account: balance, payments, receipts, reports
Customer admin
Own account: finance, traffic and performance
Pot leader
Every brand under the pot, their shares and traffic, one report for all or some
Account manager (ours)
Assigned accounts: onboarding, channels
Finance (ours)
Rates, payments, receipts, billing companies
Root admin (ours)
Every account, and the estate's exceptions
Sessions
Sign in
Email and password, then a six digit code
Trusted browsers
Allowed to skip the code, revocable from the account screen
Access token
Held in memory only, never in local storage, never in a cookie
Refresh
Token rotation locked in the database
Billing identity
The console shows the billing company's own mark, so whose data is on screen is never a guess

Stack, runtime and the daily schedule

The ledger runs on schedule every day. The engineers who built it run it, with a runbook that goes from symptom to action and a written record of what went wrong before.

Stack and runtime
Backend
Java 25, Spring Boot 4.1
Database
PostgreSQL 16, 27 Flyway migrations
Cache and sessions
Redis 7
Tests
494, run against a real PostgreSQL and Redis through Testcontainers
Console
SvelteKit 2, Svelte 5, Tailwind 4, TypeScript strict, a static app on S3 and CloudFront
Region
AWS Mumbai
Scheduled jobs
Usage fetched 02:15 UTC, closed days priced 03:15 UTC
Storage
Receipts kept, reports kept seven days

A walkthrough, written rates, then the accounts

  1. 01

    A walkthrough

    Twenty minutes in the console, on demo data, around the number of brands you serve and the channels they use.

  2. 02

    Rates for the channels in use

    Written, per channel, per brand.

  3. 03

    Accounts set up by our team

    Each person then sets their own password through an emailed link. Nobody else ever knows it.

Questions aggregators ask

What is Engage?
Engage is the CPaaS built for aggregators. It carries WhatsApp, SMS, RCS, email and voice AI agents on one account, and an aggregator runs every brand it serves, and its whole account with us, from one console.
How is Engage different from a developer-first CPaaS?
A developer-first CPaaS gives one company an API and a balance. Engage adds the layer an aggregator needs on top: an account per brand, one shared prepaid pot every brand draws from, a rate card per channel and per brand, receipts and reports from the same ledger as the bill, and roles for the aggregator and for each brand.
What is the pot?
One prepaid balance that every brand under the aggregator draws from. Each brand sends from its own account; its usage is priced daily against the pot. The console ranks the brands by what each has drawn, shows a fortnight of traffic beside every name, and flags the pot when it runs low.
How is usage priced?
Every closed day is priced the next morning from what was actually sent, per account and per channel, at the brand's rate card. Delivery and failure counts keep updating for 48 hours without rewriting the priced day, and every report reads the charged amount from the ledger, never sent multiplied by rate.
Which channels and which network?
WhatsApp through the WhatsApp Business Platform, SMS, RCS, email, and voice AI agents that answer and place calls. Traffic is carried through our official partner Infobip, with our own routing layer in front of the network, so a route change never reaches a brand.
Where does Engage run, and where is the data?
Engage runs on AWS in Mumbai, and data is stored on servers in India. Usage is fetched and priced on a daily schedule, receipts are kept, and the engineers who built the platform are the ones who run it.
How do we start?
A twenty minute walkthrough of the console on demo data, around the number of brands you serve and the channels they use. Then written rates per channel and per brand, and accounts set up by our team.
Engage

See the console on demo data

Tell us how many brands you serve and which channels they use. We will set up the walkthrough around that.

Or write to support@saasquirk.com. SAASQUIRK LLP, India.