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, carrying a transfer_failed_reason. The agent can then continue the conversation with the original caller or attempt another transfer.
transfer_failed_reason | Meaning |
|---|---|
busy | The target was busy |
rejected | The target actively declined the call |
no_answer | The target rang until timeout expired without picking up |
number_not_found | The target number does not exist |
technical_error | The call could not be delivered for technical reasons |
unknown | The outcome could not be determined |
The first three mean the target was reachable but did not take the call, so trying another target usually makes sense. The last three point at the number or the route, where a retry rarely helps.
If you transfer again and that attempt fails too, you get another session_start — the reason always describes the most recent attempt.
On a successful transfer, no further events are sent — the call ends normally once the transferred parties hang up. Because a connected transfer never returns the caller, the absence of a returning session_start is the success signal, and there is no success reason to report.
The returning event looks like this:
json
{
"type": "session_start",
"session": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"account_id": "account-123",
"phone_number": "1234567890",
"direction": "inbound",
"from_phone_number": "9876543210",
"to_phone_number": "1234567890"
},
"transfer_failed_reason": "no_answer"
}Treat a session_start that carries transfer_failed_reason 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?"). The field is absent on a new call, so you do not need to track which sessions you transferred.
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