Skip to main content
Each agent identity can have one phone number. Agents can place outbound calls, receive inbound calls, and handle audio in real time. Inkbox Voice AI calls are automatically transcribed. For calls handled through your own WebSocket, Inkbox captures transcripts when it handles speech processing; otherwise, your agent supplies them. Calls forwarded before the agent answers have forwarding history instead of transcripts. A live transfer keeps the transcript from the agent conversation before the handoff. Companion mode lets a trusted sponsor invite the agent into an eligible group MMS conversation. Reply by conversation ID; consent and opt-outs still apply to every recipient. Same-participant MMS chats share a conversation identity, so sponsorship cannot distinguish them as separate groups.

Additional calling destinations

Enable additional outbound countries from Billing in the Inkbox Console. Review the quoted charge before confirming. Country access applies to owned phone lines and also gates forwarding, transfers, and added call participants. Shared lines retain their own destination availability. See calling destinations for purchase, cancellation, and SDK details.

Connecting your agent

New identities use Inkbox Voice AI (beta) to answer incoming calls by default. It requires no WebSocket server or code. You can also handle calls with your own agent. Inkbox connects to your client_websocket_url when a call starts and disconnects when it ends. Configure this URL for incoming calls or provide it when placing an outbound call. The rest of this section describes that setup.

Speech and text

By default, Inkbox handles both speech-to-text (STT) and text-to-speech (TTS) on your behalf. Your agent only deals with text — it receives transcribed caller speech as text and responds with text that Inkbox speaks aloud. If you want to handle audio directly, you can opt out of either or both by setting X-Use-Inkbox-Speech-To-Text: false or X-Use-Inkbox-Text-To-Speech: false in your WebSocket handshake response. See Media Stream for the full protocol.

Inbound call routing

For inbound calls, you configure how Inkbox should handle them on the agent identity. The action applies to every dedicated phone or iMessage line routed to that identity:
  • auto_reject — Inkbox rejects the call immediately. Set this explicitly if you do not want incoming calls answered.
  • auto_accept — Inkbox answers automatically and connects to your client_websocket_url immediately.
  • webhook — Inkbox POSTs the incoming call to your incoming_call_webhook_url first. Your endpoint responds with {"action": "answer"|"reject"}. If answering, include a client_websocket_url in the response and Inkbox will connect to it.
  • hosted_agent — Inkbox Voice AI answers. This is the default and requires no URL.
  • forward — Inkbox sends the call to one E.164 phone number or complete SIP URI. No media WebSocket is required. See Incoming calls.
Forwarding applies to every inbound phone or iMessage line routed to the agent identity. Call history shows the destination and whether the forwarding attempt is still dialing, succeeded, or failed. The ordinary call status remains separate and continues through answered and completed.

Placing a call

Pass client_websocket_url to stream audio to your agent. The returned call object includes status and rate limit information.

Inkbox Voice AI

To hand a call to Inkbox instead of running your own WebSocket server, place it with mode="hosted_agent" and a plain-language reason. Inkbox Voice AI works the errand, records action items, and delivers the whole package — transcript, outcome, and action items — on the call.ended webhook. See the Inkbox Voice AI guide for everything it knows and can do.

Call transfers and group calls

Inkbox Voice AI can transfer an active call on a dedicated phone or dedicated iMessage line entirely to another phone number and leave the conversation. It can also add one person for a three-way conference call while staying on the line. A person on the call can tell the agent who to connect and whether it should hand over the call or stay to help. You can also include this in the call’s task brief or the identity’s Voice AI instructions. Shared iMessage lines cannot transfer calls or add conference guests.

Hanging up a call

The agent on a call ends it in-band over the media WebSocket. To end a call from anywhere else — a supervisor process, a test harness, operator tooling — hang it up by ID. This 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; a call that has already ended answers with a 409.

Pressing keypad digits

On a client-driven call, your agent presses keys over the media WebSocket with the dtmf event. Send one to 30 keys from 0-9, *, and # to navigate an automated phone menu or enter an extension:
Keypad bursts are sent in order without blocking audio. At most 20 bursts per call can be outstanding, including the one being sent; further bursts are ignored. There is no acknowledgment event. Wait for the menu’s next prompt to confirm the keys took before sending another burst or stop. A stop waits up to 10 seconds for queued keypad commands to be accepted, then hangs up; it does not wait for all tones to finish playing. Inkbox Voice AI can navigate menus and press keys as part of its task brief.

iMessage voice calls

An agent can place and receive voice calls over its iMessage line, in addition to any dedicated phone number it holds. Both shared iMessage service and dedicated iMessage lines support calls. Inbound calls on either line are governed by the identity’s incoming-call configuration. For either iMessage origination, omit from_number. Inkbox resolves the line from the agent identity.
  • Shared line: The agent never chooses or sees the underlying line. Inkbox resolves it from the identity’s active iMessage assignment to the recipient. Because the shared line is never surfaced, local_phone_number is null.
  • Dedicated line: The call uses the dedicated iMessage line attached to the identity. Inkbox returns 422 if that line is not voice-enabled or not verified, and 409 if the identity has no dedicated iMessage line.
See Calls for request fields and error codes.

Reading transcripts

After a call ends, fetch its transcript to log, summarize, or analyze what was said. Each segment has a party field — "local" is your agent; "remote" includes the original participant and any conference guest. Both the original participant and the guest share "remote" in a group call. Use SDK 0.7.19 or later for these examples. The nullable phone_number (phoneNumber in TypeScript) identifies each known speaking line. Shared local numbers and unknown attribution remain null; do not assume every remote turn belongs to the original participant.

Reading across calls

To review an agent’s recent call history — for example, to build a summary or audit log — iterate calls and fetch their transcripts together.

Post-call handover

Rather than polling for finished calls, you can subscribe an agent identity to the call.ended webhook and be handed each call as it wraps up. It’s a fire-and-forget, replayable delivery — you get it even when you never held the live call WebSocket. The payload carries the terminated call (status, duration_seconds, and the resolved contact / agent-identity matches). When the call has transcribed turns it also inlines an abridged transcript so a webhook consumer can act immediately; every payload includes a transcript_url pointing at GET /phone/calls/{id}/transcripts — the authoritative verbatim record, readable with an API key or from the Inkbox Console. For Inkbox Voice AI calls the same event also delivers the outcome and the action items the agent recorded. See Webhooks for the subscription and handler shapes.

Text messages (SMS/MMS)

Agents can send and receive SMS/MMS text messages on their phone numbers, including 1:1 conversations and beta group MMS conversations through the same API surface. Inbound MMS includes media attachments returned as presigned URLs with a 1-hour expiry. Beta: Group MMS and conversation sends are beta. Some carriers may reject group chats or MMS from 10DLC numbers even when the sender is ready and recipients have opted in. Numbers on Inkbox’s default 10DLC campaign are capped at 100 recipient sends per rolling 24-hour window. A 3-recipient group message counts as 3 recipient sends. Register your own 10DLC brand and campaign to lift the cap. A newly provisioned local number takes around 10-15 minutes for its 10DLC campaign to propagate, and sends during that window return 409 sender_sms_pending. Recipients in the US and US territories also have to opt in by texting START to any of your numbers before you can message them; see the Send text endpoint for the full opt-in / opt-out behavior.

SMS opt-ins

Inkbox tracks consent per-recipient under your org and updates the registry automatically when recipients text START / STOP. The opt-in requirement follows US carrier rules. It applies only to recipients in the US and US territories (Puerto Rico, US Virgin Islands, Guam, American Samoa, and Northern Mariana Islands). You can text recipients in other countries, such as Canada, the UK, France, Australia, the Bahamas, or Jamaica, without a prior START. For Canadian recipients, you’re responsible for having consent under Canada’s Anti-Spam Legislation (CASL). A recipient who texts STOP is blocked everywhere, and sends to them return 403 recipient_opted_out. Inkbox treats a number it can’t map to a country as US, so sends to it still return 403 recipient_not_opted_in until the recipient opts in. Reading the consent state is open to any admin caller, so you can audit who has opted in, build an “opted-out” view, or pre-check before sending. Writing consent directly — when you captured it through your own channel (a signup form, an in-product flow, a paper waiver) — is restricted to organizations on their own active, customer-managed 10DLC campaign. Orgs on the Inkbox-default campaign share consent state with everyone else on that campaign, so writes from them return 409 customer_campaign_required. See the SMS opt-ins reference for the full schema and error shapes.

Filtering inbound calls and texts

Control incoming and outgoing SMS/MMS, calls, and iMessage with modes and contact rules on the agent identity. For a simple shared policy, set phone_filter_mode and omit rule direction. New rules apply to both receiving and sending. Each identity has a phone_filter_mode field with two values:
  • blacklist (default). Unmatched numbers are permitted.
  • whitelist. Unmatched numbers are denied.
Phone rules match on exact_number, an E.164 phone number. An applicable explicit allow or block takes precedence in either mode. phone_filter_mode and phone contact rules also govern iMessage. You can configure them before assigning a dedicated phone number. Rule mutations require admin credentials or the Inkbox Console; releasing a number leaves the identity’s permissions intact. The following write examples use an admin API key. See contact communication permissions. Most agents start in blacklist mode: accept everyone, add explicit blocks for individual bad actors. Switch to whitelist when you want the opposite — locked down by default, with a known allowlist.

Separate receiving and sending

Directional options require SDK/CLI 0.7.3 or later. Inbound is from a person to the agent; outbound is from the agent to that person. To accept unmatched incoming communication while sending only to approved numbers:
Applicable exact-number rules still take precedence. Inbound permission does not grant permission to reply. Allowing outbound communication does not replace consent, channel readiness, or other send requirements. These modes also govern iMessage. Shared-line connection setup requires effective permission in both directions and never grants it. Dedicated-line traffic checks each direction separately. A shared phone_filter_mode or imessage_filter_mode write restores both defaults without changing rule coverage. Use the effective directional fields to read split state and atomic rule edits to change one side while preserving the other.

Reviewing blocked calls and texts

Blocked calls are rejected before connecting. Texts without ordinary or valid Companion permission are unavailable to identity-scoped agents and do not fire incoming text webhooks. A later Companion activation can expose retained, eligible group messages that lacked whitelist permission. It cannot override an applicable explicit block. Admin-scoped API keys and users in the Inkbox Console see everything by default. Each row carries is_blocked so a UI can render a “Blocked” badge inline. To page through just the blocked rows — e.g. for an admin “Blocked” folder in your console — pass is_blocked=true to the listing endpoints. Pass is_blocked=false to keep an admin search or conversation summary clean of blocked spam.

Org-level phone numbers

Most call operations go through the identity, but managing the number resource itself — provisioning, configuring how inbound calls are routed, or searching transcripts across all calls on a number — happens through inkbox.phone_numbers. SMS/MMS event delivery is configured separately — see the Webhooks guide for selecting text events on an identity-owned subscription.

Retry a message request

The SDK automatically reuses a generated key during bounded request retries. To retry across separate calls, supply the same idempotency_key in Python or idempotencyKey in TypeScript. The CLI accepts --idempotency-key on text send. A queued response acknowledges acceptance, not delivery or a promise of delivery retries. Use normal message reads or webhooks for delivery updates, and send lookup to recover a lost message ID.