Uptimeify Docs
Incident management

Schedules

List, read, create and delete Incident Management on-call schedules, and how a schedule's rotation cadence works.

A schedule belongs to one team and one of its escalation tiers. Its timezone, validity range, weekly windows, rotation cadence and rotation groups decide who is on shift when. A background worker turns that definition into concrete shifts up to 90 days ahead; paging, Who Is On Call and the team calendar read those shifts. These endpoints manage the definition, not the shifts.

Configure the rotation with Update a schedule, or create a fully configured schedule in one call with Add a schedule to a tier. Preview a schedule shows the resulting shifts.

Authentication

Base IM access: an IM-eligible role (admin, editor or responder) or an organization-wide API token, and Incident Management activated for the organization. Listing and reading are open to any caller with that access. Creating and deleting need the team write bar for the schedule's team: organization admin role, or team admin. An API token runs with the role of the user who created it, so only a token created by an organization admin passes.

List schedules

GET /api/im/schedules

Returns every schedule of your organization, ordered by name.

Query Parameters

ParameterTypeDefaultDescription
envelopestringnoneitems: answer as { items, total, page, perPage }. Becomes the default on 2027-01-18.

Example (cURL)

curl -X GET "$BASE_URL/api/im/schedules?envelope=items" \
  -H "Authorization: Bearer $TOKEN"

Response

200 OK

{
  "items": [
    {
      "id": 7,
      "organizationId": 1,
      "teamId": 3,
      "teamName": "Platform Team",
      "name": "Primary On-Call",
      "timezone": "Europe/Berlin",
      "tierId": 21,
      "createdAt": "2026-06-02T08:00:00.000Z",
      "updatedAt": "2026-09-14T10:12:00.000Z"
    }
  ],
  "total": 1,
  "page": 1,
  "perPage": 1
}

List form: with envelope=items the list arrives as { items, total, page, perPage }. Without it the endpoint still answers the current form (a bare array of the same schedules), which is deprecated; { items, ... } becomes the default on 2027-01-18.

Get a schedule

GET /api/im/schedules/:id

Returns the full schedule configuration, its team and its overrides (same item shape as Schedule Overrides). rotations lists the rotation groups with their members (with userImage), in the same shape as schedules[].rotations of Get a tier; they are also part of the team's escalation chain.

Example (cURL)

curl -X GET "$BASE_URL/api/im/schedules/7" \
  -H "Authorization: Bearer $TOKEN"

Response

200 OK

{
  "id": 7,
  "organizationId": 1,
  "teamId": 3,
  "tierId": 21,
  "name": "Primary On-Call",
  "timezone": "Europe/Berlin",
  "effectiveFrom": null,
  "effectiveUntil": null,
  "weeklySchedules": [],
  "rotationMode": "explicit",
  "rotationRepeats": "weekly",
  "customRepeatUnit": null,
  "customRepeatValue": null,
  "autoRotationSize": null,
  "roundRobinSize": 1,
  "roundRobinCursor": 4,
  "startsOnDayOfWeek": 1,
  "startsOnDateOfMonth": null,
  "startsOnTime": "09:00",
  "createdAt": "2026-06-02T08:00:00.000Z",
  "updatedAt": "2026-09-14T10:12:00.000Z",
  "team": { "id": 3, "name": "Platform Team" },
  "overrides": [],
  "rotations": [
    {
      "id": 31,
      "rotationOrder": 1,
      "members": [
        { "userId": "usr_abc", "userName": "Alex Example", "userImage": null, "memberOrder": 1 }
      ]
    }
  ]
}

roundRobinCursor is an internal counter for round-robin paging and cannot be set.

Create a schedule

POST /api/im/schedules

Creates an empty schedule under a tier: 24/7, rotationMode: "none", no rotation groups. It pages nobody until you add rotation groups with Update a schedule.

Request Body

FieldTypeRequiredDescription
teamIdnumberYesThe owning team. Must belong to your organization.
tierIdnumberYesA tier of that team.
namestringYes1 to 120 characters after trimming.
timezonestringYesIANA zone (e.g. Europe/Berlin). Every handover and weekly window is evaluated in this zone, across DST.

Example (cURL)

curl -X POST "$BASE_URL/api/im/schedules" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "teamId": 3, "tierId": 21, "name": "Primary On-Call", "timezone": "Europe/Berlin" }'

Response

200 OK: the new schedule, same fields as Get a schedule without team and overrides.

Delete a schedule

DELETE /api/im/schedules/:id

Deletes the schedule with its rotation groups, overrides and shifts.

Example (cURL)

curl -X DELETE "$BASE_URL/api/im/schedules/7" \
  -H "Authorization: Bearer $TOKEN"

Response

200 OK

{ "success": true }

Rotation cadence

The cadence decides how often on-call hands over. It is set with Update a schedule or when adding a schedule to a tier.

FieldTypeDescription
rotationModestringnone (one continuous shift, nobody hands over), auto (the member pool is split into groups automatically) or explicit (you define the groups). Default none.
rotationRepeatsstring | nulldaily, weekly, biweekly, monthly or custom. Must be null for none, required otherwise.
customRepeatUnitstring | nullRequired for custom: minutes, hours, days, weeks or months.
customRepeatValueinteger | nullRequired for custom: 1 or more, in the unit above.
autoRotationSizeinteger | nullRequired for auto: members per automatically built group, 1 or more.
roundRobinSizeintegerHow many rotation members are on call at the same time, 1 or more. Default 1.
startsOnTimestring | null"HH:mm", time of day of the handover in the schedule's timezone. Required unless the mode is none.
startsOnDayOfWeekinteger | nullISO weekday (1 = Monday to 7 = Sunday). Required for weekly, biweekly and custom with weeks.
startsOnDateOfMonthinteger | null1 to 31, clamped to the month's last day. Required for monthly and custom with months.

The shortest possible shift is one minute (customRepeatUnit: "minutes", customRepeatValue: 1). Handover times are minute-precise at every cadence.

Sub-day cadences (minutes, hours) step in absolute time rather than wall-clock time. Across a DST switch they keep handing over every N minutes in real time instead of duplicating or skipping an hour of handovers.

How far ahead shifts are materialized

Shifts are materialized on a rolling horizon of up to 90 days. A fast cadence is materialized less far ahead, because the number of shift rows is the horizon divided by the cadence: a one-minute rotation over 90 days would be 129,600 shifts per member. Such a schedule is kept roughly 41 hours ahead instead, topped up every hour.

This is not a coverage limit. Paging reads the shift that is current now, and the materializer runs far more often than the horizon shrinks. Only a preview far into the future is shorter for a fast cadence. Every cadence of an hour or longer keeps the full 90 days.

Common errors

  • 401 Unauthorized (unauthorized) when not authenticated
  • 403 Forbidden (imAccessDenied) for a customer-scoped token, or a session without an IM-eligible role
  • 403 Forbidden (imNotEnabled) when Incident Management is not activated for the organization
  • 403 Forbidden (imTeamWriteDenied) on create or delete when you are neither organization admin nor team admin of the team
  • 404 Not Found (imScheduleNotFound) when :id does not exist or belongs to another organization
  • 404 Not Found (imTeamNotFound) on create when teamId does not exist or belongs to another organization
  • 400 Bad Request (invalidRequestBody) when :id is not a positive integer, or on create when teamId or tierId is missing or not a positive integer, tierId is not a tier of teamId, name is missing or longer than 120 characters, or timezone is missing or not a valid IANA zone

On this page