Contactivity
Voice.md

Calls

Place outbound calls, list and fetch calls, and control live calls with actions. Paths are relative to https://api.contactivity.io/v1/projects/{project_id}; auth, errors, paging and idempotency are in the overview.

Method Path Scope Purpose
POST /calls calls:write Place a call
GET /calls calls:read List calls (paged)
GET /calls/{call_id} calls:read Fetch a call
DELETE /calls/{call_id} calls:write Archive a finished call's record
POST /calls/{call_id}/actions/{action} calls:write Control a live call

Recording starts and stops through actions (record_start, ...); the files are under recordings.

The call object

Field Type Description
id string CA…
parent_call_id string or null The call that dialed this one (<Dial>, transfer)
app_id string or null The voice app handling the call
app_kind string or null Kind of that app: coxml, call_control, ai_agent, flow
ai_agent boolean An AI agent ran on the call (an ai_agent app, or <Connect><Agent> from another app)
mode string coxml (driven by CoXML documents) or call_control (driven by actions)
direction string inbound or outbound
from, to string E.164; a carrier's 1NXXNXXXXXX (no +) is shown as +1NXXNXXXXXX
status string queued, ringing, in_progress, completed, busy, failed, no_answer, canceled
answered_by string or null Machine detection result: human, machine_start, machine_end_beep, fax, unknown
created_at, started_at, answered_at, ended_at timestamp or null
duration_secs integer or null
price money or null Set once the call is rated
quality object or null Media quality measured at hangup
client_state string or null Echoes client_state in the create response; null on other reads

Place a call

POST /calls returns 201 and the call (status queued). Give exactly one source of call logic:

Source Behaviour
app_id A voice app of the project: a coxml app with a voice URL (its URL, method, fallback and status callback apply), a call_control app (you drive the call with actions; events go to the app's webhook_url, or the webhook_url given here), or an ai_agent app (the agent talks)
coxml An inline CoXML document, at most 4000 characters
coxml_url CoXML fetched when the call is answered (coxml_method GET or POST, default POST)
webhook_url (alone) A call-control call without an app; events go to this URL
Field Type Rules
to string Required. E.164, client:<name>, or a SIP URI with a public host
from string Required. E.164; a number of the project or a verified number
app_id, coxml, coxml_url, coxml_method, webhook_url See above. webhook_url with app_id only for call_control apps
status_callback_url string Public https:// URL for status callbacks
status_callback_events string[] initiated, ringing, answered, completed (default ["completed"])
timeout_secs integer Ring time, 5-600, default 60
time_limit_secs integer 1-14400, default 14400
machine_detection string disabled (default), detect, detect_words, detect_beep, greeting_end, premium
machine_detection_config object total_analysis_time_millis, after_greeting_silence_millis, greeting_duration_millis, initial_silence_millis (each 100-60000)
record false, "single" or "dual" Record the call, mono or one channel per party
client_state string Base64, at most 4096 characters; echoed on events
sh
curl https://api.contactivity.io/v1/projects/$PROJECT_ID/calls \
  -H "Authorization: Bearer $CONTACTIVITY_API_KEY" \
  -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
  -d '{"to": "+14155550100", "from": "+12125550123",
       "coxml": "<Response><Say>Your order has shipped.</Say></Response>",
       "status_callback_url": "https://example.com/status", "status_callback_events": ["answered", "completed"]}'

Errors: 400 invalid_parameter (param to, from, app_id, coxml, coxml_url, coxml_method, webhook_url, status_callback_url, status_callback_events, timeout_secs, time_limit_secs, machine_detection, record, client_state), 400 unknown_parameter, 402 insufficient_balance, 403 caller_id_not_verified (param from), 403 destination_blocked (param to), 403 account_inactive, 409 app_disabled (param app_id: the voice app is disabled), 429 rate_limit (calls per second or simultaneous calls), 503 engine_unavailable.

List and fetch

GET /calls filters: status, direction (inbound/outbound), from, to (+1NXXNXXXXXX also matches a stored 1NXXNXXXXXX), parent_call_id, app_id (exact matches), app_kind (coxml, call_control, ai_agent, flow; ai_agent also matches agents started from another app), created_after (inclusive) and created_before (exclusive) as RFC 3339, plus limit and starting_after.

sh
curl "https://api.contactivity.io/v1/projects/$PROJECT_ID/calls?status=completed&limit=20" \
  -H "Authorization: Bearer $CONTACTIVITY_API_KEY"

GET /calls/{call_id}: 404 not_found when the call is not in the project.

GET /calls/{call_id}/detail (scope calls:read) returns everything stored about the call in one response:

Field Description
call The call object plus hangup_cause (from the carrier CDR, or null)
legs Child calls (<Dial>, transfers), each a call object with its quality
carrier_legs Rated carrier CDRs: sip_call_id, started_at, answered_at, duration_secs, price, hangup_cause
routing number (dialed number inbound, caller ID outbound), route (id, type, target, target_name: trunk, PBX app or voice app name), route_at_call_time (false: the current route; routes are not stored per call), app (id, name, kind, param_style)
ai_agent The agent session as GET /ai/calls/{call_id} plus agent_name, voice, session_sid and parts (charge per part); null when no agent ran
requests Document fetches and webhooks of the call (as the call inspector); CoXML fetches carry verbs, the verbs of the returned document (Gather>Say for nested ones)
commands API requests that changed the call (call actions, updates) from the access audit log: created_at, method, path, status, actor_type, command
events Native events of the call (kept 7 days), oldest first
errors Call errors (category, code, message, url)
recordings, transcriptions Of the call; archived ones are left out
pricing call, ai, ai_billed_secs, features (amd, noise_suppression with amount), transcriptions, total (money)

An API key gets ai_agent only with apps:read, and recordings/transcriptions only with recordings:read. Every read is written to the access audit log as sensitive (it can carry transcripts).

DELETE /calls/{call_id} archives a finished call's record: it leaves GET /calls (list archived calls with ?archived=true) and is still returned by id with archived_at set. Its webhook deliveries, errors, events, recordings and transcriptions are kept. 204; 404 not_found; 409 archived (already archived); 422 call_state while the call is live.

Actions

POST /calls/{call_id}/actions/{action} returns 200 and the call. redirect and hangup work on every call. The other actions need a call-control call (placed with a call_control app or a webhook_url); on a CoXML call they return 409 call_state (use redirect to move a CoXML call to new CoXML).

Every action takes client_state (base64, at most 4096 characters). Other fields per action; anything else is 400 unknown_parameter:

Action Fields
answer none
hangup none
reject cause
redirect exactly one of coxml_url (+ coxml_method) or coxml (at most 4000 characters)
bridge call_id (the other call), park_after_unbridge
transfer to, from, timeout_secs, machine_detection, machine_detection_config
refer sip_address
speak payload, payload_type, voice, language
play / stop_play audio_url, loop, overlay / stop
gather minimum_digits, maximum_digits, timeout_millis, terminating_digit, valid_digits, inter_digit_timeout_millis
gather_using_speak payload, payload_type, voice, language, input, hints + the gather fields
gather_using_audio audio_url + the gather fields
gather_using_ai parameters, greeting, voice, language, message_history, assistant, send_partial_results, timeout_secs
stop_gather none
record_start format, channels, play_beep, max_length, transcription, transcription_engine, transcription_language
record_stop, record_pause, record_resume none
send_dtmf digits, duration_millis
enqueue / leave_queue queue_name, max_wait_time_secs, max_size / none
stream_start / stream_stop stream_url (ws/wss), stream_track, stream_bidirectional_mode / none
transcription_start / transcription_stop language, transcription_engine, transcription_tracks, interim_results / none
ai_agent_start voice_app_id (an AI agent app), parameters
noise_suppression_start / noise_suppression_stop direction / none
update_client_state client_state (required)
sh
curl https://api.contactivity.io/v1/projects/$PROJECT_ID/calls/$CALL_ID/actions/gather_using_speak \
  -H "Authorization: Bearer $CONTACTIVITY_API_KEY" \
  -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
  -d '{"payload": "Press 1 for sales, 2 for support.", "maximum_digits": 1}'

curl https://api.contactivity.io/v1/projects/$PROJECT_ID/calls/$CALL_ID/actions/redirect \
  -H "Authorization: Bearer $CONTACTIVITY_API_KEY" \
  -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
  -d '{"coxml_url": "https://example.com/after-hours.xml", "coxml_method": "GET"}'

The Idempotency-Key replaces Call Control's command_id: a retried action with the same key runs once.

Errors: 404 unknown_action (param action), 404 not_found, 400 unknown_parameter, 400 invalid_parameter (param client_state, coxml_url, coxml, coxml_method, or a value the voice engine refused), 409 call_state (the action needs a call-control call), 422 call_state (the call has ended or is not in a state that allows the action), 502 api_error, 503 engine_unavailable.

Events of call-control calls go to the app's webhook_url; see events.md.