# AI

10 endpoints.

## Run a composer assistant intent

```http
POST https://orbitwrite.com/api/v1/ai/assistant
```

Streams AI-generated text for one of the assistant panel's intents (refine, optimize, tone, translate, CTA, hashtags, promote a URL, generate, ideas). Scoped to the session's active workspace.

**Authentication:** session cookie.

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

### Responses

#### 200

The generated text stream

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

#### 429

Rate limit exceeded

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

#### 500

No AI provider configured

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

## Refine post text

```http
POST https://orbitwrite.com/api/v1/ai/refine
```

Streams an edited version of the supplied post text for one of the refine palette's actions. The free-text `custom` action runs an abuse pre-flight (scope classifier + moderation). Scoped to the session's active workspace.

**Authentication:** session cookie.

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

- `prompt` (string, required)
- `action` (string, required, one of `improve`, `grammar`, `spelling`, `punchier`, `shorten`, `expand`, `rewrite`, `announcement`, `structure`, `positive`, `split`, `poll`, `custom`)
- `platform` (string, optional)
- `maxCharsPerPost` (integer, optional)
- `accountId` (string, optional)
- `fullContext` (string, optional)
- `instruction` (string, optional)
- `variation` (integer, optional)

### Responses

#### 200

The generated text stream

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

#### 422

Custom instruction refused by the scope guard

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

#### 429

Rate limit exceeded

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

#### 500

No AI provider configured

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

## Plan campaign post angles from an article

```http
POST https://orbitwrite.com/api/v1/ai/campaign-plan
```

Reads the article behind a campaign's source URL and breaks its content into `count` distinct post angles. Free-text sources return `reason: "not_url"` so the client can fall back to its template generator.

**Authentication:** session cookie.

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

- `source` (string, required)
- `count` (integer, required)
- `variation` (integer, optional)

### Responses

#### 200

The planned angles, or a not_url fallback signal

- `ok` (boolean, required)
- `topics` (string[], optional)
- `title` (string | null, optional)
- `truncated` (boolean, optional)
- `reason` (string, optional)
- `error` (string, optional)

#### 400

Invalid request

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

#### 401

Not signed in

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

#### 422

The URL couldn't be fetched or read

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

#### 429

Rate limit exceeded

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

#### 502

The model couldn't produce topics from the article

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

## Generate a campaign name

```http
POST https://orbitwrite.com/api/v1/ai/campaign-name
```

Generates a short campaign name from free-text context. Non-streaming.

**Authentication:** session cookie.

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

- `context` (string, required) — Free-text topic the name is derived from

### Responses

#### 200

The generated name

- `ok` (boolean, required)
- `name` (string, optional)
- `error` (string, optional)

#### 400

Invalid request

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

#### 401

Not signed in

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

#### 429

Rate limit exceeded

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

#### 500

No AI provider configured

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

## Generate alt text for an image

```http
POST https://orbitwrite.com/api/v1/ai/alt-text
```

Describes one of the workspace's uploaded images for screen readers, by `mediaId` or by its `url`. Optional `context` (the post's text) steers what the description emphasises. Returns a suggestion and stores nothing — set it as `altText` on the post's attachment to use it. Spends one AI assist; requires `media:read`. At most 1,000 characters, the shortest limit among the networks that take alt text.

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

- `mediaId` (string, optional) — The image's media id — from an upload, list_media, or a post's attachment.
- `url` (string, optional) — The image's URL, for an attachment that carries no media id. Must be one of this workspace's own uploads.
- `context` (string, optional) — The post the image goes with. Used to decide what in the image matters, never as a source of facts the image doesn't show.

### Responses

#### 200

The suggested alt text

- `mediaId` (string, required)
- `altText` (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)

#### 404

The resource does not exist

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

#### 429

Rate limit exceeded

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

#### 502

An upstream provider failed

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

## Chat with the assistant agent

```http
POST https://orbitwrite.com/api/v1/ai/agent
```

Streams an AI SDK UI message stream for a free-text conversation in which the model may call workspace tools (the MCP server's, under the caller's own permissions), app tools (run by the browser, such as opening a post) and, when `context` describes an open composer, composer tools (run by the browser on the open post). Tools that change or remove existing state stop for the caller's approval. Session only.

**Authentication:** session cookie.

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

- `messages` (any[], required)
- `organizationId` (string, optional)
- `context` (object, optional)
  - `groupId` (string | null, required)
  - `title` (string, optional)
  - `tags` (string[], optional)
  - `text` (string, optional)
  - `status` (string | null, optional)
  - `scheduledAt` (string | null, optional)
  - `channels` (object[], optional)
    - `id` (string, required)
    - `platform` (string, required)
    - `name` (string | null, required)
    - `maxChars` (integer | null, required)
    - `threads` (boolean | null, optional)
    - `maxMedia` (integer | null, optional)
    - `synced` (boolean, required)
    - `format` (string | null, optional, one of `post`, `story`, `reel`, `short`, `null`)
    - `formats` (string[], optional)
    - `engagement` (string[], optional)
  - `timezone` (string | null, optional)
  - `suggestions` (object[], optional)
    - `id` (string, required)
    - `type` (string | null, required)
    - `text` (string, required)
  - `openComments` (integer, optional)
  - `media` (object[], optional)
    - `mimeType` (string, required)
    - `alt` (string | null, required)
    - `mediaId` (string | null, optional)
- `page` (object, optional)
  - `path` (string, required)
  - `title` (string | null, optional)
  - `timezone` (string | null, optional)
  - `details` (string[], optional)
  - `focus` (object[], optional)
    - `type` (string, required, one of `campaign`, `post`, `channel`, `conversation`)
    - `id` (string, required)
    - `label` (string | null, required)
- `approvalMode` (string, optional, one of `ask`, `auto`)
- `conversationId` (string, optional)

### Responses

#### 200

The UI message stream

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

#### 429

Rate limit exceeded

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

#### 500

No AI provider configured

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

#### 501

This host serves no agent

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

## Your recent conversations with Orb AI

```http
GET https://orbitwrite.com/api/v1/assistant/conversations
```

Newest first, up to 30. Your own only. Session only.

**Authentication:** session cookie.

### Query parameters

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

### Responses

#### 200

The history list

- `conversations` (AssistantConversationSummary[], required)
  - `id` (string, required)
  - `title` (string, required)
  - `updatedAt` (string, required)

#### 401

Not signed in

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

#### 403

Not a member of the organization

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

## One of your conversations with Orb AI

```http
GET https://orbitwrite.com/api/v1/assistant/conversations/{id}
```

**Authentication:** session cookie.

### Path parameters

- `id` (string, required)

### Query parameters

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

### Responses

#### 200

The conversation

- `id` (string, required)
- `title` (string, required)
- `updatedAt` (string, required)
- `messages` (any[], required) — The AI SDK UI transcript, as the chat held it.

#### 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 one of your conversations with Orb AI

```http
DELETE https://orbitwrite.com/api/v1/assistant/conversations/{id}
```

**Authentication:** session cookie.

### Path parameters

- `id` (string, required)

### Query parameters

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

### Responses

#### 204

Deleted

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

## Record a post created from one of Orb AI's post cards

```http
POST https://orbitwrite.com/api/v1/assistant/conversations/{id}/created-posts
```

Marks the `show_post` card `toolCallId` as created as the draft `groupId`, so the card stays created after a reload and Orb AI's next turn knows the post exists. Your own conversations only. Session only.

**Authentication:** session cookie.

### Path parameters

- `id` (string, required)

### Query parameters

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

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

- `toolCallId` (string, required)
- `groupId` (string, required)

### Responses

#### 204

Recorded

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