to_number and opens a WebSocket media stream to the client_websocket_url you provide. Your agent connects to that URL to send and receive audio (or text, depending on the pipeline mode). See Media Stream for details on pipeline modes. Alternatively, place the call with mode="hosted_agent" and Inkbox runs Inkbox Voice AI on the call — no WebSocket required.
Place call
to_number and opens a bidirectional media stream to your client_websocket_url.
Request body
Request example
JSON
from_number — the outbound line is resolved automatically:
JSON
mode and a reason instead of a WebSocket URL:
JSON
hangup_reason "voicemail". Pass voicemail_message to control what it says; omit it and the agent composes a short message from reason:
JSON
on_voicemail to "hang_up" when the call should end instead — it hangs up as soon as a voicemail beep is detected, so automated greetings and phone menus are left alone. On Voice AI calls the agent stays silent from the machine report until the no-beep verdict (roughly 25–30 seconds) while keypad presses keep working. That is the default for client_websocket calls. Set "ignore" to skip detection entirely and treat whatever answers as a person. voicemail_detection remains accepted as a deprecated alias: "enabled" is "hang_up" and "disabled" is "ignore". The MCP call tool offers the same on_voicemail and voicemail_message fields; a call placed through MCP that omits both on_voicemail and voicemail_detection leaves a message.
Voice AI inherits the identity’s saved authority when
hosted_agent_authority_mode is omitted or null. An identity with no saved
Voice AI configuration uses yolo. Set contact_scoped to
narrow one call. Set yolo when the call needs identity-wide access to
contacts, email, SMS, iMessage, or historical calls:
JSON
Response (200)
JSON
rate_limit object with your organization’s rolling 24-hour usage snapshot (calls_used, calls_remaining, calls_limit, minutes_used, minutes_remaining, minutes_limit).
Active calls, including initiated calls, count provisionally toward the daily call quota. Canceled outbound calls still count when dialing reached the phone network. Failed placements, pre-dial outbound cancellations, and inbound calls that end unanswered are excluded.
These quota and call-admission rules are server-side behavior. They apply even when you use an older SDK or CLI version.
For shared_imessage_number origination, local_phone_number is null because the shared line is never surfaced. A dedicated_imessage_number call surfaces its dedicated iMessage line as local_phone_number.
Error responses
For iMessage-line originations, actionable placement rejections use these structured
422 details:
Code examples
List calls
Query parameters
Identity-scoped API keys never see contact-rule-blocked calls, regardless of
is_blocked. Admin API keys and human sessions see blocked and non-blocked calls by default; use is_blocked=true for an admin-side blocked listing.
start_datetime, end_datetime, and tz filter on created_at. Both bounds are optional and non-breaking — omit them for unchanged behavior. See Filtering by date.
Response (200)
JSON
Code examples
The number-scoped listing is deprecated.GET /numbers/{phone_number_id}/callsonly returns calls on that dedicated phone number and omits iMessage-line calls. It accepts the samestart_datetime/end_datetime/tzdate filters for parity. UseGET /callsinstead.
Get call
Path parameters
Response (200)
Returns a call object.Error responses
Code examples
The number-scoped route is deprecated.GET /numbers/{phone_number_id}/calls/{call_id}cannot address iMessage-line calls. UseGET /calls/{call_id}.
List Voice AI tool activity
contact_scoped and yolo Voice AI calls. Calls without recorded activity, including older calls and calls driven by your own WebSocket, return an empty page.
The response includes the tool name, execution status, timestamps, and a small result summary for built-in tools. source is builtin or external_mcp. MCP records also include connection_id, config_version, connection_label, and server_url. Full arguments and results are retained when supplied by the provider, but are not returned by this endpoint; arguments_available and result_available indicate whether an external payload was captured. Credentials are never returned.
Path parameters
Query parameters
Response (200)
JSON
status is "started", "succeeded", "failed", or "unknown". For MCP calls, unknown means the outcome could not be confirmed; check the external service before repeating an action. started_at can be null when only a completion was observed; observed_at records when Inkbox first observed it. Page-level incomplete: true indicates missing external observations, including when no individual tool record is available.
On yolo calls, an accepted write can remain "started" after the call ends while Inkbox finishes it. Poll this endpoint until it reaches a terminal status when completion matters.
Error responses
Code example
Hang up call
ended_at, and transcript land through the normal call lifecycle (including the call.ended webhook).
Path parameters
Response (200)
Returns the call object as of the hangup request, normally withhangup_reason set to "local". If the call ended on its own at the same moment — the carrier reports it already over before the hangup lands — the request still returns 200, but the call closes with hangup_reason "remote". Don’t branch on hangup_reason to confirm the hangup took effect.
Error responses
Code examples
Call object
Call statuses
An outbound call rings for up to 60 seconds. If nobody answers in that window, Inkbox stops the dial and the call ends unanswered — a Voice AI call reports it as the
no_answer outcome on call.ended. A call that reaches voicemail counts as answered: its hangup_reason is "voicemail" when on_voicemail ended it, whether after leaving a message or at the beep.
A destination connection does not replace the original call’s status. For
example, a call can be completed while a successful connection retains
status: "connected" and has an ended_at timestamp.
Connection history
Each item inconnections records one attempt to connect another destination.
Records are ordered from oldest to newest.
The listed
kind, trigger, and status values can grow. Preserve unfamiliar
strings and display an unknown value neutrally rather than assuming a handoff
or a successful connection.
"requested" and "dialing" do not mean the destination is connected. For a
conference, answering the destination phone is not enough: the guest must join
the conversation. A successful connection remains "connected" after it ends;
ended_at records that later event. A failed attempt does not necessarily end
the original call. A later termination reason can set failure_code without
changing a successfully connected attempt to "failed". Read it alongside
status and ended_at, and treat unfamiliar reason strings as opaque values;
the set of reasons is not exhaustive.
Automatic forwarding is kind: "handoff" with trigger: "incoming_action".
A live transfer is kind: "handoff" with trigger: "agent_tool".
A group call is kind: "conference" with trigger: "agent_tool".
Transfers and conferences are actions the Voice AI agent
takes during a conversation. This history is read-only; it does not add SDK or
CLI transfer or conference commands.
Forwarding history
forwardings contains only automatic incoming-call forwarding attempts with
trigger: "incoming_action". Live transfers and conference guests appear only
in connections, so existing clients can continue reading calls and typed
webhooks without accepting new forwarding trigger values.
For an automatic forwarding attempt, both lists use the same id, destination,
and request, dialing, ending, and failure fields, with this legacy field mapping:
Use
status, not the presence of failure_code, to determine whether forwarding
succeeded. A "forwarded" record can also carry a later termination reason.
Other status values are unchanged. Read connections when the field is present,
even if it is empty. Fall back to forwardings only for older responses that
omit connections; do not combine the two lists or count each attempt twice.
