Webhooks overview
Webhooks tell your server what happened: a message was sent, a call ended. mondochat never emails or texts your users. You decide what to send, with your own sender and branding.
Every event is a POST with the JSON body {type, timestamp, data}. Users appear by their external id, the sub you put in client tokens.
{ "type": "message.created", "timestamp": "2026-09-26T12:00:00.000000+00:00", "data": {"message_id": "01a0dd...", "conversation_id": "01a0dd...", "from": "alice", "to": "bob", "kind": "text", "first": true, "recipient_online": false, "open_url": "https://www.example.com/en/messages?with=alice"}}Before you start
Section titled “Before you start”- A dashboard login for the app, and a server that accepts
POSTrequests over https. - A way to read the raw request body, so you can verify the signature.
- Locally,
http://127.0.0.1:8081/...is the only plain http address the local egress proxy lets through.
- Open Webhooks in the dashboard and choose Add endpoint.
- Enter the https URL of your server and tick the events it wants.
- Mark the endpoint Answers callouts only if you sell inside the chat or charge calls per minute. An app has at most one enabled callout endpoint.
- Copy the signing secret (
whsec_...). It is shown once. - Verify the signature of every request before you trust it.
- Answer with a 2xx status within 15 seconds. Do slow work after you answer.
- To tell users about messages while the chat is closed, subscribe to
message.created,conversation.unreadandcall.ringing, and send your own mail, push or SMS withopen_urlas the link. Formessage.created, mail at once whenfirstis true andrecipient_onlineis false.
Check it works
Section titled “Check it works”Choose Send test event on the endpoint. mondochat sends one signed webhook.test delivery to that endpoint alone and shows your response code. The delivery appears in the delivery list like any other. See webhook.test.
When it fails
Section titled “When it fails”- The delivery list shows every delivery with its status and response code. Replay one from there.
- A non-2xx answer or a timeout is retried on a schedule. See Delivery and retries.
- Answering
410 Gonedisables the endpoint. - A request that fails your signature check is yours to refuse. See Verify signatures.
- A delivery to a private or internal address never leaves: all requests go through an egress proxy that refuses them.
Limits
Section titled “Limits”- Answer within 15 seconds.
- Message bodies are sent only with the setting
webhooks.message_text. Photos, videos and voice notes never carry media, URLs or captions. A voice note’stextis its preview, such as🎤 0:07. - Deliveries can repeat and carry no ordering guarantee. Drop duplicates by the
webhook-idheader. - Nudity between adults is not a moderation finding, so
moderation.flaggednever fires for it.
Callouts in short
Section titled “Callouts in short”Callouts ask your server a question and wait for the answer. They are only used when commerce or per-minute calls are on, and they go to the one endpoint marked for callouts. They are signed like webhooks and carry a webhook-type header.
webhook-type |
We send | You answer |
|---|---|---|
catalog |
the viewer, the seller, the conversation and the language | the items for sale and an optional balance |
charge |
the purchase, buyer, seller, item and price | a status: paid, insufficient, failed or pending |
charge_status |
the purchase id | the same as charge |
call_minute |
the call, the payer, the minute and the price | a status: paid, insufficient or failed |
Answer with 2xx JSON under 64 KB within 5 seconds. A network error is retried once, and anything else is a failure. See catalog, charge, charge_status and call_minute.