On-call deep dive
Devotel Orbit’s on-call surfaces answer the four questions incident dispatch depends on: who holds the pager right now, who is next when they miss it, what the escalation timeline will actually do, and where that timeline stands for a live incident. Two operator guides cover the endpoints one at a time — the on-call alerting guide for the endpoint-by-endpoint build and the escalation runbook for tuning timeouts and repeat rounds. This page is the consolidated operator walkthrough: one read that takes you from an empty rotation to a rehearsed pager hand-off, using the dashboard hub for setup and the On-Call API for automation.Everything here is a control your tenant owns: rotations, policies, channels, thresholds, and the incident record all live in your account or in your own store. Orbit never pages anyone on the oncall route group — every endpoint is pure compute over the request you send, and the actual send exits through the Messages API, where your sender ids, quiet-hours policy, and delivery webhooks apply exactly as they do to any other send.
What the dashboard hub covers
The on-call hub lives at Voice → On-call & escalation. It is one page with four working components, and each one wraps one endpoint of thePOST /api/v1/oncall route group:
Resolve and plan are read-only and need the
messages:read scope. The incident driver mutates incident state (acknowledge, resolve, reassign) and needs messages:write. Non-technical stakeholders carry the read role; the operators who acknowledge and resolve carry write.
Wire the route group
Every dashboard form maps to a POST on the/api/v1/oncall route group, which lets your scheduler, dispatcher, or incident script do the same work the page does. Four endpoints, one authorization ladder:
- Rotations (
/resolve). Model the rotation you already run: an anchor, a cadence, and an ordered member list. DST is correct because every shift is exactly one shift length after the anchor — there is no timezone math to tune. Backdateatto audit who held the pager at an arbitrary instant. - Policies (
/escalation/plan). Chain steps (rotationoruserstargets) with an acknowledge window (escalate_after_seconds, default 300) per step and a policy-levelrepeatloop. The plan response hands you absolutefire_atoffsets you can schedule against — the timeline an incident driver walks. - Tick (
/incident/tick). Drive a live incident on your own timer: pass the snapshot, receive the pages due now, the newpages_firedhigh-water mark to persist, andnext_tick_at. A halted (acknowledged or resolved) incident returnsdue_pages: []andnext_tick_at: null, so your scheduler stands down. - Transition (
/incident/transition). Applyack,resolve, orreassign. Invalid transitions — acknowledging a resolved incident, or reassigning after resolution — answer409 incident_transition_invalidrather than corrupting your state.
owner, admin, developer, viewer) reach the first two; drive roles (owner, admin, developer) reach tick and transition. The same split shows up in the dashboard: clearing a page to a _read key previews the timeline but hides the driver’s acknowledge and resolve buttons.
The path on the wire stays POST /api/v1/oncall/<op>; the full endpoint, scope, and field reference is the On-Call API reference.
Calling the API directly
Everything the hub does is a POST your scheduler can make verbatim. The first call below resolves a rotation; the On-Call API reference carries the per-endpoint field tables, and the worked sequence under it chains two calls into an actual page.at to resolve for the current instant. Backdate it to audit who held the pager when an alert fired — the window math is deterministic, so a replayed resolve returns the historically correct shift.
data.on_call as the member to page right now and data.next_on_call as the member who takes over at data.next_handoff_at. The shift_start / shift_end pair brackets the current shift exactly, so a due-at calculation never needs timezone math.
Escalate, then page
The worked sequence: flatten a policy with/escalation/plan (read scope), then fan the first due page out through Messaging (write scope) on the channels the plan names.
1
Plan the escalation
Send the policy definition (a Each row gives you the step, the resolved targets, and the channels to page — the exact fan-out list for the send below. Rotation targets re-resolve at each page’s
users step targeting a fixed member list reads as a responses row in the API console) and read the flattened pages[] timeline back:Responses shape — plan
fire_at, so a hand-off mid-escalation still reaches the right member.2
Send the page through Messaging
Pass each resolved target as See Send an SMS for the full send contract.
to in a POST /api/v1/messages/sms send. The send exits through the same Messaging pipeline as the rest of your traffic — your sender ids, quiet-hours policy, and delivery webhooks apply.cURL
Python
Pager hand-off — a worked example
The chain below pages the current on-call member over push and SMS within the first minute, falls to a named backup over voice after five minutes if nobody acknowledges, and repeats the loop once. Distinct responders touch the incident at distinct offsets — that is the hand-off.- Open. Your alert source (a health check, an SLO alarm, a tenant-defined trigger) opens the incident:
status: "open",pages_fired: 0,started_atset. Nothing pages yet. - First page. At offset 0 a tick reports step 0 due, with the
rotationtarget resolved at that instant — the current on-call member — and channels["push", "sms"]. Your dispatcher fans the page out through the Messages API on those channels. - Hand off to the fallback. No
acklands within the 300-second window, so a tick at offset 300 reports step 1 due —usr_9over["voice"]. Voice is the fallback channel on purpose: a call cuts through a muted phone in a way a text does not. - Acknowledge anywhere. The responder acknowledges at any offset. Your driver calls
/incident/transitionwithack { by }; the returned snapshot flips toacknowledgedand every later tick returnsdue_pages: [],next_tick_at: null. - Repeat round. If the first round fires every page and nobody acknowledges,
repeat: 1loops the policy once more — the rotation re-resolves at each fire instant, so a hand-off mid-incident still pages the right member. At the end of all roundstickreportsstatus: "exhausted".
Where agent distress lands
On-call accepts event sources, not just timers. One source you already have: the agent distress alert model defines the softphone panic button, which flips a live call into recorded state and raises a supervisor alert. A dispatch rule turns that alert into a page: the rule you call on the alert is the same escalation policy you preview in the dashboard, so “page the supervisor on shift” is the rotation step from the example above. Define the alert-to-incident mapping in your dispatcher; the On-Call API evaluates the rest. Subscribe to delivery status so a page that never landed is distinguishable from a responder who never acknowledged, before the step window elapses.Try it end-to-end in test mode
Rehearse the lifecycle from the dashboard with a signed-in test run. Sequence matters, not speed — walk every phase.- Rotate. Define a rotation with two members, a weekly cadence, and today’s anchor. Resolve it with and without a time set, and confirm
member[0]is the notional holder when the anchor is in the future. - Plan. Build the two-step policy from the example above, keeping
repeat: 1. Confirm the table lists four pages: round 0 offsets 0 and 300, round 1 offsets 900 and 1500. - Open incident. In the incident driver set an optional incident id and the current time, then Open incident. Verify the status badge flips to
OPENand the due list names step 0’s channels. - Ack. Call Acknowledge. Confirm the badge flips to
ACKNOWLEDGEDand every later tick returns an empty due list with no next wake-up. - Resolve. Call Resolve against the acknowledged incident. Confirm the badge flips to
RESOLVEDand the driver stops — the lifecycle is terminal. - Negative paths. Acknowledge the resolved incident and confirm the
409 incident_transition_invaliderror. Reassign a resolved incident and confirm the same. Then open a fresh incident and call Reassign on it: the timeline restarts from step 0 under the new policy — the supported override.
See also
- On-call alerting guide — the endpoint-by-endpoint build with curl samples
- On-call escalation runbook — tuning timeouts, repeat, channels, and threshold defaults
- Escalation model concept page — the design rationale
- Agent distress alert model — the alert source this workflow can dispatch
- On-Call API reference — endpoint, scope, and field reference with per-language samples
- Messages API — the send surface that actually pages a resolved target
- Webhooks — delivery status for pages you sent