# Connected accounts

9 endpoints.

## List a workspace's connected channels

```http
GET https://orbitwrite.com/api/v1/connected-accounts
```

Every channel in the workspace, live and disconnected, in a stable order. Read this rather than deriving channels from a page's own data when you need one channel by id — the caller then doesn't have to already hold the list. Tokens are never returned.

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

### Query parameters

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

### Responses

#### 200

The workspace's channels

- `accounts` (ConnectedAccount[], required)
  - `id` (string, required)
  - `platform` (string, required)
  - `handle` (string | null, required) — The channel's handle on its platform, as it was at connect time.
  - `displayName` (string | null, required)
  - `avatarUrl` (string | null, required)
  - `profileUrl` (string | null, required) — The channel's public profile page. Null where the platform has none (Discord, Slack) or the handle can't name one.
  - `needsReconnect` (boolean, required) — The platform credentials are dead — the channel can't publish until it's reconnected.
  - `inboxReconnectNeeded` (boolean, required) — LinkedIn Pages only: the grant predates the comment-read scope the inbox needs (`r_organization_social`). Publishing works; comments can't be pulled until the Page is reconnected.
  - `defaultSelected` (boolean, required) — Pre-selected when a fresh post is composed.
  - `disconnected` (boolean, required) — Disconnected from the workspace. Disconnecting is a soft revoke so the channel's posts survive, which is why these rows are returned rather than hidden: they still have to be reachable to reconnect or to clear their content.
  - `isPremium` (boolean, required) — X Premium, which raises the composer's character limit from 280 to 25,000.
  - `carouselUnavailable` (boolean, required) — A personal Pinterest account. Pinterest keeps carousel Pins for business accounts, so this channel posts one image or one video.
  - `canShareToInstagram` (boolean | null, required) — Threads only: whether connect-time probing found the linked Instagram account eligible for cross-sharing. Null when unknown — an older connection, or a probe that failed — which the composer treats as "allow, and let the publish path decide".
  - `autoEngagementDefaults` (AutomationDefaults | null, required) — Stored defaults that seed the composer's auto-engagement panel for this channel; null when never configured.
    - `comment` (AutoEngagementDefaultSection, required)
      - `enabled` (boolean, required)
      - `entries` (AutoEngagementDefaultEntry[], required)
        - `fromAccountId` (string, required)
        - `delayMinutes` (integer, required)
    - `like` (AutoEngagementLikeDefaultSection, required)
      - `enabled` (boolean, required)
      - `entries` (object[], required)
        - `fromAccountId` (string, required)
        - `delayMinutes` (integer, required)
        - `reaction` (string, optional, one of `LIKE`, `LOVE`, `CELEBRATE`, `INSIGHTFUL`, `CURIOUS`, `SUPPORT`)
    - `repost` (AutoEngagementDefaultSection, required)
      - `enabled` (boolean, required)
      - `entries` (AutoEngagementDefaultEntry[], required)
        - `fromAccountId` (string, required)
        - `delayMinutes` (integer, required)
    - `slack` (AutoEngagementDefaultSection, required)
      - `enabled` (boolean, required)
      - `entries` (AutoEngagementDefaultEntry[], required)
        - `fromAccountId` (string, required)
        - `delayMinutes` (integer, required)
    - `discord` (AutoEngagementDefaultSection, required)
      - `enabled` (boolean, required)
      - `entries` (AutoEngagementDefaultEntry[], required)
        - `fromAccountId` (string, required)
        - `delayMinutes` (integer, required)
    - `shareToInstagram` (boolean, optional)
- `primaryAccountId` (string | null, required) — The channel whose content the composer syncs to the others, or null when the workspace hasn't set one.

#### 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)

## Disconnect a social account

```http
POST https://orbitwrite.com/api/v1/connected-accounts/{accountId}/disconnect
```

Revokes the connection (clears its tokens and drops it out of every live-account query) but KEEPS the account row, so its posts, drafts, published history, analytics, and posting slots survive and reattach if the user reconnects the same handle. Set purgePosts to instead delete the content this channel authored AND remove the channel row itself. Requires `account:disconnect`.

**Authentication:** session cookie.

### Path parameters

- `accountId` (string, required)

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

- `purgePosts` (boolean, optional) — Also delete the posts and drafts this channel authored, AND remove the channel from the workspace entirely (nothing is left to reconnect to; connecting the same handle later starts fresh). Deletion is per post ROW, so a draft shared with other channels keeps its other channels' versions and the group itself. Irreversible. Defaults to false — disconnecting keeps content and the channel stays listed for reconnection.

### Responses

#### 200

The account was disconnected

- `ok` (boolean, required, one of `true`)
- `deletedPosts` (integer, required)
- `deletedGroups` (integer, required)
- `deletedComments` (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)

## Make an account the workspace's primary account

```http
POST https://orbitwrite.com/api/v1/connected-accounts/{accountId}/primary
```

Requires `account:update`. A disconnected channel is refused (409) — it can't publish, and the primary is what the composer syncs content from.

**Authentication:** session cookie.

### Path parameters

- `accountId` (string, required)

### Responses

#### 200

The mutation was applied

- `ok` (boolean, required, one of `true`)

#### 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)

#### 409

Conflicts with an existing resource

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

## Toggle whether the account is pre-selected in a fresh composer

```http
POST https://orbitwrite.com/api/v1/connected-accounts/{accountId}/default-selected
```

Requires `account:update`.

**Authentication:** session cookie.

### Path parameters

- `accountId` (string, required)

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

- `defaultSelected` (boolean, required)

### Responses

#### 200

The mutation was applied

- `ok` (boolean, required, one of `true`)

#### 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)

## Read an account's auto-engagement defaults

```http
GET https://orbitwrite.com/api/v1/connected-accounts/{accountId}/automation-defaults
```

The stored defaults that seed the composer's auto-engagement panel for this account; null when never configured. Any member may read (`account:read`).

**Authentication:** session cookie.

### Path parameters

- `accountId` (string, required)

### Responses

#### 200

The stored defaults

- `autoEngagementDefaults` (AutomationDefaults | null, required) — Stored defaults that seed the composer's auto-engagement panel for this channel; null when never configured.
  - `comment` (AutoEngagementDefaultSection, required)
    - `enabled` (boolean, required)
    - `entries` (AutoEngagementDefaultEntry[], required)
      - `fromAccountId` (string, required)
      - `delayMinutes` (integer, required)
  - `like` (AutoEngagementLikeDefaultSection, required)
    - `enabled` (boolean, required)
    - `entries` (object[], required)
      - `fromAccountId` (string, required)
      - `delayMinutes` (integer, required)
      - `reaction` (string, optional, one of `LIKE`, `LOVE`, `CELEBRATE`, `INSIGHTFUL`, `CURIOUS`, `SUPPORT`)
  - `repost` (AutoEngagementDefaultSection, required)
    - `enabled` (boolean, required)
    - `entries` (AutoEngagementDefaultEntry[], required)
      - `fromAccountId` (string, required)
      - `delayMinutes` (integer, required)
  - `slack` (AutoEngagementDefaultSection, required)
    - `enabled` (boolean, required)
    - `entries` (AutoEngagementDefaultEntry[], required)
      - `fromAccountId` (string, required)
      - `delayMinutes` (integer, required)
  - `discord` (AutoEngagementDefaultSection, required)
    - `enabled` (boolean, required)
    - `entries` (AutoEngagementDefaultEntry[], required)
      - `fromAccountId` (string, required)
      - `delayMinutes` (integer, required)
  - `shareToInstagram` (boolean, optional)

#### 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 an account's auto-engagement defaults

```http
PUT https://orbitwrite.com/api/v1/connected-accounts/{accountId}/automation-defaults
```

Replaces the stored defaults wholesale. Requires `account:update`.

**Authentication:** session cookie.

### Path parameters

- `accountId` (string, required)

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

- `comment` (AutoEngagementDefaultSection, required)
  - `enabled` (boolean, required)
  - `entries` (AutoEngagementDefaultEntry[], required)
    - `fromAccountId` (string, required)
    - `delayMinutes` (integer, required)
- `like` (AutoEngagementLikeDefaultSection, required)
  - `enabled` (boolean, required)
  - `entries` (object[], required)
    - `fromAccountId` (string, required)
    - `delayMinutes` (integer, required)
    - `reaction` (string, optional, one of `LIKE`, `LOVE`, `CELEBRATE`, `INSIGHTFUL`, `CURIOUS`, `SUPPORT`)
- `repost` (AutoEngagementDefaultSection, required)
  - `enabled` (boolean, required)
  - `entries` (AutoEngagementDefaultEntry[], required)
    - `fromAccountId` (string, required)
    - `delayMinutes` (integer, required)
- `slack` (AutoEngagementDefaultSection, required)
  - `enabled` (boolean, required)
  - `entries` (AutoEngagementDefaultEntry[], required)
    - `fromAccountId` (string, required)
    - `delayMinutes` (integer, required)
- `discord` (AutoEngagementDefaultSection, required)
  - `enabled` (boolean, required)
  - `entries` (AutoEngagementDefaultEntry[], required)
    - `fromAccountId` (string, required)
    - `delayMinutes` (integer, required)
- `shareToInstagram` (boolean, optional)

### Responses

#### 200

The mutation was applied

- `ok` (boolean, required, one of `true`)

#### 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)

## Read a TikTok channel's current publishing options

```http
GET https://orbitwrite.com/api/v1/connected-accounts/{accountId}/tiktok/creator-info
```

Requires `account:read`. Returns the privacy levels TikTok will accept for this creator, their comment/Duet/Stitch settings, and their own maximum video length. TikTok requires this before every Direct Post and refuses a privacy level it didn't offer, so build the post's options from this response rather than from a hard-coded list — an app still in review is offered `SELF_ONLY` and nothing else. Never cached: a creator can change these between composing and publishing.

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

### Path parameters

- `accountId` (string, required)

### Responses

#### 200

The creator's current publishing options

- `privacyLevelOptions` (string[], required)
- `commentDisabled` (boolean, required)
- `duetDisabled` (boolean, required)
- `stitchDisabled` (boolean, required)
- `maxVideoPostDurationSec` (integer, required)
- `creatorUsername` (string, optional)
- `creatorNickname` (string, optional)
- `creatorAvatarUrl` (string, optional)

#### 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)

#### 429

Rate limit exceeded

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

#### 502

TikTok couldn't be reached

- `error` (string, required)

## List a Pinterest channel's boards

```http
GET https://orbitwrite.com/api/v1/connected-accounts/{accountId}/pinterest/boards
```

Requires `account:read`. Returns the boards this Pinterest channel can save a Pin to. A Pin is always created on a board, so a post to Pinterest needs `platformOptions.pinterest.boardId` set to one of these ids before it can be scheduled or published. Secret boards aren't listed. Never cached.

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

### Path parameters

- `accountId` (string, required)

### Responses

#### 200

The channel's boards

- `boards` (PinterestBoard[], required)
  - `id` (string, required)
  - `name` (string, required)
  - `description` (string, optional)
  - `privacy` (string, optional)
  - `imageUrl` (string, optional)

#### 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)

#### 429

Rate limit exceeded

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

#### 502

Pinterest couldn't be reached

- `error` (string, required)

## Create a board on a Pinterest channel

```http
POST https://orbitwrite.com/api/v1/connected-accounts/{accountId}/pinterest/boards
```

Requires `account:update`. Creates a public board on this Pinterest channel and returns it, ready to use as `platformOptions.pinterest.boardId`. The board appears on the account's Pinterest profile immediately. Secret boards can't be created. A name Pinterest won't take (one already in use, for example) is a 400 carrying Pinterest's reason.

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

### Path parameters

- `accountId` (string, required)

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

- `name` (string, required)
- `description` (string, optional)

### Responses

#### 201

The new board

- `board` (PinterestBoard, required)
  - `id` (string, required)
  - `name` (string, required)
  - `description` (string, optional)
  - `privacy` (string, optional)
  - `imageUrl` (string, optional)

#### 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)

#### 429

Rate limit exceeded

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

#### 502

Pinterest couldn't be reached

- `error` (string, required)
