Call Transfers
Transfer calls from your AI assistant to human agents, other departments, or external numbers using SIP trunks or the built-in transfer tool.
Transfer calls from your AI assistant to human agents, other departments, or external numbers using SIP trunks or the built-in transfer tool.
Transfer Methods
1. Assistant-Initiated Transfer (Transfer Tool)
Let your AI assistant decide when to transfer based on the conversation.
2. API-Initiated Transfer (Call Control)
Transfer calls programmatically via the API.
Setting Up Assistant Transfers
Step 1: Add Transfer Tool
Add the transfer tool to your assistant's configuration:
curl -X PATCH https://api.hmsovereign.com/api/v1/assistants/ASSISTANT_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"llm_config": {
"tools": [
{
"type": "transfer_call",
"destinations": [
{
"type": "number",
"number": "+31612345678",
"description": "Sales team - for pricing and quotes",
"message": "I'm transferring you to our sales team, one moment please."
},
{
"type": "number",
"number": "+31687654321",
"description": "Technical support - for product issues and troubleshooting",
"message": "I'm transferring you to technical support."
},
{
"type": "number",
"number": "+31698765432",
"description": "Billing department - for invoice and payment questions",
"message": "I'm transferring you to the billing department."
}
]
}
]
}
}'Step 2: Guide the Assistant
Update your system prompt to guide when to transfer:
{
"messages": [
{
"role": "system",
"content": "You are a customer service agent. You can answer most questions yourself, but transfer to:\n- Sales: for questions about pricing, quotes, or new products\n- Technical support: for technical issues you cannot resolve\n- Billing: for specific billing questions\n\nAlways try to help first before transferring."
}
]
}Transfer Tool Schema
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | transfer_call |
destinations | array | Yes | List of transfer destinations |
destinations[].type | string | Yes | number |
destinations[].number | string | Yes | Phone number in E.164 format |
destinations[].description | string | Yes | When to use this destination (for LLM) |
destinations[].message | string | No | Message spoken before transfer |
wait_for_answer | boolean | No | Wait for the destination to answer before connecting the caller (default false, see below) |
answer_timeout_seconds | number | No | Max ring time before giving up (default 20, only with wait_for_answer) |
fallback_destinations | array | No | Backup numbers tried in order on no answer (only with wait_for_answer) |
fallback_destinations[].number | string | Yes | Phone number in E.164 format |
fallback_destinations[].message | string | No | Announcement before dialling this backup; silent dial if omitted |
No-Answer Handling (Monitored Transfers)
By default a transfer is blind: the caller is connected to the destination as soon as it starts ringing. If nobody picks up, the caller ends up in the destination's voicemail — and the assistant is no longer there to help.
Set wait_for_answer: true to make the transfer monitored. The destination is dialled first, and the caller is only connected once someone actually answers:
- Answered → the call is bridged exactly as with a blind transfer.
- No answer within
answer_timeout_seconds, busy, or declined → the assistant stays with the caller and receives a tool result telling it what happened (no answervsbusy), so it can take a message, offer an alternative, or end the call politely. It is explicitly instructed never to claim the transfer succeeded.
Optionally add fallback_destinations: when the chosen destination does not answer, each backup number is tried in order, and the first one to pick up gets the call. Only when every number fails does control return to the assistant.
{
"type": "transfer_call",
"wait_for_answer": true,
"answer_timeout_seconds": 18,
"destinations": [
{
"type": "number",
"number": "+31612345678",
"description": "Building manager - for urgent repairs",
"message": "I'm connecting you to the building manager, one moment please."
}
],
"fallback_destinations": [
{ "number": "+31687654321", "message": "Trying the emergency line instead." }
]
}Voicemail counts as an answer. When a destination's voicemail picks up, the phone network reports the call as answered — indistinguishable from a human. Set
answer_timeout_secondsbelow the destination's ring-to-voicemail delay (typically 20–30 seconds) so the assistant pulls back before voicemail answers.
Existing transfer tools are unaffected: without wait_for_answer the behaviour is the blind transfer described above, unchanged.
API-Initiated Transfers
Transfer an active call via the Call Control API:
curl -X POST https://api.hmsovereign.com/api/v1/calls/CALL_ID/control \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "transfer",
"destination": "+31612345678",
"message": "One moment, I'm transferring you to a colleague."
}'Transfer Command Fields
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | transfer |
destination | string | Yes | Phone number or SIP URI |
message | string | No | Message before transfer |
Using SIP Trunks
For transfers via your own phone system, configure a SIP trunk.
Step 1: Create SIP Trunk
curl -X POST https://api.hmsovereign.com/api/v1/sip-trunks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Office PBX",
"host": "pbx.example.com",
"port": 5060,
"username": "hms-sovereign",
"password": "secure-password"
}'Step 2: Assign to Phone Number
curl -X PATCH https://api.hmsovereign.com/api/v1/numbers/NUMBER_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"transfer_trunk_id": "TRUNK_ID"
}'Now transfers from this number will route through your SIP trunk.
Transfer Best Practices
- Clear descriptions - Help the assistant know exactly when to transfer
- Informative messages - Tell callers where they're being transferred
- Avoid over-transferring - Train your assistant to handle common questions
- Test destinations - Verify all transfer numbers are working
- Monitor transfers - Track transfer rates to identify training opportunities
Example: Complete Transfer Setup
{
"name": "Support Assistant",
"first_message": "Welcome to Acme support, how can I help you?",
"llm_config": {
"provider": "openai",
"model": "gpt-4o-mini",
"messages": [
{
"role": "system",
"content": "You are a support agent for Acme. Help customers with questions about products and services. Transfer only if:\n1. The customer explicitly asks for a human\n2. You cannot answer a question after 2 attempts\n3. There is a complaint that requires escalation"
}
],
"tools": [
{
"type": "transfer_call",
"destinations": [
{
"type": "number",
"number": "+31612345678",
"description": "Human support assistant for complex issues or when customer explicitly requests a human",
"message": "I'm transferring you to one of my colleagues, one moment please."
}
]
},
{
"type": "end_call"
}
]
}
}See Call Control API and SIP Trunks API for complete details.