Viber and WhatsApp push reports
For Viber and WhatsApp we can call your server when something happens: a message changes status, a person
writes to you, or WhatsApp reviews one of your templates. This page lists each push, its fields and the rules
for your receiver.SMS works differently: you give callback_url in each send call. See
Delivery reports.The five pushes#
| Push | Sent when | Set its address in |
|---|
| Viber message status | A Viber message is delivered, seen, expires or fails | Viber Key → Webhook Message Status |
| Viber inbound message | A person writes to your Viber sender | Viber Key → Webhook Inbound |
| WhatsApp message status | A WhatsApp message is sent, delivered, read or fails | WhatsApp Key → Webhook Message Status |
| WhatsApp inbound message | A person writes to your WhatsApp number | WhatsApp Key → Webhook Inbound |
| WhatsApp template status | WhatsApp approves, rejects or pauses a template | WhatsApp Key → Webhook Template Status |
Set it up#
2.
On the Viber Key or WhatsApp Key card, enter the address of your receiver for each push you want and
save. An empty field switches that push off.
3.
Copy the key shown on the card. We send it with every push so that you can recognise our calls.
What we send#
Every push is an HTTP POST with a JSON body and these headers:Content-Type: application/json; charset=utf-8
X-VeloSMS-Token: 3f2b8c1e-5d47-4a9b-8e21-6c0d9f7a1b34
X-VeloSMS-Token holds your Viber Key for the two Viber pushes and your WhatsApp Key for the three
WhatsApp pushes. When you make a new key on the dashboard, the next push carries the new one.Things that are the same in every body:Field names start with a capital letter (ToPhoneNumber, Status).
Fields without a value are sent as null, not left out.
Dates are in UTC, written as ISO 8601, for example 2026-10-08T09:15:30.123456Z.
Some statuses and types are sent as numbers. The tables below give the meaning of each number.
Read the body with a JSON parser. Do not compare the raw text: letters outside the basic Latin alphabet and
the + sign are written as escapes such as +.
A body can hold more fields than this page lists. Use only the listed ones; the others are internal and can
change.
Rules for your receiver#
Check the key. Compare X-VeloSMS-Token with your key and answer 401 when it differs. The body is not
signed, so this header is how you know the call is ours. Use an https:// address so the key cannot be read
on the way.
Answer HTTP 200 within a few seconds. Save the body, answer, and do slow work afterwards.
Expect repeats and any order. The same event can arrive twice, and two events for one message can
arrive out of order. Make your handler safe to run twice.
Not every message is pushed. Pushes cover messages sent with the Viber and WhatsApp calls of the
Messaging API. Messages sent with Campaigns (v2) and replies sent from the inbox are not pushed; read their
result with the campaign and record calls.
Viber message status#
Sent when a Viber message changes status. There is no push when a message is merely accepted for sending; the
first push for a good message comes when Viber reports on it.{
"CampaignId": 7731,
"From": "MyBrand",
"ToPhoneNumber": "37491234567",
"SendDate": "2026-10-08T09:15:30.123456Z",
"Price": 0.02,
"Currency": "USD",
"Status": 1,
"Message": "Hello Anna, your order is ready.",
"ActionUrl": null,
"AttachmentUrl": null,
"AttachmentType": null,
"CreatedAt": "2026-10-08T09:15:30.123456Z"
}
| Field | Type | Meaning |
|---|
CampaignId | integer | The id you got when you sent: data[0] of Send a Viber campaign, or data[0].ids[0] of Send a Viber one-time code. |
ToPhoneNumber | string | The recipient. |
From | string | Your sender name. |
Status | integer | See the table below. |
SendDate | date-time or null | When we sent the message. |
Price, Currency | number, string or null | What the message cost you. |
Message | string or null | The text. |
ActionUrl, AttachmentUrl, AttachmentType | string or null | The button link and the attachment of the message, if it had them. |
CreatedAt | date-time | When the message record was made. |
To find the message on your side, use CampaignId together with ToPhoneNumber. Do not use Id: it is 0
for a message that failed at sending.Status | Name | Meaning |
|---|
0 | Delivered | The message reached the phone. |
1 | Seen | The person opened it. |
2 | Expired | It was not delivered before it ran out of time. |
99 | SendFailed | The send was refused. Nothing was delivered. |
100 | Sent | Viber took the message; no delivery result yet. |
8, 9 | DefaultAutoReply, CustomAutoReply | Automatic-reply events. You can ignore them. |
After a person replies to a message, later status changes of that message are no longer pushed.Viber inbound message#
Sent when a person writes to your Viber sender.{
"ChatId": "3f2b8c1e-5d47-4a9b-8e21-6c0d9f7a1b34",
"From": "37491234567",
"To": "MyBrand",
"UserName": "Anna Petrosyan",
"Type": 1,
"Message": "Yes, please.",
"AttachmentUrl": null,
"AttachmentType": null,
"ReceivedAt": "2026-10-08T09:20:05Z"
}
| Field | Type | Meaning |
|---|
ChatId | string | The id of the conversation. Use it with List messages of a conversation. |
From | string | The person's phone number. |
To | string | Your sender name. |
UserName | string or null | The name of the matching contact in your contact list. A single space when there is none. |
Type | integer | 1 text, 2 image, 3 video, 4 file, 7 video with text. |
Message | string or null | The text. |
AttachmentUrl | string or null | A temporary link to the picture, video or file. Download it at once; the link stops working after a short time. |
AttachmentType | string or null | Image, Video or File. |
ReceivedAt | date-time | When the message arrived. |
An answer to an opt-in invitation is recorded as an opt-in and is not pushed.WhatsApp message status#
Sent when WhatsApp reports on a message you sent.{
"Id": 30977,
"CampaignId": 7802,
"PhoneNumber": "37491234567",
"Country": "AM",
"SendDate": "2026-10-08T09:25:10.654321Z",
"Price": 0.05,
"Currency": "USD",
"Status": "delivered",
"WhatsAppMessageId": "wamid.SAMPLE0000000000000001",
"Message": "Hello Anna, your order is ready.",
"CreatedAt": "2026-10-08T09:25:10.654321Z"
}
| Field | Type | Meaning |
|---|
Id | integer | Our id of the message record. |
CampaignId | integer | The id you got from Send a WhatsApp campaign. |
PhoneNumber | string | The recipient. |
Status | string | The status word as WhatsApp reports it: usually sent, delivered, read or failed. Compare it without regard to capital letters. |
WhatsAppMessageId | string or null | WhatsApp's id of the message. Together with Status it tells a repeat from a new event. |
Message | string or null | The final text, with the template variables filled in. |
SendDate | date-time or null | When we sent the message. |
Price, Currency, Country | number, string or null | What the message cost you, and the country of the template. |
CreatedAt | date-time | When the message record was made. |
A failed message carries no reason in this push. There is no push at the moment of sending.WhatsApp inbound message#
Sent when a person writes to your WhatsApp number. One push for each message.{
"Id": 55102,
"ChatId": "8a1d2c3b-4e5f-4a6b-9c7d-0e1f2a3b4c5d",
"FromPhoneNumber": "37491234567",
"ToPhoneNumber": "37410123456",
"Message": "Hi, is my order ready?",
"ReceivedAt": "2026-10-08T09:25:41Z",
"WhatsAppMedias": []
}
| Field | Type | Meaning |
|---|
Id | integer | Our id of the message. |
ChatId | string | The id of the conversation. Use it with List conversation messages. |
FromPhoneNumber | string or null | The person's phone number. |
ToPhoneNumber | string or null | Your WhatsApp number. |
Message | string or null | The text. null for a picture, video, document, voice message or sticker; a caption is not included. |
ReceivedAt | date-time | When the person sent it. |
WhatsAppMedias | list | The attached files. Empty for a text message. |
WhatsAppMedias[].Url | string | A download link that works for 24 hours. Download the file and keep your own copy. |
WhatsApp template status#
Sent when WhatsApp reviews one of your templates or changes its state.{
"Id": 412,
"Name": "order_ready",
"Message": "Hello {{1}}, your order is ready.",
"CreatedAt": "2026-10-01T08:00:00.123456Z",
"ModifiedAt": "2026-10-08T09:30:12.3456789Z",
"WhatsAppApprovalStatus": 2
}
| Field | Type | Meaning |
|---|
Id | integer | The id of the template, as in List WhatsApp templates. |
Name | string | The name of the template. |
Message | string | The text of the template. |
WhatsAppApprovalStatus | integer or null | The state of the template at WhatsApp. See the table below. |
ModifiedAt | date-time or null | When the state changed. |
WhatsAppApprovalStatus | Name | Can you send with the template? |
|---|
1 | Pending | Not yet |
2 | Approved | Yes |
3 | Rejected | No |
4 | Paused | No, until WhatsApp lifts the pause |
5 | Disabled | No |
6 | Archived | No |
7 | PendingDeletion | No |
8 | Deleted | No |
9 | InAppeal | Not yet |
10 | LimitExceeded | No |
The body also has a field named Status. Ignore it: only WhatsAppApprovalStatus follows WhatsApp's review.
The reason for a rejection is not part of the push. Modified at 2026-10-08 11:10:56