Developers
Webhooks
Everything that happens on the line arrives as an event: consistent envelope, HMAC-signed, ordered per resource, and retried with backoff until your endpoint returns a 2xx.
{
"id": "evt_01kzv9f2x8…",
"type": "message.received",
"tenant_id": "tnt_01kzv90afex…",
"data": { "object": "message", … }
}Event catalog
- message.receivedAn inbound text arrived on a tenant's number
- message.deliveredAn outbound message reached the handset
- message.failedDelivery failed, with a carrier-level reason
- call.startedAn inbound call began ringing
- call.completedA call ended, with duration and outcome
- call.missedA call went unanswered with no voicemail
- voicemail.createdA voicemail landed, with recording and transcript
- brand.status_changed10DLC brand vetting progressed
- campaign.status_changedCampaign approval progressed
Verifying signatures
Each delivery carries a Handset-Signature header. Recompute the HMAC over {timestamp}.{body} with your endpoint secret and compare in constant time. Reject anything older than five minutes.
// Handset-Signature: t=1755012239,v1=5f3a… const expected = crypto .createHmac("sha256", secret) .update(`${t}.${rawBody}`) .digest("hex"); const ok = timingSafeEqual(expected, v1); // ✓
Wire your first endpoint in an afternoon.
We're onboarding a small group of vertical SaaS platforms. Tell us what your customers need to say, and to whom.