diff --git a/fern/calls/call-dynamic-transfers.mdx b/fern/calls/call-dynamic-transfers.mdx index 15e62661c..15fb8abb9 100644 --- a/fern/calls/call-dynamic-transfers.mdx +++ b/fern/calls/call-dynamic-transfers.mdx @@ -339,18 +339,29 @@ sequenceDiagram console.log(`Transfer request: ${department} - ${reason} (${urgency})`); // Determine destination based on department + // Include transferPlan for warm transfers with context let destination; if (department === 'support') { destination = { type: "number", - number: "+1234567890" + number: "+1234567890", + transferPlan: { + mode: "warm-transfer-say-message", + message: `Incoming call about: ${reason}. Priority: ${urgency}.` + } }; } else if (department === 'sales') { destination = { type: "number", - number: "+1987654321" + number: "+1987654321", + transferPlan: { + mode: "warm-transfer-wait-for-operator-to-speak-first-and-then-say-message", + message: `Hi, I have a customer interested in our products. Reason: ${reason}.`, + timeout: 30 + } }; } else { + // Default to blind transfer for general inquiries destination = { type: "number", number: "+1555555555" @@ -413,22 +424,33 @@ sequenceDiagram print(f"Transfer request: {department} - {reason} ({urgency})") # Determine destination based on department + # Include transferPlan for warm transfers with context if department == 'support': destination = { "type": "number", - "number": "+1234567890" + "number": "+1234567890", + "transferPlan": { + "mode": "warm-transfer-say-message", + "message": f"Incoming call about: {reason}. Priority: {urgency}." + } } elif department == 'sales': destination = { "type": "number", - "number": "+1987654321" + "number": "+1987654321", + "transferPlan": { + "mode": "warm-transfer-wait-for-operator-to-speak-first-and-then-say-message", + "message": f"Hi, I have a customer interested in our products. Reason: {reason}.", + "timeout": 30 + } } else: + # Default to blind transfer for general inquiries destination = { "type": "number", "number": "+1555555555" } - + # Execute transfer via Live Call Control async with httpx.AsyncClient() as client: await client.post( @@ -452,7 +474,7 @@ sequenceDiagram **SIP transfers:** To transfer to a SIP endpoint, use `"type": "sip"` with `"sipUri"` instead: - + ```json { "type": "transfer", @@ -464,6 +486,19 @@ sequenceDiagram } ``` + + + **Warm transfer modes:** The examples above show warm transfers using `transferPlan`. Available modes include: + - `blind-transfer` - Immediate transfer (default when no `transferPlan` is specified) + - `warm-transfer-say-message` - Say a custom message to the operator + - `warm-transfer-say-summary` - Say an AI-generated conversation summary + - `warm-transfer-wait-for-operator-to-speak-first-and-then-say-message` - Wait for operator response before delivering message + - `warm-transfer-wait-for-operator-to-speak-first-and-then-say-summary` - Wait for operator response before delivering summary + - `warm-transfer-twiml` - Execute custom TwiML instructions + - `warm-transfer-experimental` - Use a transfer assistant for intelligent handoffs + + See [Live Call Control](/calls/call-features#5-transfer-call) and [Assistant-based warm transfer](/calls/assistant-based-warm-transfer) for more details. + diff --git a/fern/calls/call-features.mdx b/fern/calls/call-features.mdx index fed5b8a6a..73ad1a863 100644 --- a/fern/calls/call-features.mdx +++ b/fern/calls/call-features.mdx @@ -114,11 +114,14 @@ curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/742 ``` ### 5. Transfer Call -Transfer the call to a different destination. +Transfer the call to a different destination. Transfers support both blind (immediate) and warm (with context) modes. + +#### Blind Transfer (Default) +Immediately transfer the call without any context to the receiving party. ```bash -curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' --H 'content-type: application/json' +curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' +-H 'content-type: application/json' --data-raw '{ "type": "transfer", "destination": { @@ -132,8 +135,8 @@ curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/742 You can also transfer to a SIP URI: ```bash -curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' --H 'content-type: application/json' +curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' +-H 'content-type: application/json' --data-raw '{ "type": "transfer", "destination": { @@ -144,6 +147,99 @@ curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/742 }' ``` +#### Warm Transfer +Provide context to the receiving party before connecting the customer. Use the `transferPlan` property to configure warm transfer behavior. + +**Say a message before connecting:** + +```bash +curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' +-H 'content-type: application/json' +--data-raw '{ + "type": "transfer", + "destination": { + "type": "number", + "number": "+1234567890", + "transferPlan": { + "mode": "warm-transfer-say-message", + "message": "Incoming call from a customer asking about billing issues." + } + }, + "content": "Please hold while I transfer you." +}' +``` + +**Provide an AI-generated summary:** + +```bash +curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' +-H 'content-type: application/json' +--data-raw '{ + "type": "transfer", + "destination": { + "type": "number", + "number": "+1234567890", + "transferPlan": { + "mode": "warm-transfer-say-summary" + } + }, + "content": "Transferring you now." +}' +``` + +**Wait for operator to speak first:** + +```bash +curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' +-H 'content-type: application/json' +--data-raw '{ + "type": "transfer", + "destination": { + "type": "number", + "number": "+1234567890", + "transferPlan": { + "mode": "warm-transfer-wait-for-operator-to-speak-first-and-then-say-message", + "message": "Hi, I have a customer on the line who needs help with their order.", + "timeout": 30 + } + }, + "content": "Connecting you to our support team." +}' +``` + +**Use TwiML for custom announcements:** + +```bash +curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' +-H 'content-type: application/json' +--data-raw '{ + "type": "transfer", + "destination": { + "type": "number", + "number": "+1234567890", + "transferPlan": { + "mode": "warm-transfer-twiml", + "twiml": "Incoming transfer from support AI.Customer issue: billing question." + } + }, + "content": "Please hold for transfer." +}' +``` + + +Warm transfer modes require Twilio, Vapi phone numbers, or SIP trunks. They do not support Telnyx or Vonage. + + +**Available transfer plan modes:** +- `blind-transfer` - Immediate transfer (default) +- `blind-transfer-add-summary-to-sip-header` - Add summary to SIP headers +- `warm-transfer-say-message` - Say a custom message to the operator +- `warm-transfer-say-summary` - Say an AI-generated summary +- `warm-transfer-wait-for-operator-to-speak-first-and-then-say-message` - Wait for operator, then say message +- `warm-transfer-wait-for-operator-to-speak-first-and-then-say-summary` - Wait for operator, then say summary +- `warm-transfer-twiml` - Execute TwiML instructions +- `warm-transfer-experimental` - Use a transfer assistant for intelligent handoffs (see [Assistant-based warm transfer](/calls/assistant-based-warm-transfer)) + ### 6. Handoff Call Handoff the call to a different assistant.