Prerequisites
- A live, non-terminal call that is currently answered by a human agent (one that was escalated from the AI earlier, or answered by a person directly).
- The call’s
conference_id(the escalation creates the conference the human and caller now share). - The AI agent’s id — optional: if omitted, the handback re-invites the
same AI agent that originally escalated, read from the call’s handoff
record. Supply
ai_agent_idonly when a call was human-answered from the start, or when you want a different agent to resume.
Hand the call back
Send the human agent’s own conference leg ashuman_participant_call_sid
so it disconnects once the AI rejoins:
Request fields
POST /api/v1/voice/calls/{call_id}/handback accepts:
The response is
202 Accepted:
Node SDK
The endpoint is one POST on any HTTP client. With the Node SDK(the rawrequest helper works for any route, including ones not yet wrapped as named methods):
What the AI agent resumes with
The AI agent does not start over. It rejoins the call carrying:- everything it captured before escalating (collected details like an order number or verified identity), and
- the full merged conversation — the bot leg plus the human leg — so nothing the caller told the human has to be repeated.
handback_count in the persisted record
tracks how many times the call has returned.
The human never leaves the caller alone
The ordering is deliberate: the AI agent is invited back into the conference first, and the human’s leg is only disconnected after the AI confirms it answered. If the AI does not answer, the human stays on the line and the response reportsbot_answered: false, human_dropped: false — the caller is never left without anyone on the call.
Omit human_participant_call_sid for a monitor-only re-invite: the AI
rejoins but no leg is disconnected, so a human supervisor can keep
listening.
Every handback is recorded
Each handback appends avoice.handback.initiated entry to your audit log
carrying the reason, the initiating user, the conference and agent ids, the
answer and drop outcomes, and the round-trip counter — the same way the
original AI-to-human escalation is recorded. There is no dedicated
handback webhook event; subscribe to Audit log events
if you want the action pushed to a sink.
Error matrix
404 responses with
PARTICIPANT_NOT_IN_CONFERENCE leave no side effects on
the call: no re-invite, no persisted record, no audit entry.
Edge cases
- Double handback counts up. A call can bounce between AI and human
any number of times. Every successful handback appends one round-trip to
handback_count, starting at 1. - Racing a hangup. If the caller hangs up after the request checks pass
but before the handback completes, the response is still
202— the call was live at lookup time. A repeat request once the call has ended fails 409 (CALL_TERMINAL) with the final call state indetails.status. - Monitor-only re-invite. With
human_participant_call_sidomitted, the AI rejoins but nothing is dropped — a supervisor can keep listening. The response reportshuman_dropped: false. - AI fails to answer. When the re-invited agent does not confirm
within the answer window, the human leg is retained and the response
carries
bot_answered: false,human_dropped: false. Retry the handback — the round-trip counter and audit are written even for a failed answer. - Empty
reasonis rejected. A blankreasonfails the same 422 path as a malformedconference_id.
Cross-references
- Escalate the other way (AI to human) via handoff targets: Handoff Targets
- Voice channel reference: Channels → Voice
- Voice API reference: API → Voice & Numbers