> Documentation index for AI agents: https://docs.pagerduty.com/llms.txt

# Update a schedule

`PUT https://api.pagerduty.com/v3/schedules/{id}`

<!-- theme: info -->

> **Important note:** Shift-based schedules use the V3 API and are not compatible with V2 automations. **To create automations for Shift-Based Schedules, you need to:**
>
> 1. **Update your automations** to use the V3 API for all new shift-based schedules
> 2. **Keep the V2 endpoint** for your existing schedules
>
> An upgrade tool for existing schedules is coming soon; your legacy schedules will keep working in the meantime. [Learn more](https://support.pagerduty.com/main/docs/shift-based-schedules-api-upgrade-examples).

Update schedule metadata (name, description, time zone). `time_zone`
is required; `name` and `description` are optional and keep their
current values when omitted.

To modify rotations or events, use their respective endpoints.

**Rejected fields:** `rotations` and `escalation_policies` are not
accepted and will result in a 400 error.

## Authorization

- **api_key** (apiKey) — `Authorization` header. The API Key with format `Token token=<API_KEY>`

## Path parameters

| Name | Type | Required | Description |
|---|---|---|---|
| `id` | string | yes | The ID of the schedule. |

## Request body (`application/json`) — required

| Field | Type | Required | Description |
|---|---|---|---|
| `schedule` | object | yes | `time_zone` is required. `name` and `description` are optional; an omitted field keeps its current value. |
| `schedule.name` | string |  | Min length: 1. Max length: 255. |
| `schedule.time_zone` | string | yes |  |
| `schedule.description` | string |  | Max length: 1024. |
| `schedule.teams` | array of object |  | Teams to associate with this schedule. |
| `schedule.teams[].id` | string | yes |  |
| `schedule.teams[].type` | string | yes | One of: `team_reference`. |

Example: Update name only

```json
{
  "schedule": {
    "name": "New Schedule Name"
  }
}
```

Example: Update multiple fields

```json
{
  "schedule": {
    "name": "Updated Schedule",
    "time_zone": "America/Los_Angeles",
    "description": "Updated description"
  }
}
```

## Response 200

Schedule updated successfully

### `application/json`

| Field | Type | Required | Description |
|---|---|---|---|
| `schedule` | object | yes |  |
| `schedule.id` | string | yes |  |
| `schedule.type` | string | yes | Always `"schedule_v3"` for schedules created with this API. Schedules created with the legacy `/schedules` API use `"schedule"`. One of: `schedule_v3`. |
| `schedule.name` | string | yes |  |
| `schedule.time_zone` | string | yes |  |
| `schedule.description` | string |  |  |
| `schedule.teams` | array of object |  |  |
| `schedule.teams[].id` | string | yes | Read-only. |
| `schedule.teams[].summary` | string \| null |  | A short-form, server-generated string that provides succinct, important information about an object suitable for primary labeling of an entity in a client. In many cases, this will be identical to `name`, though it is not intended to be an identifier. Read-only. |
| `schedule.teams[].type` | string | yes | One of: `team_reference`. |
| `schedule.teams[].self` | string \| null (url) |  | the API show URL at which the object is accessible. Read-only. |
| `schedule.teams[].html_url` | string \| null (url) |  | a URL at which the entity is uniquely displayed in the Web app. Read-only. |
| `schedule.escalation_policies` | array of object |  | Escalation policies that reference this schedule. |
| `schedule.escalation_policies[].id` | string | yes | Read-only. |
| `schedule.escalation_policies[].summary` | string \| null |  | A short-form, server-generated string that provides succinct, important information about an object suitable for primary labeling of an entity in a client. In many cases, this will be identical to `name`, though it is not intended to be an identifier. Read-only. |
| `schedule.escalation_policies[].type` | string | yes | One of: `escalation_policy_reference`. |
| `schedule.escalation_policies[].self` | string \| null (url) |  | the API show URL at which the object is accessible. Read-only. |
| `schedule.escalation_policies[].html_url` | string \| null (url) |  | a URL at which the entity is uniquely displayed in the Web app. Read-only. |
| `schedule.users` | array of object |  | All users referenced in this schedule (only present when include[]=users) |
| `schedule.users[].id` | string | yes | Read-only. |
| `schedule.users[].summary` | string \| null |  | A short-form, server-generated string that provides succinct, important information about an object suitable for primary labeling of an entity in a client. In many cases, this will be identical to `name`, though it is not intended to be an identifier. Read-only. |
| `schedule.users[].type` | string | yes | One of: `user_reference`. |
| `schedule.users[].self` | string \| null (url) |  | the API show URL at which the object is accessible. Read-only. |
| `schedule.users[].html_url` | string \| null (url) |  | a URL at which the entity is uniquely displayed in the Web app. Read-only. |
| `schedule.rotations` | array of object |  | Rotations in this schedule. |
| `schedule.rotations[].id` | string | yes |  |
| `schedule.rotations[].type` | string | yes | One of: `schedule_rotation`. |
| `schedule.rotations[].events` | array of object |  | Events in this rotation. |
| `schedule.rotations[].events[].id` | string | yes |  |
| `schedule.rotations[].events[].type` | string | yes | One of: `schedule_event`. |
| `schedule.rotations[].events[].name` | string | yes | Display name for this event. |
| `schedule.rotations[].events[].start_time` | object | yes | A time-of-day value with an explicit time zone. Used for event `start_time` and `end_time` to define the recurring window of coverage (e.g., 9 AM–5 PM every Monday in New York). |
| `schedule.rotations[].events[].start_time.date_time` | string (date-time) | yes | The date and time. |
| `schedule.rotations[].events[].start_time.time_zone` | string | yes | IANA timezone identifier. |
| `schedule.rotations[].events[].end_time` | object | yes | A time-of-day value with an explicit time zone. Used for event `start_time` and `end_time` to define the recurring window of coverage (e.g., 9 AM–5 PM every Monday in New York). Same fields as `schedule.rotations[].events[].start_time` above. |
| `schedule.rotations[].events[].effective_since` | string (date-time) | yes | When this event starts producing shifts (UTC) |
| `schedule.rotations[].events[].effective_until` | string \| null (date-time) |  | When this event stops producing shifts (UTC). Null means indefinite. |
| `schedule.rotations[].events[].recurrence` | array of string | yes | RFC 5545 recurrence rules defining the repeating pattern. This must be an array containing: <br> - Exactly one <b>RRULE</b> <br>- Zero or more <b>EXDATE</b> <br>- Zero or more <b>RDATE</b>. |
| `schedule.rotations[].events[].assignment_strategy` | object | yes | Defines how users are assigned on-call within an event's time window. - `rotating_member_assignment_strategy`: users rotate in sequence. `shifts_per_member` controls how many consecutive shift periods each member covers before rotating. - `every_member_assignment_strategy`: all listed members are on-call simultaneously for every occurrence. |
| `schedule.rotations[].events[].assignment_strategy.type` | string | yes | One of: `rotating_member_assignment_strategy`, `every_member_assignment_strategy`. |
| `schedule.rotations[].events[].assignment_strategy.shifts_per_member` | integer |  | Required for `rotating_member_assignment_strategy`. Number of consecutive shift occurrences each member covers before the next member takes over. Must be omitted (or null) for `every_member_assignment_strategy`. **UI editor constraint:** When `recurrence` uses `FREQ=WEEKLY`, `shifts_per_member` must be evenly divisible by the number of days listed in the RRULE `BYDAY` parameter. Events that violate this are fully functional via the API but cannot be loaded in the web schedule editor. Minimum: 1. |
| `schedule.rotations[].events[].assignment_strategy.members` | array of object | yes | Min items: 1. Max items: 60. |
| `schedule.rotations[].events[].assignment_strategy.members[].type` | string | yes | `user_member` — a specific user is assigned. `empty_member` — the slot is intentionally unassigned. One of: `user_member`, `empty_member`. |
| `schedule.rotations[].events[].assignment_strategy.members[].user_id` | string |  | The ID of the user. Required when type is `user_member`. |
| `schedule.rotations[].events[].self` | string (uri) |  |  |
| `schedule.rotations[].events[].html_url` | string (uri) |  |  |
| `schedule.rotations[].self` | string (uri) |  |  |
| `schedule.rotations[].html_url` | string (uri) |  |  |
| `schedule.final_schedule` | object |  | Computed on-call assignments for the requested time range. Only present when `include[]=final_schedule` is specified and `since`/`until` are provided. |
| `schedule.final_schedule.type` | string | yes | One of: `final_schedule`. |
| `schedule.final_schedule.rendered_coverage_percentage` | number (double) | yes | Percentage of the requested time range that has on-call coverage (0–100) |
| `schedule.final_schedule.computed_shift_assignments` | array of object | yes |  |
| `schedule.final_schedule.computed_shift_assignments[].type` | string | yes | One of: `computed_shift_assignment`. |
| `schedule.final_schedule.computed_shift_assignments[].start_time` | string (date-time) | yes |  |
| `schedule.final_schedule.computed_shift_assignments[].end_time` | string (date-time) | yes |  |
| `schedule.final_schedule.computed_shift_assignments[].member` | object | yes | A member (user) assigned to a shift or rotation slot. |
| `schedule.final_schedule.computed_shift_assignments[].member.type` | string | yes | `user_member` — a specific user is assigned. `empty_member` — the slot is intentionally unassigned. One of: `user_member`, `empty_member`. |
| `schedule.final_schedule.computed_shift_assignments[].member.user_id` | string |  | The ID of the user. Required when type is `user_member`. |
| `schedule.final_schedule.computed_shift_assignments[].source` | object | yes | Where a computed shift assignment originated. |
| `schedule.final_schedule.computed_shift_assignments[].source.type` | string | yes | One of: `schedule_rotation`, `custom_shift`, `schedule_rotation_override`, `custom_shift_override`. |
| `schedule.final_schedule.computed_shift_assignments[].source.rotation_id` | string |  | Present for schedule_rotation and schedule_rotation_override sources. |
| `schedule.final_schedule.computed_shift_assignments[].source.shift_id` | string |  | Present for custom_shift and custom_shift_override sources. |
| `schedule.final_schedule.computed_shift_assignments[].source.override_id` | string |  | Present for schedule_rotation_override and custom_shift_override sources. |
| `schedule.http_cal_url` | string (uri) |  | iCal HTTP feed URL for this schedule. |
| `schedule.web_cal_url` | string (uri) |  | iCal webcal URL for this schedule. |
| `schedule.self` | string (uri) |  |  |
| `schedule.html_url` | string (uri) |  |  |

Example: Example response

```json
{
  "schedule": {
    "id": "PS1A2B3C",
    "type": "schedule_v3",
    "name": "Updated Schedule",
    "time_zone": "America/Los_Angeles",
    "self": "https://api.pagerduty.com/v3/schedules/PS1A2B3C"
  }
}
```

## Response 400

Bad Request — The request contains invalid parameters or data

### `application/json`

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | object | yes |  |
| `error.message` | string | yes |  |
| `error.code` | integer | yes |  |
| `error.errors` | object |  | Map of field path to list of validation messages for that field. Field paths use dot notation prefixed by the resource type (e.g. `event.effective_since`, `rotation.events`). |

Example: default

```json
{
  "error": {
    "message": "Invalid Request",
    "code": 2001,
    "errors": {
      "event.effective_since": [
        "Date cannot be more than 12 months in the future"
      ]
    }
  }
}
```

## Response 401

Caller did not supply credentials or did not provide the correct credentials.
If you are using an API key, it may be invalid or your Authorization header may be malformed.

### `application/json`

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | object |  |  |
| `error.code` | integer |  | Read-only. |
| `error.message` | string |  | Error message string. Read-only. |
| `error.errors` | array of string |  | Read-only. |

## Response 403

Caller is not authorized to view the requested resource.
While your authentication is valid, the authenticated user or token does not have permission to perform this action.

### `application/json`

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | object |  |  |
| `error.code` | integer |  | Read-only. |
| `error.message` | string |  | Error message string. Read-only. |
| `error.errors` | array of string |  | Read-only. |

## Response 404

The requested resource was not found.

### `application/json`

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | object |  |  |
| `error.code` | integer |  | Read-only. |
| `error.message` | string |  | Error message string. Read-only. |
| `error.errors` | array of string |  | Read-only. |

## Response 500

Internal Server Error the PagerDuty server experienced an error.

### `application/json`

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | object |  |  |
| `error.code` | integer |  | Read-only. |
| `error.message` | string |  | Error message string. Read-only. |
| `error.errors` | array of string |  | Read-only. |

## Developer Agreement

Your access to and use of the PagerDuty Developer Services is governed by the [PagerDuty Developer Agreement](https://docs.pagerduty.com/developer/pagerduty-developer-agreement).
