Delivery Callbacks
The Cascade API is asynchronous: the send request only confirms that the batch was accepted. Delivery, read, expiry and failure events are pushed to your server as HTTP callbacks. Statuses can also be polled.
Where callbacks are sent
- Per message: the
callbackUrlfield of the message in the send request. The query string is stored and sent as is, sohttps://example.com/status?channel=viber-botarrives with the query intact. - Per organization: one callback URL configured for the whole organization, used when a message has no
callbackUrl. It can carry your own authorization header (headerName/headerValue). Managed throughGET/POST/PUT/DELETE /organizations/callback_urls(see Swagger) or by your account manager.
The callback address does not depend on the channel that finally delivered the message: every event of a message goes to that message’s single address, and the delivered channel is reported in the channel field. If your receiver needs separate endpoints for different bots, put different callbackUrl values on the messages you send through each bot.
Request format
POST to the callback URL with Content-Type: application/json. One JSON object per event; events are not batched.
{
"message_id": "c7a1b2d3-1111-2222-3333-444455556666",
"track_id": "ORDER-12345",
"channel": "viber",
"status": "delivered",
"delivered_at": "2026-08-21T14:29:00Z",
"read_at": null,
"timestamp": "2026-08-21T14:30:00Z"
}
| Field | Description |
|---|---|
message_id | SMSBAT message GUID, the messageId returned by the send request. |
track_id | Your id from the send request; null if it was not provided. |
channel | Channel that actually delivered the message, see below. null when the channel is not determined. |
status | Current/final status, see below. |
delivered_at | Delivery time (UTC, ISO 8601). |
read_at | Read time; filled only for Viber channels. |
timestamp | Time the callback was generated. |
A reason field for undeliverable / blocked is not returned at the moment.
Channels
channel | Meaning |
|---|---|
telegram | Delivered through the Telegram bot |
viber_bot | Delivered through the Viber bot |
viber | Delivered through Viber Business Messages |
sms | Delivered by SMS, including the SMS fallback |
email | Delivered by email |
push | Delivered by push (Firebase) |
null | Channel not determined |
Statuses
status | Meaning |
|---|---|
delivered | Delivered to the device |
read | Read by the recipient (Viber and Viber bot only) |
undeliverable | Cannot be delivered: number unreachable, provider rejected, or every channel of the cascade failed |
expired | The message TTL passed before delivery |
canceled | Canceled |
blocked | The contact is in the promo stop list or failed validation; nothing was sent |
Delivery and retries
- Respond with HTTP
200to acknowledge a callback. - If your server does not respond, the callback is retried 3 times.
- Callbacks are sent per event, so a message may produce several (for example
delivered, thenread).
Polling instead of callbacks
GET /api/CascadeMessage/status_guid/{guid} # by SMSBAT messageId
GET /api/CascadeMessage/status_id/{id} # by your id
Use the same authentication headers as for sending.