> ## Documentation Index
> Fetch the complete documentation index at: https://www.voiceflow.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Live agent handoff connection API

> Implement HTTPS endpoints relative to the Base URL configured in Custom Handoff. Your service translates requests into your support platform’s APIs.

## What this API connects

Voiceflow calls your HTTPS service, which translates requests into your support platform’s APIs. These are endpoints **you implement**, relative to the Base URL configured in **Custom Handoff**. They are not Voiceflow REST API endpoints.

## Conversation lifecycle

Create one provider conversation, save its mapping to the ID your service returns, then relay messages until closure. Key the mapping by Voiceflow project and connection conversation ID. Persist the mapping before replying to create. Provider events may arrive immediately: queue them until creation has completed.

The support platform conversation ID and the ID your service returns may differ. Every callback must use the latter. Keep user identity separate from conversation identity.

## Endpoints and authentication

| Method and path | Request | Successful result |
| --- | --- | --- |
| `POST /conversations` | Customer, context, routing and Voiceflow metadata below | JSON with non-empty string `conversationId`; optional `message` |
| `POST /conversations/{id}/messages` | Text or file message | A successful HTTP status |
| `POST /conversations/{id}/end` | `{ "timestamp": "ISO_TIMESTAMP" }` | A successful HTTP status |

Voiceflow sends the configured authentication header verbatim. Use a non-empty secret, such as `Authorization: Bearer YOUR_SERVICE_TOKEN`. Base URL must be HTTPS; redirects are not followed. The runtime rejects unsafe destinations.

### Create fields

| Field | Meaning |
| --- | --- |
| `endUser.externalId` | Customer ID; falls back to Voiceflow user ID when unconfigured |
| `endUser.name`, `email`, `phone` | Customer information; unavailable values may be null |
| `endUser.locale` | Language; runtime fallback is `en` |
| `queueId` | Optional routing identifier; translate it to your provider |
| `context.type` | `full`, `custom`, or `none` |
| `context.summary` | Custom context string or null |
| `context.transcript` | Array of `{role, content, timestamp}`; role is user or assistant |
| `metadata` | Configured JSON metadata |
| `voiceflow` | Project, environment, session, transcript and channel identifiers |

Creation includes `X-Voiceflow-Idempotency-Key`. Repeated attempts with the same key must return the same conversation without creating another. Scope this key to the authenticated connection.

### Message fields

Text: `type: "text"`, `id`, `timestamp`, `text`. File: `type: "file"`, `id`, `timestamp`, `text: null`, and `file` containing `url`, `name`, `contentType`, `size`, `expiresAt`, and `checksumSha256` (currently null). Deduplicate by message ID. Voiceflow sends one file per request. The custom connection upload path permits up to 25 MB; vendor limits can be smaller. Download the outbound signed file before its one-hour expiry. Validate destinations and size before fetching or storing files.

## Example create request

```json
{
  "endUser": {
    "externalId": "customer-123",
    "name": "Alex",
    "email": "alex@example.com",
    "phone": null,
    "locale": "en"
  },
  "queueId": "support",
  "context": {
    "type": "custom",
    "summary": "Customer needs help with order 123.",
    "transcript": []
  },
  "metadata": {},
  "voiceflow": {
    "projectId": "YOUR_PROJECT_ID",
    "environmentId": "YOUR_ENVIRONMENT_ID",
    "sessionId": "test-user",
    "transcriptId": "YOUR_TRANSCRIPT_ID",
    "channel": "webchat"
  }
}
```

Example response:

```json
{
  "conversationId": "connection-conversation-123",
  "message": "Connecting you to support."
}
```

These are illustrative IDs; use actual values from the request and the persisted mapping.

## Related guides

[Build the connection](/docs/developers/handoff/connect) · [Webhook events](/docs/developers/handoff/webhook-events)

## Errors and retry behavior

Return an error object such as `{ "error": { "code": "unavailable", "message": "Provider unavailable", "retryAfterSeconds": 2 } }` with an appropriate HTTP error status. Codes: `invalid_request`, `unauthorized`, `not_found`, `rejected`, `rate_limited`, `internal`, `unavailable`. `retryAfterSeconds`, when supplied, is a positive integer.

The custom service bounds individual requests to 10 seconds and retries eligible transient failures. Do not rely on an exact total delivery count: the handoff handler also retries. Use idempotency for creation and messages, durable event delivery, and a failure path. A timeout can happen after the provider accepted a request; reconcile before creating a duplicate.
