Documentation
Sign inGet started

Voice events

Bird emits webhook events as a call starts, is answered, and ends. Use them to update your systems without polling. See Webhooks for subscriptions, signatures, retries, and replay.
A call's path through the event types:
  1. voice_call.initiated: Bird accepted the call setup request (a SIP INVITE) and started routing the call
  2. voice_call.answered: the number you called picked up. Only answered calls get this event
  3. voice_call.ended: the call is over, and the event carries the outcome
voice_call.initiated confirms that a call exists, while voice_call.ended reports its outcome. A call Bird refuses after accepting the INVITE still emits voice_call.ended with status: "failed" and sip_response_code: 503.
The event type is an open enum: Bird may add types over time, so match the ones you handle and ignore the rest rather than treating an unfamiliar type as an error.

The event envelope

Voice events arrive in the same nested envelope as every other Bird event, described in the Webhooks guide: type, timestamp, and a type-specific data object. The event's identity is in the webhook-id HTTP header rather than the body.
FieldDescription
typeOne of the three types on this page, for example voice_call.ended
timestampWhen the event occurred (RFC 3339). Sort by this, never by arrival order
dataEvent-specific payload, always carrying the same call identity fields
Every voice event's data contains the same identity fields for correlation. Both numbers use E.164 format: a leading +, country code, and national number.
FieldDescription
call_idThe call record's id (vcl_…), the same one shown in the Call log
session_idShared by every leg of a transferred or multi-party call (vcs_…). Null when no session correlation applies
workspace_idThe workspace the call belongs to
directionoutbound for calls your equipment placed
fromThe calling number
toThe number that was called

voice_call.initiated

Bird received the INVITE and began routing.
代码示例
{
  "type": "voice_call.initiated",
  "timestamp": "2026-06-10T14:30:00Z",
  "data": {
    "call_id": "vcl_01krdgeqcxet5s7t44vh8rt9mg",
    "session_id": "vcs_01krdgeqcxet5s7t44vh8rt9mh",
    "workspace_id": "wsp_01krdgeqcxet5s7t44vh8rt9mj",
    "direction": "outbound",
    "from": "+14155551234",
    "to": "+16505559876"
  }
}

voice_call.answered

The recipient answered, and billable time started. An unanswered call does not emit this event.
The payload is the call identity fields every voice event carries, with timestamp set to the moment of answer.

voice_call.ended

The call is over. This event adds the outcome:
FieldDescription
statusHow it ended: answered, no_answer, failed, rejected, or unknown (see Statuses)
sip_response_codeThe call's final SIP code, for example 200 or 486. A call Bird refused carries 503; null when no final code was recorded
duration_msTotal call length in milliseconds, from the moment Bird received the call to hangup
billable_msAnswered time in milliseconds, so a call nobody answered reports zero
代码示例
{
  "type": "voice_call.ended",
  "timestamp": "2026-06-10T14:31:05Z",
  "data": {
    "call_id": "vcl_01krdgeqcxet5s7t44vh8rt9mg",
    "session_id": "vcs_01krdgeqcxet5s7t44vh8rt9mh",
    "workspace_id": "wsp_01krdgeqcxet5s7t44vh8rt9mj",
    "direction": "outbound",
    "from": "+14155551234",
    "to": "+16505559876",
    "status": "answered",
    "sip_response_code": 200,
    "duration_ms": 65000,
    "billable_ms": 60000
  }
}
The call record holds two details that this event omits: the rejection reason and cost. Open the call in the call log to distinguish a Bird refusal from a carrier failure. Cost appears after rating completes.

Consuming them safely

  • Deduplicate on webhook-id. Bird delivers at least once, and a call's initiated event can be published more than once when a signaling retry replays. Same call, same stage, same webhook-id, so keying on it collapses the duplicate.
  • Do not rely on order. Deliveries are not ordered, so answered can reach you after ended. Sort by timestamp, and let a later-arriving event with an earlier timestamp lose.
  • Treat ended as the only reliable outcome. It is the event that carries status and durations, and it is the one to key your own records off.
  • Reconcile against call records. Events provide timely updates, while the call log holds the call record. Export calls as CSV for reconciliation.

Next steps

PageWhat it covers
Webhooks & eventsEndpoint setup, signature verification, retries, and replay
Call logEvery field on a call record, and CSV export