On-call schedule reference
The full request schemas live in the auto-generated API Reference. This page is the human-readable cheat sheet.
Schedule
Section titled “Schedule”| Field | Type | Default | Description |
|---|---|---|---|
name | string | required | Schedule label, referenced from escalation levels. |
timezone | string | UTC | IANA timezone name stored on the schedule. Layer handoffs are interpreted in it; an unrecognized value falls back to UTC at resolution time. |
Created under /on_call_schedule/{schedule_id}/layer.
| Field | Type | Default | Description |
|---|---|---|---|
layer_number | int | max(existing) + 1 | Layer position. Layers with a higher layer_number are evaluated first and shadow lower ones during their effective windows. |
rotation_type | enum | required | daily, weekly, or custom. |
rotation_interval_days | int | none | Days per handoff. Required for custom (a custom layer without it never resolves). Ignored for daily / weekly. |
handoff_time | string | required | HH:MM (24-hour) handoff time, interpreted in the schedule’s timezone. Anchors the rotation. |
handoff_day | int | none | Weekly layers only: weekday of the handoff, 0=Sunday .. 6=Saturday, in the schedule’s timezone. Values outside 0..6 are rejected at creation. Ignored for daily / custom. |
participants | uuid[] | required | Ordered user list. The rotation walks it and wraps around. A layer with no participants never matches. |
effective_from | rfc3339 | none | Layer applies only from this instant. |
effective_until | rfc3339 | none | Layer stops applying at this instant. |
Rotation periods:
rotation_type | Period |
|---|---|
daily | 24 hours per participant. |
weekly | 7 days per participant. |
custom | rotation_interval_days days per participant. |
Override
Section titled “Override”Created under /on_call_schedule/{schedule_id}/override. An override is a hard “this user is on call” window that beats every layer.
| Field | Type | Description |
|---|---|---|
user_id | uuid | The covering user. |
start_at | rfc3339 | Window start (inclusive). |
end_at | rfc3339 | Window end (exclusive). |
How “who’s on call at time T” is resolved
Section titled “How “who’s on call at time T” is resolved”- Overrides first. If any override covers
T, that user is on call. When overrides overlap, the most recently created one wins. - Layers next, highest
layer_numberfirst. A layer is skipped when it has no participants orTis outside itseffective_from/effective_untilwindow. - For the first matching layer, the on-call participant is computed from the number of full rotation periods since the layer’s anchor handoff, wrapped around
participants. The anchor is the layer’s start date (itseffective_from, else its creation date) athandoff_timein the schedule’s timezone; periods are counted in local calendar days, so handoffs stay athandoff_timelocal across DST changes. - A weekly layer with a
handoff_dayanchors on that weekday instead: coverage starts immediately ateffective_from(the first participant serves a shortened first stint) and every handoff lands on the configured weekday athandoff_time. - If nothing matches, the schedule has a coverage gap and resolves to no one.
Endpoints
Section titled “Endpoints”| Method | Path | Purpose |
|---|---|---|
POST / GET | /on_call_schedule | Create / list schedules. |
GET / PUT / DELETE | /on_call_schedule/{schedule_id} | Detail (with layers + overrides) / update / delete. |
POST / GET | /on_call_schedule/{schedule_id}/layer | Create / list layers. |
DELETE | /on_call_schedule/{schedule_id}/layer/{layer_id} | Delete a layer. |
POST / GET | /on_call_schedule/{schedule_id}/override | Create / list overrides. |
DELETE | /on_call_schedule/{schedule_id}/override/{override_id} | Delete an override. |
Layers and overrides have no update endpoint: delete and recreate to change one.
See also
Section titled “See also”- On-call overview for patterns (follow-the-sun, primary + secondary).
- Rotation overrides for holiday cover and swaps.
- Escalation policy reference for wiring schedules into paging.