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

# Transfer a live call: blind, warm, and queue handoffs

> Choose the right live-call transfer, run blind or warm handoffs, send callers to a queue or voicemail, and audit the result.

# Transfer a live call: blind, warm, and queue handoffs

Use a live-call transfer when the current agent should hand the caller to a
better destination without ending the conversation. Devotel Orbit supports
three transfer modes from the live call surface:

* **Blind**: send the caller directly to a number, extension, or SIP target.
* **Warm (attended)**: call the destination first, brief the recipient, then
  bridge the caller only after the recipient is ready.
* **Queue**: return the caller to a tenant-owned ACD queue so its dispatcher can
  match the next available agent.

You can start a transfer from the softphone or call the Voice API. The examples
below use an API key with the `voice:write` scope and a call id for an active
call.

## 1. Choose the transfer mode

Choose the least disruptive handoff that still gives the next person enough
context.

| Destination or situation | Mode | What the caller experiences | Destination accepted by the transfer restrictions |
| - | - | - | - |
| A known colleague who can take the call now | Blind | The destination rings; the caller joins when it answers | An E.164 number, an on-net extension, or an allowed SIP target |
| A supervisor, specialist, or external partner who needs context | Warm (attended) | The caller stays on hold while you consult privately, then joins when you complete the handoff | A permitted E.164 number, extension, or SIP target |
| A caller who should be matched by skills or availability | Queue | The caller enters the selected queue and follows that queue's dispatch and overflow rules | A queue in the same tenant |
| A caller who should leave the live conversation and record a message | Voicemail | The call ends in the selected voicemail box terminal | A tenant-owned voicemail box |

The tenant's **Voice → Transfer restrictions** policy is applied before the
call is redirected. It can limit destination kinds and specific extensions or
queues. A destination that is valid in format can still be rejected by policy;
see [Troubleshooting: transfer target restricted](/troubleshooting/voice-transfer-target-restricted).

## 2. Blind transfer

A blind transfer closes the current agent leg and sends the active call to the
target. The target receives no private introduction from the current agent.

### API request

Call `POST /api/v1/voice/calls/{id}/transfer` with `type: "blind"` and an
optional `transfer_reason`:

```bash cURL theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/voice/calls/call_abc123/transfer" \
  -H "X-API-Key: ${ORBIT_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "blind",
    "to": "+14155557890",
    "transfer_reason": "expertise"
  }'
```

`type` is the API field for the blind mode. If omitted, the transfer body uses
the blind shape for backwards-compatible callers. `to` is validated by
`transferTargetSchema` and accepts:

* An E.164 telephone number such as `+14155557890`.
* An on-net extension such as `1001` when the tenant has that extension.
* An allowed `sip:` or `sips:` target such as `sip:alice@example.net`.

The platform still applies the tenant's destination restrictions and any
country or transfer policy for the target kind. Do not send a raw SIP URI
without its `sip:` or `sips:` scheme, a URL, or an arbitrary display string.

### Handle 422 and policy failures

A `422` means the request body or target did not satisfy the transfer contract.
Check these items before retrying:

1. Use `type: "blind"`, a non-empty `to`, and a valid `transfer_reason` when
   you include one.
2. Use E.164 for a telephone number. Do not send a national-format number.
3. For SIP, include the complete `sip:` or `sips:` URI. A raw value such as
   `alice@example.net` is rejected.
4. Confirm that the extension, SIP destination, or queue is permitted by the
   tenant's transfer-restrictions policy. A policy denial may be returned as a
   target-restricted error rather than a validation error.
5. Confirm that the call is still active. A completed or already-transferred
   call cannot be redirected again.

If the target is valid but the destination is not allowed for the agent, change
the tenant-owned transfer policy or choose an allowed destination. Do not work
around the restriction by changing the target's spelling.

## 3. Warm transfer lifecycle

A warm transfer creates a consultation leg while the original caller remains
protected from the conversation with the recipient. The current agent can
explain the caller's need, complete the bridge, or cancel and return to the
caller.

### Start the consultation

Call:

```text theme={null}
POST /api/v1/voice/calls/{id}/warm-transfer
```

The request takes `destination`, `consultFirst`, and optional context fields:

```json theme={null}
{
  "destination": "1001",
  "consultFirst": true,
  "contextWhisper": true,
  "context": "Caller needs help with an enterprise billing issue.",
  "transfer_reason": "escalation"
}
```

`destination` accepts the same E.164, extension, and permitted SIP target
shapes as a blind transfer. Set `consultFirst` to `true` for the normal
attended flow. `contextWhisper: true` enables the context whisper; provide
`context` for a custom message of up to 220 characters. If you omit the custom
text, Orbit can generate the whisper from the available call context.

While the consultation leg is being established, the original caller is held.
The hold treatment uses the tenant's warm-transfer music-on-hold asset when one
is configured (`warm-transfer-moh`); otherwise the configured tenant fallback
is used. The hold asset is tenant-owned and does not change the destination's
transfer policy.

### Complete or cancel

When the recipient answers and is ready, bridge the caller with:

```text theme={null}
POST /api/v1/voice/calls/{id}/warm-transfer/complete
Content-Type: application/json

{
  "originalCallControlId": "cc_original_abc",
  "consultationCallControlId": "cc_consult_xyz"
}
```

The original agent leaves and the caller and recipient remain connected. The
consult leg is the leg returned when the warm transfer starts; store both call
control ids in the softphone state rather than guessing them from the call id.

If the recipient cannot help, cancel instead:

```text theme={null}
POST /api/v1/voice/calls/{id}/warm-transfer/cancel
Content-Type: application/json

{
  "originalCallControlId": "cc_original_abc",
  "consultationCallControlId": "cc_consult_xyz"
}
```

Cancellation hangs up the consultation leg and resumes the original caller
with the current agent. Treat complete and cancel as mutually exclusive terminal
actions for one consultation.

### Softphone click-through

1. Open the active call and select **Transfer**.
2. Choose **Warm / attended** rather than **Blind**.
3. Select an extension or enter an allowed E.164 or SIP destination.
4. Turn on **Context whisper** if the recipient should hear an introduction.
   Edit the message if the automatically generated context is not sufficient.
5. Click **Start consultation**. The caller is held while the destination
   rings.
6. Speak privately with the recipient. Click **Complete transfer** when they
   accept the call.
7. Click **Cancel transfer** if they decline or do not answer. The caller
   returns to the original agent.

The same three stages are available to a custom softphone through the three API
endpoints. A UI should disable Complete and Cancel until a consultation leg is
available, and should surface a failed consultation without ending the caller's
original leg.

## 4. Transfer to a queue

Use a queue transfer when the next agent should be selected by skills,
availability, priority, and the queue's overflow policy rather than by one
specific target. The queue must belong to the same tenant as the live call.

Call the common transfer endpoint with the queue shape:

```bash cURL theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/voice/calls/call_abc123/transfer" \
  -H "X-API-Key: ${ORBIT_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "queue",
    "queue_id": "queue_support",
    "priority": 10,
    "required_skills": ["billing"],
    "transfer_reason": "wrong-queue"
  }'
```

`transferCallToQueue` validates the queue's tenant ownership, re-enters the
call into that queue's dispatcher, and applies the optional priority and skill
requirements. Queue SLA counters then measure the caller's wait against the
target queue's service-level settings. The queue's normal maximum wait and
overflow action still apply, so configure voicemail, another queue, or hangup
before using queue transfer in production.

A queue transfer is not a park operation. It does not leave the caller in a
numbered park slot and the caller never hears park-lobby hold music in the
middle of the handoff. If the queue later puts the caller on hold, the queue's
own tenant-configured announcements and hold treatment apply.

### Worked example: IVR overflow

An IVR first sends billing callers to `queue_billing`. When that queue reaches
its configured overflow threshold, the flow can transfer the active call to
`queue_general`:

```json theme={null}
{
  "type": "queue",
  "queue_id": "queue_general",
  "priority": 20,
  "required_skills": ["english"],
  "transfer_reason": "wrong-queue"
}
```

The call is then dispatched by `queue_general`. Keep the queue's SLA and
overflow settings aligned with the IVR's promise to the caller; transferring
to a queue does not reset the need to monitor wait time and abandonment.

## 5. Transfer to voicemail

Use voicemail when a live conversation is no longer needed and the caller
should leave a message for a tenant-owned mailbox. In the dashboard, choose
**Transfer → Voicemail**, select the mailbox, and confirm the handoff. The
voicemail destination is terminal for that live call: the caller records a
message and the agent's leg is released.

Set the mailbox greeting, notification recipients, retention, and transcription
controls in the tenant's Voice voicemail settings. If the caller needs an
agent, use a queue or warm transfer instead; voicemail does not create a
consultation leg or preserve a live bridge.

## 6. Record the transfer reason

`transfer_reason` is optional on blind, warm, and queue transfers. When present,
it must be one of these values:

| Value | Use when |
| - | - |
| `wrong-queue` | The caller reached the wrong ACD queue. |
| `escalation` | The current agent needs a supervisor or higher support tier. |
| `language-mismatch` | The current agent cannot support the caller's language. |
| `expertise` | The caller needs a specialist, such as billing or fraud support. |
| `other` | The transfer does not fit the categories above. |

Orbit stores the latest value at `call_logs.metadata.transfer_reason` and
appends each transfer event to `call_logs.metadata.transfer_history[]`. The
history is append-only, so a call that moves from an IVR overflow to a
specialist retains both events. Read the call detail or your tenant's call-log
export after the call ends to reconcile the history.

A simple **Transfers by Reason** report groups completed transfer events by the
stored reason rather than inferring intent from the destination:

```sql theme={null}
SELECT
  metadata->>'transfer_reason' AS transfer_reason,
  COUNT(*) AS transfers
FROM call_logs
WHERE started_at >= :from
  AND started_at < :to
  AND metadata ? 'transfer_reason'
GROUP BY metadata->>'transfer_reason'
ORDER BY transfers DESC;
```

Run analytics against your tenant's permitted call-log surface. If an
installation exposes transfer history as an array for reporting, unnest that
array and count one row per history event so repeated handoffs are not lost.

## 7. Webhooks and retries

Subscribe your tenant's event destination to observe transfer outcomes. A
successful attended handoff emits `warm-transfer-completed` after the bridge
has completed. The event includes the call id, transfer type, original and
consultation call-control ids, transfer reason when supplied, and completion
timestamp. A consumer can use the call id plus event id as its idempotency key
and then fetch the call record for the authoritative `transfer_history[]`.

A representative payload is:

```json theme={null}
{
  "type": "warm-transfer-completed",
  "id": "evt_transfer_01J...",
  "call_id": "call_abc123",
  "transfer_type": "warm",
  "originalCallControlId": "cc_original_abc",
  "consultationCallControlId": "cc_consult_xyz",
  "transfer_reason": "escalation",
  "completed_at": "2026-10-10T14:35:22.000Z"
}
```

Treat the event as a notification, not as permission to repeat the transfer.
Deduplicate by event id, and use the call record when you need the complete
history.

Blind transfers retry a transient gateway failure according to the gateway's
retry policy. A retry is intended to recover a failed handoff, not to create a
second customer conversation. Your webhook consumer should therefore be
idempotent, and your UI should show the transfer as pending or failed until the
final result arrives. Do not issue a second blind-transfer request just because
the first HTTP response timed out; fetch the call state or transfer event first.

## 8. TCPA and FCC consent on transferred calls

A transfer does not erase consent or create a new permission to contact the
caller. Keep the following controls tenant-owned:

* Preserve the consent record and its purpose when a call moves between agents,
  queues, or a voicemail box.
* Keep automated outreach, recording announcements, quiet hours, and
  do-not-call handling enabled for the tenant's configured policy.
* For a warm transfer, tell the recipient what the caller consented to and
  avoid adding an automated or recorded message that the original consent does
  not cover.
* Do not infer consent from a successful transfer, an answered consult leg, or
  a caller's presence in a queue.

Apply your organization's legal policy and required notices to every call leg.
Orbit provides tenant controls and transfer state; it does not determine your
legal basis for a particular campaign or conversation.

## Troubleshooting checklist

* **422 on `to`**: use E.164, a complete `sip:`/`sips:` URI, or an existing
  extension. Remove URL syntax and national-format numbers.
* **Target restricted**: review the tenant's transfer-restrictions policy and
  choose a permitted destination.
* **Warm transfer has no consult leg**: wait for the start response before
  enabling Complete or Cancel; retain the returned call-control ids.
* **Caller returns to the agent unexpectedly**: inspect the consultation result
  and cancel/timeout state before retrying.
* **Queue transfer is rejected**: verify the queue id belongs to the same
  tenant, then check queue membership, skills, SLA, and overflow settings.
* **Analytics count is low**: read `metadata.transfer_history[]` as events and
  do not count only the latest `metadata.transfer_reason` value.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.