Take the conversation over (stops the AI agent)
const url = 'https://app.whatsetter.com/api/v1/leads/example/handoff';const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://app.whatsetter.com/api/v1/leads/example/handoff \ --header 'Authorization: Bearer <token>'Hands the conversation to a human: the AI agent stops replying to this
lead immediately, and stays silent until you call /resume.
This is the exact same mechanism as the dashboard’s “prendre la main” toggle — same workflow, same flags — so the two never disagree. The conversation appears as Manual Control in the dashboard and the agent is gated before it can compose a reply.
The lead’s business status is preserved: handing over does not mark the lead as stopped, qualified, or anything else. Only who is driving changes.
Idempotent: calling it on a lead already handed over is a no-op that
answers 200. Requires scope leads:write.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The WhatSetter lead id — the id from GET /leads, and the contact.id you receive on webhooks.
Responses
Section titled “Responses”The agent is now stopped on this conversation
object
Who is driving a conversation after a handoff/resume call.
object
The lead id.
Your own id, echoed so you can log the action against your record.
false after /handoff, true after /resume.
true when a human holds the conversation.
The lead’s business status — unchanged by these calls.
Whether the leads-list mirror was updated too. false means the agent is correctly stopped but the dashboard list may lag; the conversation view is always right.
Examplegenerated
{ "data": { "id": "example", "external_reference": "example", "agent_active": true, "manual_override": true, "status": "example", "dashboard_synced": true, "updated_at": "2026-04-15T12:00:00Z" }}Missing, unknown or revoked API key
object
object
Examplegenerated
{ "error": { "code": "example", "message": "example" }}Resource not found in this workspace
object
object
Examplegenerated
{ "error": { "code": "example", "message": "example" }}invalid_state: the lead has no conversation to hand over — it has not been contacted yet (queued or pending), or the workflow found no conversation row for it.
object
object
Example
{ "error": { "code": "invalid_state", "message": "Handoff applies to leads the agent has already engaged. This one is \"queued\" — it has not been contacted yet." }}Agent control is not configured on this deployment (internal_error)
object
object
Examplegenerated
{ "error": { "code": "example", "message": "example" }}upstream_error: the agent-control workflow was unreachable or refused the change. Safe to retry.
object
object
Example
{ "error": { "code": "upstream_error", "message": "The agent-control workflow is unreachable. Try again in a moment." }}
