# Inbox

15 endpoints.

## List team inboxes

```http
GET https://orbitwrite.com/api/v1/inbox/inboxes
```

Requires `teamInbox:read`. The workspace's routable inboxes with their sources and membership.

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

### Query parameters

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

### Responses

#### 200

The team inboxes

- `inboxes` (TeamInbox[], required)
  - `id` (string, required)
  - `name` (string, required)
  - `description` (string | null, required)
  - `method` (string, required, one of `manual`, `round_robin`, `balanced`)
  - `skillsEnabled` (boolean, required)
  - `awayReassign` (boolean, required)
  - `rrAssignWhenAway` (boolean, required)
  - `position` (number, required) — Routing order: a new conversation goes to the first team inbox, lowest position first, with a source that matches it. Set with `PUT /inbox/inboxes/order`.
  - `wrapUpMinutes` (number, required)
  - `createdAt` (string, required)
  - `updatedAt` (string, required)
  - `sources` (TeamInboxSource[], required)
    - `id` (string, required)
    - `accountId` (string | null, required)
    - `platform` (string | null, required)
    - `type` (string | null, required, one of `reply`, `mention`, `null`)
    - `keywords` (string[], required) — Matches when the preview contains any of these, ignoring case. Empty: no keyword condition.
  - `members` (TeamInboxMember[], required)
    - `userId` (string, required)
    - `tier` (string, required, one of `primary`, `secondary`)
    - `capacity` (number | null, required)
    - `skills` (string[] | null, 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)

## Create a team inbox

```http
POST https://orbitwrite.com/api/v1/inbox/inboxes
```

Requires `teamInbox:create` (manager+). A team inbox receives what its `sources` claim — the first team inbox in the routing order (`PUT /inbox/inboxes/order`; a new one goes last) with a matching source wins — and everything else stays with the workspace's own assignment (`/inbox/assignment`). A source needs at least one condition: account, platform, type, or keywords.

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

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

- `organizationId` (string, optional) — Session callers only — an API key already determines the workspace.
- `name` (string, required)
- `description` (string | null, optional)
- `method` (string, optional, one of `manual`, `round_robin`, `balanced`)
- `skillsEnabled` (boolean, optional)
- `awayReassign` (boolean, optional)
- `rrAssignWhenAway` (boolean, optional)
- `wrapUpMinutes` (integer, optional)
- `sources` (object[], optional)
  - `accountId` (string | null, optional)
  - `platform` (string | null, optional, one of `bluesky`, `twitter`, `threads`, `mastodon`, `facebook_page`, `instagram`, `linkedin_page`, `null`)
  - `type` (string | null, optional, one of `reply`, `mention`, `null`)
  - `keywords` (string[] | null, optional)
- `members` (object[], optional)
  - `userId` (string, required)
  - `tier` (string, optional, one of `primary`, `secondary`)
  - `capacity` (integer | null, optional)
  - `skills` (string[] | null, optional)

### Responses

#### 200

The created inbox

- `id` (string, required)
- `name` (string, required)
- `description` (string | null, required)
- `method` (string, required, one of `manual`, `round_robin`, `balanced`)
- `skillsEnabled` (boolean, required)
- `awayReassign` (boolean, required)
- `rrAssignWhenAway` (boolean, required)
- `position` (number, required) — Routing order: a new conversation goes to the first team inbox, lowest position first, with a source that matches it. Set with `PUT /inbox/inboxes/order`.
- `wrapUpMinutes` (number, required)
- `createdAt` (string, required)
- `updatedAt` (string, required)
- `sources` (TeamInboxSource[], required)
  - `id` (string, required)
  - `accountId` (string | null, required)
  - `platform` (string | null, required)
  - `type` (string | null, required, one of `reply`, `mention`, `null`)
  - `keywords` (string[], required) — Matches when the preview contains any of these, ignoring case. Empty: no keyword condition.
- `members` (TeamInboxMember[], required)
  - `userId` (string, required)
  - `tier` (string, required, one of `primary`, `secondary`)
  - `capacity` (number | null, required)
  - `skills` (string[] | null, 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)

## Set the team inboxes' routing order

```http
PUT https://orbitwrite.com/api/v1/inbox/inboxes/order
```

Requires `teamInbox:update` (manager+). A new conversation goes to the first team inbox, in this order, with a source that matches it; anything no team inbox claims goes to the workspace's assignment. `inboxIds` must list every team inbox exactly once.

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

### Query parameters

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

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

- `inboxIds` (string[], required)

### Responses

#### 200

The team inboxes, in their new order

- `inboxes` (TeamInbox[], required)
  - `id` (string, required)
  - `name` (string, required)
  - `description` (string | null, required)
  - `method` (string, required, one of `manual`, `round_robin`, `balanced`)
  - `skillsEnabled` (boolean, required)
  - `awayReassign` (boolean, required)
  - `rrAssignWhenAway` (boolean, required)
  - `position` (number, required) — Routing order: a new conversation goes to the first team inbox, lowest position first, with a source that matches it. Set with `PUT /inbox/inboxes/order`.
  - `wrapUpMinutes` (number, required)
  - `createdAt` (string, required)
  - `updatedAt` (string, required)
  - `sources` (TeamInboxSource[], required)
    - `id` (string, required)
    - `accountId` (string | null, required)
    - `platform` (string | null, required)
    - `type` (string | null, required, one of `reply`, `mention`, `null`)
    - `keywords` (string[], required) — Matches when the preview contains any of these, ignoring case. Empty: no keyword condition.
  - `members` (TeamInboxMember[], required)
    - `userId` (string, required)
    - `tier` (string, required, one of `primary`, `secondary`)
    - `capacity` (number | null, required)
    - `skills` (string[] | null, 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)

## Get my inbox availability

```http
GET https://orbitwrite.com/api/v1/inbox/status
```

Requires a signed-in user. The caller's own status.

**Authentication:** session cookie.

### Query parameters

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

### Responses

#### 200

The caller's status

- `userId` (string, required)
- `status` (string, required, one of `active`, `away`, `away_reassign`)
- `autoAway` (boolean, required)
- `updatedAt` (string, 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)

## Set inbox availability

```http
PUT https://orbitwrite.com/api/v1/inbox/status
```

Requires `inboxStatus:update` for your own status; naming another `userId` needs `inboxStatus:manageAny` (manager+) and a member of the workspace. A workspace API key has no status of its own, so it must name `userId` and needs `inboxStatus:manageAny`. Away/away_reassign gate a teammate out of automatic assignment.

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

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

- `organizationId` (string, optional) — Session callers only — an API key already determines the workspace.
- `userId` (string, optional)
- `status` (string, required, one of `active`, `away`, `away_reassign`)

### Responses

#### 200

The updated status

- `userId` (string, required)
- `status` (string, required, one of `active`, `away`, `away_reassign`)
- `autoAway` (boolean, required)
- `updatedAt` (string, 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)

## Heartbeat: I'm active in the inbox

```http
POST https://orbitwrite.com/api/v1/inbox/presence
```

Requires a signed-in user. Records the caller as active so the auto-away sweep doesn't flag them; resuming after an auto-away clears it immediately.

**Authentication:** session cookie.

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

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

### Responses

#### 200

Recorded

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

## The team pool

```http
GET https://orbitwrite.com/api/v1/inbox/team
```

Requires `inboxStatus:read`. Every member with their availability and current open-conversation load.

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

### Query parameters

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

### Responses

#### 200

The team pool

- `members` (TeamPoolMember[], required)
  - `userId` (string, required)
  - `name` (string, required)
  - `avatarUrl` (string | null, required)
  - `status` (string, required, one of `active`, `away`, `away_reassign`)
  - `autoAway` (boolean, required)
  - `openCount` (number, 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)

## Get workspace inbox settings

```http
GET https://orbitwrite.com/api/v1/inbox/settings
```

Requires `teamInbox:read`. Defaults when never configured.

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

### Query parameters

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

### Responses

#### 200

The settings

- `defaultMemberCapacity` (number, required)
- `autoAwayThresholdMinutes` (number, required)
- `autoAwayPausesAssignment` (boolean, required)
- `collisionHandling` (string, required, one of `off`, `warn`, `soft_lock`)

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

## Update workspace inbox settings

```http
PUT https://orbitwrite.com/api/v1/inbox/settings
```

Requires `teamInbox:update` (manager+). Partial — omitted fields stay.

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

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

- `organizationId` (string, optional) — Session callers only — an API key already determines the workspace.
- `defaultMemberCapacity` (integer, optional)
- `autoAwayThresholdMinutes` (integer, optional)
- `autoAwayPausesAssignment` (boolean, optional)
- `collisionHandling` (string, optional, one of `off`, `warn`, `soft_lock`)

### Responses

#### 200

The updated settings

- `defaultMemberCapacity` (number, required)
- `autoAwayThresholdMinutes` (number, required)
- `autoAwayPausesAssignment` (boolean, required)
- `collisionHandling` (string, required, one of `off`, `warn`, `soft_lock`)

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

## How the workspace assigns conversations

```http
GET https://orbitwrite.com/api/v1/inbox/assignment
```

Requires `teamInbox:read`. The method and rotation applied to every conversation no team inbox claims, plus `waitingCount` — how many open conversations have no owner. A workspace that has never changed it reads as the default: round robin across everyone.

**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 assignment

- `method` (string, required, one of `manual`, `round_robin`, `balanced`)
- `allMembers` (boolean, required) — The rotation is every workspace member, including people who join later. When false, `members` is the rotation.
- `members` (TeamInboxMember[], required) — The named rotation. Kept while `allMembers` is on, so switching back restores it.
  - `userId` (string, required)
  - `tier` (string, required, one of `primary`, `secondary`)
  - `capacity` (number | null, required)
  - `skills` (string[] | null, required)
- `rrAssignWhenAway` (boolean, required)
- `wrapUpMinutes` (number, required)
- `waitingCount` (number, required) — Open conversations with no owner right now.
- `waitingInManual` (object[], required) — Of the waiting conversations, those routing files under a manual inbox, per inbox. `POST /inbox/assignment/distribute` can't assign these; someone pulls them.
  - `inboxId` (string, required)
  - `name` (string, required)
  - `isWorkspace` (boolean, required) — The workspace inbox itself — the workspace's assignment is manual.
  - `count` (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)

## Set how the workspace assigns conversations

```http
PUT https://orbitwrite.com/api/v1/inbox/assignment
```

Requires `teamInbox:update` (manager+). A patch: omitted fields keep their value. `allMembers:true` puts every workspace member in the rotation, including people who join later; with it off, `members` is the rotation and must name someone while the method assigns automatically. Applies to conversations arriving after it — `POST /inbox/assignment/distribute` hands out the ones already waiting.

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

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

- `organizationId` (string, optional) — Session callers only — an API key already determines the workspace.
- `method` (string, optional, one of `manual`, `round_robin`, `balanced`)
- `allMembers` (boolean, optional)
- `members` (object[], optional)
  - `userId` (string, required)
  - `tier` (string, optional, one of `primary`, `secondary`)
  - `capacity` (integer | null, optional)
  - `skills` (string[] | null, optional)
- `rrAssignWhenAway` (boolean, optional)
- `wrapUpMinutes` (integer, optional)

### Responses

#### 200

The updated assignment

- `method` (string, required, one of `manual`, `round_robin`, `balanced`)
- `allMembers` (boolean, required) — The rotation is every workspace member, including people who join later. When false, `members` is the rotation.
- `members` (TeamInboxMember[], required) — The named rotation. Kept while `allMembers` is on, so switching back restores it.
  - `userId` (string, required)
  - `tier` (string, required, one of `primary`, `secondary`)
  - `capacity` (number | null, required)
  - `skills` (string[] | null, required)
- `rrAssignWhenAway` (boolean, required)
- `wrapUpMinutes` (number, required)
- `waitingCount` (number, required) — Open conversations with no owner right now.
- `waitingInManual` (object[], required) — Of the waiting conversations, those routing files under a manual inbox, per inbox. `POST /inbox/assignment/distribute` can't assign these; someone pulls them.
  - `inboxId` (string, required)
  - `name` (string, required)
  - `isWorkspace` (boolean, required) — The workspace inbox itself — the workspace's assignment is manual.
  - `count` (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)

## Hand out the conversations already waiting

```http
POST https://orbitwrite.com/api/v1/inbox/assignment/distribute
```

Requires `teamInbox:update` (manager+). Assigns open conversations that have no owner, oldest first, through the same routing a new arrival gets — the workspace's assignment, or a team inbox's when one claims the conversation. Routing only decides a conversation when it arrives, so this is how a backlog gets owners. Up to 500 a call; `waiting` is how many still have none (a manual method, or nobody available, assigns nothing), and `waitingInManual` which of those a manual inbox holds — another call won't assign them.

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

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

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

### Responses

#### 200

How many were assigned, and how many still wait

- `assigned` (integer, required)
- `waiting` (integer, required)
- `waitingInManual` (object[], required) — Of the waiting conversations, those routing files under a manual inbox, per inbox. `POST /inbox/assignment/distribute` can't assign these; someone pulls them.
  - `inboxId` (string, required)
  - `name` (string, required)
  - `isWorkspace` (boolean, required) — The workspace inbox itself — the workspace's assignment is manual.
  - `count` (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)

## Get a team inbox

```http
GET https://orbitwrite.com/api/v1/inbox/inboxes/{inboxId}
```

Requires `teamInbox:read`.

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

### Path parameters

- `inboxId` (string, required)

### Query parameters

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

### Responses

#### 200

The team inbox

- `id` (string, required)
- `name` (string, required)
- `description` (string | null, required)
- `method` (string, required, one of `manual`, `round_robin`, `balanced`)
- `skillsEnabled` (boolean, required)
- `awayReassign` (boolean, required)
- `rrAssignWhenAway` (boolean, required)
- `position` (number, required) — Routing order: a new conversation goes to the first team inbox, lowest position first, with a source that matches it. Set with `PUT /inbox/inboxes/order`.
- `wrapUpMinutes` (number, required)
- `createdAt` (string, required)
- `updatedAt` (string, required)
- `sources` (TeamInboxSource[], required)
  - `id` (string, required)
  - `accountId` (string | null, required)
  - `platform` (string | null, required)
  - `type` (string | null, required, one of `reply`, `mention`, `null`)
  - `keywords` (string[], required) — Matches when the preview contains any of these, ignoring case. Empty: no keyword condition.
- `members` (TeamInboxMember[], required)
  - `userId` (string, required)
  - `tier` (string, required, one of `primary`, `secondary`)
  - `capacity` (number | null, required)
  - `skills` (string[] | null, 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)

## Update a team inbox

```http
PATCH https://orbitwrite.com/api/v1/inbox/inboxes/{inboxId}
```

Requires `teamInbox:update` (manager+). `sources` and `members`, when present, replace the existing lists.

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

### Path parameters

- `inboxId` (string, required)

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

- `organizationId` (string, optional) — Session callers only — an API key already determines the workspace.
- `name` (string, optional)
- `description` (string | null, optional)
- `method` (string, optional, one of `manual`, `round_robin`, `balanced`)
- `skillsEnabled` (boolean, optional)
- `awayReassign` (boolean, optional)
- `rrAssignWhenAway` (boolean, optional)
- `wrapUpMinutes` (integer, optional)
- `sources` (object[], optional)
  - `accountId` (string | null, optional)
  - `platform` (string | null, optional, one of `bluesky`, `twitter`, `threads`, `mastodon`, `facebook_page`, `instagram`, `linkedin_page`, `null`)
  - `type` (string | null, optional, one of `reply`, `mention`, `null`)
  - `keywords` (string[] | null, optional)
- `members` (object[], optional)
  - `userId` (string, required)
  - `tier` (string, optional, one of `primary`, `secondary`)
  - `capacity` (integer | null, optional)
  - `skills` (string[] | null, optional)

### Responses

#### 200

The updated inbox

- `id` (string, required)
- `name` (string, required)
- `description` (string | null, required)
- `method` (string, required, one of `manual`, `round_robin`, `balanced`)
- `skillsEnabled` (boolean, required)
- `awayReassign` (boolean, required)
- `rrAssignWhenAway` (boolean, required)
- `position` (number, required) — Routing order: a new conversation goes to the first team inbox, lowest position first, with a source that matches it. Set with `PUT /inbox/inboxes/order`.
- `wrapUpMinutes` (number, required)
- `createdAt` (string, required)
- `updatedAt` (string, required)
- `sources` (TeamInboxSource[], required)
  - `id` (string, required)
  - `accountId` (string | null, required)
  - `platform` (string | null, required)
  - `type` (string | null, required, one of `reply`, `mention`, `null`)
  - `keywords` (string[], required) — Matches when the preview contains any of these, ignoring case. Empty: no keyword condition.
- `members` (TeamInboxMember[], required)
  - `userId` (string, required)
  - `tier` (string, required, one of `primary`, `secondary`)
  - `capacity` (number | null, required)
  - `skills` (string[] | null, 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)

## Delete a team inbox

```http
DELETE https://orbitwrite.com/api/v1/inbox/inboxes/{inboxId}
```

Requires `teamInbox:delete` (manager+). Its conversations keep their owners and go back to the workspace's own assignment.

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

### Path parameters

- `inboxId` (string, required)

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

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

### Responses

#### 200

Deleted

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