# Custom API transfer (/docs/integrations/custom-api-transfer)

> Transfer live calls to a phone number your API chooses, using one reserved response key.

Custom API transfer lets your agent hand a live call to a phone number your
API picks at that moment: the right branch, the next available person on a
rotation, or a number looked up from your records.

Your API asks for the transfer by including one reserved key in its JSON
response:

```json
{
  "__omni_transfer_number": "+911140154466",
  "__omni_transfer_message": "One moment, connecting you now."
}
```

When a custom API response contains `__omni_transfer_number` and the agent
has **Custom API transfer** enabled, the platform completes the transfer
itself, immediately and reliably. The agent doesn't decide anything, and no
other configuration is needed.

## The reserved keys [#the-reserved-keys]

| Key                       | Required | Meaning                                                                                                   |
| ------------------------- | -------- | --------------------------------------------------------------------------------------------------------- |
| `__omni_transfer_number`  | Yes      | The destination. Any common format works: `+911140154466`, `(415) 555-2671`, or digits with country code. |
| `__omni_transfer_message` | No       | Spoken to the caller while the call is handed over. Defaults to "Transferring".                           |

The keys can appear at the top level or nested (up to 8 levels deep). A
response without `__omni_transfer_number` is never transferred, no matter
how many phone numbers it contains, so your ordinary lookup APIs are
unaffected. Only successful responses count: an error response is never
scanned for the key.

## Set it up [#set-it-up]

  
    ### Enable transfers on the agent [#enable-transfers-on-the-agent]

    In your agent's call transfer settings, turn on **Custom API transfer**.
  

  
    ### Return the reserved key from your API [#return-the-reserved-key-from-your-api]

    Add `__omni_transfer_number` to the response of whichever API should hand
    the call over, only in the cases where a transfer should happen. Your API
    stays in control: return the key when the caller should be connected, leave
    it out when they shouldn't.
  

  
    ### Test it [#test-it]

    Use the **Test** tab on your custom API integration. When a successful
    response contains the reserved key, the test result confirms the transfer
    request and shows the number found. The number itself is validated at call
    time.
  

## A worked example [#a-worked-example]

An entertainment company routes callers to the right branch:

1. Caller: "Can I talk to someone at the Connaught Place branch?"
2. The agent calls the `get_branch_number` integration with
   `branch_name = "Connaught Place"` (a normal custom API with one
   agent-filled input).
3. The API responds:

```json
{
  "branch": "Connaught Place",
  "__omni_transfer_number": "+911140154466",
  "__omni_transfer_message": "Connecting you to the Connaught Place team."
}
```

4. The caller hears the announcement and the call is handed to
   `+91 11 4015 4466`.

## What the caller experiences [#what-the-caller-experiences]

The agent speaks its usual reply while your API is called, then the
announcement plays and the call is handed over. Once the transfer starts,
it completes even if the caller talks over the announcement. A call is
transferred at most once.

## When the transfer can't happen [#when-the-transfer-cant-happen]

If `__omni_transfer_number` is present but doesn't hold a valid phone
number, or resolves to the caller's own number, the call is not
transferred: the agent tells the caller the transfer couldn't be completed
and keeps helping. It never claims a transfer happened when it didn't.

If your API is unreachable or errors, no reserved key arrives, so nothing
transfers and the agent continues the conversation.

## Tips [#tips]

* Keep your API fast. The lookup happens during the live call, and the
  request times out after the timeout you configure (10 seconds by
  default).
* Return the key only when a transfer should actually happen. "Business
  hours check" style APIs simply omit it outside hours.
* Prefer international format (`+` and country code) for the number; other
  common formats are resolved using the call's own country.