Skip to main content

Schedules and on-call

Set up a team's on-call schedule, see who is on call, and create overrides.

D
Written by Dave Rochwerger

Part of the Phoenix Alerts Management API reference.

Each team has one on-call schedule: an ordered rotation of members, a timezone, and a rotation start time. Phoenix Alerts uses the schedule to work out who's on call right now, and pages them when an alert escalates to that team.

Get a team's schedule

GET /v1/teams/{team_uuid}/schedule

Response (200):

{
"object": "team_schedule",
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"team": {
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"name": "Platform Team",
"key": "platform"
},
"timezone": "America/New_York",
"rotation_start_at": "2026-06-09T09:00:00.000-05:00",
"members": [],
"rotation": {"name": "Weekly"},
"current_on_call": null,
"next_handoff_at": null,
"created_at": "2026-06-12T00:00:00.000Z",
"updated_at": "2026-06-12T00:00:00.000Z"
}

Add ?expand=overrides to include upcoming overrides in the response.

Create or replace a schedule

PUT /v1/teams/{team_uuid}/schedule

Field

Type

Required

Notes

timezone

string

yes

IANA timezone, e.g. America/New_York.

rotation_start_at

string

yes

ISO-8601 datetime for the start of the first rotation period.

members

array

yes

Ordered list of user UUID strings. An empty array clears the schedule.

Example request body:

{
"timezone": "America/New_York",
"rotation_start_at": "2026-06-09T09:00:00.000-05:00",
"members": ["b2c3d4e5-f6a7-8901-bcde-f12345678901"]
}

This replaces the whole schedule — supply the full member list every time, not just the changes.

Who's on call right now

GET /v1/teams/{team_uuid}/on-call

Response (200):

{
"object": "on_call",
"team": {
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"name": "Platform Team",
"key": "platform"
},
"as_of_at": "2026-06-12T00:00:00.000Z",
"on_call_user": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"display_name": "Alice Example",
"jira_account_id": "abc123"
},
"source": "rotation",
"rotation": {"name": "Weekly"},
"override": null,
"shift_end": "2026-06-16T09:00:00.000-05:00"
}

Pass ?at=<ISO-8601 datetime> to check a different moment (up to 365 days from now, past or future). on_call_user is null when an override has skipped coverage or no schedule is configured.

To see who's on call across every team at once, use GET /v1/on-call — same shape, one entry per team.

Preview upcoming shifts

GET /v1/teams/{team_uuid}/on-call/preview?from=<ISO-8601>&to=<ISO-8601>

Returns the ordered list of shifts in that window. GET /v1/on-call/preview does the same across every team, with cursor pagination via ?cursor= and ?limit=.

Overrides (vacations, swaps)

An override temporarily replaces (or skips) whoever the rotation would normally put on call.

POST /v1/teams/{team_uuid}/schedule/overrides

Field

Type

Required

Notes

start_at

string

yes

ISO-8601 datetime with offset.

end_at

string

yes

ISO-8601 datetime with offset. Must be after start_at.

reason

string

yes

"VACATION", "SWAP", "UNAVAILABLE", or "OTHER".

replacement_user_uuid

string or null

no

Who covers instead. null skips coverage entirely — the alert escalates to the next step.

Example request body:

{
"start_at": "2026-06-14T09:00:00.000-05:00",
"end_at": "2026-06-21T09:00:00.000-05:00",
"reason": "VACATION",
"replacement_user_uuid": "d4e5f6a7-b8c9-0123-def0-123456789012"
}

Returns 409 if the window overlaps an existing override.

List overrides with GET /v1/teams/{team_uuid}/schedule/overrides (defaults to future and active ones; add ?include_past=true for history). Delete one with DELETE /v1/teams/{team_uuid}/schedule/overrides/{override_uuid}.

Did this answer your question?