Hand off a conversation

PATCH
/v1/conversations/{id}

Changes who answers a conversation's incoming messages: agent (your VoiceLayer agent replies), api (your code replies) or human (a person replies from the dashboard). Use it to escalate to a person, or to take a conversation over from the agent. Each change emits one conversation.controller_changed event.

Pass expectedController to change it only if nobody else already has: otherwise the request is refused with 409 controller_conflict.

Requires an API key with the conversations:control scope.

Authorization

apiKey
headerAuthorizationBearer <token>

A secret API key from the dashboard (Developers → API keys): vl_live_…, or vl_test_… for test mode. Each operation says which scope the key needs.

Path Parameters

id*string

The conversation id.

Header Parameters

idempotency-key?string

A unique value (a UUID works) that makes a retry safe: sending the same key again returns the first result instead of acting twice. 1–255 printable characters.

Length1 <= length <= 255

Request Body

application/json
  1. body
controller*string

Who answers from now on: agent, api or human.

Value in"agent""api""human"
reason?string

Why, in a sentence. Shown to the person who takes over and recorded in the event.

Length1 <= length <= 500
expectedController?string

Change it only if this is the current controller. Use it to avoid two handoffs racing each other.

Value in"agent""api""human"

Response Body

The conversation after the change

application/json
  1. response
conversation*
changed*boolean
Example Request
curl -X PATCH "https://api.vlayers.ai/v1/conversations/$CONVERSATION_ID" \  -H "Authorization: Bearer $VOICELAYER_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "controller": "human",    "reason": "The customer asked for a refund."  }'
Example Response
{  "conversation": {    "id": "0192f5b0-7c3e-7a51-9b2d-4e8f1a6c3d21",    "channel": "sms",    "lineId": "0192f5a8-1a2b-7c3d-8e4f-5a6b7c8d9e01",    "bindingId": null,    "peer": {      "address": "+15550123"    },    "controller": "human",    "status": "open",    "openedAt": "2026-10-20T15:04:05.000Z",    "lastActivityAt": "2026-10-20T15:04:05.000Z",    "test": true  },  "changed": true}