Skip to main content

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 the POST /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:
  1. 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. Backdate at to audit who held the pager at an arbitrary instant.
  2. Policies (/escalation/plan). Chain steps (rotation or users targets) with an acknowledge window (escalate_after_seconds, default 300) per step and a policy-level repeat loop. The plan response hands you absolute fire_at offsets you can schedule against — the timeline an incident driver walks.
  3. Tick (/incident/tick). Drive a live incident on your own timer: pass the snapshot, receive the pages due now, the new pages_fired high-water mark to persist, and next_tick_at. A halted (acknowledged or resolved) incident returns due_pages: [] and next_tick_at: null, so your scheduler stands down.
  4. Transition (/incident/transition). Apply ack, resolve, or reassign. Invalid transitions — acknowledging a resolved incident, or reassigning after resolution — answer 409 incident_transition_invalid rather than corrupting your state.
Read roles (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.

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.
  1. Open. Your alert source (a health check, an SLO alarm, a tenant-defined trigger) opens the incident: status: "open", pages_fired: 0, started_at set. Nothing pages yet.
  2. First page. At offset 0 a tick reports step 0 due, with the rotation target 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.
  3. Hand off to the fallback. No ack lands within the 300-second window, so a tick at offset 300 reports step 1 due — usr_9 over ["voice"]. Voice is the fallback channel on purpose: a call cuts through a muted phone in a way a text does not.
  4. Acknowledge anywhere. The responder acknowledges at any offset. Your driver calls /incident/transition with ack { by }; the returned snapshot flips to acknowledged and every later tick returns due_pages: [], next_tick_at: null.
  5. Repeat round. If the first round fires every page and nobody acknowledges, repeat: 1 loops 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 rounds tick reports status: "exhausted".
The escalation runbook walks this same chain with the four-row timeline table and the offset arithmetic spelled out.

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.
  1. 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.
  2. 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.
  3. Open incident. In the incident driver set an optional incident id and the current time, then Open incident. Verify the status badge flips to OPEN and the due list names step 0’s channels.
  4. Ack. Call Acknowledge. Confirm the badge flips to ACKNOWLEDGED and every later tick returns an empty due list with no next wake-up.
  5. Resolve. Call Resolve against the acknowledged incident. Confirm the badge flips to RESOLVED and the driver stops — the lifecycle is terminal.
  6. Negative paths. Acknowledge the resolved incident and confirm the 409 incident_transition_invalid error. 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.
When the sequence runs clean against the dashboard, wire the same four endpoints into your scheduler and run the cycle against your own incident store.

See also