Help center Rotation API

Learn how to interact with Rotation App programmatically using our REST API to get on-call users, assign users, and manage rotation queues.

Who can use the API?
  • All Slack workspace users with access to the rotation.
  • API authentication requires an API key that you can generate from the Home tab.

The Rotation App REST API provides developers with programmatic access to rotation data and controls. Use this API to build custom applications, scripts, and integrations that interact directly with your rotations through HTTP requests.

Example use cases:

  • Build monitoring dashboards that fetch current on-call users via API calls.
  • Create custom scheduling scripts that assign users based on complex business logic.
  • Integrate rotation data into existing applications and services (project management, incident management, etc.)
  • Develop automated tools that manage rotation queues programmatically instead of on a schedule.
  • Build custom incident management systems that query and update rotations.
Looking for other integration options?

Webhooks: Receive real-time event notifications when rotations change

• Developers: Build event-driven applications that react to rotation changes
• No-code: Connect with tools like Slack Workflows, Zapier, Make, or other webhook-compatible platforms

Slack Workflows: No-code automation directly within Slack

• Set up automated responses and notifications using Slack’s visual Workflow Builder

API Base URL and Authentication

All API requests should be made to:

https://api.rotation.app/v1/t/<team_id>/r/<rotation_id>/<action_type>

URL Parameters:

  • team_id: Your Slack workspace/team ID
  • rotation_id: The unique identifier of your rotation
  • action_type: The specific API action you want to perform

Authentication:

All API requests require authentication using an API key. Include your API key in the x-api-key header:

-H "x-api-key: YOUR_API_KEY"

Learn how to configure your API key

Finding Your Team and Rotation IDs

To use the API, you’ll need your team_id and rotation_id. Learn how to find these identifiers in our dedicated guide: Learn how to find your rotation and team IDs

Available API Actions

Read shifts:

Modify the queue:

Modify individual shifts:


Get Current Shift Assignees

Retrieve the list of users currently assigned to the rotation.

Endpoint: GET /v1/t/<team_id>/r/<rotation_id>/get_current_shift_assignees

Parameters: None required

Example Request:

curl -X GET "https://api.rotation.app/v1/t/T123456/r/ROTA123/get_current_shift_assignees" \
  -H "x-api-key: YOUR_API_KEY"

Response Format:

{
  "current_shift_user_ids": ["user_id_1", "user_id_2", "user_id_3"],
  "current_shift_user_ids_0": "user_id_1",
  "current_shift_user_ids_1": "user_id_2",
  "current_shift_user_ids_2": "user_id_3"
}

Response Fields:

  • current_shift_user_ids: Array of user IDs currently on call
  • current_shift_user_ids_<index>: Individual user ID at the specified index (provided for no-code tool compatibility)

Get Next Shift Assignees

Retrieve the list of users who will be assigned in the next shift.

Endpoint: GET /v1/t/<team_id>/r/<rotation_id>/get_next_shift_assignees

Parameters: None required

Example Request:

curl -X GET "https://api.rotation.app/v1/t/T123456/r/ROTA123/get_next_shift_assignees" \
  -H "x-api-key: YOUR_API_KEY"

Response Format:

{
  "next_shift_user_ids": ["user_id_1", "user_id_2", "user_id_3"],
  "next_shift_user_ids_0": "user_id_1",
  "next_shift_user_ids_1": "user_id_2",
  "next_shift_user_ids_2": "user_id_3"
}

Response Fields:

  • next_shift_user_ids: Array of user IDs assigned to the next shift
  • next_shift_user_ids_<index>: Individual user ID at the specified index (provided for no-code tool compatibility)

Get Other Shift Assignees

Retrieve the list of users assigned to future shifts (3rd, 4th, or 5th shift from now).

Available Endpoints:

  • GET /v1/t/<team_id>/r/<rotation_id>/get_shift_3_assignees - Third shift
  • GET /v1/t/<team_id>/r/<rotation_id>/get_shift_4_assignees - Fourth shift
  • GET /v1/t/<team_id>/r/<rotation_id>/get_shift_5_assignees - Fifth shift

Parameters: None required

Example Request:

curl -X GET "https://api.rotation.app/v1/t/T123456/r/ROTA123/get_shift_3_assignees" \
  -H "x-api-key: YOUR_API_KEY"

Response Format:

{
  "shift_3_user_ids": ["user_id_1", "user_id_2", "user_id_3"],
  "shift_3_user_ids_0": "user_id_1",
  "shift_3_user_ids_1": "user_id_2",
  "shift_3_user_ids_2": "user_id_3"
}

Response Fields:

  • shift_<N>_user_ids: Array of user IDs assigned to that shift
  • shift_<N>_user_ids_<index>: Individual user ID at the specified index (provided for no-code tool compatibility)

Assign Specific User

Assign a specific user to be on call for the rotation.

Endpoint: POST /v1/t/<team_id>/r/<rotation_id>/assign_user

Body Parameters:

  • user_id (required): The ID of the user to assign

Example Request:

curl -X POST "https://api.rotation.app/v1/t/T123456/r/ROTA123/assign_user" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"user_id": "user_id_1"}'

Response Format:

{
  "on_call_user_ids": ["user_id_1"],
  "on_call_user_ids_0": "user_id_1"
}

Response Fields:

  • on_call_user_ids: Updated array of user IDs now on call
  • on_call_user_ids_<index>: Individual user ID at the specified index

Assign Next User(s)

Assign the next user(s) in the rotation queue to be on call.

Endpoint: POST /v1/t/<team_id>/r/<rotation_id>/assign_next

Parameters: None required

Example Request:

curl -X POST "https://api.rotation.app/v1/t/T123456/r/ROTA123/assign_next" \
  -H "x-api-key: YOUR_API_KEY"

Response Format:

{
  "on_call_user_ids": ["user_id_1", "user_id_2", "user_id_3"],
  "on_call_user_ids_0": "user_id_1",
  "on_call_user_ids_1": "user_id_2",
  "on_call_user_ids_2": "user_id_3"
}

Response Fields:

  • on_call_user_ids: Updated array of user IDs now on call
  • on_call_user_ids_<index>: Individual user ID at the specified index

Shuffle Rotation Queue

Randomize the order of users in the rotation queue.

Endpoint: POST /v1/t/<team_id>/r/<rotation_id>/shuffle_rotation_queue

Body Parameters:

  • include_currently_on_call (optional): Boolean indicating whether currently on-call users should be included in the shuffle

Example Request:

curl -X POST "https://api.rotation.app/v1/t/T123456/r/ROTA123/shuffle_rotation_queue" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"include_currently_on_call": true}'

Response Format:

{
  "on_call_user_ids": ["user_id_1", "user_id_2", "user_id_3"],
  "on_call_user_ids_0": "user_id_1",
  "on_call_user_ids_1": "user_id_2",
  "on_call_user_ids_2": "user_id_3"
}

Response Fields:

  • on_call_user_ids: Updated array of user IDs now on call after shuffle
  • on_call_user_ids_<index>: Individual user ID at the specified index

Get Shifts

Retrieve a range of upcoming shifts with their dates and assignees. Useful for pushing the rotation to dashboards, calendars, or external scheduling tools.

Endpoint: GET /v1/t/<team_id>/r/<rotation_id>/get_shifts

Query Parameters:

  • from (optional): Inclusive lower bound. Either a date (YYYY-MM-DD) or a 1-based shift number ("1", "2", …). Defaults to shift 1 (the current shift).
  • to (optional): Inclusive upper bound, same format as from. Defaults to from + 29 (a 30-shift window). The maximum window size is 365 shifts.
  • verbose (optional): If true, each shift value is an object { "assignees": [...], "naturalAssignees": [...] } instead of a bare user ID, array, or null. Useful for seeing who the queue would have placed at a shift if there were no overrides.

Example Request:

curl -X GET "https://api.rotation.app/v1/t/T123456/r/ROTA123/get_shifts?from=2026-05-04&to=2026-05-08" \
  -H "x-api-key: YOUR_API_KEY"

Response Format:

{
  "shifts": {
    "2026-05-04": "user_id_1",
    "2026-05-05": "user_id_2",
    "2026-05-06": null,
    "2026-05-07": "user_id_3",
    "2026-05-08": "user_id_1"
  }
}

Response Fields:

  • shifts: An object keyed by shift date (YYYY-MM-DD, in the rotation’s local timezone) for cron-scheduled rotations, or by 1-based shift number for manual rotations. Values are user IDs for assigned shifts, arrays of user IDs for group rotations, or null for shifts where nobody is assigned (skipped or cancelled).
  • In verbose mode, each value is an object { "assignees": [...] | null, "naturalAssignees": [...] }. assignees is null for skipped or cancelled shifts; naturalAssignees always shows who the queue would place there in the absence of overrides.

Set Shifts

Substitute, cancel, or set multiple shifts in a single call. This is the most flexible endpoint for syncing your rotation with an external source of truth (e.g. a Google Sheet or planning tool).

Endpoint: POST /v1/t/<team_id>/r/<rotation_id>/set_shifts

Body Parameters:

  • shifts (required): An object keyed by shift date (YYYY-MM-DD) or 1-based shift number ("1", "2", …). Values are:
    • A user ID ("U06S3JJUU92") to substitute that shift with the given user.
    • An array of user IDs (["U06S3JJUU92", "U02M888M3C7"]) for group rotations (length must equal the rotation’s group size).
    • null to cancel the shift (no assignee; following shifts stay on schedule). See Cancelling a shift for the semantics.
  • verbose (optional): If true, each shift value in the response becomes an object { "assignees": [...] | null, "naturalAssignees": [...] } instead of a bare user ID, array, or null.

Example Request (substitute and cancel):

curl -X POST "https://api.rotation.app/v1/t/T123456/r/ROTA123/set_shifts" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "shifts": {
      "2026-05-04": "U06S3JJUU92",
      "2026-05-05": null
    }
  }'

Response Format:

{
  "shifts": {
    "2026-05-04": "U06S3JJUU92",
    "2026-05-05": null
  }
}

Verbose response (?verbose=true):

{
  "shifts": {
    "2026-05-04": {
      "assignees": ["U06S3JJUU92"],
      "naturalAssignees": ["U02M888M3C7"]
    },
    "2026-05-05": {
      "assignees": null,
      "naturalAssignees": ["U06S3JJUU92"]
    }
  }
}

Values are the computed post-write state for each shift you addressed, useful for verifying what actually landed. In verbose mode, naturalAssignees shows who the queue would place there if the override were removed. If a write was rejected (for example, a user ID not in the rotation), the API returns HTTP 400 with a per-key error map under errors.

Dates are interpreted in the rotation’s local timezone. Use shift numbers ("1", "2") if you’d rather address shifts positionally. "1" is the current shift.

Substitute Shift

Substitute the assigned user(s) at a single shift. A convenience wrapper around set_shifts with a one-entry payload, for callers that prefer one operation per request (Slack Workflows, single-shift automations).

Endpoint: POST /v1/t/<team_id>/r/<rotation_id>/substitute_shift

Body Parameters:

  • shift (required): The date (YYYY-MM-DD) or 1-based shift number to substitute.
  • user_id (required for single-user rotations): The user ID to assign for this shift.
  • user_ids (required for group rotations): Array of user IDs (length must equal the rotation’s group size).
  • verbose (optional): Same as set_shifts — toggles the per-shift response shape.

Example Request:

curl -X POST "https://api.rotation.app/v1/t/T123456/r/ROTA123/substitute_shift" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "shift": "2026-05-04",
    "user_id": "U06S3JJUU92"
  }'

Response Format:

Same shape as set_shifts — a shifts object keyed by the shift you addressed, with the computed post-write state as the value.

{
  "shifts": {
    "2026-05-04": "U06S3JJUU92"
  }
}

Cancel Shift

Cancels a single shift. Nobody is assigned, the natural assignee’s turn is used up, and the rest of the queue stays on the original schedule. See Cancelling a shift for the full semantics. A convenience wrapper around set_shifts with a null value.

Endpoint: POST /v1/t/<team_id>/r/<rotation_id>/cancel_shift

Body Parameters:

  • shift (required): The date (YYYY-MM-DD) or 1-based shift number to cancel.
  • verbose (optional): Same as set_shifts, toggles the per-shift response shape.

Example Request:

curl -X POST "https://api.rotation.app/v1/t/T123456/r/ROTA123/cancel_shift" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "shift": "2026-05-04" }'

Response Format:

Same shape as set_shifts. The value is null for the cancelled shift.

{
  "shifts": {
    "2026-05-04": null
  }
}
The INSERT-style skip described in the Manage Rotation Shifts guide (which defers the queue by one shift instead of using up the natural assignee’s turn) isn’t currently exposed in the public API. Use the Slack queue manager for that.

Uncancel Shift

Reverts a previously cancelled shift back to its natural assignee.

Endpoint: POST /v1/t/<team_id>/r/<rotation_id>/uncancel_shift

Body Parameters:

  • shift (required): The date (YYYY-MM-DD) or 1-based shift number to uncancel.
  • verbose (optional): Same as set_shifts, toggles the per-shift response shape.

Example Request:

curl -X POST "https://api.rotation.app/v1/t/T123456/r/ROTA123/uncancel_shift" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "shift": "2026-05-04" }'

Response Format:

Same shape as set_shifts. The value is the natural assignee that now occupies the shift.

{
  "shifts": {
    "2026-05-04": "U06S3JJUU92"
  }
}

Errors:

  • 400 if the shift isn’t currently cancelled or skipped.
  • 400 if the shift was skipped via the queue manager’s INSERT-style “Skip this shift” action. Those need to be undone from Slack’s queue manager first.

Undo Substitution

Remove a substitution from a shift, returning it to the natural assignee.

Endpoint: POST /v1/t/<team_id>/r/<rotation_id>/undo_substitution

Body Parameters:

  • shift (required): The date (YYYY-MM-DD) or 1-based shift number whose substitution to remove.
  • verbose (optional): Same as set_shifts — toggles the per-shift response shape.

Example Request:

curl -X POST "https://api.rotation.app/v1/t/T123456/r/ROTA123/undo_substitution" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "shift": "2026-05-04" }'

Response Format:

Same shape as set_shifts. The value is the natural assignee that now occupies the shift.

{
  "shifts": {
    "2026-05-04": "U06S3JJUU92"
  }
}

Errors:

  • 400 if the shift doesn’t currently have an active substitution to undo.

Integration Examples

Dashboard Integration

Use get_current_shift_assignees to display current on-call users on monitoring dashboards or status pages.

Incident Management

Combine get_current_shift_assignees with incident management tools to automatically assign incidents to the current on-call user.

Custom Scheduling

Use assign_user and assign_next to implement custom scheduling logic based on external factors like workload or availability.

Load Balancing

Use shuffle_rotation_queue periodically to ensure fair distribution of on-call duties across team members.

CSV-to-rotation push

Use set_shifts to push an externally-managed schedule (a Google Sheet, a planning tool, an HR system) into Rotation App. Send the whole next month in one call, with assignments as user IDs and days off as null. Combine with get_shifts?verbose=true afterwards to verify the result.