Call flip and call pickup: the handoff-token and ringing-registry models
Call flip moves a call you are already on from one of your devices to another. Call pickup lets you answer a call that is still ringing on a colleague’s extension. Both re-target a leg that already exists in your tenant through the softswitch control plane: neither originates a PSTN leg, so neither touches your termination paths, caller id, or per-minute cost at all. This page defines the two models — the flip’s two-step token handoff, the pickup’s ringing-leg registry, the one-shot claim arbitration they share, the DTMF parity codes, and the border with park, conference, SLA mirroring, and delegation — so the procedural guides stay thin. Read it before you wire a client against/api/v1/voice/call-flip or
/api/v1/voice/pickup. The full FLIP_… / PICKUP_… code matrix lives in
the flip and pickup troubleshooting
catalog; this page explains the
model those codes name.
1. One invariant, two verbs
- Flip re-targets an answered leg between your own devices: the remote party stays on the line while your end hops, say, from the desk phone to the mobile softphone.
- Pickup claims a ringing, pre-answer leg of a colleague: nobody has answered yet, and your device becomes the one that does.
2. Call flip: the two-step token handoff
Flip is a push-then-pull protocol between two of your devices, mediated by a short-lived handoff token.- Issue. From the device holding the call,
POST /api/v1/voice/call-flipwith the livecallSid. Optionally pin the pull to one device withtargetDeviceUsername, and passremotePartyNumber/remotePartyNamefor tray display. The response carries the handoff: the fulltoken, a 4-digitshortCode, and anexpiresAtabout two minutes out. - Pull. From the destination device,
POST /api/v1/voice/call-flip/pullwith thetokenand the pulling device’spulledByDeviceUsername. The claim is atomic: exactly one of two simultaneous pulls wins, and the winner’s response resolves thecallSidso the soft client can attach its media path while the softswitch re-INVITEs the leg.
- Re-issue is idempotent. Issuing again for the same call as the same user while a live token exists returns the existing handoff instead of stacking a second token.
- Losers learn why. A pull on a consumed token returns
FLIP_ALREADY_PULLEDwith adetails.priorview naming the device that won; on a stale one,FLIP_EXPIRED; from a device other than the pinned target,FLIP_TARGET_MISMATCHnaming the expected device. A loser re-lists, it does not blind-retry. - The issuer can change their mind.
POST /api/v1/voice/call-flip/:id/cancelretires an unused token; a later pull reads it as gone. Owners, admins, and supervisors may cancel any flip in the tenant — the recovery path when an agent walked away — while everyone else cancels only their own. - The list never leaks the token.
GET /api/v1/voice/call-flipreturns the tenant’s live handoffs, newest first, for a pending-flips tray. The full token exists only in the issue response to the issuing user, and never re-appears on any read.
The desk-phone path: *7 plus the short code
A registered device that renders no UI pulls by DTMF instead: dial *7
then the 4-digit short code. The IVR resolves the code against your tenant
through an authenticated internal endpoint and runs the same atomic claim
as the HTTP pull — the dial path is a second door onto one handoff, not a
second model.
Keep the digit ranges straight: *1 through *9 retrieve park slots
(the slot aliasing model); *7 plus a
4-digit code pulls a flip. Different registries, different verbs.
3. Call pickup: the ringing-leg registry
Pickup’s claimable set is the org’s ringing registry: an org-namespaced sorted set holding exactly the pre-answer legs, each scored by when it started ringing so oldest-first is the native read order. It is deliberately not the active-call ledger, which records answered legs only and therefore can never answer “what is ringing on 201 right now.” Ringing is sub-30-second ephemeral state with a natural expiry: entries self-evict shortly after the worst-case ring timeout even when a terminal webhook drops, so a phantom ring can never sit in the tray. The softswitch’s ringing and terminal webhooks feed the registry through authenticated internal endpoints; nothing you code against writes to it directly. Three calls read and claim it:- List.
GET /api/v1/voice/pickupreturns every claimable ringing call, oldest first: the extension and username it rings on, the caller’s number and name, and ringing-since. That is the pickup tray. - Directed pickup.
POST /api/v1/voice/pickup/directedwithtargetExtensionand yourpickingUpDeviceUsername— answer the call ringing on 201, the API form of the desk phone’s**201. When an extension has several calls ringing at once (hunt-group fan-out), the oldest is the one claimed. - Group pickup.
POST /api/v1/voice/pickup/groupwith yourpickingUpDeviceUsername— answer the oldest ringing call in your pickup group, the API form of*8. PassgroupMembersto scope the claim to a named set of extensions, the same membership shape the floor already uses for team chat; omit it and the whole organization is the default pickup group.
PICKUP_ALREADY_TAKEN and re-lists. When nothing matches, the
answer is PICKUP_NO_RINGING_CALL, and the discipline is the same: re-list
with GET /api/v1/voice/pickup rather than retrying the claim. A tray miss
means the call was answered, taken first, or rang out — only a fresh tray
tells you which.
Two limits stated plainly: pickup reaches still-ringing inbound legs
only — an answered call is transfer or flip territory — and the registry
is a live cache of ringing, not a call record.
4. One-shot claims, and reading them in analytics
Flip and pickup share one arbitration shape: a resolve step that names a candidate, then a single atomic claim that can succeed exactly once across the cluster. One bridge, one audit entry, one winning device; every contested outcome (already-pulled, expired, already-taken) is the ledger telling the loser what the winner did. That one-shot nature is what makes the analytics reading clean. The recurring conference-floor pattern — a participant flipped out of a live room into a directed 1:1 hand-off — emitsparticipant_left while the
room continues (the conference
model names the pattern). Count it as a
directed hand-off, never as a room or leg failure: the leg did not fail,
it moved. Symmetrically, a ringing entry that vanishes while an answered
leg appears on another device is a pickup, not a missed call.
5. Partitioning the handoff space
Six features partition “move a call” by trigger state and by who may act:
Read the rows as exclusive choices over the same floor: park publishes
your own active call for anyone to retrieve later; pickup claims
someone else’s ringing call right now; flip follows your own
answered call to another of your devices. A park lobby survives for
minutes; a pickup entry exists only as long as the ring; a flip token
lives about two minutes. The neighboring guides: park
lobby,
conferences,
delegation.
6. Surface map
- Dashboard active-call view — the flip action on a live call issues the token; the pending-flips tray reads the list endpoint.
- Desk phones —
*7+ short code pulls a flip;**+ extension is directed pickup;*8is group pickup. - Attendant console — the pickup tray lists ringing calls and the console’s pickup actions drive directed pickup (attendant console).
- Softphone — attaches the
callSidresolved by a pull or pickup response to its registered contact; the softswitch completes the bridge.
See also
- Call flip and pickup troubleshooting — the full
FLIP_…/PICKUP_…/CONF_…matrix and claim-race diagnosis - Call park and the lobby — the slot aliasing model for your own active calls
- The conference model — multi-leg bridging, and the flip-pickup analytics pattern
- Conferences — the conference operating surface
- Attendant console — the operator tray that surfaces pickup
- The team chat model — the membership shape named pickup groups draw on
- Call delegation for executive assistants — owner-grants-delegate scope