Call error codes (mpbx-api calls routes, mpbx-b2bua originate)
Returned by the call routes of the signed-in user (MVP-GAP-04): POST /api/v1/calls/click-to-call,
POST /api/v1/calls/lookup, POST /api/v1/calls/{id}/conference, POST /api/v1/calls/{id}/split,
POST /api/v1/calls/{id}/pull (W6-TEL-08), and the SIP test call of POST /api/v1/me/devices/{id}/test-call; the MPBX-CALL-* codes of the
engine come from B2bua::originate and B2bua::find_call. Merge and split return the conference
codes of conference.md. Messages never contain numbers, names or SIP identifiers.
Guide: Click-to-call, test call and conference from the API.
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
MPBX-CALL-SESSION-REQUIRED | 403 | An API key called a route that places or controls a call for a signed-in user. | Use a user session. Call control for integrations is the Call Control REST API (/api/v1/call-control/..., W7-API-01, call-control.md). |
MPBX-CALL-NO-EXTENSION | 409 | The user has no extension, or the extension or the user is disabled. Also answered by GET and PUT /me/intercom, whose switch lives on the extension. | Give the user an enabled extension. |
MPBX-CALL-ENGINE-UNAVAILABLE | 503 | No call engine can take the request: this node has none ([sip] enabled = false) and, on an API-only node (mpbx run --role api, FU-GAP04-6), no engine (role engine or all) has registered on the call-control bus in the last 15 seconds. | Start an engine (role engine or all) on the same Valkey, or enable SIP. |
MPBX-CALL-BUS-TIMEOUT | 503 | API-only node (FU-GAP04-6): the engines did not answer in time over the call-control bus (6 s; 45 s for a new call). The call may still have been placed or changed. | Retry after checking the call list; check the engines and Valkey. |
MPBX-CALL-BUS-BAD-FRAME | 500 | API-only node: a call-control bus message did not decode (an engine of another version during an upgrade). | Upgrade every node to the same version. |
MPBX-CALL-UNSUPPORTED | 503 | The engine cannot originate calls: no media service (mpbx-media) is wired, it did not answer, or the dial plan could not be read. | Check [media] and the media service; retry. |
MPBX-CALL-DEVICE-UNAVAILABLE | 409 | None of the user's devices (or not the chosen one) is registered or can be woken by a push now. | Open the app or the browser phone (it registers), then retry. |
MPBX-CALL-DESTINATION-REFUSED | 403 | The company's dial plan refuses the destination for this user (no outbound rule, the calling profile does not allow it, a blocked or premium number, a feature code), or it is not a dialable number. Nothing rang. | The same number cannot be dialled on the user's phone either; ask an administrator for the calling permission. |
MPBX-CALL-FORBIDDEN | 403 | Never through the API: an emergency number (dial it on the phone), the user's own extension, an extension that is not the user's. | Dial emergency numbers on the phone. |
MPBX-CALL-BUSY | 409 | The user is in a call already and has call waiting off. | Hang up the other call first. |
MPBX-CALL-OVERLOADED | 503 | The engine is at its call limit, or the call state store (Valkey) did not answer. | Retry after Retry-After. |
MPBX-CALL-REMOTE-CONTROL-OFF | 409 | Click-to-call with auto_answer ("Call using" a desk phone, W6-TEL-08) on a device whose remote control is off (the default). Nothing rang. | The device's owner turns it on: PUT /api/v1/me/devices/{id}/remote-control {"enabled": true}, or call without auto_answer (the phone rings). |
MPBX-CALL-NOT-FOUND | 404 | POST /calls/lookup: no live call in which you have a leg with that SIP Call-ID on one of your devices (another user's leg, a trunk leg, another company's call and an ended call look the same). | Check the Call-ID of your own leg; the call may have ended. |
Call pull (POST /api/v1/calls/{id}/pull, B2bua::pull)
Guide: Call pull and remote call control.
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
MPBX-PULL-CALL-NOT-FOUND | 404 | No live, answered call of this company in which you are a party on one of your devices (another user's call, a trunk leg, another company's call, an ended call and an unknown id look the same). | Check the call id (POST /calls/lookup, call.* events); the call may have ended. |
MPBX-PULL-STATE | 409 | The call is busy with something else: a transfer, park, conference, voicemail deposit, another pull, or a click-to-call whose destination has not answered. Nothing changed. | Retry when it is done. |
MPBX-PULL-SAME-DEVICE | 409 | The call is already on that device. | Choose another of your devices. |
MPBX-PULL-DEVICE-UNAVAILABLE | 409 | The device is not registered now and cannot be woken by a push, or it is not a device of your extension. Nothing changed. | Open the app or the browser phone (it registers), then retry. |
MPBX-PULL-FORBIDDEN | 403 | An emergency call is never moved to another device; or the extension's devices are not yours. | Stay on the device the emergency call is on. |
A device that is not one of your own active devices is refused by the API before the engine is
asked: 400 MPBX-INVALID-ARGUMENT on device_id.
The pull dial code (*85 by default, dial codes) answers with SIP
statuses instead: 404 (no call of yours on another device), 485 Ambiguous (several), 488 (no
SDP offer), 491 (the call is busy with something else), 403 (an emergency call; a device
without a user).
Also: MPBX-RATE-LIMITED (429, api.md) beyond 10 calls started or 60 call-control
requests a minute per user, and one test call per device every 10 seconds.
Audit records (W3-AUD-01): call.click_to_call (details destination, device_id,
auto_answer when asked, result: ok or the error code), call.pulled (entity the call; details
via = api or dial_code, to_device_id, result: ok, the error code, not_your_device,
or for the dial code not_found, ambiguous, forbidden or the SIP status; the actor is the user,
or the dialling device for the dial code), call.conference_merged (with_call_id, conference_id, result),
call.conference_split (result) and device.test_call (call_id, result).