# Platform Schedule Configuration

Platform schedule configuration defines when a platform can publish and which time slots
publication schedules can reference.

This page describes platform-level configuration. Publication instances use the dedicated
[Publication Scheduling](/docs/guides/editorial-workflows/publication-scheduling) contract under
`/api/v2/elements/{id}/publications/{publicationId}/schedule`.

## Schedule Modes

Each platform has one schedule mode:

| Mode | v2 field | Use |
|------|----------|-----|
| Weekly | `weeklySchedule` | The platform publishes on selected weekdays. |
| Manual | `manualSchedule` | The platform publishes on explicitly configured issue dates. |

:::caution{title="Schedule modes are mutually exclusive"}

Non-null `weeklySchedule` and `manualSchedule` payloads are mutually exclusive.

:::

When `POST /api/v2/platforms` omits both schedule fields, or sends both as `null`, v2 creates a
default weekly schedule with all seven weekdays set to `true`. `PATCH` treats explicit `null`
schedule fields as invalid.

## Weekly Schedule

Weekly schedule payloads use explicit day flags:

```json title="Weekly schedule"
{
  "weeklySchedule": {
    "mon": true,
    "tue": true,
    "wed": true,
    "thu": true,
    "fri": true,
    "sat": false,
    "sun": false
  }
}
```

When `weeklySchedule` is provided, all seven flags are required and `null` is invalid.

## Manual Schedule

Manual schedules are arrays of publication dates:

```json title="Manual schedule"
{
  "manualSchedule": [
    {
      "externalId": "issue-2026-01",
      "date": "2026-01-15",
      "note": "January issue"
    }
  ]
}
```

Create rules:

- `manualSchedule` must not be empty.
- each entry requires `date`.
- `id` must be omitted on create.
- `externalId` and `note` are optional.
- dates must be unique within the request.

## PUT Replacement

`PUT /api/v2/platforms/{id}` is full replacement for writable platform fields.

For schedule fields:

- a weekly platform must be replaced with `weeklySchedule`.
- a manual platform must be replaced with `manualSchedule`.
- replacing a weekly platform with `manualSchedule` is rejected.
- replacing a manual platform with `weeklySchedule` is rejected.
- a manual replacement list replaces the resulting manual date set.
- manual entries with existing `id` values update those entries; entries without `id` create new
  dates.
- unknown manual schedule entry IDs are rejected.

## PATCH Semantics

`PATCH /api/v2/platforms/{id}` is presence-aware.

For weekly platforms:

- omit `weeklySchedule` to leave it unchanged.
- send the complete `weeklySchedule` object to replace all seven day flags.
- sending `manualSchedule` is rejected because it would change the platform schedule mode.

For manual platforms:

- omit `manualSchedule` to leave it unchanged.
- `manualSchedule: []` is a no-op instruction list.
- send an entry without `id` and with `date` to add a manual date.
- send an entry with `id` to patch that existing date.
- use `DELETE /api/v2/platforms/{platformId}/manual-schedule/{manualScheduleId}` to delete an
  existing manual date.
- deleting the last remaining manual date through that DELETE endpoint is rejected.
- duplicate manual entry IDs, duplicate resulting dates, unknown IDs, and whitespace-only
  `externalId` values are rejected. Empty string is normalized to `null` and clears the value when
  the field is present.

`weeklySchedule: null` and `manualSchedule: null` are invalid in patch requests.

## Time Slots

Platform responses can include `timeSlots[]`:

```json title="Platform response"
{
  "timeSlots": [
    {
      "id": 6001,
      "name": "Morning Edition",
      "start": "06:00",
      "end": "11:59"
    }
  ]
}
```

Use these IDs in publication schedule timing:

```json title="Publication schedule timing"
{
  "kind": "single",
  "date": "2026-01-15",
  "timing": {
    "type": "timeSlot",
    "timeSlotId": 6001
  }
}
```

:::info{title="Time slots are read-only here"}

Time-slot IDs are read from platform configuration and are not created through publication schedule
requests.

:::

Platform create, PUT, and PATCH request schemas do not include a `timeSlots` write field. For
publication-level slot behavior, see
[Publication Scheduling](/docs/guides/editorial-workflows/publication-scheduling#time-slot-context).

## Platform Type Constraints

A platform's `typeCode` sets its publishing medium:

| `typeCode` | Platform kind     |
|------------|-------------------|
| `0`        | Digital / broadcast |
| `1`        | Print             |
| `2`        | Other             |

v2 validates platform type combinations explicitly:

- `typeCode` must be `0`, `1`, or `2`.
- `typeCode: 0` (digital/broadcast) must use `printingTimeInDays: 0`.
- `typeCode: 0` cannot set `displayStoryByIssue` to `false`.
- print platforms (`typeCode: 1`) cannot keep time slots in their resulting state.

## Related Guides

- [Configuration Resources](/docs/guides/resource-guides/configuration-resources)
- [Publication Scheduling](/docs/guides/editorial-workflows/publication-scheduling)
- [Platform Schedule Configuration Migration](/docs/migration-from-v1/platform-schedule-configuration)
