Skip to content
Inkbox

Inkbox

DocsPricingBlogContact
GuidesAPI ReferenceChangelog

Ctrl K

GuidesAPI ReferenceChangelog

Jump to

Calls

Place outbound calls with bidirectional audio streaming, and retrieve call records. Calls are scoped to your agent identity and span both origins — the dedicated phone numbers your organization owns (past and present) and your agent identity's shared iMessage line.

When you place a call, Inkbox dials the 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 POST

POST /place-call

Initiate an outbound call. Inkbox dials the to_number and opens a bidirectional media stream to your client_websocket_url.

Request body

FieldTypeRequiredDescription
originationstringNo"dedicated_number" (default) or "shared_imessage_number". Selects whether the call goes out from a dedicated number you own or from your agent identity's shared iMessage line
from_numberstring | nullConditionalCaller ID in E.164 — REQUIRED for dedicated_number origination and must be an active number in your org. Ignored for shared_imessage_number (the outbound line is resolved automatically from the identity's active iMessage assignment to the recipient)
to_numberstringYesDestination number in E.164 format
agent_identity_idUUID | nullConditionalThe agent identity placing the call. Required for shared_imessage_number when using an admin API key or the Inkbox Console; identity-scoped API keys resolve their own identity automatically (naming a different one returns 403)
client_websocket_urlstring | nullNoWebSocket URL (wss://) your agent listens on. Can carry text or audio, depending on how the connection is configured. Falls back to the identity's configured client_websocket_url (see Incoming calls) if omitted (400 if none is set). Must be absent when mode is "hosted_agent" (422)
modestringNoWho drives the call: "client_websocket" (default — your agent, over the media stream) or "hosted_agent" (Inkbox Voice AI)
reasonstring | nullConditionalThe voice agent's task brief — what this call is for, in plain language. REQUIRED with mode="hosted_agent" (non-empty, max 2,000 characters); invalid with mode="client_websocket" (422)

Request example

JSONJSON

To place the call from your agent identity's shared iMessage line, omit from_number — the outbound line is resolved automatically:

JSONJSON

To have Inkbox Voice AI run the call, pass mode and a reason instead of a WebSocket URL:

JSONJSON

Response (200)

JSONJSON

The place call response includes a rate_limit object with your organization's rolling 24-hour usage snapshot (calls_used, calls_remaining, calls_limit, minutes_used, minutes_remaining, minutes_limit).

For shared_imessage_number origination the response has "origin": "shared_imessage_number" and local_phone_number is null — the shared line is internal routing detail and is never surfaced.

Error responses

StatusDescription
400from_number is not active, or no WebSocket URL is available
403Recipient rejected for policy reasons (also returned if an identity-scoped key names a different identity)
404from_number not found
409(shared line) No active shared connection to the recipient, the agent identity is not active, or the agent identity is not iMessage-enabled
422Cannot call the number itself; for shared lines, also returned when the line is not voice-enabled or not verified. Also returned for mode/reason shape violations: mode="hosted_agent" without a reason (or with a client_websocket_url), or a reason with mode="client_websocket"
429Organization has exceeded 100 calls or 100 minutes in the last 24 hours. Response includes Retry-After (seconds), X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers
502Upstream dial failed
503hosted_agent_at_capacity — Voice AI capacity is momentarily saturated, retry shortly; or hosted_agent_unavailable — Inkbox Voice AI is not available. hosted_agent mode only

Code examples


List calls GET

GET /calls

List calls for an agent identity, newest first — spans both dedicated numbers and shared iMessage lines.

Query parameters

ParameterTypeDefaultDescription
agent_identity_idUUIDThe agent identity whose calls to list. Required for admin API keys and Console sessions (omitting it returns 422); identity-scoped keys resolve their own automatically and cannot name another (403)
limitinteger50Number of results to return (1–200)
offsetinteger0Pagination offset
is_blockedbooleanFilter by blocked state. true returns only blocked rows, false returns only non-blocked rows, and omitting it applies the caller's default visibility
start_datetimestringOnly calls created on or after this date/time
end_datetimestringOnly calls created on or before this date/time; a bare date includes the whole day
tzstringUTCIANA zone for interpreting zone-less start_datetime/end_datetime values. Defaults to UTC

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)

JSONJSON

Code examples

The number-scoped listing is deprecated. GET /numbers/{phone_number_id}/calls only returns calls on that dedicated number and omits shared iMessage calls. It accepts the same start_datetime/end_datetime/tz date filters for parity. Use GET /calls instead.


Get call GET

GET /calls/{call_id}

Get a single call by ID. Addresses calls of either origin — dedicated numbers or shared iMessage lines.

Path parameters

ParameterTypeDescription
call_idUUIDUnique identifier of the call

Response (200)

Returns a call object.

Error responses

StatusDescription
404Call not found (for identity-scoped keys, cross-identity reads are masked as 404)

Code examples

The number-scoped route is deprecated. GET /numbers/{phone_number_id}/calls/{call_id} cannot address shared iMessage calls. Use GET /calls/{call_id}.


Hang up call POST

POST /calls/{call_id}/hangup

End a live call from outside it. The agent on the call can always end it in-band over the media WebSocket; this endpoint is the lever for everything else — tests, operator tooling, or any process that only holds the call ID. It works identically on Inkbox Voice AI calls, where it's the operator kill switch.

The carrier confirms the teardown asynchronously, so the returned call may still show its live status for a moment; the final status, ended_at, and transcript land through the normal call lifecycle (including the call.ended webhook).

Path parameters

ParameterTypeDescription
call_idUUIDUnique identifier of the call

Response (200)

Returns the call object as of the hangup request, normally with hangup_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

StatusDescription
404Call not found (for identity-scoped keys, cross-identity calls are masked as 404)
409call_already_ended — the call already finished; or call_not_active — the call has no active carrier leg yet

Code examples


Call object

FieldTypeDescription
idUUIDUnique call identifier
originstring"dedicated_number" or "shared_imessage_number"
local_phone_numberstring | nullYour number (E.164) for dedicated_number calls. null for shared_imessage_number calls — the shared line is never surfaced.
remote_phone_numberstringThe other party's number (E.164)
directionstring"outbound" or "inbound"
statusstringCall status (see below)
client_websocket_urlstring | nullWebSocket URL the call was streamed to
modestringWho drove the call: "client_websocket" or "hosted_agent"
reasonstring | nullThe voice agent's task brief on outbound hosted_agent calls; null otherwise
post_call_action_itemsarrayOpen action items Inkbox Voice AI recorded, ordered by seq — each { id, seq, action, details, status }, the same shape the call.ended webhook delivers. Always present; empty for client_websocket calls and Voice AI calls with none
use_inkbox_ttsboolean | nullWhether Inkbox handles text-to-speech (null until negotiated via WebSocket)
use_inkbox_sttboolean | nullWhether Inkbox handles speech-to-text (null until negotiated via WebSocket)
hangup_reasonstring | nullWhy the call ended: "local", "remote", "max_duration", "voicemail", "rejected", or "failed"
started_atstring | nullWhen the call was answered (ISO 8601)
ended_atstring | nullWhen the call ended (ISO 8601)
is_blockedbooleanWhether the call was rejected by a contact rule or by default-block in whitelist mode. Identity-scoped API keys never receive rows where this is true
created_atstringCreation timestamp (ISO 8601)
updated_atstringLast updated timestamp (ISO 8601)

Call statuses

StatusDescription
initiatedCall created, dialing in progress
ringingRemote party is ringing
answeredCall connected and active
completedCall ended normally
canceledCall ended before being answered
failedCall could not be connected

Inkbox

Copyright © 2026 Inkbox

This site is protected by reCAPTCHA.

Google Privacy Policy and Terms of Service apply.

Website

Inkbox

Copyright © 2026 Inkbox

This site is protected by reCAPTCHA.

Google Privacy Policy and Terms of Service apply.

Website

Y CombinatorBacked by Y Combinator
Calls