The classes carry over from HTTP, and the familiar numbers mean roughly what you expect. One code in ordinary use means something quite different from what the standard says.
What do the classes mean?
SIP uses six response classes, numbered like HTTP's and read the same way. RFC 3261, which defines SIP, names them in section 7.2:
1xx: Provisional -- request received, continuing to process the request;
2xx: Success -- the action was successfully received, understood, and accepted;
3xx: Redirection -- further action needs to be taken in order to complete the request;
4xx: Client Error -- the request contains bad syntax or cannot be fulfilled at this server;
5xx: Server Error -- the server failed to fulfill an apparently valid request;
6xx: Global Failure -- the request cannot be fulfilled at any server.
The one class with no HTTP equivalent is 6xx. The difference between a 4xx and a 6xx is scope. A client error says this server could not fulfill the request, while a global failure says no server can. There is no point trying an alternative route after a 6xx. In practice you will rarely see one.
What do the common codes mean?
403 means the far end refused the call. 404 means the number is not allocated. 486 means the end system was reached and is busy. 503 means the server will not take the request now. RFC 3261 defines them in section 21:
403 Forbidden: "The server understood the request, but is refusing to fulfill it."404 Not Found: "The server has definitive information that the user does not exist at the domain specified in the Request-URI."486 Busy Here: "The callee's end system was contacted successfully, but the callee is currently not willing or able to take additional calls at this end system."503 Service Unavailable: "The server is temporarily unable to process the request due to a temporary overloading or maintenance of the server."
The wording on 486 carries the diagnosis: the end system was contacted successfully, and then declined. A 404 means the number is not allocated. Both point at the number you dialed rather than at your own setup. That is the opposite of the instinct a 4xx usually triggers. A trunk that is working correctly does not need auditing.
Why did my call get a 503?
Two quite different things answer 503, and the call log is what separates them.
A 503 with a matching call record is a refusal. Bird checks the caller ID, the destination, the account's limits and the wallet balance before dialing out, and a call failing one of those checks is refused with 503. The record carries the rejection reason naming the check it failed. Retrying an identical call gets the same answer, so the fix is the setting the reason points at rather than another attempt.
The reason is deliberately not on the wire. Your phone system gets the bare 503; the specific reason lives on the authenticated call record instead. That is a security decision rather than an omission. A SIP INVITE is the method that requests a call, and anyone can send you one. Putting the cause in the response would tell them whether a destination is enabled, whether a caller ID is verified, or whether an account is out of balance.
A 503 with no call record at all is not a refusal. No check rejected the call, so there is no reason to read and nothing appears in the log. This is the case where the RFC's own definition is the better guide, and where a retry is the right move.
So the workflow is: see the 503 on your side, then look for the call in the log. If it is there, the rejection reason tells you what to change, and every reason and its fix is listed under rejected calls. If it is not there, treat it as transient and retry rather than going looking for a setting to fix.
Rejected, Failed, or something else?
The SIP code is only half the answer. The call's status is the other half, and reading them together is what makes either useful.
| Status | What happened |
|---|---|
answered | The destination picked up |
no_answer | It rang and was not answered before timing out |
rejected | It was refused rather than carried through |
failed | It was attempted and did not work, and the SIP response is what came back |
unknown | No final response ever arrived, so the outcome could not be determined |
Rejected covers two different refusals, and the rejection reason is what separates them. If there is a reason, Bird refused the call and the reason names the check it failed, with the 503 above as the code. If there is no reason, the far end declined it outright and the SIP response carries the far end's own code. An incoming call that the number it dialed turned away is also rejected with no reason, because it failed no check of Bird's. What the number was set to do is recorded as its inbound route.
Failed is not a refusal at all. The call was attempted and did not work. This is where a 486 or a 404 lands.
Two further statuses exist in the API and never reach a record. busy and canceled are reserved for incoming calls delivered to your own numbers. busy covers a called party that rejected the call as busy. canceled covers a caller who hung up before it was picked up. Neither is emitted, and both outcomes are reported as failed. Reading failed together with the SIP response is what tells them apart. A branch on either status never runs, and a search of your records for them returns nothing.
The table above is the outcomes an ended call can carry. A call still in progress reads ringing or in_progress, so filtering the call list meets those two as well. The list is open in the other direction too: match the ones you handle and treat an unrecognized value as a status you do not handle rather than as an error.
How do I see this across many calls?
One call at a time is the wrong tool for a pattern. The voice statistics endpoint aggregates response codes across your traffic, which is how you tell a systemic problem from a bad number.
A rise in 503 is about your account or your configuration, since those are Bird's own refusals. A rise in 486 or 404 is about the numbers being dialed. The first is something you can fix in a setting, and the second usually means a list needs cleaning.
Voice troubleshooting works through the individual cases. The call log covers what each record holds, including the call ID to quote when only Bird can resolve a reason.
In short
Whether a 503 is a refusal depends on the call log.
A 503 with a record is a refusal, and the record names the reason. A 503 with no record is not, and that one is worth retrying.
Rejected and Failed are different outcomes.
Rejected means the call was refused. Failed means it was attempted and did not work, and the SIP code is what came back.
A 486 or a 404 is about the number you dialed.
Busy and unallocated are answers from the far end, so they point at the destination rather than at your configuration.
Two call statuses exist but are never emitted.
busyandcanceledare reserved for incoming calls. Neither is emitted, and both outcomes are reported asfailed.