Tonedocs

Outbound calls

Placing a call, and reading what happened.

curl "$TONE_API/v1/calls" -X POST \
  -H "Authorization: Bearer $TONE_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H 'content-type: application/json' \
  -d "{\"agentId\":\"$AGENT\",\"numberId\":\"$NUMBER\",\"toE164\":\"+919876543210\"}"

agentId is required on a number that routes to a Tone agent and forbidden on a BYO number — the number decides which, and either mistake is a 422.

What happens before the carrier is called

The compliance gate runs inside the same transaction as the call record. So a refusal is a 403 with the audit rows already written and no carrier contacted — the block and its evidence are the same event.

One thing runs before the gate: your concurrency quota. Over it, you get 429 concurrent_call_limit_reached with no verdict recorded, because no dial was attempted. That is a different failure from a rate limit and needs a different response — see Limits.

Lifecycle

status
queuedAccepted; the carrier has not connected it yet
in_progressConnected
endedFinished. disposition now says how
disposition
answeredA person picked up
no_answerRang out
busyEngaged
voicemailAn answering machine took it
failedThe carrier could not complete it
unknownWe genuinely do not know

Treat both as open sets — new values can appear and are not a breaking change.

Two honesty rules worth knowing: a call abandoned in queued reads as ended after 15 minutes, and one stuck in_progress past 65 minutes reads as ended with unknown and bills nothing. We would rather report "we do not know" than invent an outcome or charge for one.

When the carrier's lines are all busy

Every carrier account carries a fixed number of calls at once, shared by everyone dialling through it. When they are all in use, your dial is still accepted: you get 201 with status: queued, and Tone places the call the moment a line frees, in the order calls arrived. A call that waits longer than 10 minutes is not placed. It ends with disposition: failed and endReason: carrier_capacity, and you get the usual call.completed and call.failed events.

A promotional call whose calling window closes while it waits ends with endReason: calling_window_closed instead of being placed late.

Reading it back

Poll if you must, but the call log is not where you should learn a call ended:

curl "$TONE_API/v1/calls/$CALL" -H "Authorization: Bearer $TONE_KEY"

Subscribe to call.completed instead. See Webhooks.

To find every call one campaign placed — retries included — filter the call log rather than reading the recipient list, which names only each recipient's last attempt:

curl -H "Authorization: Bearer $TONE_KEY" \
  "$TONE_API/v1/calls?campaign_id=$CAMPAIGN&limit=100"

Test mode

The magic numbers produce fixed outcomes, so CI can assert on them, and nothing rings. See Test mode.

Was this page helpful?

On this page