Guides
Inbound webhooks
The URL messaging platforms call, how it is verified, and how to simulate a message without a real provider.
Webhooks in engage-ai run one way: messaging platforms call engage-ai. When a customer messages your WhatsApp number or Telegram bot, the platform sends the message to your connection's webhook URL. Your own application does not call these endpoints, and engage-ai does not currently send webhooks to you.
The URL
POST /channels/connect returns the URL to register:
https://api.getengageai.app/webhooks/{providerKey}?connection={externalAccountId}For example https://api.getengageai.app/webhooks/telegram_bot?connection=7654321.
providerKeyselects the platform. One route serves every platform.?connection=identifies which of your accounts the request is for. Keep it when you paste the URL; without it, verification fails.
What happens on each request
- Verify. The request is checked with the connection's own credential: the HMAC signature made with your WhatsApp app secret, or the secret token you chose for Telegram. The check uses the exact bytes received.
- Store. The raw event is saved before anything else, so it can be replayed if processing fails.
- Acknowledge. The platform gets
200within about 50 ms. - Process. Everything else (contact, conversation, retrieval, reply) happens on a queue afterwards.
Duplicates are ignored. Platforms redeliver events. Each event is stored once, keyed by the platform's own event id, so a redelivery does nothing.
Responses
| Status | When |
|---|---|
200 | Always, except a failed signature check. Even an event that cannot be processed returns 200, because platforms disable webhooks that keep failing. The event is kept and can be replayed. |
401 | The signature or secret token did not match. Check the app secret (WhatsApp) or webhookSecretToken (Telegram). |
The verification handshake
Some platforms check the URL before sending any events. Meta sends a GET with hub.mode, hub.verify_token and hub.challenge. engage-ai echoes the challenge back only if hub.verify_token equals the verifyToken you set when connecting. Platforms without a handshake get a plain 200.
Simulate a message
You can test the whole pipeline without a real platform by posting a Telegram-shaped update yourself. Use the secret token you set as webhookSecretToken:
curl -X POST "https://api.getengageai.app/webhooks/telegram_bot?connection=7654321" \
-H "Content-Type: application/json" \
-H "X-Telegram-Bot-Api-Secret-Token: <your webhookSecretToken>" \
-d '{
"update_id": 1,
"message": {
"message_id": 1,
"date": 1758196800,
"text": "Do the Trailhead boots come in UK 11?",
"chat": { "id": 555000 },
"from": { "id": 555000, "first_name": "Jamie" }
}
}'A conversation with Jamie appears in GET /conversations and, after a few seconds, a draft or reply. Change update_id for each new test message; repeating one is treated as a redelivery and ignored.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Meta says the callback could not be verified | The verify token in Meta differs from verifyToken, or the ?connection= part of the URL is missing. |
Every request gets 401 | Wrong app secret (WhatsApp) or secret token (Telegram). For Telegram, check the credential key is webhookSecretToken. |
Platform shows 200 but nothing appears | The externalAccountId does not match what the platform sends. For WhatsApp it must be the phone number ID, not the business account ID. |
| Nothing arrives at all | The webhook was never registered, or for WhatsApp the messages field is not subscribed. For Telegram, check getWebhookInfo. |