Call legs and identifiers
The A-leg identifier is the key you use everywhere - it targets the Transfer API, it looks up the CDR, and it owns any recording.
The transfer is a redirect
Transferring a live call means pointing a leg at a new XML document. See Transfer a call for the request itself. When the transfer is accepted:- The leg stops executing its current XML document. Pending elements in that document are discarded.
- Vobiz requests the new URL, sending the standard call parameters.
- The XML returned becomes the leg’s new document and starts executing immediately.
<Dial> does, so return a <Dial> from the transfer URL:
Elements placed after
<Dial> run only when no bridge is established, which makes them the natural place for no-answer handling.Webhook sequence
For a call that is answered, transferred, bridged, and then ended by the original party:hangup_url reports the A-leg. It fires once per call. The transferred leg does not produce its own hangup webhook, so an integration listening only on hangup_url sees the original leg and not the destination. Configure the Dial callbackUrl to observe the B-leg - see Dial status reporting.
Recording completion arrives after hangup. The file is finalised once the call ends, so RecordStop is the point at which the recording URL is ready to fetch.
Correlating the two legs
CaptureDialBLegUUID from the real-time Dial callbackUrl. DialAnswer is the earliest event that carries it, and the real-time channel reports it for every attempt - including destinations that never answered, where the final action result may arrive with an empty DialBLegUUID.
After the call, the two legs are linked by bridge_uuid. Each leg’s record carries the other leg’s identifier:
The relationship is symmetric, so either leg works as a starting point for reconciliation.
bridge_uuid comes from the CDR detail endpoint - see CDR.
bridge_uuid is null when no bridge was established. A transfer whose destination never answered produces a B-leg record with no bridge, because the legs were never connected. For those calls, correlate on the DialALegUUID and DialBLegUUID pair from the Dial callback.Recording across a transfer
A session recording survives the transfer. A recording started when the call is answered continues through the redirect, captures the bridged conversation, and ends when the call ends:<Record> at answer time therefore captures the whole call, transferred portion included. Adding a second <Record> before <Dial> produces a second, overlapping file covering only the transferred segment, and is billed as an additional recording. The number of recordings follows the number of <Record> elements that execute, not the number of legs.
Every recording is attributed to the A-leg CallUUID, including one started immediately before <Dial>. Look recordings up by the original call’s identifier rather than the transferred leg’s.
See Record for attributes and the completion webhook.
Billing
Each leg is charged independently, so a transferred call produces two charges. The original leg is billed for its whole life, which includes the bridged period. The transferred leg is billed for its own life only. Billable time isbillsec, measured from answer to hangup - ring time is not billed - and rounded up to the next pulse. On a 60-second pulse:
A complete transferred call reconciles like this, with the original leg spanning the whole call and the transferred leg only its own portion:
The durations relate as
duration = ring_time + billsec.
Webhooks carry duration, the CDR carries cost.
BillDuration and DialBLegBillDuration arrive already rounded to the pulse and match the CDR, so they are what you reconcile against in real time. Read cost and total_cost from the CDR API for the charge itself.billsec and cost at zero and the ring duration recorded in ring_time. Unanswered legs are not charged, and they remain visible in reporting.
Recording storage is metered separately, applying the same pulse rounding - a 43-second recording is stored and billed as 60 seconds.