voice is covered in Voice engines and
Compose a voice engine. This page is about the rest.
Where each value comes from
Most fields are yours to write. These are the ones that reference something else, and the endpoint that lists the valid values:
An id belonging to another account is reported as a
404, not a 403: whether
a resource exists on someone else’s account is not information this API gives
out.
Testing an agent
phrase overrides
what it says; the default is the agent’s own opening_message, which is what a
real caller would hear first.
For an actual conversation, place an ordinary call with POST /v1/calls. Human
transfer is deliberately switched off during a test call, so a test cannot tell
you whether a transfer destination answers.
Human transfer
When a caller asks for a person, the agent can hand the live call to one.The model is only ever told the
id and the name. Numbers are resolved
server-side at dial time, so an agent that invents a destination cannot dial an
arbitrary number — the worst it can do is name one that does not exist. That is
why destinations are a list you authorise rather than a number the model
produces.- Destination ids must be unique.
default_destination_idmust name an enabled destination.enabled: trueneeds at least one enabled destination.
max_transfers_per_call stops a loop where the agent keeps re-dialling someone
who is not there. With return_to_agent_on_failure, a destination that does not
pick up hands the caller back to the agent rather than dropping the line.
What happened on a transfer
GET /v1/calls/{id} carries a transfers array, one entry per attempt:
ring_duration_ms is usually the fastest way to tell two very different
failures apart: a long ring ending in no_answer is a person who was not at
their desk, while a failure in the first second is nearly always configuration —
a number your carrier will not dial, or one it does not believe you own.
sip_cause is the raw Q.850 code from the carrier for the cases where that
distinction is not obvious.
Changing an agent
PATCH changes only the fields you send. Two of them are replaced whole rather
than merged, because merging them would be ambiguous:
voice— send the complete configuration.human_transfer— send the complete configuration, including every destination you want to keep. This is whydestinationshas no default: a body of{"human_transfer": {"enabled": false}}is rejected rather than quietly emptying your destination list.

