/api/v1/voice/ring-groups
Authentication: Clerk session (Authorization: Bearer <token>) or API key (X-API-Key).
Scope: create, update, and delete require an owner or admin role. Reads are available to owner, admin, developer, and viewer roles.
1. When a ring group beats a queue
Both answer inbound calls with a group of people, but they behave differently at call time:- Ring group — the inbound call rings member destinations directly (SIP devices, external numbers, or even other ring groups). The first member to answer owns the call. There is no hold position, no queue depth, and no agent staffing model.
- Queue — the caller waits in FIFO with hold music and a position, and the platform dispatches them to an eligible, available agent. Queues give you SLA metrics, occupancy, and agent-level routing; ring groups give you “ring these phones.”
2. Create the group in the dashboard
Open Voice → Ring groups and click Create ring group. The modal carries three fields:- Name — unique per organization (1–100 characters).
- Strategy — how the group offers the call to its members:
simultaneousrings every member at once;sequentialrings one member at a time in list order;round_robinrotates the starting member on each call;longest_idleoffers the member who has been idle longest;fewest_callsoffers the member with the fewest handled calls. - Ring timeout — how long the group tries members before the DID’s fallback or voicemail fires (5–300 seconds; default 30).
- SIP username — an extension registered under Voice → Extensions / Devices.
- Phone number (PSTN) — an E.164 number with leading
+(e.g.+14155550123). The leading+is required; a bare-digit number is rejected. - Ring group — another group in your organization, for nesting (e.g. “front desk” inside “all support”). Cycles are rejected.
3. Attach it to a DID
A ring group does nothing until a routing rule references it. The common pattern is a DID whose primary route is the group: Dashboard: Numbers → your number → Routing, pick Ring group as the route type, and select the group. API:PUT /api/v1/numbers/:e164/routing with type: "ring_group" and the sibling ring_group_id field — the config object is empty because the group identity lives in that sibling field.
cURL
- Send the group id as
ring_group_id, not insideconfig.configaccepts{}for this type; aconfig.ringGroupIdkey is rejected as a shape error. - Pair it with a fallback. If every member is busy or offline, the route falls through to the DID’s fallback (
voicemailin the example above). Without a fallback, the caller hears nothing useful.
4. Test with the IVR simulator and call log
For theivr route type, the simulator (POST /api/v1/voice/ivr-flows/:id/simulate) walks the published flow without burning a live minute — run it before attaching a flow that routes into a ring group. The response returns the nodes visited and the verbs emitted per turn, so you can confirm the flow reaches your group step before callers do.
For a directly-attached ring group, verification is a real inbound call to the DID, watched in the Calls log — you see each member destination rung and which one answered, plus whether the fallback fired. Attach-time validation rejects a bad group id with a 422, so a misroute surfaces at write time rather than at ring time.
5. Tune the strategy
The strategy changes fan-out behavior more than anything else:simultaneous(default) — fastest answer; every member rings and the first to pick up owns the call. Right when the group is a handful of destinations and you want the shortest time-to-answer. The trade-off is that it can ring phones nobody wants to answer.sequential— rings one member at a time in roster order. Right when you have a defined order (lead first, then deputies). Slower to answer than simultaneous because each member’s ring timeout runs in series.round_robin— rotates the starting member so share is even over many calls. Right when members are interchangeable and you want fairness rather than speed.longest_idle— offers the member idle longest. Right when you want to spread load without a round-robin rotation.fewest_calls— offers the member who has handled the fewest calls. Right when you want to even out handled-call counts over a shift.
simultaneous for a small desk (the whole group rings, first answer wins) and revisit once the ring log shows one member answering most calls.
6. API walkthrough
Manage the roster from code the same way the dashboard does:cURL
warnings array — for example when a PSTN member also belongs to another group — so a caller can surface “this number is already in group X” instead of rejecting an intentional overlap.
7. Troubleshooting
Worked example: after-hours pilot desk
You run a support line Mon–Fri, but after hours a fixed set of phones should ring: the night manager’s deskphone, their cell, and — if nobody answers — a shared voicemail box.- In Voice → Ring groups, create
After-hours deskwith strategysimultaneous, ring timeout20, and three members: the deskphone’s SIP username, the manager’s PSTN cell (+12025550123), and (only if useful) another ring group such asEscalation. - In Numbers → support line → Routing, set the primary route to that group with fallback
voicemailpointing at the department box. - Add a
business_hourswindow to the route so after-hours callers hit the group while daytime callers hit the queue. - Place a test call after hours and watch the Calls log — you should see all three destinations ring and the one that answered.