Skip to content

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

FieldTypeRequiredDescription
typestringYesAlways "transfer"
session_idstring (UUID)YesSession identifier from event
target_phone_numberstringYesPhone number to transfer to (E.164 format without leading + recommended)
caller_id_namestringYesCaller ID name to display
caller_id_numberstringYesCaller ID number to display
timeoutinteger (5–120)NoSeconds 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 timeout seconds
  • 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

  1. Announce transfer - Tell user before transferring
  2. Use E.164 format - International phone numbers
  3. Set caller ID - Identify the source
  4. Log transfers - Track routing decisions

Next Steps