A voice product may expose HTTP endpoints without accepting an HTTP request that places a call.
Knowing which one you are being sold matters, because they run over different protocols and only one of them is HTTP.
What does a voice API actually do?
A voice API manages calls over HTTP, while SIP handles the signalling for each call.
Signalling is the work of setting up a call: reaching the far end, agreeing on the media, ringing, answering, hanging up. That is a real-time protocol's job, and on almost every network in the world the protocol is SIP. What is SIP covers what it does and what it deliberately leaves alone.
Management is everything around the call: which of your numbers may be presented as the caller, which countries you may reach, who is allowed to send you calls, and what each call ended up costing. None of that is real-time, so it is an ordinary HTTP API.
Bird's voice API is the second of those. Its writes create and configure SIP trunks and their delivery gateways, register and verify caller IDs, set what a number does with an incoming call, turn destination countries on and off, and mint a session credential. Its reads return calls and the statistics over them.
One of those writes does dial. Registering a caller ID starts a verification call: the endpoint "places a verification call to the number that reads out a code", and you submit the code to prove you control the number. You choose neither the destination nor the moment. The number is the one you are proving, the call is Bird's, and there is nothing to place a second one.
How does a call actually get placed?
Over SIP, by a client that authenticates against one of your trunks.
Your phone system, softphone or browser sends the SIP INVITE method that requests a call to the trunk's SIP domain. Bird checks the caller ID, the destination country, the account's limits and the wallet balance, and if the call passes those it routes it to a carrier. Placing calls covers what Bird reads off the INVITE.
Bird's own tooling demonstrates that placing a call is a signalling job rather than an HTTP one. The CLI can place a real test call, and the way it does it is to write a throwaway account file, run a local SIP client against your trunk, and delete the file when the call ends. There is no request it could send instead.
The HTTP half does have one part in getting a call up, and it is the credential. A POST to the session credentials endpoint issues a credential for a SIP client that is short-lived and limited to one workspace: "a short-lived, workspace-scoped SIP digest credential for a calling client". The username is always bird, and the response is the only place the password is returned: it "appears only in this response". The credential expires within minutes rather than hours. A browser client also receives a handshake_token to open the connection, while its password authenticates every call: it "authorizes the connection only; each call still authenticates with password".
The HTTP request returns the credential that the SIP client uses.
What can I read back about a call?
The calls themselves, at any point in their life, and the aggregates over them.
One call is a GET by its ID, and it answers whether the call is ringing, connected or long finished. Its duration, billable time, end time and cost stay empty until it ends, while its ID stays the same. The specification states: "A call in flight carries no economics yet: duration_ms, billable_ms, ended_at, and cost are null until it ends. It keeps the same id throughout, so the same call answers under one identity from the first ring to settlement."
That matters for how you poll. The absence of a cost on an in-flight call is expected; the absence of one on a call that has ended is not, and what is a call detail record covers the difference between a cost that has not arrived and a cost of zero.
Use three other reads for lists, patterns and state changes:
- The list, filtered by direction, status, trunk, either party's number, a tag or a time window. In-flight and final statuses can be combined in one page, so "what is happening right now" and "what happened yesterday" are the same query with a different filter.
- The statistics, aggregated by day, by hour, by country and by SIP response code, plus a summary. If your question is about a pattern rather than a call, this is the read, and it exists precisely so you do not rebuild it over the raw records.
- The events.
voice_call.initiated,voice_call.answeredandvoice_call.endedare pushed to your endpoint, so your systems learn a call ended without asking. Voice events has the payloads.
Which half do I need?
Both, in most cases, and in a fixed order.
The first step remains required. "No telephony infrastructure" is a fair description of what you avoid, but it describes not running a PBX rather than not having a trunk: a browser and a command-line client are both SIP clients, and both authenticate against a trunk that a human turned on. SIP trunks covers that setup, and SIP client setup maps it onto the fields a specific client asks for.
- Configure, over HTTP or in the dashboard. Create a SIP trunk, turn the direction you need on, and allow something to send it calls. Register and verify the number you will present as the caller. Turn on the countries you call.
- Signal, over SIP. Point a private branch exchange (PBX), a softphone, a browser or a voice agent at the trunk and let it place the calls.
- Read, over HTTP. Take the outcome from the events if you need it promptly, from the call record if you need the detail, and from the statistics if you need the shape.
In short
Two jobs travel under one name, over two protocols.
Setting up a call is signalling, which is SIP. Configuring who may call and reading what happened is HTTP, and that is the part called an API.
No endpoint places a call you control.
One write dials, and it is caller ID verification calling you to read out a code. Nothing takes a destination you choose, so every call you place crosses a trunk.
One call answers under one identity throughout.
The same call ID returns the in-flight record and later the settled one. Cost, billable time and the end time are null until the call ends.
The HTTP half's part in placing a call is the credential.
A short-lived SIP digest credential is minted over HTTP and then used over SIP by the client that actually dials. Its password is returned once.