Escalate a live call to a person with call.transfer(...). Pass { to } to forward the audio to a phone number over a SIP REFER, or { agent } to re-attach the call to a different (human-backed) agent in place. Either way the original sid keeps addressing the call, so recordings, CDRs, and analytics keyed on it stay intact. Every snippet assumes a configured Voice client:
import { Voice } from "@telequick/sdk/voice";

const v = new Voice({
  baseUrl: "https://engine.telequick.dev",
  apiKey:  process.env.TELEQUICK_CREDENTIALS!,
  orgId:   "org_abc",
});

Forward the call to a person’s phone

Transfer to an E.164 number. The SIP gateway issues a REFER toward the target and emits a transferred lifecycle event; the same sid continues.
const call = await v.calls.get({ sid });
await call.transfer({ to: "+15557654321" });   // SIP REFER to a desk phone
call.transfer("+15557654321") (a bare string) is shorthand for { to: "+15557654321" } in the TypeScript SDK.

Hand a bot call to a human queue

When an AI agent decides it needs a person, re-attach the call to a human-backed agent by id. The engine swaps the audio bridge to the new agent in place — no off-net forwarding — and the caller’s sid is preserved so the transcript and recording continue on one record.
// call started with agent: "triage-bot"; the bot asks to escalate
await call.transfer({ agent: "human-queue" });
The target agent routes into your ACD skill queue; the first available human agent (browser softphone or a registered SIP phone) is offered the call and, on accept, is bridged to the caller.

Full bot → human escalation

Originate with a triage bot, then escalate on the bot’s cue — first try an in-platform human queue, and fall back to forwarding to an on-call phone.
async function escalate(to: string) {
  // 1. start with an AI triage agent
  const call = await v.calls.originate({
    to, from: "+15558675309", trunkId: "trunk_main",
    agent: "triage-bot",
  });

  // 2. bot decides a human is needed → re-attach to the human queue
  await call.transfer({ agent: "human-queue" });

  // 3. or, forward the live audio to an on-call agent's phone
  // await call.transfer({ to: "+15557654321" });

  return call.sid;   // unchanged across the handoff
}
Pass exactly one of to or agent. The Python SDK enforces the XOR and raises if you pass both or neither; the TypeScript SDK requires at least one.
Routing and accept are wired end-to-end, but the rich warm-handoff context (the screen-pop of intent, qualification, and auth the bot captured before the human hears audio) is a product-level payload you assemble in your app — see AI ↔ human handoff for how the human agent subscribes to the live caller audio.

Confirm the transfer landed

transfer() returns once the control plane accepts the request, not when the target answers. Poll the call — or watch the transferred / cleared lifecycle events — to see how it resolved.
await call.transfer({ to: "+15557654321" });

const c = await v.calls.get({ sid });
console.log("post-transfer status:", c.status);

AI ↔ human handoff

The full warm-handoff flow: mirroring caller audio to a human agent leg.

Handoffs

How transfers, re-attach, and re-hosting fit the session model.

Call lifecycle

The transferred event and the rest of the CTI stream.

Outbound call

Originate the call you’re about to transfer.