Dynamic call transfers

Route calls to different destinations based on real-time conversation context and external data.

Overview

Dynamic call transfers enable intelligent routing by determining transfer destinations in real-time based on conversation context, customer data, or external system information. Unlike static transfers with predefined destinations, dynamic transfers make routing decisions on-the-fly during the call.

Key capabilities:

  • Real-time destination selection based on conversation analysis
  • Integration with CRM systems, databases, and external APIs
  • Conditional routing logic for departments, specialists, or geographic regions
  • Context-aware transfers with conversation summaries
  • Fallback handling for unavailable destinations

Prerequisites

  • A Vapi account
  • A server or cloud function that can receive webhooks from Vapi
  • (Optional) CRM system or customer database for enhanced routing logic

How It Works

Dynamic transfers support two patterns. Choose one per your architecture:

  1. Assistant-supplied destination (no webhook)

    • The transfer tool includes custom parameters (e.g., phoneNumber).
    • The assistant determines the destination (via reasoning or tools) and calls the transfer tool with that parameter.
    • Vapi executes the transfer directly. The transfer-destination-request webhook is not sent.
  2. Server-supplied destination (webhook)

    • The transfer tool has an empty destinations array and no destination parameter is provided by the assistant.
    • Vapi sends a transfer-destination-request to your server.
    • Your server decides the destination and responds with it.

Available context to servers (webhook pattern): Your webhook receives conversation transcript, extracted variables, function parameters (if any), and call metadata.

Parameters for transfer tools are fully customizable. You can name and structure them however you like to guide routing (for example phoneNumber, department, reason, urgency, etc.).


Quick Implementation Guide

1

Create a dynamic transfer tool

  • Navigate to Tools in your dashboard
  • Click Create Tool
  • Select Transfer Call as the tool type
  • Important: Leave the destinations array empty — this enables dynamic routing
  • Set function name: dynamicTransfer
  • Add a description describing when this tool should be used
  • Decide your pattern:
    • If the assistant will provide the destination: add a custom parameter like phoneNumber
    • If your server will provide the destination: omit destination params and add any context params you want (e.g., reason, urgency)
2

Create an assistant with the transfer tool

  • Navigate to Assistants
  • Create a new assistant or edit an existing one
  • Add your dynamic transfer tool to the assistant
  • Optional: Enable the transfer-destination-request server event and set your server URL if using the server-supplied pattern. This is not required when the assistant provides phoneNumber directly.
3

Build your webhook server

This step is only required for the server-supplied destination pattern. If your assistant provides a phoneNumber directly when calling the transfer tool, the transfer-destination-request webhook will not be sent.

1import express from 'express';
2import crypto from 'crypto';
3
4const app = express();
5app.use(express.json());
6
7function verifyWebhookSignature(payload: string, signature: string) {
8 const expectedSignature = crypto
9 .createHmac('sha256', process.env.WEBHOOK_SECRET!)
10 .update(payload)
11 .digest('hex');
12 return crypto.timingSafeEqual(
13 Buffer.from(signature),
14 Buffer.from(expectedSignature)
15 );
16}
17
18app.post('/webhook', (req, res) => {
19 try {
20 const signature = req.headers['x-vapi-signature'] as string;
21 const payload = JSON.stringify(req.body);
22
23 if (!verifyWebhookSignature(payload, signature)) {
24 return res.status(401).json({ error: 'Invalid signature' });
25 }
26
27 const request = req.body;
28
29 if (request.type !== 'transfer-destination-request') {
30 return res.status(200).json({ received: true });
31 }
32
33 // Simple routing logic - customize for your needs
34 const { functionCall, customer } = request;
35 const urgency = functionCall.parameters?.urgency || 'medium';
36
37 let destination;
38 if (urgency === 'critical') {
39 destination = {
40 type: "number",
41 number: "+1-555-EMERGENCY",
42 message: "Connecting you to our emergency team."
43 };
44 } else {
45 destination = {
46 type: "number",
47 number: "+1-555-SUPPORT",
48 message: "Transferring you to our support team."
49 };
50 }
51
52 res.json({ destination });
53 } catch (error) {
54 console.error('Webhook error:', error);
55 res.status(500).json({
56 error: 'Transfer routing failed. Please try again.'
57 });
58 }
59});
60
61app.listen(3000, () => {
62 console.log('Webhook server running on port 3000');
63});
4

Test your dynamic transfer system

  • Create a phone number and assign your assistant
  • Call the number and test different transfer scenarios
  • Monitor your webhook server logs to see the routing decisions
  • Verify transfers are working to the correct destinations

Implementation Approaches

Assistant-based implementation uses transfer-type tools with conditions interpreted by the assistant through system prompts. The assistant determines when and where to route calls based on clearly defined tool purposes and routing logic in the prompt. Best for quick setup and simpler routing scenarios.

Workflow-based implementation uses conditional logic based on outputs from any workflow node - tools, API requests, conversation variables, or other data sources. Conditions evaluate node outputs to determine routing paths within visual workflows. Best for complex business logic, structured decision trees, and team-friendly configuration.

Routing Patterns

Common Use Cases

  • Customer support routing - Route based on issue type, customer tier, agent availability, and interaction history. Enterprise customers and critical issues get priority routing to specialized teams.

  • Geographic routing - Direct calls to regional offices based on customer location and business hours. Automatically handle time zone differences and language preferences.

  • Load balancing - Distribute calls across available agents to optimize wait times and agent utilization. Route to the least busy qualified agent.

  • Escalation management - Implement intelligent escalation based on conversation tone, issue complexity, and customer history. Automatically route urgent issues to senior agents.

Transfer Configuration

  1. Warm transfers provide context to receiving agents with AI-generated conversation summaries, ensuring smooth handoffs with full context.

  2. Cold transfers route calls immediately with predefined context messages, useful for simple departmental routing.

  3. Conditional transfers apply different transfer modes based on routing decisions, such as priority handling for enterprise customers.

  4. Destination types include phone numbers for human agents, SIP endpoints for VoIP systems, and Vapi assistants for specialized AI agents.

Security considerations: Always verify webhook signatures to ensure requests come from Vapi. Never log sensitive customer data, implement proper access controls, and follow privacy regulations like GDPR and CCPA when handling customer information in routing decisions.

Troubleshooting

  • If transfers work but you never see transfer-destination-request on your webhook, your assistant likely provided the destination (e.g., phoneNumber) directly in the tool call. This is expected and no webhook will be sent in that case.
  • If you expect a webhook but it’s not firing, ensure your transfer tool has an empty destinations array and the assistant is not supplying a destination parameter.
  • If the assistant transfers to an unexpected number, audit your prompts, tools that return numbers, and any variables the assistant can access.
  • Call Forwarding - Static transfer options and transfer plans
  • Webhooks - Webhook security and event handling patterns
  • Custom Tools - Build custom tools for advanced routing logic