Guides
Transfers
The three transfer modes — cold, warm, and warm-return — what each one sounds like to the caller and the person picking up, and when to choose which.
When a caller needs a person, the assistant hands the call over. How it hands over is the difference between someone answering blind and someone answering prepared — and between a missed hand-off ringing out and the caller coming back to a voice that explains what happened.
There are three modes. This page covers all three. For routing to a named person or department resolved at call time, see Dynamic transfer.
The three modes at a glance#
| Mode | The person picking up hears | If nobody answers | Use it for |
|---|---|---|---|
| Cold | The caller, immediately | The call has already left OnCore — your phone system handles it | Always-staffed lines, IVRs, overflow numbers |
| Warm | A spoken briefing, then the caller | The call has left OnCore — your phone system handles it | Named people, anything where context matters |
| Warm-return | A spoken briefing, then the caller | The caller returns to the assistant, which explains and continues | Lines that are not always staffed |
The choice is really two questions. Does the person picking up need context? — that is cold versus warm. What should happen if nobody picks up? — that is warm versus warm-return.
Cold transfer#
The blind hand-off, and the default. OnCore connects the caller to the destination and steps out of the call entirely.
caller ──► assistant ──► destination
└── OnCore leaves the callThe person answering gets a ringing phone and a stranger on the line. They have no idea who is calling or why, so the caller repeats everything they already told the assistant.
That is a real cost, but cold is the right choice more often than it sounds:
- The destination is a system, not a person — an IVR, a queue, a voicemail box. A briefing spoken to a menu is wasted.
- The line is always staffed — a call centre with agents waiting does not need warm-return, and the extra seconds before connection are a worse trade than the missing context.
- You want the shortest possible path — cold is the fastest hand-off available.
Once a cold transfer connects, the call is out of OnCore's hands. If it rings out, hits voicemail, or drops, that is your telephony system's behavior, not something OnCore can recover from.
Warm transfer#
Before the two are connected, OnCore speaks a short briefing — a whisper — to the person picking up: who is calling and what they need, drawn from the conversation so far.
caller ──► assistant ──► destination rings
(holding) └── whisper: "Call from Maria Santos about
a billing question on invoice 4471."
└── caller joinsThe caller does not hear the whisper. The person picking up answers already knowing the situation, and the caller does not have to start over.
Two things worth knowing:
- The whisper is spoken in the language of the call. A Spanish-speaking caller produces a Spanish briefing.
- You can delay it.
warmWhisperDelaySeconds(0–30, default0) pauses before the whisper plays, which helps when the destination has a greeting or an answering system that talks first and would otherwise talk over it.
Like cold, once the caller is connected the call has left OnCore. Warm improves the hand-off; it does not give you a safety net.
Warm-return#
Everything warm does, plus the safety net: if the hand-off does not succeed, the caller comes back to the assistant instead of ringing out into nothing.
caller ──► assistant ──► destination rings
(holding)
├── answered ──► caller connected, OnCore leaves
└── no answer ──► caller returns to the assistant
"I could not reach anyone just now…"
└── conversation continuesThe caller hears wording you control, and the conversation resumes — so the assistant can take a message, offer a callback, or try a different destination, rather than leaving the caller listening to a dead line.
This is the mode to reach for on any line that is not guaranteed to be staffed: a single named person, a small team, anything out of hours, anything where "nobody picked up" is a realistic outcome rather than an edge case.
What the caller hears on return#
Set warmReturnMessage on the assistant — up to 2000 characters. Send "" to restore the built-in wording.
curl -X PATCH https://core-api.heysadie.ai/assistants/ASSISTANT_ID \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"warmReturnMessage": "Sorry — nobody on the billing team is free right now. I can take a message and have them call you back, or I can try our general line. Which would you prefer?"
}'Write it as an opening, not an apology. The caller is still on the phone and the assistant is still able to help, so the message should hand them a next step rather than a dead end.
TODO — verify: what counts as "no answer"
The end-of-call report documents supervisor_answered as true when the transferred call was answered, and explicitly notes that voicemail counts as answered. That means a destination whose answering machine picks up may be treated as a successful transfer rather than triggering the return path.
Confirm with the platform team whether warm-return distinguishes a machine from a person, and correct this section and the field description together. This matters: "the caller comes back if a machine answers" and "voicemail counts as answered" cannot both be true.
Choosing a mode#
Is the destination a person?
├── No (IVR, queue, voicemail) ──► cold
└── Yes
└── Is the line always staffed?
├── Yes (call centre, rota) ──► warm
└── No (named person, small team) ──► warm-returnIf you are unsure, warm-return is the safest default for a human destination. Its only cost over warm is the return path, which only runs when the hand-off has already failed.
Configuring it#
Transfer mode is set on the assistant and applies to its escalations.
curl -X PATCH https://core-api.heysadie.ai/assistants/ASSISTANT_ID \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"transferMode": "cold-transfer",
"warmWhisperDelaySeconds": 2
}'| Field | Type | Notes |
|---|---|---|
transferMode | string | Transfer behavior for escalations. Defaults to cold-transfer. |
warmWhisperDelaySeconds | integer | 0–30. Pause before the whisper plays. Defaults to 0. Stored under settings.warmWhisperDelaySeconds. |
warmReturnMessage | string | Max 2000 characters. What the caller hears on return. Stored under settings.warmReturnMessage; "" restores the default. |
TODO — verify: the accepted values of transferMode
The OpenAPI spec types transferMode as a plain string with no enum, and documents only the default: 'cold-transfer'. The warm and warm-return values are therefore not confirmed — "warm-transfer" and "warm-return-transfer" are the obvious guesses given the default's shape, but this page will not print a value it cannot verify.
Note also that dynamic transfer uses a different value space for the same concept — "cold", "warm", "warm-return". Confirm both sets, and whether the difference is deliberate.
Per-destination modes#
With dynamic transfer, your directory server can choose the mode per destination, so the same assistant can hand off cold to a queue and warm-return to a named person:
{ "status": "resolved", "destination": "+15551234567", "mode": "warm-return" }Precedence is server mode → defaultMode → "cold".
When a transfer happens#
Transfer reasons are the rules that decide when to hand off and where to send each kind of request — a billing question to one number, a complaint to another. Modes decide how the hand-off is performed; reasons decide whether it happens at all.
The two compose: a transfer reason picks the destination, the mode governs the hand-off.
Seeing the outcome#
Every attempted transfer appears on the end-of-call report:
| Field | Meaning |
|---|---|
transfer_reason_id | Set whenever a transfer was attempted, regardless of how the call ended |
supervisor_answered | true answered, false unanswered (no-answer, busy, failed, canceled), null when there was no transfer |
supervisor_answered: false is the signal worth acting on — it means a caller wanted a person and did not reach one. Alert the team, queue a callback, or log it against the destination so you can see which numbers keep missing calls.
function onCallReport(event) {
if (event.transfer_reason_id && event.supervisor_answered === false) {
// A caller asked for a human and nobody answered.
void alertTeam({
callId: event.call_id,
caller: event.customer_number,
reason: event.transfer_reason_id,
});
}
}Common problems#
The whisper talks over the destination's greeting. Raise warmWhisperDelaySeconds. Two to three seconds is usually enough to clear an automated greeting.
Callers report dead air after asking for a human. Almost always a cold transfer to an unstaffed line — the call left OnCore and rang out. Switch that destination to warm-return.
supervisor_answered is null on a call you expected to transfer. No transfer was attempted. Check that a transfer reason actually matches the situation, and that its description tells the model when to use it.
The transfer never fires at all. Work through the tool and prompt checks in Calls and assistant behavior.
Related#
- Dynamic transfer — resolving a destination by name at call time.
- Transfer Reasons API — defining when and where.
- Assistants — the full field reference.
- End-of-call report — transfer outcome fields.
New to this? Call transfers explains what it does and when to use it, without the API detail.