voice-legs

Get a leg

Returns a single leg at any point in its lifecycle. A leg that is still ringing or connected answers with its in-flight status and no economics: duration_ms, billable_ms, and ended_at fill in once it ends, at this same URL, and cost does too unless the leg was never rated, as with a verification call Bird places and answers on your behalf. Returns a 404 not_found_error if the leg does not exist in the workspace.

get/v1/voice/legs/{leg_id}

Request

  • Base URL: https://us1.platform.bird.com
  • URL: https://us1.platform.bird.com/v1/voice/legs/{leg_id}
  • Auth: one of:
    • HTTP bearer
    • API key in cookie bird_session

Headers

X-Workspace-Idstring

Workspace context for the request. Required for dashboard authentication and master keys. Workspace keys and access tokens already identify their workspace; send that workspace or omit the header. A different one is rejected.

X-Organization-Idstring

Organization context for the request. Required for dashboard authentication. An API key or access token carries its own organization, so send either that organization or no header at all; a different one is rejected.

Response

The leg's current status, timing, and routing details.

idstring required
call_idstring
workspace_idstring required
direction'inbound' | 'outbound' required

Whether the call was placed from your side, by your PBX, the API, the browser or Bird dialing onward for you (outbound), or arrived from a remote party (inbound).

fromstring required

Calling party number in E.164 format.

tostring required

Called party number in E.164 format.

sip_trunk_idstring
sip_call_idstring

The SIP Call-ID of this leg's signalling. We relay it unchanged, so it matches what the carrier and your own equipment logged for the same leg: the carrier's value on an incoming leg, and your system's value on a leg you place through a SIP trunk. Use it to match this leg against a carrier's records or your PBX logs. Legs recorded before this field existed carry it only if they were answered.

status'answered' | 'no_answer' | 'busy' | 'canceled' | 'failed' | 'rejected' | 'unknown' | 'ringing' | 'in_progress' required

Call status.

A call that has ended carries one of:

  • answered means it connected and the far end picked up.
  • no_answer means nobody picked up before the call timed out.
  • rejected means it was refused rather than attempted. Either we turned it away before dialing a carrier, in which case rejection_reason names the check it failed where there was one, or the far end declined it.
  • failed means it was attempted and did not work, and sip_response_code is what came back.
  • unknown means the outcome could not be determined. Contact support with the call id if you see one.

An active call carries ringing before it is picked up and in_progress afterward. The call list's status filter takes any mix of the two sets.

busy and canceled are reserved for incoming calls delivered to your own numbers: busy for a called party that rejected the call as busy, canceled for a caller who hung up before it was picked up. Neither is emitted yet and both outcomes are reported as failed today.

sip_response_codeinteger nullable

Final SIP response code received from the carrier. null when no SIP response was received, for example on timeout or DNS failure.

rejection_reason'source_not_allowed' | 'caller_id_not_verified' | 'routing_not_configured' | 'no_route_found' | 'destination_blocked' | 'destination_not_enabled' | 'insufficient_balance' | 'daily_spend_exceeded' | 'concurrent_calls_exceeded' | 'calls_per_second_exceeded' | 'call_not_permitted' | 'number_ownership_not_verified'

Why we rejected the leg. Use rejection_reason to identify the cause; sip_response_code alone cannot distinguish these reasons.

You can resolve these issues:

  • source_not_allowed: The leg came from an IP address that is not in the trunk's allowed-address list. Add the address your PBX sends from.
  • caller_id_not_verified: The number in the From header is not a verified caller ID for this workspace. Verify it or use a verified caller ID.
  • number_ownership_not_verified: The ownership documents for this purchased number have not yet been accepted under its country's requirements. We block outgoing and incoming legs on the number until verification is complete. Blocked incoming legs never reach your PBX, and their route type is reject regardless of the number's configuration. Open the number under Numbers and complete its ownership requirements, then retry the leg.
  • destination_not_enabled: Calling to this destination country is disabled. Enable it in your voice destination settings.
  • insufficient_balance: Your wallet balance was too low for the leg. Top up or enable automatic top-ups.
  • daily_spend_exceeded: The leg would exceed your organization's daily voice spend limit. Retry after the limit resets at the start of the next UTC day.
  • concurrent_calls_exceeded: You already have as many legs in progress as your account allows. Wait for one to end or ask support to raise the limit.
  • calls_per_second_exceeded: You placed legs faster than your account allows. Reduce your dialing rate and retry.

For all other reasons, contact support and provide the leg id:

  • routing_not_configured: This trunk has no dial plan, which can happen on a new trunk.
  • no_route_found: A dial plan is attached, but no rule in it covers this destination.
  • destination_blocked: The destination is blocked by our routing configuration.
  • call_not_permitted: The leg could not be priced for your account.
started_atstring date-time required

When the leg was initiated.

answered_atstring date-time nullable

When the leg was answered (200 OK received). null for unanswered legs.

ended_atstring date-time nullable

When the leg ended (BYE or final non-2xx response). null for legs that ended abnormally without a recorded end event.

duration_msinteger nullable

Total leg duration in milliseconds, measured from the first INVITE to the BYE or final response. null while the leg is still in progress and has no final duration yet.

pdd_msinteger

Post-dial delay in milliseconds: how long the caller heard nothing between dialing and the phone starting to ring at the other end. High values are what callers experience as the leg not going through. Absent when the leg never rang, either because it failed first or because the carrier answered it immediately.

billable_msinteger nullable

Billable duration in milliseconds, measured from answer to leg end. Zero for unanswered legs, and null while the leg is still in progress.

Example response

{
  "id": "vcl_01krdgeqcxet5s7t44vh8rt9mg",
  "call_id": "vcs_01krdgeqcxet5s7t44vh8rt9mg",
  "workspace_id": "ws_01krdgeqcxet5s7t44vh8rt9mg",
  "direction": "outbound",
  "from": "+14155551234",
  "to": "+16505559876",
  "actor": {
    "id": "usr_01krdgeqcxet5s7t44vh8rt9mg",
    "type": "user"
  },
  "sip_trunk_id": "spt_01krdgeqcxet5s7t44vh8rt9mg",
  "sip_call_id": "3f9a1c8e7b2d4a5f@sip.example.net",
  "status": "answered",
  "sip_response_code": 200,
  "rejection_reason": "destination_not_enabled",
  "route": {
    "type": "trunk"
  },
  "tags": [
    {
      "name": "category",
      "value": "welcome"
    }
  ],
  "duration_ms": 65000,
  "pdd_ms": 850,
  "billable_ms": 60000,
  "media_quality": {
    "mos": 4.32,
    "jitter_ms": 12,
    "packet_loss_pct": 1.5,
    "round_trip_time_ms": 42
  },
  "cost": {
    "amount": "0.013000",
    "currency_code": "EUR",
    "outbound_amount": "0.013000"
  }
}

Changes

No recorded changes to this operation across all 2 revisions of this API.