Skip to content
TriedDocs
Webhooks

transfer_ended

Sent when a bridged transfer finishes because both legs have hung up.

transfer_ended closes a successful transfer. It tells you the caller and the transfer destination have finished their conversation, so you know the total handling time including the human part.

When it fires#

When the media room for a transferred call closes, Tried checks the call:

  • It has a transfer_bridged entry.
  • It does not have a transfer_ended entry yet.
  • The call is already ended, error or not_connected.

If all three hold, a transfer_ended event is recorded and the webhook is sent. This is usually well after call_ended and call_analyzed, because the agent leaves the call as soon as the transfer is bridged.

It never fires for transfers that were cancelled. Phone calls only.

Which settings enable it#

  • Off by default. Add transfer_ended to the agent's webhook_events.
  • URL: the agent's webhook_url, else the workspace URL (no {{variable}} substitution).
  • Timeout: the workspace timeout, else 10 s.

Payload#

{
  "event": "transfer_ended",
  "call": {
    "call_id": "call_8c2e5a1f7b3d9e0c4a6f2b18",
    "call_type": "phone_call",
    "agent_id": "agent_5b0e2c7d9a1f4e3b8c6d2a10",
    "agent_version": 2,
    "agent_name": "Bondi Dental Front Desk",
    "call_status": "ended",
    "direction": "inbound",
    "from_number": "+61412345678",
    "to_number": "+61291234567",
    "metadata": {},
    "retell_llm_dynamic_variables": { "business_name": "Bondi Dental" },
    "collected_dynamic_variables": {},
    "start_timestamp": 1760675400120,
    "end_timestamp": 1760675422400,
    "duration_ms": 22280,
    "transcript": "Agent: Hi, thanks for calling Bondi Dental, this is Ava. How can I help you today?\nUser: I need to talk to the dentist about my bill.\nAgent: Sure, I'll put you through to our practice manager now.",
    "transcript_object": [
      { "role": "agent", "content": "Hi, thanks for calling Bondi Dental, this is Ava. How can I help you today?", "words": [] },
      { "role": "user", "content": "I need to talk to the dentist about my bill.", "words": [] },
      { "role": "agent", "content": "Sure, I'll put you through to our practice manager now.", "words": [] }
    ],
    "transcript_with_tool_calls": [
      { "role": "agent", "content": "Hi, thanks for calling Bondi Dental, this is Ava. How can I help you today?", "ts": 1760675400340 },
      { "role": "user", "content": "I need to talk to the dentist about my bill.", "ts": 1760675405910 },
      { "role": "tool_call_invocation", "tool_call_id": "call_tool_01", "name": "transfer_to_manager", "arguments": "{}", "ts": 1760675406650 },
      { "role": "agent", "content": "Sure, I'll put you through to our practice manager now.", "ts": 1760675406700 },
      { "role": "transfer", "event": "transfer_started", "destination": "+61298765432", "ts": 1760675409210 },
      { "role": "transfer", "event": "transfer_bridged", "destination": "+61298765432", "ts": 1760675421880 },
      { "role": "transfer", "event": "transfer_ended", "destination": "+61298765432", "ts": 1760675734050 }
    ],
    "recording_url": "https://tried-recordings.s3.ap-southeast-2.amazonaws.com/ws_7d1c0a9e4b2f6a8c3e5d1b90/call_8c2e5a1f7b3d9e0c4a6f2b18/mixed.ogg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=86400&X-Amz-Signature=9e2a...",
    "recording_multi_channel_url": null,
    "public_log_url": "https://api.tried.com.au/public/calls/call_8c2e5a1f7b3d9e0c4a6f2b18/log?exp=1761280534100&sig=0e3a6d9c2f5b8e1a4d7c0f3b6e9a2d5c8f1b4e7a0d3c6f9b2e5a8d1c4f7b0e3a",
    "knowledge_base_retrieved_contents_url": "https://api.tried.com.au/public/calls/call_8c2e5a1f7b3d9e0c4a6f2b18/kb-retrievals?exp=1761280534100&sig=b6e9a2d5c8f1b4e7a0d3c6f9b2e5a8d1c4f7b0e3a6d9c2f5b8e1a4d7c0f3b6e9",
    "transfer_destination": "+61298765432",
    "llm_token_usage": { "values": [1650, 1720], "average": 1685, "num_requests": 2 },
    "disconnection_reason": "call_transfer",
    "call_analysis": {
      "call_summary": "The caller asked about a bill and was transferred to the practice manager.",
      "in_voicemail": false,
      "user_sentiment": "Neutral",
      "call_successful": true,
      "custom_analysis_data": {}
    },
    "latency": {
      "e2e": { "p50": 702, "p90": 702, "p95": 702, "p99": 702, "max": 702, "min": 688, "num": 2, "values": [688, 702] }
    },
    "call_cost": {
      "product_costs": [
        { "product": "voice_infra", "unit_price": 0.08, "cost": 0.030667 },
        { "product": "gpt-5.6-terra", "unit_price": 0.1, "cost": 0.038333 },
        { "product": "voice_standard", "unit_price": 0.06, "cost": 0.023 }
      ],
      "total_duration_seconds": 23,
      "combined_cost": 0.092
    },
    "batch_call_id": null,
    "contact_id": "contact_6e2a9c1f4b7d0e3a5c8f1b24"
  },
  "transfer": {
    "destination": "+61298765432",
    "timestamp": 1760675734050
  }
}

Fields#

Field Type Description
transfer.destination string The destination that was bridged
transfer.timestamp integer When the transfer ended, Unix ms

The talk time with the destination is transfer.timestamp minus the ts of the transfer_bridged entry in call.transcript_with_tool_calls.

call.call_cost covers the time the agent was on the call. Tried adds no charge for the transferred leg: it runs on your own trunk and your carrier bills it.

How to respond#

Reply 2xx. The body is ignored. Retries: up to 3 (1 s, 2 s, 4 s).