Webhooks

Control-plane events emitted as conversations start, end, and stream

Outbound customer webhooks for Voice Agents are on the near-term roadmap. Today, the definitive source of conversation events is GET /v1/conversations/{id} and GET /v1/conversations/{id}/messages — polled or called after you receive a higher-level notification from your own system.

When the outbound webhook subscription API lands you’ll be able to register a URL for any subset of these events:

EventFires when
conversation.startedThe realtime voice session is provisioned and the agent joins.
conversation.endedThe session closes. Payload carries the final duration_ms, status, and any recording_url.
message.createdA turn is added to the transcript (user speech, agent speech, or tool call/result).
evaluation.completedThe post-call evaluator finished scoring the conversation against the agent’s criteria.

Signature verification

Every delivery carries X-Speechify-Signature, the same t=…,v1=<hex HMAC-SHA256> format used for webhook-tool calls. See Tools → Verifying the signature for code.

Payload shape

1{
2 "type": "conversation.ended",
3 "id": "evt_01HS...",
4 "created_at": "2026-04-17T17:32:08Z",
5 "data": {
6 "conversation_id": "c_01HS...",
7 "agent_id": "a_01HS...",
8 "status": "completed",
9 "duration_ms": 142300,
10 "started_at": "2026-04-17T17:29:46Z",
11 "ended_at": "2026-04-17T17:32:08Z",
12 "recording_url": null
13 }
14}

Respond with 2xx within 5 seconds. We retry non-2xx responses with exponential backoff up to 24 hours.

While you wait

For long-running polling, the two endpoints you’ll want are:

  • GET /v1/conversations/{id} — single-row status lookup
  • GET /v1/conversations/{id}/messages — full transcript, ordered

Both are fast and cheap. A 1-second poll on an active conversation is fine; once status=completed arrives, stop polling and fetch the evaluations.