{ "event", "data", "sent_at" }, signed the same way. Webhooks covers the setup, the signature, the timeout and the retries; this page covers what each event means.
Index
Handling any event
- Verify the signature first, over the raw body. See Verifying the signature.
- Answer
2xxwithin 5 seconds, then do the work from a queue. - Deduplicate on
data.idtogether withevent. The same event can arrive twice. - Do not rely on order. Compare the status in
datawith what you stored, and never move a record backwards. - Skip test events. An envelope with
"test": trueis a rehearsal from the console’s Send a test event. - Ignore what you do not know. New events and new
datafields can be added; an unknown event deserves a2xxand nothing else.
Verification events
The data is the verification, in the same shape for the three events. A partner’s copy addsexternal_id.
Codes sent with a test key fire these events too, with
mode: "test". Canceling a verification fires no event.
When a code is verified
verification.verified fires on the check that matched the code, once per verification. A later check of the same id answers verified again but sends no second event.
reference as confirmed, if your own check call has not done so already. Your server already knows the outcome from the check answer; the event matters when another service makes the check, or as a record.
When a verification fails
verification.failed fires when a wrong code uses the last attempt (max_attempts, 3 by default), or when a check finds the attempts already used. The code can no longer be verified.
start (502 send_failed) fires no event: the API answer is the news.
Handle it by refusing the action behind reference. Repeated failures from one number or one address are a fraud signal worth logging.
When a code expires
verification.expired fires when a code reaches expires_at unused. A check, a GET /v1/verify/{id} or a cancel that finds the expiry fires it at once; otherwise a sweep finds it, every ten minutes, at least five minutes after the expiry. Expect it up to about a quarter of an hour late.
expires_at itself.
Message events
message.sent, message.delivered, message.read and message.failed follow a WhatsApp template message sent through Tawked Notifications, from the API or from the console. They reach the application’s own webhook only; a partner’s client applications send no WhatsApp.
How the events behave:
- They arrive within about a minute of Meta reporting the status, and a message is followed for 48 hours after its send.
- A status only moves forward:
sent, thendelivered, thenread. A step can be skipped: a message read before its delivery was reported firesmessage.readalone. readandfailedare final. Nothing follows them.- A send refused at once answers
502 send_failedto the API call and fires nomessage.failed.
id and ignoring an event whose status is behind the stored one. Sending messages has the status lifecycle.
Partner events
Theservice.* events and balance.low reach a partner’s webhook only, for the client applications it provisions and for its balance. Each service.* event carries service_id, application_id and the partner’s external_id.
reason_code of a rejection, the subscriptions and the feed to poll instead.