# Posting slots

3 endpoints.

## Posting slots for every connected account

```http
GET https://orbitwrite.com/api/v1/posting-slots/by-account
```

Requires `postingSchedule:read`. One entry per live connected account with its weekly slots and the timezone they're anchored to. `GET /posting-slots` collapses the workspace to one distinct set of times; this keeps them separated, which is what a per-account posting queue needs to place a post.

**Authentication:** bearer token or session cookie.

### Query parameters

- `organizationId` (string, optional) — Session callers only — an API key already determines the workspace.

### Responses

#### 200

Each account's posting schedule

- `accounts` (AccountPostingSchedule[], required)
  - `accountId` (string, required)
  - `timezone` (string | null, required) — IANA timezone the account's slot times are anchored to — the workspace's, falling back to the account's own for a workspace that never set one. Workspace-first on purpose: the calendar renders every account's slots against the single workspace zone, and a queue anchored to a diverging per-account zone places its instants off the slots the calendar shows — so it re-offers a slot that visibly holds a post. Slots recur at this wall-clock time, so the instant they fire shifts with DST. Null when neither is configured: the caller applies its own fallback, because only it knows the zone the times will be read in (the app uses the viewer's display timezone, matching the calendar).
  - `slots` (PostingSlot[], required) — The account's own slots, falling back to the workspace's distinct set when it has none of its own — an account connected after onboarding has no rows, and the calendar already places it on the workspace's times. Empty only when the workspace has no slots at all; callers apply their own default there rather than being handed an invented one.
    - `dayOfWeek` (integer, required) — 0 = Monday … 6 = Sunday
    - `minuteOfDay` (integer, required) — Minutes since local midnight

#### 400

Invalid request

- `error` (string, required)
- `issues` (any[], optional)

#### 401

Not signed in

- `error` (string, required)
- `issues` (any[], optional)

#### 403

Not a member of the organization

- `error` (string, required)
- `issues` (any[], optional)

## List a workspace's posting slots

```http
GET https://orbitwrite.com/api/v1/posting-slots
```

Requires `postingSchedule:read`. Returns the distinct weekly (dayOfWeek, minuteOfDay) slots for the organization, plus its timezone. Used by the settings “Posting schedule” tab.

**Authentication:** bearer token or session cookie.

### Query parameters

- `organizationId` (string, optional) — Session callers only — an API key already determines the workspace.
- `accountId` (string, optional) — Scope to one connected account's schedule instead of the organization-wide default. When the account has no customized schedule yet, the organization's values are returned as a fallback.

### Responses

#### 200

The workspace's posting slots

- `slots` (PostingSlot[], required)
  - `dayOfWeek` (integer, required) — 0 = Monday … 6 = Sunday
  - `minuteOfDay` (integer, required) — Minutes since local midnight
- `timezone` (string | null, required) — IANA timezone the slots are anchored to, e.g. "Europe/London"
- `frequencyPerWeek` (number | null, required) — Posts-per-week goal the schedule was set to (from onboarding), used to restore the smart-mode stepper. Null when never configured.
- `mode` (string | null, required, one of `smart`, `manual`, `null`) — Whether the schedule was last saved in smart or manual mode. Null when never configured.

#### 400

Invalid request

- `error` (string, required)
- `issues` (any[], optional)

#### 401

Not signed in

- `error` (string, required)
- `issues` (any[], optional)

#### 403

Not a member of the organization

- `error` (string, required)
- `issues` (any[], optional)

#### 404

The resource does not exist

- `error` (string, required)
- `issues` (any[], optional)

## Replace a workspace's posting slots

```http
POST https://orbitwrite.com/api/v1/posting-slots
```

Requires `postingSchedule:update`. Replaces the posting slots for every connected account in the organization — or for one account, with `accountId` — with the set derived from the chosen schedule (frequency + smart/manual). Idempotent: re-running replaces rather than accumulates.

**Authentication:** bearer token or session cookie.

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

- `organizationId` (string, optional) — Session callers only — an API key already determines the workspace.
- `accountId` (string, optional) — Scope the update to one connected account instead of every account in the organization. The organization's own schedule columns are seeded from this write only while they're still unconfigured — once set, account-scoped writes never touch the org-wide fallback.
- `mode` (string, optional, one of `smart`, `manual`)
- `frequencyPerWeek` (number, optional) — Smart mode: how many slots to spread across the week
- `slots` (ManualSlotInput[], optional) — Manual mode: the checked day×time grid cells
  - `time` (string, required) — Display time, e.g. "9:00 AM" or "14:30"
  - `days` (boolean[], required) — One boolean per day, Monday..Sunday
- `timezone` (string, optional) — IANA timezone to anchor the schedule to, e.g. "America/Los_Angeles". Checked against the runtime's zone database — an unknown zone is a 400 rather than a schedule whose times nothing can resolve later.

### Responses

#### 200

How many slots were created across how many accounts

- `created` (integer, required)
- `accounts` (integer, required)
- `slotsPerAccount` (integer, required)

#### 400

Invalid request

- `error` (string, required)
- `issues` (any[], optional)

#### 401

Not signed in

- `error` (string, required)
- `issues` (any[], optional)

#### 403

Not a member of the organization

- `error` (string, required)
- `issues` (any[], optional)

#### 404

The resource does not exist

- `error` (string, required)
- `issues` (any[], optional)
