Events
Receive webhooks
Each delivery is a JSON envelope with id, type, created_at, account_id, line_id, channel and data. HTTPS is required; private, loopback and link-local URL targets are rejected.
line_id is the line the event belongs to (null for account-wide events). An endpoint created with line_ids receives
only the events of those lines, line.* events included, so each app can listen to its own line alone.
Verify the signature#
Every delivery carries the header MyComm-Signature: t=<unix seconds>,v1=<hex>. The value is the HMAC-SHA256 of the string <t>.<exact raw body> with the endpoint's signing secret. While a rotated secret is still valid the header holds two v1 values; accept the delivery when any of them matches. Compare in constant time and reject a t more than 300 seconds from your clock. Deliveries also carry MyComm-Event-Id, MyComm-Event-Type, MyComm-Delivery-Id and MyComm-Delivery-Attempt. Working PHP and Node receivers are in the receive quickstart.
De-duplicate by the event id (the same on every retry); MyComm-Delivery-Id is different per delivery.
Retries and replay#
The relay retries non-2xx responses with exponential backoff, preserves event ordering per aggregate, and records the final response. Return 2xx only after durable processing. Replay one delivery with POST /v1/webhook-deliveries/{id}/replay, or the dead deliveries of an endpoint (up to 10,000 per call, oldest first) with POST /v1/webhook-endpoints/{id}/replay; the event id stays the same.
Event types#
Subscribe an endpoint to the types it needs. data holds the resource the event is about: for message events data.message is
the message resource and data.conversation is {id, created}; data.sender_attempt_count is how many senders the message
has been on (data.message.sender_attempts lists them); message.received adds data.contact_created. line.failover
reports messages that moved to another sender (one event per pair of senders, with message_count and up to 100
message_ids), and line.no_sender a line that has no healthy sender left. line.alarm tells of a condition that needs
attention once per episode (kind failover, no_sender, pool_member_blocked, budget_80, self_loop,
sponsor_quota_low or unconfirmed, with a count), however often it repeats until it clears; the line's
alarm_thresholds set when budget_80 and self_loop fire. Partner lines add line.connected,
line.needs_attention, line.recovered, line.detached, line.quota_low, line.quota_exhausted and line.recovery_requested (see
Partners). The
event catalogue shows a sample payload for every type, generated from the API contract. Ignore types you do not
know and answer 2xx: new types are added within v1.
The envelope also has api_version, the version of the API document the payload follows; log it, and compare it with the
version your integration was built against when something looks different.
- Campaign:
campaign.scheduled,campaign.unscheduled,campaign.started,campaign.paused,campaign.resumed,campaign.completed,campaign.cancelled - Contact:
contact.created,contact.updated,contact.deleted,contact.opted_out,contact.opted_in - Import:
import.completed,import.failed - Export:
export.completed - Line:
line.sender_changed,line.failover,line.no_sender,line.connected,line.needs_attention,line.recovered,line.detached,line.quota_low,line.quota_exhausted,line.alarm,line.recovery_requested - Conversation:
conversation.handed_over,conversation.read,conversation.unread,conversation.archived,conversation.unarchived,conversation.deleted - Link:
link.clicked - Channel:
channel.connected,channel.verification_failed,channel.disconnected,channel.paused,channel.resumed,channel.health_changed,channel.volume_warning,channel.qr_updated - Device:
device.paired,device.online,device.degraded,device.offline,device.revoked - Account:
account.suspended,account.reactivated,account.deletion_scheduled - Message:
message.queued,message.sent,message.delivered,message.read,message.failed,message.expired,message.cancelled,message.received - Ping:
pingpingis sent only byPOST /v1/webhook-endpoints/{id}/testand cannot be subscribed to.