Documentation / Complete
The 9 event types with their payload
8 subscribable types + webhook.test (not subscribable). An endpoint with an explicit events list receives ONLY those types; empty/omitted = all (new ones arrive on their own). The data of each:
| Type | Subscribable | Description |
|---|---|---|
message.received | ✓ | A customer messaged you. data.message = WhatsApp message object (text/image/audio/…); data.contacts[] identifies the sender. |
message.echo | ✓ | 🌟 The Coexistence differentiator: a message the OWNER sent FROM THE PHONE, with its content. origin='device' (does not consume the plan). from = your business number. |
message.status | ✓ | Receipt for a message you sent via /v1. origin (api|device) tells your send apart from one made by hand on the phone. A 'device' receipt has NO message of yours behind it — that's expected. |
connection.created | ✓ | A new number connected (panel or hosted onboarding). Your externalId travels in the envelope → provision the end-customer in your system. |
connection.status_changed | ✓ | A connection's status changed (e.g. status='disconnected'). Alert or pause sends to that number. |
connection.usage_threshold_reached | ✓ | ONE number's limit (its monthlyMessageLimit) hit 70/90/100%. Emitted ONCE per (number, period, threshold). The commercial one: warn that end-customer or raise the cap. |
usage.threshold_reached | ✓ | The ACCOUNT plan (sum of all numbers) hit a threshold. connection is null, sequence 0. Decide upgrade or cutoff. |
history.synced | ✓ | (Coexistence) summary of the conversation backfill at connect. shared:false = the owner did not share their history. ⚠ Historical messages are NOT forwarded one by one. |
webhook.test | — | The panel 'Test' button event. NOT subscribable: it is ALWAYS delivered to that endpoint (even with an explicit event list) to validate connectivity + signature. connection=null, data.test=true. Never treat it as real traffic. |
message.received — data
{
"message": {
"id": "wamid.HBgL…",
"from": "5493511234567",
"type": "text",
"text": {
"body": "hola"
}
},
"contacts": [
{
"wa_id": "5493511234567",
"profile": {
"name": "Ana"
}
}
]
}message.echo — data
{
"origin": "device",
"message": {
"id": "wamid.HBgL…",
"from": "5493516516690",
"to": "5493511234567",
"type": "text",
"timestamp": "1754531482",
"text": {
"body": "te confirmo el turno para mañana 10hs"
}
}
}message.status — data
{
"messageId": "wamid.HBgL…",
"status": "read",
"origin": "device",
"recipient": "5493511234567",
"timestamp": "2026-08-06T00:31:25.000Z"
}connection.created — data
{
"status": "connected"
}connection.status_changed — data
{
"status": "disconnected",
"previousStatus": "connected"
}connection.usage_threshold_reached — data
{
"scope": "connection",
"threshold": 90,
"used": 900,
"limit": 1000,
"period": "2026-08",
"connection": {
"id": "conn_4eede070e5a84d1590bdce2ea1d837bc",
"label": "Farmacia López",
"externalId": "farmacia-lopez"
}
}usage.threshold_reached — data
{
"scope": "account",
"threshold": 90,
"used": 22610,
"limit": 25000,
"period": "2026-08"
}history.synced — data
{
"conversations": 34,
"messages": 512,
"shared": true,
"phase": 0
}webhook.test — data
{
"type": "test",
"test": true,
"message": "WAIA Connect test event — your endpoint is reachable and verifying signatures. This is NOT real traffic."
}