Uptimeify Docs
Incident management

Escalation Tiers

Read and edit a team's escalation chain: ordered tiers, their auto-escalation and repeat settings, and the schedules under each tier.

A team's escalation chain is an ordered list of tiers. Tier 1 is paged first; the people on call in a tier are whoever the tier's schedules have on shift right now. Each tier decides whether and when the incident moves on to the next tier, and how often the tier is paged again first. Whole-chain repeats live on the team (Update a team).

Authentication

Base IM access: an IM-eligible role or an organization-wide API token, and Incident Management activated for the organization. Reading the chain is open to any caller with that access. Every write needs the team write bar: organization admin role, or team admin of this team. An API token runs with the role of the user who created it, so only a token created by an organization admin passes.

Tier fields

FieldTypeDescription
tierOrderintegerPosition in the chain, 1 = paged first. Changed only through Reorder.
autoEscalationEnabledbooleanWhether the incident moves on to the next tier automatically. Default true.
autoEscalationAfterMinutesintegerMinutes before it moves on, 0 or more. Default 5.
autoEscalationStopModestringacknowledged or resolved: the incident state that stops the escalation. Default acknowledged.
autoEscalationSeveritiesarray | nullSeverities that escalate automatically: a subset of critical, warning, minor. null = all.
autoEscalationTimeFiltersarrayWeekly windows in which auto-escalation may fire, up to 50, each { from: "HH:mm", until: "HH:mm", days: number[] } with ISO weekdays (1 = Monday). until may be "24:00". [] = always.
repeatsintegerHow many more times this tier is paged before moving on, 0 or more. Default 0.
repeatsAfterMinutesinteger | nullMinutes between those repeats. null = use autoEscalationAfterMinutes.
repeatsStopModestringacknowledged or resolved: the incident state that stops the repeats. Default acknowledged.

Read the escalation chain

GET /api/im/teams/:id/escalations

Returns all tiers in order, each with its schedules, rotation groups and members, plus the team's escalation settings.

Example (cURL)

curl -X GET "$BASE_URL/api/im/teams/3/escalations" \
  -H "Authorization: Bearer $TOKEN"

Response

200 OK

{
  "tiers": [
    {
      "id": 21,
      "tierOrder": 1,
      "autoEscalationEnabled": true,
      "autoEscalationAfterMinutes": 5,
      "autoEscalationStopMode": "acknowledged",
      "autoEscalationSeverities": null,
      "autoEscalationTimeFilters": [],
      "repeats": 0,
      "repeatsAfterMinutes": null,
      "repeatsStopMode": "acknowledged",
      "schedules": [
        {
          "id": 7,
          "displayName": "Primary On-Call",
          "timezone": "Europe/Berlin",
          "effectiveFrom": null,
          "effectiveUntil": null,
          "weeklySchedules": [],
          "rotationMode": "explicit",
          "rotationRepeats": "weekly",
          "customRepeatUnit": null,
          "customRepeatValue": null,
          "autoRotationSize": null,
          "roundRobinSize": 1,
          "startsOnDayOfWeek": 1,
          "startsOnDateOfMonth": null,
          "startsOnTime": "09:00",
          "rotations": [
            {
              "id": 12,
              "rotationOrder": 1,
              "members": [
                { "userId": "u_abc123", "userName": "Ada Lovelace", "userImage": null, "memberOrder": 1 }
              ]
            }
          ]
        }
      ]
    }
  ],
  "teamSettings": {
    "timezone": "Europe/Berlin",
    "escalationRepeats": 1,
    "escalationRepeatsAfterMinutes": 15,
    "escalationRepeatsStopMode": "acknowledged",
    "engagementReportEnabled": false,
    "engagementReportDayOfWeek": null,
    "engagementReportTime": null
  }
}

The schedule fields are explained under Rotation cadence and Update a schedule.

Add a tier

POST /api/im/teams/:id/tiers

Appends a tier at the end of the chain (tierOrder = highest + 1) with the default settings from the table above. In the same step it creates one schedule under the tier: named Tier N schedule, 24/7, rotationMode: "none", in the team's timezone (or UTC if the team has none), with one rotation group holding the given members in the given order.

Request Body

FieldTypeRequiredDescription
memberUserIdsstring[]Yes1 to 200 distinct user ids, all members of this team.

Example (cURL)

curl -X POST "$BASE_URL/api/im/teams/3/tiers" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "memberUserIds": ["u_abc123", "u_def456"] }'

Response

200 OK: the tier fields plus schedules, holding the one new schedule in the same shape as in the escalation chain (members without userImage).

{
  "id": 22,
  "tierOrder": 2,
  "autoEscalationEnabled": true,
  "autoEscalationAfterMinutes": 5,
  "autoEscalationStopMode": "acknowledged",
  "autoEscalationSeverities": null,
  "autoEscalationTimeFilters": [],
  "repeats": 0,
  "repeatsAfterMinutes": null,
  "repeatsStopMode": "acknowledged",
  "schedules": [
    {
      "id": 8,
      "displayName": "Tier 2 schedule",
      "timezone": "Europe/Berlin",
      "effectiveFrom": null,
      "effectiveUntil": null,
      "weeklySchedules": [],
      "rotationMode": "none",
      "rotationRepeats": null,
      "customRepeatUnit": null,
      "customRepeatValue": null,
      "autoRotationSize": null,
      "roundRobinSize": 1,
      "startsOnDayOfWeek": null,
      "startsOnDateOfMonth": null,
      "startsOnTime": null,
      "rotations": [
        {
          "id": 14,
          "rotationOrder": 1,
          "members": [
            { "userId": "u_abc123", "userName": "Ada Lovelace", "memberOrder": 1 },
            { "userId": "u_def456", "userName": "Bob Fixit", "memberOrder": 2 }
          ]
        }
      ]
    }
  ]
}

Update a tier

PATCH /api/im/teams/:id/tiers/:tierId

Every field from the tier fields table except tierOrder is optional and patchable. Only fields present in the body change.

Example (cURL)

curl -X PATCH "$BASE_URL/api/im/teams/3/tiers/21" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "autoEscalationAfterMinutes": 10,
    "autoEscalationSeverities": ["critical"],
    "autoEscalationTimeFilters": [{ "from": "18:00", "until": "08:00", "days": [1, 2, 3, 4, 5] }]
  }'

Response

200 OK: the tier fields after the update (without schedules).

Delete a tier

DELETE /api/im/teams/:id/tiers/:tierId

Deletes the tier together with its schedules, rotation groups and shifts. The remaining tiers keep their tierOrder, so deleting tier 2 of 3 leaves orders 1 and 3. Close the gap with Reorder if you need contiguous numbers.

Example (cURL)

curl -X DELETE "$BASE_URL/api/im/teams/3/tiers/22" \
  -H "Authorization: Bearer $TOKEN"

Response

200 OK

{ "success": true }

Reorder tiers

POST /api/im/teams/:id/tiers/reorder

Renumbers the chain to 1..n in the order you send.

Request Body

FieldTypeRequiredDescription
tierIdsnumber[]YesEvery tier id of this team exactly once, in the new order.

Example (cURL)

curl -X POST "$BASE_URL/api/im/teams/3/tiers/reorder" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "tierIds": [22, 21] }'

Response

200 OK

{ "tiers": [{ "id": 22, "tierOrder": 1 }, { "id": 21, "tierOrder": 2 }] }

Add a schedule to a tier

POST /api/im/teams/:id/tiers/:tierId/schedules

Creates a further schedule under a tier, for example a follow-the-sun schedule in another timezone, with its cadence and rotation groups in one call. The tier's on-call set is the union of what all its schedules have on shift.

Request Body

FieldTypeRequiredDescription
namestringYes1 to 120 characters after trimming.
timezonestringYesIANA zone the schedule is evaluated in.
effectiveFromstring | nullNoISO timestamp before which the schedule pages nobody.
effectiveUntilstring | nullNoISO timestamp after which the schedule pages nobody.
weeklySchedulesarrayNoOn-call windows, same shape as autoEscalationTimeFilters. Omitted or [] = 24/7.
rotationsarrayNoRotation groups, up to 50, each { members: string[] } with up to 200 distinct members of this team. Array order is rotation order.

Plus the cadence fields from Rotation cadence. Omitted cadence fields default to rotationMode: "none", roundRobinSize: 1, everything else null. The resulting cadence is validated as a whole.

Example (cURL)

curl -X POST "$BASE_URL/api/im/teams/3/tiers/21/schedules" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "APAC Follow-the-Sun",
    "timezone": "Asia/Singapore",
    "weeklySchedules": [{ "from": "09:00", "until": "18:00", "days": [1, 2, 3, 4, 5] }],
    "rotationMode": "explicit",
    "rotationRepeats": "weekly",
    "startsOnDayOfWeek": 1,
    "startsOnTime": "09:00",
    "rotations": [{ "members": ["u_abc123"] }, { "members": ["u_def456"] }]
  }'

Response

200 OK: the new schedule in the same shape as in the escalation chain (members without userImage).

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 any write when you are neither organization admin nor team admin of this team
  • 404 Not Found (imTeamNotFound) when the team does not exist or belongs to another organization
  • 404 Not Found (imEscalationTierNotFound) when :tierId is not a tier of this team
  • 404 Not Found (imTeamMemberNotFound) when a user id in memberUserIds or rotations is not a member of this team
  • 400 Bad Request (invalidRequestBody) when a path id is not a positive integer, memberUserIds is missing, empty or holds an empty id, tierIds is missing, empty, or not distinct positive integers, name or timezone is missing or invalid, effectiveFrom/effectiveUntil is not a valid timestamp, or rotations is malformed
  • 422 Unprocessable Entity (imTierReorderMismatch) when tierIds is not exactly this team's set of tier ids
  • 422 Unprocessable Entity (imInvalidRequestBody) when autoEscalationEnabled is not a boolean
  • 422 Unprocessable Entity (imInvalidNumber) when autoEscalationAfterMinutes, repeats or repeatsAfterMinutes is not an integer of 0 or more, or a cadence number is not an integer of 1 or more
  • 422 Unprocessable Entity (imInvalidStopMode) when a stop mode is not acknowledged or resolved
  • 422 Unprocessable Entity (imInvalidSeverities) when autoEscalationSeverities is neither null nor a list of critical, warning, minor
  • 422 Unprocessable Entity (imInvalidTimeFilter) when a window list is not an array, has more than 50 entries, or an entry is not an object or has no days array
  • 422 Unprocessable Entity (imInvalidTimeOfDay) when a window's from/until or startsOnTime is not "HH:mm"
  • 422 Unprocessable Entity (imInvalidDayOfWeek) when a window day or startsOnDayOfWeek is not 1 to 7
  • 422 Unprocessable Entity (imInvalidRotationMode) when rotationMode is not none, auto or explicit
  • 422 Unprocessable Entity (imInvalidRotation) when the cadence does not hold together, a list exceeds 200 members or 50 rotation groups, or a user id appears twice in one list
  • 409 Conflict (imTierOrderConflict) when two tiers were added at the same moment; retry

On this page