---
title: "Get Call Transfer Flow"
method: GET
path: "/calls/{call_id}/transfer-flow"
tags: ["Calls"]
---

# Get Call Transfer Flow

`GET /calls/{call_id}/transfer-flow`

## Request

- Base URL: `https://api.openintake.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.openintake.ai/calls/{call_id}/transfer-flow`
- Auth: none declared

Reconstruct a transferred call's flow: our AI → transfer destination →
the PBX queue/agent hop chain (intake → fallback → who answered).

Debugging view for developers, and for firm users with the
calls.transfer_flow permission (admins, by default) when the customer's
transfer_flow_admin_enabled call-detail setting is on. PBX
hops come from a live read-only NetSapiens CDR read; customers without
NetSapiens (or an untransferred call) get just the our-side segment.

## Path parameters

- `call_id` string, uuid, required

## Response `200`

Successful Response

- TransferFlowResponse: Developer-only transfer-flow reconstruction for a call.
  - `transferred` boolean, required: Whether the call was transferred at all
  - `hops` TransferFlowHop[]: Ordered flow hops
    - `source` string, required: 'openintake' (our side) or 'pbx'
    - `timestamp` string, date-time, nullable: When this hop started
    - `label` string, required: Human-readable hop, e.g. 'Intake Dept' or 'AI Assistant'
    - `action` string, nullable: Verb/action, e.g. 'Transferred', 'Queue dispatch'
    - `queue_name` string, nullable: PBX queue name if this hop rang a queue
    - `agent_name` string, nullable: Staff member who was rung/answered
    - `answered` boolean, nullable: Whether this hop was answered
    - `talk_seconds` integer, nullable: Seconds of actual conversation on this hop (the agent leg's own duration, excluding queue wait)
    - `ring_seconds` integer, nullable: Seconds the agent's device rang before pickup; null when unanswered, parked, retrieved from a park orbit (the caller was on hold, so nothing rang), or captured before the PBX ring time was recorded
    - `detail` string, nullable: Extra context, e.g. release reason or transfer outcome
    - `parked` boolean: Hop is a park orbit, not a person. The PBX records a park as an ANSWERED leg, so 'answered' alone reads as a staff pickup on a call that was only parked — the UI must label these differently
    - `retrieved_from_park` boolean: A person took the caller back OFF a park orbit — a genuine pickup that names an orbit, so it must render as answered even though the PBX books it against the orbit. Never true together with 'parked'; the hop has no ring time because the caller was on hold rather than ringing
    - `queue_refused` boolean: The PBX could not resolve the queue this leg was routed to and hung up on the caller — its own release text is 'No Queue'. Never true together with 'parked' or 'answered': the caller never reached the queue or orbit at all, so there is no hold to come off and nobody to retrieve them. Applies equally to a refused park dial, a refused onward transfer, and a refused inbound route
    - `inferred` boolean: Hop reconstructed from the forward-rule chain at capture time (the PBX emits no CDR row for unanswered intermediate queues)
    - `observed` boolean: The PBX's live call events saw this queue: the timestamp is when the call reached it and 'rang' lists the phones it rang. Makes an inferred roll-through a confirmed one
    - `rang` string[]: Names (or 'Ext N') of the phones this queue rang, per the PBX's live call events. Empty when the events were not retained
    - `rang_seconds` integer, nullable: Seconds from this queue's first ring to the last of its phones stopping, per the PBX's live call events
    - `post_answer` boolean: Hop after the first answered PBX hop (staff-side onward transfers); the UI collapses these behind an 'additional transfers' toggle. Never set on a park hop: a park is not an onward transfer, and a park that FAILS sorts last (it begins when the answerer hangs up), so collapsing it would hide the moment the caller was dropped
  - `pbx_available` boolean, required: Whether PBX-side hops could be resolved (NetSapiens configured)
  - `in_progress` boolean: The caller is still on the phone with staff, so the flow is not final. A live transfer has no PBX hops yet (CDRs post at completion), which would otherwise render as an empty, absent card.

## Other responses

- `422`: Validation Error

## Changes

- **2026-10-20** `0b14aa0ec87c`: 3 info
  - added the optional property `hops/items/observed` to the response with the `200` status
  - added the optional property `hops/items/rang` to the response with the `200` status
  - added the optional property `hops/items/rang_seconds` to the response with the `200` status
- **2026-09-11** `546117b4e7b4`: 1 info
  - added the optional property `hops/items/queue_refused` to the response with the `200` status
- **2026-09-10** `7026155e615c`: 1 info
  - added the optional property `hops/items/retrieved_from_park` to the response with the `200` status
- **2026-09-09** `32f6d8075c56`: 1 info
  - added the optional property `hops/items/parked` to the response with the `200` status
- **2026-09-07** `b883e03846c6`: 2 info
  - added the optional property `hops/items/ring_seconds` to the response with the `200` status
  - added the optional property `in_progress` to the response with the `200` status

[Operation history](https://skmtc.dev/openintake/apis/openintake-api/changes/calls/:call_id/transfer-flow/get.md)

---

[API](https://skmtc.dev/openintake/apis/openintake-api.md) - [All operations](https://skmtc.dev/openintake/apis/openintake-api/llms.txt) - [OpenAPI document](https://skmtc.dev/openintake/apis/openintake-api/revisions/de90a8dcbc07?raw)
