> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# On-call deep dive: from dashboard hub to a working pager

> Set up a rotation and escalation policy in the dashboard's on-call hub, drive the route-group API, hand the pager off between responders, catch agent distress alerts, and rehearse the full open → ack → resolve lifecycle with a test alert.

# 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](/guides/oncall-alerting) for the endpoint-by-endpoint build and the [escalation runbook](/guides/oncall-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.

<Note>
  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](/api-reference/endpoints/messaging), where your sender ids, quiet-hours policy, and delivery webhooks apply exactly as they do to any other send.
</Note>

## 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:

| Component               | What it runs                                                                      | What you read out of it                                                                                                                                                                                                                                                                   |
| ----------------------- | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Who's on call**       | `POST /api/v1/oncall/resolve`                                                     | The rotation form returns the current on-call member, the shift window, the next member, and the next hand-off instant. Setting a "Resolve at" time replays the rotation at any instant — the way to verify a roster before it goes live, or to answer "who was on call when this fired." |
| **Escalation timeline** | `POST /api/v1/oncall/escalation/plan`                                             | The policy form adds steps (a rotation or a fixed member list as the target, the channels to page, an acknowledge window) and returns the flattened timeline: every page's round, step, offset, fire instant, targets, and channels. Preview it before an incident depends on it.         |
| **Incident driver**     | `POST /api/v1/oncall/incident/tick` and `POST /api/v1/oncall/incident/transition` | A live test incident you can advance, acknowledge, resolve, and reassign — a status badge, the pages-due list, and the next wake-up instant on every step.                                                                                                                                |

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](/api-reference/oncall).

## 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](/guides/oncall-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](/concepts/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

* [On-call alerting guide](/guides/oncall-alerting) — the endpoint-by-endpoint build with curl samples
* [On-call escalation runbook](/guides/oncall-escalation-runbook) — tuning timeouts, repeat, channels, and threshold defaults
* [Escalation model concept page](/concepts/oncall-escalation-model) — the design rationale
* [Agent distress alert model](/concepts/agent-distress-alert-model) — the alert source this workflow can dispatch
* [On-Call API reference](/api-reference/oncall) — endpoint, scope, and field reference
* [Messages API](/api-reference/endpoints/messaging) — the send surface that actually pages a resolved target
* [Webhooks](/webhooks/overview) — delivery status for pages you sent
