Appearance
Transfer Action
Transfer the call to another phone number.
Action Structure
json
{
"type": "transfer",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"target_phone_number": "1234567890",
"caller_id_name": "Support Department",
"caller_id_number": "1234567890",
"timeout": 30
}Fields
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Always "transfer" |
session_id | string (UUID) | Yes | Session identifier from event |
target_phone_number | string | Yes | Phone number to transfer to (E.164 format without leading + recommended) |
caller_id_name | string | Yes | Caller ID name to display |
caller_id_number | string | Yes | Caller ID number to display |
timeout | integer (5–120) | No | Seconds to wait for the transfer target to answer. When set, enables transfer fallback (see below). When omitted, transfer failures end the call. |
Transfer Fallback
When timeout is provided, the call is returned to the agent if the transfer fails:
- Target does not answer within
timeoutseconds - Target rejects the call (busy, unavailable)
- Target hangs up without answering
On a failed transfer, the service re-emits a session_start event with the same session.id and the agent can either continue the conversation with the original caller or attempt another transfer.
On a successful transfer, no further events are sent — the call ends normally once the transferred parties hang up.
json
{
"type": "transfer",
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"target_phone_number": "1234567890",
"caller_id_name": "Support Department",
"caller_id_number": "1234567890",
"timeout": 30
}Your webhook should treat a repeated session_start for a known session id as "the call came back" and respond with a recovery prompt (for example: "Sorry, no one picked up. Would you like to try something else?").
Examples
Python
python
@app.route('/webhook', methods=['POST'])
def webhook():
event = request.json
if event['type'] == 'user_speak':
user_text = event['text'].lower()
if 'sales' in user_text:
return jsonify({
'type': 'transfer',
'session_id': event['session']['id'],
'target_phone_number': '1234567890',
'caller_id_name': 'Sales Department',
'caller_id_number': '1234567890'
})Node.js
javascript
app.post('/webhook', (req, res) => {
const event = req.body;
if (event.type === 'user_speak') {
const userText = event.text.toLowerCase();
if (userText.includes('sales')) {
return res.json({
type: 'transfer',
session_id: event.session.id,
target_phone_number: '1234567890',
caller_id_name: 'Sales Department',
caller_id_number: '1234567890'
});
}
}
});Go
go
if strings.Contains(text, "sales") {
action := map[string]interface{}{
"type": "transfer",
"session_id": session["id"],
"target_phone_number": "1234567890",
"caller_id_name": "Sales Department",
"caller_id_number": "1234567890",
}
json.NewEncoder(w).Encode(action)
}Phone Number Format
Use E.164 format without leading + (recommended):
- ✅
1234567890 - ✅
491234567890 - ❌
123-456-7890(not recommended)
Use Cases
- Route to departments - Sales, support, billing
- Escalate to human - When AI can't help
- Specialized services - Connect to experts
- Emergency routing - Urgent situations
Best Practices
- Announce transfer - Tell user before transferring
- Use E.164 format - International phone numbers
- Set caller ID - Identify the source
- Log transfers - Track routing decisions
Next Steps
- Hangup Action - End the call
- Event Types - What triggers actions
- Event Flow - Understand the complete flow