call_sid. You consume the events in one of two
ways: as signed HTTP POSTs to an endpoint that you register, or off the
real-time event bus that your app already subscribes to.
The events on this page 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 ClutchCall Streams. The signing, retry,
and delivery log below are that system. Voice event-type registration is
rolling out on that shared delivery plane. Check in the console which
call.*
types your workspace can subscribe to before you depend on push delivery. 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 these events
from initiated through cleared.
Subscribe to a set of exact names, or use
* to receive everything. A prefix
glob such as call.* matches every call event.
Event payload
Every event is a flat JSON object. Only the fields that the engine actually knows for that transition are present. Absent fields are omitted, not null.string
required
The universal call identifier. Correlate every event, the CDR, recordings,
and the audio bridge through this one key.
string
required
The lifecycle state, e.g.
established or cleared. The call. prefix is
on the event name; the payload does not repeat it.string
required
The workspace that owns the call.
integer
required
The event time in milliseconds since the Unix epoch. Use it to order events
and to reject stale re-deliveries.
integer
The Q.850 clearing cause on
cleared/failed (e.g. 16 = normal clearing).
On call.dtmf this field carries the detected digit.integer
The billable talk duration in seconds. Present on
cleared.string
The calling number (the “from”).
string
The dialed number (the “to”).
string
inbound or outbound.string
The SIP trunk that the call matched or used.
string
The agent that owns this segment, when the engine knows it (AI or outbound).
data field of a call.<state> message. The message
channel has a workspace scope.
Register an endpoint
You set up endpoints in the console, on the same Webhooks screen that all products use. Each endpoint gets its own HMAC signing secret.1
Add an endpoint
Open Webhooks in the voice console (
agent.clutchcall.dev). Click
Add endpoint. Enter the HTTPS URL plus the event types to
receive. The event types are a comma-separated list, where * matches
everything (e.g. call.*).2
Store the signing secret
On create, the console shows the per-endpoint signing secret once. The
secret looks like
whsec_…. Copy it and set it on your receiver. It never
appears again.3
Pause, resume, or delete
Each row shows a health state: Healthy, Paused, or Failing (Nx)
after N consecutive non-2xx responses. Pause to stop deliveries without
loss of the endpoint. Delete to remove the endpoint (its delivery history
stays in the logs).
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 the digest over the exact bytes that you received, before
any JSON parse. Compare the digests in constant time. Reject any delivery that
does not match. Also 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. The worker treats any other status (or a timeout / connection error) as a failure and retries with backoff. - Retries. The delivery worker re-fires failed deliveries automatically, with increasing spacing. After a run of consecutive failures, the endpoint flips to Failing (Nx). Sustained failure pauses the endpoint, 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. You can filter the log by All / Delivered / Failed.
- Resend. You can re-queue any delivery row from the log with Resend. Resend re-fires the same event within seconds. Use it after you fix a receiver that returned errors.
Make your handler idempotent. Because of retries and manual resends, the
same
(call_sid, event, timestamp_ms) can arrive more than once. Dedupe on
that tuple. Do not assume 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 publish live on a workspace-scoped channel — the
same bus that the agent control channel and consoles subscribe to. Best to
drive a UI in real time.Observability pipeline
The pipeline folds every lifecycle transition 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 that 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
The status codes and failure causes that you will see on
call.failed and
call.cleared.
