Skip to content

On-call schedule reference

The full request schemas live in the auto-generated API Reference. This page is the human-readable cheat sheet.

FieldTypeDefaultDescription
namestringrequiredSchedule label, referenced from escalation levels.
timezonestringUTCIANA 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.

FieldTypeDefaultDescription
layer_numberintmax(existing) + 1Layer position. Layers with a higher layer_number are evaluated first and shadow lower ones during their effective windows.
rotation_typeenumrequireddaily, weekly, or custom.
rotation_interval_daysintnoneDays per handoff. Required for custom (a custom layer without it never resolves). Ignored for daily / weekly.
handoff_timestringrequiredHH:MM (24-hour) handoff time, interpreted in the schedule’s timezone. Anchors the rotation.
handoff_dayintnoneWeekly 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.
participantsuuid[]requiredOrdered user list. The rotation walks it and wraps around. A layer with no participants never matches.
effective_fromrfc3339noneLayer applies only from this instant.
effective_untilrfc3339noneLayer stops applying at this instant.

Rotation periods:

rotation_typePeriod
daily24 hours per participant.
weekly7 days per participant.
customrotation_interval_days days per participant.

Created under /on_call_schedule/{schedule_id}/override. An override is a hard “this user is on call” window that beats every layer.

FieldTypeDescription
user_iduuidThe covering user.
start_atrfc3339Window start (inclusive).
end_atrfc3339Window end (exclusive).

How “who’s on call at time T” is resolved

Section titled “How “who’s on call at time T” is resolved”
  1. Overrides first. If any override covers T, that user is on call. When overrides overlap, the most recently created one wins.
  2. Layers next, highest layer_number first. A layer is skipped when it has no participants or T is outside its effective_from / effective_until window.
  3. 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 (its effective_from, else its creation date) at handoff_time in the schedule’s timezone; periods are counted in local calendar days, so handoffs stay at handoff_time local across DST changes.
  4. A weekly layer with a handoff_day anchors on that weekday instead: coverage starts immediately at effective_from (the first participant serves a shortened first stint) and every handoff lands on the configured weekday at handoff_time.
  5. If nothing matches, the schedule has a coverage gap and resolves to no one.
MethodPathPurpose
POST / GET/on_call_scheduleCreate / list schedules.
GET / PUT / DELETE/on_call_schedule/{schedule_id}Detail (with layers + overrides) / update / delete.
POST / GET/on_call_schedule/{schedule_id}/layerCreate / list layers.
DELETE/on_call_schedule/{schedule_id}/layer/{layer_id}Delete a layer.
POST / GET/on_call_schedule/{schedule_id}/overrideCreate / 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.