call_sid, and you consume them either
as signed HTTP POSTs to an endpoint you register or off the real-time
event bus your app already subscribes to.
The events described here are shipped and flow on every call today (they are
the same records that power reports and
dashboards). Programmable per-endpoint
HTTP webhooks for voice ride the same signed-delivery system that powers
TeleQuick Streams — signing, retry, and the delivery log below are that
system. Voice event-type registration is rolling out on that shared
delivery plane; confirm which
call.* types your workspace can subscribe to in
the console before you depend on push delivery, and use the real-time bus or the
observability pipeline in the meantime.What you can subscribe to
Every event is namedcall.<state>. One call produces a stream of them from
initiated through cleared.
| Event | Fires when | Carries |
|---|---|---|
call.initiated | An inbound INVITE arrives or you originate a call | ani, dnis, direction, trunk_id |
call.delivered | The call reached the destination (alerting / early media) | — |
call.established | The call was answered (two-way media up) | handler_id when AI/agent-handled |
call.held / call.retrieved | The call was put on hold / taken off hold | — |
call.reinvited | Media was renegotiated mid-call (re-INVITE) | — |
call.transferred | A REFER transfer occurred | — |
call.dtmf | A DTMF digit was detected on the leg | digit in cause |
call.failed | Setup failed before answer | cause (Q.850) |
call.cleared | The call ended | cause (Q.850), duration_sec |
* to receive everything. A prefix
glob such as call.* matches every call event.
Event payload
Every event is a flat JSON object. Only fields the engine actually knows for that transition are present — absent fields are omitted, not null.The universal call identifier. Correlate every event, the CDR, recordings, and
the audio bridge through this one key.
The lifecycle state, e.g.
established or cleared (the call. prefix is on
the event name, not repeated inside the payload).The workspace the call belongs to.
Event time in milliseconds since the Unix epoch. Use it for ordering and for
rejecting stale re-deliveries.
Q.850 clearing cause on
cleared/failed (e.g. 16 = normal clearing). On
call.dtmf this carries the detected digit.Billable talk duration in seconds — present on
cleared.Calling number (the “from”).
Dialed number (the “to”).
inbound or outbound.The SIP trunk the call matched or used.
The agent that owns this segment, when the engine knows it (AI or outbound).
data field of a call.<state>
message on a channel scoped to the workspace.
Register an endpoint
Endpoints are configured in the console, on the same Webhooks screen used across products. Each endpoint gets its own HMAC signing secret.Add an endpoint
Open Webhooks in the voice console (
agent.telequick.dev), click Add
endpoint, and enter the HTTPS URL plus the event types to receive —
a comma-separated list where * matches everything (e.g. call.*).Store the signing secret
On create, the console shows the per-endpoint signing secret once — it
looks like
whsec_…. Copy it and set it on your receiver; it never appears
again.Verify the signature
Every delivery is signed. The engine’s delivery worker computesHMAC-SHA256(secret, rawBody) and sends it as a hex digest in a signature
header. Recompute it over the exact bytes you received (before any JSON
parse) and compare in constant time. Reject anything that does not match, and
reject payloads whose timestamp_ms is far outside your clock tolerance to
blunt replays.
- TypeScript
- Python
Delivery, retry, and inspection
- Acknowledge with 2xx. Any
2xxresponse marks the delivery successful. Any other status (or a timeout / connection error) is treated as a failure and retried with backoff. - Retries. Failed deliveries are re-fired automatically by the delivery worker with increasing spacing. After a run of consecutive failures the endpoint flips to Failing (Nx); sustained failure pauses it so a dead receiver cannot back up the queue.
- Delivery log. The console keeps a per-delivery record — event type, target object, endpoint, response code, a short response-body preview, attempt number, and timestamp — filterable by All / Delivered / Failed.
- Resend. Any delivery row can be re-queued from the log with Resend, which re-fires the same event within seconds. Use it after fixing a receiver that was returning errors.
Make your handler idempotent. Retries and manual resends mean the same
(call_sid, event, timestamp_ms) can arrive more than once; dedupe on that tuple
rather than assuming exactly-once delivery.Consume events without an endpoint
You do not have to run a public HTTPS receiver. The same events are available in two other places today:Real-time event bus
call.<state> messages are published live on a workspace-scoped channel —
the same bus the agent control channel and consoles subscribe to. Best for
driving a UI in real time.Observability pipeline
Every lifecycle transition is folded per
call_sid into the durable
reporting store behind dashboards and CDRs. Best for after-the-fact
reporting and reconciliation.Related
Calls API
Originate, look up, transfer, and hang up — the control plane for the
call_sid these events key off.Call traces
Follow one call end-to-end across signalling, media, and the agent runtime.
Agent control channel
The event surface for human-agent softphones: offers, state changes, accept
and reject.
Errors
Status codes and failure causes you will see on
call.failed and
call.cleared.