> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scaling.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Schedules

> Create and manage on-call schedules for your organization.

An on-call schedule defines a named rotation with a timezone. Rotation layers attached to a schedule determine who is on call at any given time. Use these endpoints to manage schedule metadata and resolve the current on-call responder.

<Note>
  Layers are managed separately. See [Rotation Layers](/api/oncall/layers) for
  endpoints that add, update, or remove rotation layers from a schedule.
</Note>

***

## `GET /oncall/schedules`

List all on-call schedules for your organization. Returns schedule metadata only — to include rotation layers, fetch an individual schedule with `GET /oncall/schedules/{scheduleId}`.

### Response fields

<ResponseField name="data" type="object[]" required>
  Array of schedule objects.

  <Expandable title="Schedule object fields">
    <ResponseField name="id" type="string" required>
      Unique schedule ID (UUID).
    </ResponseField>

    <ResponseField name="orgId" type="string" required>
      The organization this schedule belongs to.
    </ResponseField>

    <ResponseField name="name" type="string" required>
      Display name of the schedule. Unique within your organization.
    </ResponseField>

    <ResponseField name="description" type="string | null" required>
      Optional description. `null` if not set.
    </ResponseField>

    <ResponseField name="timezone" type="string" required>
      IANA timezone identifier, e.g. `America/New_York`.
    </ResponseField>

    <ResponseField name="createdBy" type="string" required>
      ID of the user or API key that created the schedule.
    </ResponseField>

    <ResponseField name="createdAt" type="string" required>
      ISO 8601 timestamp of when the schedule was created.
    </ResponseField>

    <ResponseField name="updatedAt" type="string" required>
      ISO 8601 timestamp of the last update.
    </ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://api.scaling.cloud/v1/oncall/schedules \
    --header 'Authorization: Bearer scl_live_your_api_key_here'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": [
      {
        "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "orgId": "org_2abc123def456",
        "name": "Platform On-call",
        "description": "Primary rotation for the platform engineering team",
        "timezone": "America/New_York",
        "createdBy": "user_9xyz",
        "createdAt": "2026-01-01T09:00:00.000Z",
        "updatedAt": "2026-03-15T14:22:00.000Z"
      },
      {
        "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
        "orgId": "org_2abc123def456",
        "name": "Data Infrastructure On-call",
        "description": null,
        "timezone": "America/Los_Angeles",
        "createdBy": "user_8wxy",
        "createdAt": "2026-02-10T11:30:00.000Z",
        "updatedAt": "2026-02-10T11:30:00.000Z"
      }
    ]
  }
  ```

  ```json 401 theme={null}
  {
    "statusCode": 401,
    "type": "not_authorized_error",
    "code": "not_authorized",
    "requestId": "550e8400-e29b-41d4-a716-446655440000"
  }
  ```
</ResponseExample>

### Error codes

| HTTP  | Code             | Description                 |
| ----- | ---------------- | --------------------------- |
| `401` | `not_authorized` | Missing or invalid API key. |
| `500` | `server_error`   | Unexpected server error.    |

***

## `POST /oncall/schedules`

Create a new on-call schedule for your organization. The `name` must be unique within your org.

### Request body

<ParamField body="name" type="string" required>
  Display name for the schedule. Must be unique within your organization. 1–255
  characters.
</ParamField>

<ParamField body="description" type="string">
  Optional description of the schedule's purpose.
</ParamField>

<ParamField body="timezone" type="string" required>
  IANA timezone identifier for the schedule, e.g. `America/Chicago`. All
  rotation layer handoff times are interpreted in this timezone.
</ParamField>

### Response fields

<ResponseField name="data" type="object" required>
  The created schedule object.

  <Expandable title="Schedule object fields">
    <ResponseField name="id" type="string" required>
      Unique schedule ID (UUID). Stable — never changes after creation.
    </ResponseField>

    <ResponseField name="orgId" type="string" required>
      The organization this schedule belongs to.
    </ResponseField>

    <ResponseField name="name" type="string" required>
      Display name of the schedule.
    </ResponseField>

    <ResponseField name="description" type="string | null" required>
      Description, or `null` if not provided.
    </ResponseField>

    <ResponseField name="timezone" type="string" required>
      IANA timezone identifier.
    </ResponseField>

    <ResponseField name="createdBy" type="string" required>
      ID of the user or API key that created the schedule.
    </ResponseField>

    <ResponseField name="createdAt" type="string" required>
      ISO 8601 creation timestamp.
    </ResponseField>

    <ResponseField name="updatedAt" type="string" required>
      ISO 8601 last-updated timestamp.
    </ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.scaling.cloud/v1/oncall/schedules \
    --header 'Authorization: Bearer scl_live_your_api_key_here' \
    --header 'Content-Type: application/json' \
    --data '{
      "name": "Platform On-call",
      "description": "Primary rotation for the platform engineering team",
      "timezone": "America/New_York"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "orgId": "org_2abc123def456",
      "name": "Platform On-call",
      "description": "Primary rotation for the platform engineering team",
      "timezone": "America/New_York",
      "createdBy": "user_9xyz",
      "createdAt": "2026-04-07T10:00:00.000Z",
      "updatedAt": "2026-04-07T10:00:00.000Z"
    }
  }
  ```

  ```json 400 theme={null}
  {
    "statusCode": 400,
    "type": "invalid_request_error",
    "code": "invalid_timezone",
    "requestId": "550e8400-e29b-41d4-a716-446655440000"
  }
  ```

  ```json 401 theme={null}
  {
    "statusCode": 401,
    "type": "not_authorized_error",
    "code": "not_authorized",
    "requestId": "550e8400-e29b-41d4-a716-446655440000"
  }
  ```
</ResponseExample>

### Error codes

| HTTP  | Code               | Description                                         |
| ----- | ------------------ | --------------------------------------------------- |
| `400` | `invalid_timezone` | `timezone` is not a valid IANA timezone identifier. |
| `401` | `not_authorized`   | Missing or invalid API key.                         |
| `500` | `server_error`     | Unexpected server error.                            |

***

## `GET /oncall/schedules/{scheduleId}`

Retrieve a single schedule by ID, including all of its rotation layers.

### Path parameters

<ParamField path="scheduleId" type="string" required>
  The UUID of the schedule to retrieve.
</ParamField>

### Response fields

<ResponseField name="data" type="object" required>
  The schedule object with its rotation layers.

  <Expandable title="Schedule object fields">
    <ResponseField name="id" type="string" required>
      Unique schedule ID (UUID).
    </ResponseField>

    <ResponseField name="orgId" type="string" required>
      The organization this schedule belongs to.
    </ResponseField>

    <ResponseField name="name" type="string" required>
      Display name of the schedule.
    </ResponseField>

    <ResponseField name="description" type="string | null" required>
      Description, or `null` if not set.
    </ResponseField>

    <ResponseField name="timezone" type="string" required>
      IANA timezone identifier.
    </ResponseField>

    <ResponseField name="createdBy" type="string" required>
      ID of the user or API key that created the schedule.
    </ResponseField>

    <ResponseField name="createdAt" type="string" required>
      ISO 8601 creation timestamp.
    </ResponseField>

    <ResponseField name="updatedAt" type="string" required>
      ISO 8601 last-updated timestamp.
    </ResponseField>

    <ResponseField name="layers" type="object[]" required>
      Rotation layers attached to this schedule. See [Rotation
      Layers](/api/oncall/layers) for field definitions.
    </ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://api.scaling.cloud/v1/oncall/schedules/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
    --header 'Authorization: Bearer scl_live_your_api_key_here'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "orgId": "org_2abc123def456",
      "name": "Platform On-call",
      "description": "Primary rotation for the platform engineering team",
      "timezone": "America/New_York",
      "createdBy": "user_9xyz",
      "createdAt": "2026-01-01T09:00:00.000Z",
      "updatedAt": "2026-03-15T14:22:00.000Z",
      "layers": [
        {
          "id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
          "scheduleId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
          "orgId": "org_2abc123def456",
          "name": "Primary rotation",
          "rotationType": "weekly",
          "rotationLengthDays": 7,
          "handoffTime": "09:00",
          "effectiveFrom": "2026-01-01T00:00:00.000Z",
          "effectiveUntil": null,
          "participantIds": ["user_aaa111", "user_bbb222", "user_ccc333"],
          "createdAt": "2026-01-01T09:05:00.000Z",
          "updatedAt": "2026-01-01T09:05:00.000Z"
        }
      ]
    }
  }
  ```

  ```json 404 theme={null}
  {
    "statusCode": 404,
    "type": "invalid_request_error",
    "code": "not_found",
    "requestId": "550e8400-e29b-41d4-a716-446655440000"
  }
  ```
</ResponseExample>

### Error codes

| HTTP  | Code             | Description                                               |
| ----- | ---------------- | --------------------------------------------------------- |
| `401` | `not_authorized` | Missing or invalid API key.                               |
| `404` | `not_found`      | No schedule found with the given ID in your organization. |
| `500` | `server_error`   | Unexpected server error.                                  |

***

## `PATCH /oncall/schedules/{scheduleId}`

Update one or more fields on a schedule. All fields are optional — only the fields you include are updated.

### Path parameters

<ParamField path="scheduleId" type="string" required>
  The UUID of the schedule to update.
</ParamField>

### Request body

<ParamField body="name" type="string">
  New display name for the schedule. Must be unique within your organization.
  1–255 characters.
</ParamField>

<ParamField body="description" type="string | null">
  Updated description. Pass `null` to clear the description.
</ParamField>

<ParamField body="timezone" type="string">
  New IANA timezone identifier. Changing the timezone affects how all existing
  rotation layer handoff times are interpreted.
</ParamField>

### Response fields

<ResponseField name="data" type="object" required>
  The updated schedule object (metadata only — does not include layers).
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request PATCH \
    --url https://api.scaling.cloud/v1/oncall/schedules/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
    --header 'Authorization: Bearer scl_live_your_api_key_here' \
    --header 'Content-Type: application/json' \
    --data '{
      "description": "Primary rotation — platform and infrastructure teams",
      "timezone": "America/Chicago"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "orgId": "org_2abc123def456",
      "name": "Platform On-call",
      "description": "Primary rotation — platform and infrastructure teams",
      "timezone": "America/Chicago",
      "createdBy": "user_9xyz",
      "createdAt": "2026-01-01T09:00:00.000Z",
      "updatedAt": "2026-04-07T10:30:00.000Z"
    }
  }
  ```

  ```json 400 theme={null}
  {
    "statusCode": 400,
    "type": "invalid_request_error",
    "code": "invalid_timezone",
    "requestId": "550e8400-e29b-41d4-a716-446655440000"
  }
  ```

  ```json 404 theme={null}
  {
    "statusCode": 404,
    "type": "invalid_request_error",
    "code": "not_found",
    "requestId": "550e8400-e29b-41d4-a716-446655440000"
  }
  ```
</ResponseExample>

### Error codes

| HTTP  | Code               | Description                                               |
| ----- | ------------------ | --------------------------------------------------------- |
| `400` | `invalid_timezone` | `timezone` is not a valid IANA timezone identifier.       |
| `401` | `not_authorized`   | Missing or invalid API key.                               |
| `404` | `not_found`        | No schedule found with the given ID in your organization. |
| `500` | `server_error`     | Unexpected server error.                                  |

***

## `DELETE /oncall/schedules/{scheduleId}`

Delete a schedule and all of its rotation layers. This action is permanent and cannot be undone.

### Path parameters

<ParamField path="scheduleId" type="string" required>
  The UUID of the schedule to delete.
</ParamField>

### Response fields

<ResponseField name="success" type="boolean" required>
  `true` when the schedule was deleted.
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request DELETE \
    --url https://api.scaling.cloud/v1/oncall/schedules/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
    --header 'Authorization: Bearer scl_live_your_api_key_here'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "success": true
  }
  ```

  ```json 404 theme={null}
  {
    "statusCode": 404,
    "type": "invalid_request_error",
    "code": "not_found",
    "requestId": "550e8400-e29b-41d4-a716-446655440000"
  }
  ```
</ResponseExample>

### Error codes

| HTTP  | Code             | Description                                               |
| ----- | ---------------- | --------------------------------------------------------- |
| `401` | `not_authorized` | Missing or invalid API key.                               |
| `404` | `not_found`      | No schedule found with the given ID in your organization. |
| `500` | `server_error`   | Unexpected server error.                                  |

***

## `GET /oncall/schedules/{scheduleId}/resolve`

Resolve who is currently on call for a schedule. Returns three views in one response: the **Schedule Owner** (a single user for the incident **Lead**), the **Paging Targets** (the full set of users an escalation policy targeting this schedule would page), and the **Current On-call View** (a richer, position-ordered breakdown including override provenance).

By default this returns the resolution at the current time. Pass the optional `at` query parameter to resolve at a specific moment.

The Schedule Owner is the lowest-positioned currently-active rotation layer's resolved participant — with the schedule's active override applied if one is in effect. If position 0 is between effective windows, owner resolution falls through to the next-lowest position.

### Path parameters

<ParamField path="scheduleId" type="string" required>
  The UUID of the schedule to query.
</ParamField>

### Query parameters

<ParamField query="at" type="string">
  ISO 8601 datetime to resolve on-call for. Defaults to the current server time
  if omitted. Example: `2026-06-15T14:00:00.000Z`.
</ParamField>

### Response fields

<ResponseField name="data" type="object" required>
  The on-call resolution result.

  <Expandable title="Resolution fields">
    <ResponseField name="owner" type="object | null" required>
      The Schedule Owner — `null` if no rotation layer resolves to a user at the
      requested time. Populated as the incident **Lead** when an incident is
      created against this schedule.
    </ResponseField>

    <ResponseField name="pagingTargets" type="object[]" required>
      Users to page when an escalation policy layer targets this schedule. One
      entry per currently-active rotation layer in position order, with each
      entry's override applied if active.
    </ResponseField>

    <ResponseField name="currentOncallView" type="object" required>
      Full reduced view of the schedule at `resolvedAt`.

      <Expandable title="Current on-call view fields">
        <ResponseField name="scheduleId" type="string" required>
          The schedule ID that was resolved.
        </ResponseField>

        <ResponseField name="resolvedAt" type="string" required>
          ISO 8601 timestamp of the point in time that was resolved (either
          `now` or the value of `at`).
        </ResponseField>

        <ResponseField name="owner" type="object | null" required>
          Same Schedule Owner as the top-level `owner`. Repeated here so callers
          that only consume `currentOncallView` get the full picture.
        </ResponseField>

        <ResponseField name="entries" type="object[]" required>
          One entry per currently-active rotation layer, ordered by `position`
          ascending. Empty if no layer is active.

          <Expandable title="Entry fields">
            <ResponseField name="rotationLayerId" type="string" required>
              ID of the rotation layer that produced this entry.
            </ResponseField>

            <ResponseField name="rotationLayerName" type="string" required>
              Name of the rotation layer.
            </ResponseField>

            <ResponseField name="position" type="integer" required>
              The layer's position within the schedule. Lower = higher
              precedence; position 0 is the owner-bearing layer.
            </ResponseField>

            <ResponseField name="user" type="object" required>
              The user currently on-call for this layer — the **override user**
              if `source` is `override`, otherwise the resolved rotation
              participant.
            </ResponseField>

            <ResponseField name="source" type="string" required>
              Either `rotation` (the layer's rotation produced this entry) or
              `override` (an active override substituted in for this layer).
            </ResponseField>

            <ResponseField name="overriddenUser" type="object">
              Only present when `source` is `override`. The rotation participant
              the override displaced.
            </ResponseField>

            <ResponseField name="viaOverrideId" type="string">
              Only present when `source` is `override`. The ID of the override
              row producing this entry.
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
  ```bash cURL — current on-call theme={null}
  curl --request GET \
    --url https://api.scaling.cloud/v1/oncall/schedules/a1b2c3d4-e5f6-7890-abcd-ef1234567890/resolve \
    --header 'Authorization: Bearer scl_live_your_api_key_here'
  ```

  ```bash cURL — on-call at a specific time theme={null}
  curl --request GET \
    --url 'https://api.scaling.cloud/v1/oncall/schedules/a1b2c3d4-e5f6-7890-abcd-ef1234567890/resolve?at=2026-06-15T14%3A00%3A00.000Z' \
    --header 'Authorization: Bearer scl_live_your_api_key_here'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "owner": {
        "user": {
          "id": "user_bbb222",
          "firstName": "Alice",
          "lastName": "Chen",
          "email": "alice@acme.io"
        }
      },
      "pagingTargets": [
        {
          "user": {
            "id": "user_bbb222",
            "firstName": "Alice",
            "lastName": "Chen",
            "email": "alice@acme.io"
          }
        },
        {
          "user": {
            "id": "user_ccc333",
            "firstName": "Bob",
            "lastName": "Martinez",
            "email": "bob@acme.io"
          }
        }
      ],
      "currentOncallView": {
        "scheduleId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "resolvedAt": "2026-04-07T10:00:00.000Z",
        "owner": {
          "user": {
            "id": "user_bbb222",
            "firstName": "Alice",
            "lastName": "Chen",
            "email": "alice@acme.io"
          }
        },
        "entries": [
          {
            "rotationLayerId": "c3d4e5f6-a7b8-9012-cdef-123456789012",
            "rotationLayerName": "Primary",
            "position": 0,
            "user": {
              "id": "user_bbb222",
              "firstName": "Alice",
              "lastName": "Chen",
              "email": "alice@acme.io"
            },
            "source": "rotation"
          },
          {
            "rotationLayerId": "d4e5f6a7-b8c9-0123-defa-2345678901234",
            "rotationLayerName": "Secondary",
            "position": 1,
            "user": {
              "id": "user_ccc333",
              "firstName": "Bob",
              "lastName": "Martinez",
              "email": "bob@acme.io"
            },
            "source": "rotation"
          }
        ]
      }
    }
  }
  ```

  ```json 200 — override active on position 0 theme={null}
  {
    "data": {
      "owner": {
        "user": {
          "id": "user_eee555",
          "firstName": "Eve",
          "lastName": "Nguyen",
          "email": "eve@acme.io"
        }
      },
      "pagingTargets": [
        {
          "user": {
            "id": "user_eee555",
            "firstName": "Eve",
            "lastName": "Nguyen",
            "email": "eve@acme.io"
          }
        }
      ],
      "currentOncallView": {
        "scheduleId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "resolvedAt": "2026-04-15T10:00:00.000Z",
        "owner": {
          "user": {
            "id": "user_eee555",
            "firstName": "Eve",
            "lastName": "Nguyen",
            "email": "eve@acme.io"
          }
        },
        "entries": [
          {
            "rotationLayerId": "c3d4e5f6-a7b8-9012-cdef-123456789012",
            "rotationLayerName": "Primary",
            "position": 0,
            "user": {
              "id": "user_eee555",
              "firstName": "Eve",
              "lastName": "Nguyen",
              "email": "eve@acme.io"
            },
            "source": "override",
            "overriddenUser": {
              "id": "user_bbb222",
              "firstName": "Alice",
              "lastName": "Chen",
              "email": "alice@acme.io"
            },
            "viaOverrideId": "f7a8b9c0-d1e2-3456-fab7-89cdef012345"
          }
        ]
      }
    }
  }
  ```

  ```json 200 — no active layer theme={null}
  {
    "data": {
      "owner": null,
      "pagingTargets": [],
      "currentOncallView": {
        "scheduleId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "resolvedAt": "2025-12-01T03:00:00.000Z",
        "owner": null,
        "entries": []
      }
    }
  }
  ```

  ```json 404 theme={null}
  {
    "statusCode": 404,
    "type": "invalid_request_error",
    "code": "not_found",
    "requestId": "550e8400-e29b-41d4-a716-446655440000"
  }
  ```
</ResponseExample>

### Error codes

| HTTP  | Code             | Description                                               |
| ----- | ---------------- | --------------------------------------------------------- |
| `401` | `not_authorized` | Missing or invalid API key.                               |
| `404` | `not_found`      | No schedule found with the given ID in your organization. |
| `500` | `server_error`   | Unexpected server error.                                  |
