Incident alerting comes down to three primitives, the same ones every PagerDuty-style tool is built on: a rotation that answers "who is on call right now," an escalation policy that answers "who gets paged next if nobody responds," and an incident that travels open → acknowledged → resolved (or exhausted when nobody ever responds). Devotel Orbit ships these as four compute endpoints over the channels you already run — push, SMS, voice, email — so an alerting path lives on the same account as the rest of your messaging instead of a second vendor. The On-Call API shipped in June with the endpoint reference and docs guides landing since, but it had zero blog coverage, so this explainer is its announcement of record: what each primitive is, how the pure-compute shape works, and the tenant-owned controls around it.
The three primitives
Rotation. An ordered members list plus a shift cadence — daily (24-hour shifts), weekly (7-day shifts), or custom with an explicit shift_length_seconds — anchored to an absolute ISO instant. Anchoring to an instant rather than a "every Monday 09:00" calendar string is what keeps the math DST-proof: you pick the first hand-off once, in whatever timezone you like, and every hand-off after that is exactly one shift length later. Members are opaque strings — E.164 numbers, email addresses, push tokens, your own user ids — the engine picks which one, never interprets the value. Before the anchor, member one holds the notional shift so a query that lands early is never pager-less; a backdated at returns the historically correct holder, which is how you answer "who was on call when this fired."
Escalation policy. An ordered list of steps. Each step names a target (a live rotation, resolved at page time, or a fixed users list), the channels to page (push and SMS early, voice as the fallback that cuts through a muted phone), and escalate_after_seconds — how long to wait for an acknowledgement before the next step loads, five to fifteen minutes being the usual band. repeat (0–10) loops the whole policy when nobody ever acknowledges.
Incident. One occurrence of something that needs a human: a snapshot with its policy, started_at, current status, and a pages_fired high-water mark. Because the timeline fires in strictly increasing order, one integer is a complete progress record — replaying a tick with a stale snapshot re-returns the same due pages, never a double page.
The four endpoints
- `POST /api/v1/oncall/resolve` — who is on call for a rotation, now or at a given instant, with the current shift window and the next hand-off.
- `POST /api/v1/oncall/escalation/plan` — the full page timeline up front: every page's round, step, offset,
fire_at, targets, and channels, plus the total page count. Preview it before an incident depends on it — the dashboard's Voice → On-call & escalation page runs the same preview. - `POST /api/v1/oncall/incident/tick` — what's due now: the pages to send, the new high-water mark to persist, and
next_tick_at. An acknowledged or resolved incident returns an empty list and a null next-tick, so your scheduler stands down. - `POST /api/v1/oncall/incident/transition` — apply
ack,resolve, orreassign(the one override path: substitute a broader policy mid-incident and the timeline restarts from step 0). Invalid transitions come back409instead of silently corrupting your snapshot.
Every one is pure compute over the request body: no rotation registry, no stored policy, no hidden cron on Orbit's side. That is the deliberate split — the engine never touches a provider and never sends; the page itself exits through the Messages API, where your sender ids, quiet-hours policy, and delivery webhooks apply exactly as they do to any other send. You own the incident record; the engine answers questions about it. Subscribe to delivery status so "the page never landed" is distinguishable from "they never acknowledged" before the step window elapses.
Tenant-owned thresholds
Three knobs tune the alarm:
- `escalate_after_seconds` per step — the acknowledgement window. Too short trains responders to ignore pages that already escalated; too long burns MTTR on a missed primary.
- `repeat` — the policy-level cooldown. What to do when the whole chain fires and nobody answers: re-run the chain instead of going silent.
- Exhaustion handling — when every page across every round has fired with no
ack,tickreportsexhaustedwith a null next-tick. Treat exhaustion as its own alert — page a fallback channel or open a ticket — rather than keep a scheduler awake on a null next-tick. That terminal signal is what an intentionally silenced alarm still owes you: either it acknowledges, or it surfaces as exhausted.
Why one account beats a second vendor
Teams that run on-call on a dedicated incident tool accept a split-bill arrangement: the alerting vendor on one invoice, the channels underneath on another. On Devotel Orbit the pages ride the same channels and credits as the rest of your messaging, per-message like any other send, and the full rotation/policy definition travels in the request. The vendor-versus-vendor discussion frames the ecosystem comparison in general terms; the math here is simpler: one account, one usage record, and a paging path you can rehearse end to end in test mode.
Frequently asked questions
Is the rotation registry stored on Orbit?
No. The rotation definition travels in the request body — the engine is pure compute and keeps no registry. You can fire a one-off resolve for a rotation that exists nowhere else.
What happens when the escalation policy runs out?
Once every page in plan has fired with no ack, tick reports status: "exhausted" and next_tick_at: null. Handle it as its own alert — page a fallback channel or open a ticket — rather than waking a scheduler for nothing.
How long should each step wait before escalating?
Five to fifteen minutes per step is the usual band. Shorter trains responders to ignore pages that have already escalated; longer burns MTTR when the primary misses. Tune per severity: Sev-1 chains typically sit at the short end.
Do pages ride my existing sender ids and quiet hours?
Yes. The actual page exits through the Messages API on the channels the step named, so your sender ids, quiet-hours policy, and delivery webhooks apply exactly as they do to any other send.
Where to go next
The on-call alerting guide is the endpoint-by-endpoint build; the escalation model concept page is the design rationale; the roster & escalation runbook walks tuning thresholds and missed-primary behavior in detail; and the on-call deep dive maps the four dashboard components to the routes and closes with a six-step rehearsal you can run in test mode. The API reference pairs every endpoint with cURL, Python, and Go samples and walks the returned rows one by one.