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.

event.json
{
  "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.

verify.ts
// 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.