VOICE

Voice calls

Place outbound calls and answer inbound ones, then drive what happens on the call with a small set of instructions — speak text, play audio, collect keypad input, record, or transfer.

The call object

FieldDescription
idUnique identifier, prefixed call_.
statusqueued, ringing, in_progress, completed, busy, no_answer, failed.
to / fromCalled party and caller ID, both E.164.
directionoutbound or inbound.
answered_byWhen machine detection is on: human or machine.
durationBillable call length in seconds, set on completion.
recording_urlPresent when recording was enabled and has finished.

Place a call

POST/v1/calls
ParameterDescription
to stringREQUIREDNumber to call, E.164.
from stringREQUIREDCaller ID — one of your provisioned numbers.
flow arrayCONDITIONALInline list of call instructions (see below). Provide this or answer_url.
answer_url stringCONDITIONALURL AtomMatrix requests when the call connects; it should return a flow array. Use this for dynamic calls.
machine_detection boolOPTIONALDetect voicemail vs. a person; result in answered_by.
record boolOPTIONALRecord the call. Requires appropriate consent in your jurisdiction.
status_callback stringOPTIONALURL for call lifecycle events.
curl https://api.atommatrix.ai/v1/calls \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+14155550123",
    "from": "+14155550999",
    "machine_detection": true,
    "flow": [
      { "action": "say", "text": "Hi, this is a reminder that your appointment is tomorrow at 9 AM.", "voice": "en-US" },
      { "action": "gather", "num_digits": 1, "prompt": "Press 1 to confirm, or 2 to reschedule." }
    ]
  }'

Call flow instructions

A flow is an ordered array of actions the call runs top to bottom. Return one from your answer_url to build dynamic IVR, or pass it inline for simple calls.

ActionDescription
saySpeak text with text-to-speech. Fields: text, voice (language/voice, 90+ languages).
playPlay an audio file. Field: url.
gatherCollect DTMF keypad input. Fields: num_digits, prompt, timeout. The digits arrive at your answer_url as digits.
recordRecord the caller. Fields: max_length, play_beep.
transferConnect the call to another number. Field: to.
connect_agentHand the live call to an AI voice agent. Field: agent_id. The agent handles the conversation from that point.
hangupEnd the call.

Answer with an AI voice agent

Instead of scripting every branch of an IVR, hand the call to an AI agent. It listens, transcribes speech in real time, understands intent, calls your tools to look things up or make changes, and answers in natural synthesized speech — in 90+ languages. The same agent you run on chat or SMS can take the phone call, so behavior and guardrails stay consistent across channels.

Put an agent on the call

Add a connect_agent action to a flow (or return one from your answer_url). Everything after it — turn-taking, barge-in, tool calls mid-call, and knowledge retrieval — is handled by the agent.

curl https://api.atommatrix.ai/v1/calls \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+14155550123",
    "from": "+14155550999",
    "flow": [
      { "action": "say", "text": "Connecting you to our assistant.", "voice": "en-US" },
      { "action": "connect_agent", "agent_id": "agt_support_en" }
    ]
  }'

During the call the agent can invoke tools just as it does in text — checking an order, booking a slot — and speak the result back. When a case needs a person, the agent uses transfer to route the live call to the right queue and passes along a summary. Every turn is written to the conversation transcript, and if recording is enabled the recording_url is attached on completion.

Inbound works the same way. Point an inbound number's answer_url at a flow that returns connect_agent, or attach an agent to the number in the console, and inbound callers reach the voice agent directly.

Retrieve & list calls

GET/v1/calls/{id}
GET/v1/calls

Retrieve a single call for its final status, duration, answered_by, and recording_url; or list calls with the same cursor pagination and time filters as messages.

Call events

Calls emit lifecycle events to your status_callback or account webhook: call.initiated, call.ringing, call.answered, call.completed, and call.recording.ready. Each carries the current call object.

{
  "type": "call.completed",
  "created_at": "2026-07-07T12:07:41Z",
  "data": {
    "id": "call_01HN9P...",
    "status": "completed",
    "answered_by": "human",
    "duration": 34
  }
}