Four new webhook events
TimelinesAI now emits four additional webhook events that you can subscribe to from your workspace's webhook settings:
call:incoming:missed— fires when an incoming WhatsApp call ends without being answered.call:incoming:ended— fires when an incoming WhatsApp call ends after being answered or declined.call:outgoing:ended— fires when an outgoing WhatsApp call ends (answered, no-answer, or rejected by recipient).message:reaction— fires when an emoji reaction is added or removed on any synced message (text, file, voice, call) in direct or group chats.
Subscribe via the Workspace → Integrations → Webhooks page or the Public API webhook endpoints.
Heads up: Each workspace can register up to 10 webhook endpoints. Reach out if that's tight for your use case — we're actively gathering feedback on multi-event subscriptions.
When call webhooks fire
Only after a call ends — never on call start.
Calls in "Ringing" status do not fire any webhook. Once the call moves to a final status (
Missed,Answered,Rejected,Ended,No Answer), the appropriate event fires.Scheduled calls do not fire any call webhook on their own — only when an actual call happens.
Group-chat calls do fire webhooks (unlike CRM sync, which skips them).
New shared fields on call + reaction events
The new events introduce three fields that are also part of message:reaction and may be added to other events in the future:
Field | Block | Value |
|
|
|
|
|
|
|
| The WhatsApp WID, e.g. |
Call event payload
{
"event_type": "call:incoming:missed",
"chat": {
"full_name": "Agent Smith",
"chat_url": "https://app.timelines.ai/chat/123456/messages/",
"chat_id": 123456,
"chat_type": "direct",
"platform": "whatsapp",
"phone": "+123456789",
"responsible_name": "Agent Brown",
"responsible_email": "[email protected]"
},
"whatsapp_account": {
"whatsapp_account_wid": "[email protected]",
"full_name": "Agent Brown",
"email": "[email protected]",
"phone": "+123456789"
},
"call_details": {
"duration": null,
"direction": "incoming",
"is_video": false,
"status": "Missed",
"timestamp": "2026-05-24 10:35:18 +0200",
"message_uid": "c7ec509d-0171-1ead-a84b-c6943a644768",
"caller": {
"full_name": "John Smith",
"phone": "+123456789"
},
"recipient": {
"full_name": "Agent Brown",
"phone": "+987654321"
}
}
}call_details.status values:
Direction | Status values |
Incoming ( |
|
Incoming ( |
|
Outgoing ( |
|
Note on status wording. Webhook payloads use Rejected when a call was declined by the recipient (both for incoming declined by your WhatsApp device, and for outgoing rejected by the remote contact). The text shown on the Pipedrive / HubSpot activity stream for the same call may still say Declined — they refer to the same event.
call_details.duration is in seconds when available; null otherwise. It is always present in the payload (never omitted).
message:reaction payload
{
"event_type": "message:reaction",
"chat": {
"full_name": "Agent Smith",
"chat_url": "https://app.timelines.ai/chat/123456/messages/",
"chat_id": 123456,
"chat_type": "direct",
"platform": "whatsapp",
"phone": "+123456789",
"responsible_name": "Agent Brown",
"responsible_email": "[email protected]"
},
"whatsapp_account": {
"whatsapp_account_wid": "[email protected]",
"full_name": "Agent Brown",
"email": "[email protected]",
"phone": "+15559876543"
},
"reaction": {
"message_uid": "a5bbb005-37f2-402c-96fa-e479a2e09b02",
"action": "set",
"emoji": "👍",
"reactor": {
"full_name": "John Doe",
"phone": "+15551234567"
},
"timestamp": "2026-05-24 12:00:00 +0200",
"reactions": {
"👍": "2",
"❤️": "1"
}
}
}reaction.action is set when a reaction was added, clear when removed. reaction.emoji is the added or removed emoji. reaction.reactions is the current aggregate emoji → count map after this event (same format as MessageInfo.reactions on the Public API). reaction.reactor is null if attribution isn't available at dispatch time.
A few things worth knowing about message:reaction:
One event fires per reaction — no batching. A group chat with 10 people reacting to the same message will produce 10 webhook events. We may add optional aggregation later; tell us if you'd benefit.
Fires for reactions on any message type — text, file/media, voice, call.
Fires for reactions added or cleared in WhatsApp itself or in TimelinesAI's Shared Inbox.
If a reaction is added to a message that wasn't synced into TimelinesAI, the reaction is skipped (no event).
