Call log
The leg log under Voice > Legs lists each connection your workspace placed or received, newest first. A call can contain several legs, such as the incoming and forwarded connections. Each entry is a call detail record (CDR), including connections that rang out or were refused. Use it to inspect duration, the final SIP response, and cost.
Bird writes each record when the leg ends, so each entry in the log has a final outcome. The Live tab beside it holds the legs that are still up.
For the complete interaction, open Voice > Calls. A call groups related legs and participants. Keep the Call ID for correlation and the Leg ID when investigating one connection; they identify different records.
The call list
Each row is one leg. A call with multiple legs has multiple rows:
| Column | What it shows |
|---|---|
| Status | How the leg ended (see Statuses) |
| From | The calling number, the caller ID your equipment presented |
| To | The number that was called |
| Direction | Outbound for the legs your equipment placed, inbound for the legs that arrived on your numbers |
| Duration | Total length of the leg, from the moment Bird received it to hangup |
| Started | When Bird received the leg |
The list is paginated, 25 legs per page. Select any row to open the leg record.
Live calls
The Live tab lists the legs up right now, and carries a count so you can see how many are up without opening it. A live leg holds one of two statuses:
| Status | What is happening |
|---|---|
| Ringing | An active call attempt is awaiting an answer; this does not confirm that the destination rang |
| In progress | The destination picked up, and the call is connected |
The columns match the leg log except for Elapsed, which replaces Duration. It counts from the answer for a connected leg and from the start for a ringing leg. The tab refreshes every few seconds. When a leg ends, it moves to the leg log with its final outcome.
Searching and filtering
The page leads with a number search and its filters. They combine: a status filter plus a date range narrows to the legs matching both.
Search by number. The search box matches a number against either side of the leg, so one query finds the legs to it and the legs from it.
Direction. Filter to outbound or inbound legs.
Status. Filter to one of answered, no answer, failed, rejected, or unknown. Each is defined in Statuses. On the Live tab the choices are ringing and in progress.
Date. On the call log, pick a preset (the last 24 hours, 7 days, or 30 days) or choose a custom range on the calendar.
Usage this month
The monthly summary contains three tiles for the current calendar month in UTC:
| Tile | What it counts |
|---|---|
| Legs | Completed leg records in the month, including unanswered and refused ones |
| Total duration | Each leg's full length added up, from the moment Bird received it to hangup |
| Billable time | Each leg's answered time added up |
The difference between total duration and billable time is unanswered ring time. An unanswered leg has no billable time.
Each destination rate rounds billable time to its billing increment. See Cost and billing for pricing details.
These tiles cover the whole month whatever you filter the list to.
Statuses
A leg in the log ended with one of these outcomes:
| Status | What happened |
|---|---|
| Answered | The destination picked up. Billable time is answer to hangup |
| No answer | The attempt timed out without an answer; this does not prove the destination phone rang |
| Rejected | The call was refused rather than carried through |
| Failed | The call was attempted and did not work, and SIP response is what came back |
| Unknown | The outcome could not be determined, for example when no final response ever arrived |
Rejected covers two refusals, and the rejection reason separates them. Either Bird refused the call before a carrier was involved, in which case the reason names the check it failed, or the far end declined it outright, in which case SIP response carries its answer and there is no reason. An incoming call that the number it dialed turned away is Rejected with no reason too, because it failed no check: its Inbound route says what the number was set to do. See Rejected calls.
Failed is not a refusal. It means the call was attempted and did not work: a busy number is Failed with carrier response 486, and an unallocated one is Failed with 404.
If you read these values from your own tooling, match the ones you handle and treat any other as a status you do not handle rather than an error. The list also carries busy and canceled, reserved for incoming calls delivered to your own numbers. Neither is emitted yet, and both outcomes are reported as failed today.
Inspecting a call
Opening a leg shows what Bird recorded about that connection:
| Field | What it tells you |
|---|---|
| Status | The leg's outcome (see Statuses). A leg Bird refused also shows the reason and what to do about it |
| SIP response | The leg's final SIP code, for example 200 or 486. A leg Bird refused carries 503, with no carrier involved |
| From / To | Both numbers, each copyable |
| Inbound route | On an incoming call, the route selected for the number, such as a trunk, forward, sequence, or rejection. Links to that number |
| Trunk | The SIP trunk the call came in on, or was delivered to, useful when several sites share a workspace |
| Started | When Bird received the leg |
| Answered | When the leg was picked up, or Not answered |
| Ended | When the leg was torn down |
| Leg ID | The connection record's own ID (vcl_…). Use it with GET /v1/voice/legs/{leg_id} and quote it to support. |
| Call ID | Shared by every leg of one call (vcs_…). Use the call_id filter to find related legs. A forwarded call has two legs sharing one. |
| Billing | Billable time, total duration, and the leg's cost once it has been rated |
Inbound route appears on incoming calls and records the selected route. A trunk route on a rejected call means the call did not reach a working answer. Receiving calls explains the routes and what each one records.
Rejected calls
A rejected call was refused rather than carried through, and two different things produce that.
Bird refused it before a carrier was involved. Before dialing out, Bird checks the caller ID, destination, account limits, and wallet balance, and refuses a call that fails one of them. Your phone system receives SIP 503, while the authenticated call record stores the specific reason. This prevents unauthenticated callers from learning account details. Open the call to see the cause and a link to the relevant setting.
The number that was dialed turned the call away. An incoming call to a number set to reject, or to a number nobody has pointed anywhere, is rejected with no reason at all: it failed no check of ours. Inbound route is what says so. Receiving calls works through those refusals.
The reasons below are the first kind. They apply to incoming calls as well as outgoing ones, because the account limits and the wallet are checked either way.
Reasons you can fix
| Reason | What happened | What to do |
|---|---|---|
source_not_allowed | The call arrived from an address the trunk's IP allow list does not cover | Add the address your phone system sends from to the trunk |
caller_id_not_verified | The number in the From header is neither an eligible Bird number nor a verified external caller ID in this workspace | Use an eligible Bird number, or verify the external number |
destination_not_enabled | Calling to that country is switched off for your workspace | Turn the country on under Destinations |
insufficient_balance | Your wallet did not cover the call, so Bird refused it up front | Top up, or turn on automatic top-ups so a low balance does not interrupt calling |
daily_spend_exceeded | The call would have passed your organization's daily voice spend ceiling | Wait for the ceiling to reset at the start of the next UTC day, or ask Bird to raise it |
concurrent_calls_exceeded | You have as many calls in progress as your account allows | Wait for a call to end, or contact support to raise the ceiling |
calls_per_second_exceeded | You placed new calls faster than your account allows | Slow your dial rate, then retry. Retrying immediately gets the same answer |
number_ownership_not_verified | You bought this number, but the country that issued it has not accepted the paperwork proving you own it | Complete what the number's ownership field asks for, then place the call again |
A campaign dialer can hit calls_per_second_exceeded while nowhere near the concurrent-call ceiling, so check which of the two you got before changing anything.
Reasons Bird resolves for you
These sit on Bird's side of the setup. Contact support and quote the Leg ID from the record:
| Reason | What happened |
|---|---|
routing_not_configured | Your workspace's routing is still being attached, which is expected while a new voice setup is being completed |
no_route_found | Routing is attached, but it does not cover the number you dialed. Contact support with the leg ID to check the route |
destination_blocked | Bird's routing configuration blocks calls to that destination |
call_not_permitted | Bird could not complete the call for your account, so it refused the call rather than place it on unknown terms |
How a refusal reads
Read the status and the rejection reason together:
- Rejected with a rejection reason. Bird refused the call, and the reason identifies the failed check. The
SIP responseis the503your phone system received. Follow the reason's account or routing resolution. - Rejected with no rejection reason. On an outgoing call, the far end declined it outright and
SIP responsecarries its code. On an incoming call, the number that was dialed turned it away, and Inbound route says what that number was set to do. - Failed. The call was attempted and did not work, and
SIP responsecontains the code that came back. A486means busy, while404means the number is unallocated. This usually points at the number rather than at your setup.
A call Bird cannot admit at all is turned away before a record exists, so it never reaches the log. Voice troubleshooting covers those calls.
Getting the records out
Four ways to work with these records outside the dashboard:
- Export CSV. Download CSV on the Leg log tab exports the records matching your current filters across pages, up to 10,000 legs. A larger selection returns an error without a file; narrow your date range or filters and export each selection separately. Use it for reconciliation and ad-hoc reporting.
- Read them over the API.
GET /v1/voice/legsreturns the filtered list, andGET /v1/voice/legs/{leg_id}returns one record. Both require an API key with thevoicescope atreadlevel. Check the API reference for the published operations for other Voice resources and their required scopes. - Read them from the terminal. The Bird CLI provides
bird voice legs list,bird voice legs get, andbird voice stats. The MCP server exposes the same reads to agents. - Subscribe to the events.
voice_call.initiated,voice_call.answered, andvoice_call.endedare pushed to your endpoint as calls happen, so your own systems stay current without polling. See Voice events.
Next steps
| Page | What it covers |
|---|---|
| Voice events | The three call events, their payloads, and how to consume them |
| Placing calls | What Bird expects on the INVITE, and how a call is priced |
| Receiving calls | Pointing a number at a trunk or a forward, and what it records |
| SIP trunks | The IP allow list, allowed API keys, and Digest settings |
| Voice destinations | Enabling countries, and what availability means |
| Errors | The API error envelope and its recovery fields |
Related resources
Continue with the documentation, guides and examples for this topic.