> ## Documentation Index
> Fetch the complete documentation index at: https://raveculture-mintlify-api-spec-sync-1774445910.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Agents API

> Create, manage, and interact with agents

# Agents API

Create, manage, and interact with agents.

<Note>All agent endpoints that require authentication are scoped to the authenticated user's data through [row-level security](/security#row-level-security). You can only access agents that belong to your account.</Note>

## List agents

```http theme={null}
GET /api/agents
```

Returns all agents owned by the authenticated user. When no session is present, returns an empty list instead of a `401` error.

### Response (backend)

The backend returns a flat array of agent objects:

```json theme={null}
[
  {
    "id": "agent_123",
    "status": "active",
    "created": "2026-03-01T00:00:00Z",
    "subdomain": "agent_123.agents.localhost",
    "url": "https://agent_123.agents.localhost"
  }
]
```

| Field          | Type   | Description                 |
| -------------- | ------ | --------------------------- |
| `[].id`        | string | Agent identifier            |
| `[].status`    | string | Current agent status        |
| `[].created`   | string | ISO 8601 creation timestamp |
| `[].subdomain` | string | Agent subdomain             |
| `[].url`       | string | Agent URL                   |

### Response (web proxy)

The web proxy wraps the response in an object:

```json theme={null}
{
  "agents": [
    {
      "id": "agent_123",
      "name": "My Agent",
      "model": "claude-opus-4-6",
      "status": "running",
      "websocketUrl": "ws://openclaw-gateway:10000/agent/user_123",
      "createdAt": "2026-03-01T00:00:00Z",
      "updatedAt": "2026-03-01T12:00:00Z"
    }
  ],
  "count": 1,
  "status": "ok"
}
```

| Field                   | Type   | Description                                           |
| ----------------------- | ------ | ----------------------------------------------------- |
| `agents`                | array  | List of agent objects owned by the authenticated user |
| `agents[].id`           | string | Agent identifier                                      |
| `agents[].name`         | string | Agent name                                            |
| `agents[].model`        | string | AI model assigned to the agent                        |
| `agents[].status`       | string | Current agent status                                  |
| `agents[].websocketUrl` | string | WebSocket URL for the agent gateway                   |
| `agents[].createdAt`    | string | ISO 8601 creation timestamp                           |
| `agents[].updatedAt`    | string | ISO 8601 last update timestamp                        |
| `count`                 | number | Total number of agents returned                       |
| `status`                | string | Response status (`ok`)                                |

<Note>The backend and web proxy return different response shapes. The backend returns a flat array with `created`, `subdomain`, and `url` fields. The web proxy wraps the data in an `agents` key and includes `name`, `model`, `websocketUrl`, `createdAt`, and `updatedAt` fields.</Note>

## Create agent

```http theme={null}
POST /api/agents
```

Creates a new agent with an auto-generated ID and stores its metadata on disk. Requires bearer token authentication (backend).

### Request body

| Field               | Type   | Required | Description                                                       |
| ------------------- | ------ | -------- | ----------------------------------------------------------------- |
| `name`              | string | Yes      | Agent name                                                        |
| `config`            | object | No       | Agent configuration                                               |
| `config.plan`       | string | No       | Plan tier (for example, `solo`, `collective`, `label`, `network`) |
| `config.aiProvider` | string | No       | AI provider (for example, `openrouter`, `anthropic`)              |

### Response (201 Created)

```json theme={null}
{
  "id": "agent_123",
  "name": "My Agent",
  "agentId": "agent_123",
  "status": "pending",
  "subdomain": "agent_123.agents.localhost",
  "url": "https://agent_123.agents.localhost",
  "createdAt": "2026-03-19T00:00:00Z"
}
```

### Errors

| Code | Description            |
| ---- | ---------------------- |
| 400  | Agent name is required |
| 401  | Unauthorized           |
| 500  | Failed to create agent |

<Note>For provisioning an agent with messaging channel tokens and a live Render service deployment, use [`POST /api/agents/provision`](#provision-agent) or [`POST /api/provision`](#provision-with-channel-tokens) instead.</Note>

## Get agent

```http theme={null}
GET /api/agents/:id
```

Requires authentication and ownership of the agent.

### Response (backend)

The backend returns the agent object directly without a wrapper:

```json theme={null}
{
  "id": "agent_123",
  "status": "active",
  "startedAt": "2026-03-01T00:00:00Z",
  "plan": "solo",
  "subdomain": "agent_123.agents.localhost",
  "url": "https://agent_123.agents.localhost",
  "openclawVersion": "2026.3.22",
  "verified": false,
  "verificationType": null,
  "attestationUid": null,
  "verifiedAt": null
}
```

### Response (web proxy)

The web proxy wraps the agent in an object:

```json theme={null}
{
  "agent": {
    "id": "agent_123",
    "status": "active",
    "startedAt": "2026-03-01T00:00:00Z",
    "plan": "solo",
    "subdomain": "agent_123.agents.localhost",
    "url": "https://agent_123.agents.localhost",
    "openclawVersion": "2026.3.22",
    "verified": false,
    "verificationType": null,
    "attestationUid": null,
    "verifiedAt": null
  },
  "status": "ok"
}
```

<Note>The backend returns the agent object directly. The web proxy wraps it in an `agent` key and adds a top-level `status` field.</Note>

### Errors

| Code | Description                          |
| ---- | ------------------------------------ |
| 401  | Unauthorized                         |
| 404  | Agent not found or not owned by user |
| 500  | Failed to fetch agent                |

## Update agent

```http theme={null}
PUT /api/agents/:id
```

Updates an agent's metadata including plan, AI provider, and configuration. Requires bearer token authentication (backend).

### Request body

| Field        | Type   | Required | Description              |
| ------------ | ------ | -------- | ------------------------ |
| `plan`       | string | No       | Plan tier                |
| `aiProvider` | string | No       | AI provider              |
| `config`     | object | No       | Additional configuration |

### Response

```json theme={null}
{
  "id": "agent_123",
  "plan": "collective",
  "aiProvider": "anthropic",
  "subdomain": "agent_123.agents.localhost",
  "status": "active",
  "message": "Agent updated"
}
```

### Errors

| Code | Description            |
| ---- | ---------------------- |
| 401  | Unauthorized           |
| 404  | Agent not found        |
| 500  | Failed to update agent |

<Note>To update agent configuration through the web proxy with session authentication, use [`PUT /api/agents/:id/config`](#update-agent-configuration) instead.</Note>

## Delete agent

```http theme={null}
DELETE /api/agents/:id
```

Destroys the agent's Render service and removes its metadata. Requires bearer token authentication (backend).

### Response

```json theme={null}
{
  "id": "agent_123",
  "deleted": true
}
```

### Errors

| Code | Description            |
| ---- | ---------------------- |
| 401  | Unauthorized           |
| 500  | Failed to delete agent |

<Note>The backend uses best-effort cleanup (service destruction and metadata removal). If the agent does not exist, the operation succeeds silently and returns `deleted: true`.</Note>

## Provision agent

```http theme={null}
POST /api/agents/provision
```

Provisions a new agent. Requires an active subscription unless the caller is an admin.

<Note>Provisioning requests may be processed asynchronously through the background task queue. The agent is created immediately with a `provisioning` status and transitions to `running` once the backend deployment endpoint confirms the deployment. If deployment fails, the status changes to `error`.</Note>

<Note>The provisioning endpoint calls `POST /api/deployments` on the backend to deploy the agent as a Render service. The request includes a 15-second timeout. When the model is set to `claude-opus-4-6`, the AI provider is automatically set to `anthropic`; otherwise it falls back to the provider specified in the agent configuration (default: `openrouter`). The plan sent to the backend defaults to `label` when no tier is specified.</Note>

### Request body

| Field    | Type   | Required | Description                                                                                                                                                                                                                                 |
| -------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`   | string | Yes      | Agent name                                                                                                                                                                                                                                  |
| `model`  | string | No       | AI model (default: `claude-opus-4-6`). Options: `claude-opus-4-6`, `gpt-4`, `custom`                                                                                                                                                        |
| `config` | object | No       | Agent configuration                                                                                                                                                                                                                         |
| `tier`   | string | No       | Subscription tier hint. Options: `starter`, `pro`, `enterprise`. This value is forwarded to the backend as the `plan` field (mapped to `solo`, `collective`, `label`, `network`). When omitted, the backend deployment defaults to `label`. |

<Note>The web proxy enforces agent limits based on the subscription tier (`starter`: 1, `pro`: 3, `enterprise`: 100). The backend provisioning route (`POST /api/provision`) enforces its own limits (`solo`: 1, `collective`: 3, `label`: 10, `network`: practically unlimited). Plan resource allocations: `solo` → 2 GB RAM / 1 CPU, `collective` → 4 GB RAM / 2 CPUs, `label` → 8 GB RAM / 4 CPUs, `network` → 16 GB RAM / 4 CPUs. The limit cannot be overridden in the request body.</Note>

### Admin bypass

Admin users (configured via `ADMIN_EMAILS`) are exempt from the following restrictions:

* **Subscription requirement** — admins can provision agents without an active subscription (the `402` error is not returned).
* **Agent limit** — admins receive an elevated agent slot limit instead of the plan-based cap.

### Response (201 Created)

```json theme={null}
{
  "success": true,
  "agent": {
    "id": "agent_789",
    "name": "My Agent",
    "status": "running",
    "websocketUrl": "ws://openclaw-gateway:10000/agent/user_123",
    "model": "claude-opus-4-6",
    "createdAt": "2026-03-19T00:00:00Z"
  }
}
```

### Errors

| Code | Description                                                                                                                                                                                                                                                                                             |
| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400  | Agent name is required                                                                                                                                                                                                                                                                                  |
| 401  | Unauthorized                                                                                                                                                                                                                                                                                            |
| 402  | Active subscription required to provision agents                                                                                                                                                                                                                                                        |
| 429  | Agent limit reached for your plan (web proxy). Response includes `current` (agent count) and `limit` fields. Limits: `starter` 1, `pro` 3, `enterprise` 100. Users without a recognized plan default to a limit of 1. The backend returns `402` with code `AGENT_LIMIT_REACHED` for the same condition. |
| 500  | Failed to provision agent                                                                                                                                                                                                                                                                               |

## Clone agent

```http theme={null}
POST /api/agents/clone
```

Creates a new agent by cloning an existing parent agent. Requires a verified payment proof on the Tempo chain (x402 protocol). The caller must pay 1.0 pathUSD to clone an agent.

<Note>This endpoint uses the [x402 Tempo protocol](/payments/x402#tempo-chain) for payment verification. The payment must be completed on the Tempo chain (chain ID `4217`) before calling this endpoint.</Note>

### Request body

| Field            | Type   | Required | Description                                                                                                               |
| ---------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------- |
| `parentAgentId`  | string | Yes      | ID of the agent to clone                                                                                                  |
| `name`           | string | Yes      | Name for the new agent                                                                                                    |
| `specialization` | string | No       | Agent specialization. Options: `general` (default), `ar`, `promo`, `booking`, `support`, `analytics`                      |
| `paymentProof`   | object | Yes      | On-chain payment proof (see below)                                                                                        |
| `generation`     | number | No       | Current generation depth of the parent agent (default: `1`). The cloned agent's generation is set to this value plus one. |

#### Payment proof object

| Field             | Type   | Required | Description                                            |
| ----------------- | ------ | -------- | ------------------------------------------------------ |
| `transactionHash` | string | Yes      | Transaction hash on Tempo chain (must start with `0x`) |
| `amount`          | string | Yes      | Payment amount (must be at least `1.0`)                |
| `currency`        | string | Yes      | Must be `pathUSD`                                      |
| `chainId`         | number | Yes      | Must be `4217` (Tempo chain)                           |
| `from`            | string | Yes      | Sender wallet address                                  |
| `to`              | string | Yes      | Recipient wallet address                               |
| `timestamp`       | number | Yes      | Unix timestamp of the payment                          |

### Response (200)

```json theme={null}
{
  "success": true,
  "agentId": "agent_1711234567890_a1b2c3",
  "walletAddress": "0x1234...abcd",
  "parentAgentId": "agent_789",
  "generation": 2,
  "transactionHash": "0xabc123...",
  "specialization": "general",
  "status": "provisioning",
  "message": "Agent \"My Clone\" cloned successfully. Wallet funded with 0 pathUSD."
}
```

| Field             | Type    | Description                                           |
| ----------------- | ------- | ----------------------------------------------------- |
| `success`         | boolean | Whether the clone was created                         |
| `agentId`         | string  | Unique identifier for the new agent                   |
| `walletAddress`   | string  | Wallet address assigned to the new agent              |
| `parentAgentId`   | string  | ID of the parent agent                                |
| `generation`      | number  | Generation depth (number of hops from the root agent) |
| `transactionHash` | string  | Transaction hash from the payment proof               |
| `specialization`  | string  | Agent specialization                                  |
| `status`          | string  | Always `provisioning` on success                      |
| `message`         | string  | Human-readable confirmation message                   |

### Errors

| Code | Description                                                         |
| ---- | ------------------------------------------------------------------- |
| 400  | Missing required fields: `parentAgentId`, `name`, or `paymentProof` |
| 402  | Invalid payment proof — transaction not verified on Tempo chain     |
| 500  | Clone failed                                                        |

### Clone service health

```http theme={null}
GET /api/agents/clone
```

Returns the clone service status and protocol configuration. No authentication required.

```json theme={null}
{
  "service": "agentbot-clone",
  "version": "0.1.0",
  "protocol": "x402-tempo",
  "clonePrice": "1.0 pathUSD",
  "chainId": 4217
}
```

| Field        | Type   | Description                      |
| ------------ | ------ | -------------------------------- |
| `service`    | string | Service identifier               |
| `version`    | string | Clone service version            |
| `protocol`   | string | Payment protocol used            |
| `clonePrice` | string | Current price to clone an agent  |
| `chainId`    | number | Blockchain chain ID for payments |

## List provisioned agents

```http theme={null}
GET /api/agents/provision
```

Requires session authentication.

### Response

```json theme={null}
{
  "success": true,
  "agents": [
    {
      "id": "agent_789",
      "name": "My Agent",
      "model": "claude-opus-4-6",
      "status": "running",
      "websocketUrl": "ws://openclaw-gateway:10000/agent/user_123",
      "createdAt": "2026-03-19T00:00:00Z",
      "updatedAt": "2026-03-19T00:00:00Z"
    }
  ],
  "count": 1
}
```

### Errors

| Code | Description           |
| ---- | --------------------- |
| 401  | Unauthorized          |
| 500  | Failed to list agents |

## Get agent configuration

```http theme={null}
GET /api/agents/:id/config
```

Returns the current configuration for an agent. Requires authentication and ownership.

### Response

```json theme={null}
{
  "config": {},
  "status": "ok"
}
```

### Errors

| Code | Description                                      |
| ---- | ------------------------------------------------ |
| 401  | Unauthorized                                     |
| 404  | Agent not found or agent configuration not found |
| 500  | Failed to fetch agent configuration              |

## Update agent configuration

```http theme={null}
PUT /api/agents/:id/config
```

Updates the configuration for an agent. Requires authentication and ownership. The request body is forwarded to the backend.

### Response

```json theme={null}
{
  "config": {},
  "status": "updated"
}
```

### Errors

| Code | Description                          |
| ---- | ------------------------------------ |
| 401  | Unauthorized                         |
| 404  | Agent not found                      |
| 500  | Failed to update agent configuration |

## Get agent logs

```http theme={null}
GET /api/agents/:id/logs
```

Returns logs for an agent. Requires authentication and ownership.

<Warning>This endpoint currently returns mock data. Log entries are generated placeholders, not real agent logs. For real-time logs, use the [live log stream](#stream-agent-logs) endpoint instead.</Warning>

### Query parameters

| Parameter | Type   | Description                                                |
| --------- | ------ | ---------------------------------------------------------- |
| `limit`   | number | Maximum log entries to return (default: 50, max: 100)      |
| `level`   | string | Filter by log level (for example, `info`, `error`, `warn`) |

### Response

```json theme={null}
{
  "logs": [
    {
      "id": "log_1",
      "timestamp": "2026-03-19T00:00:00Z",
      "level": "info",
      "message": "Agent activity log entry 1",
      "source": "agent",
      "agentId": "agent_123"
    }
  ],
  "total": 50,
  "limit": 50,
  "status": "ok"
}
```

### Errors

| Code | Description          |
| ---- | -------------------- |
| 401  | Unauthorized         |
| 404  | Agent not found      |
| 500  | Failed to fetch logs |

## Stream agent logs

<Info>The live log streaming endpoints (`/api/logs/:agentId/stream`, `/api/logs/:agentId/history`, `POST /api/logs/:agentId/stop`, and `GET /api/logs/active`) are planned for a future release. See the [live log tail](/api-reference/log-tail) page for the intended specification.</Info>

## Get agent messages

```http theme={null}
GET /api/agents/:id/messages
```

Returns paginated messages for an agent. Requires authentication and ownership.

### Query parameters

| Parameter | Type   | Description                                        |
| --------- | ------ | -------------------------------------------------- |
| `limit`   | number | Maximum messages to return (default: 50, max: 100) |
| `offset`  | number | Offset for pagination (default: 0)                 |

### Response

```json theme={null}
{
  "messages": [
    {
      "id": "msg_1",
      "agentId": "agent_123",
      "sender": "user",
      "content": "Hello",
      "timestamp": "2026-03-19T00:00:00Z",
      "platform": "telegram"
    }
  ],
  "total": 0,
  "limit": 50,
  "offset": 0,
  "status": "ok"
}
```

<Warning>This endpoint currently returns mock data. Message entries are generated placeholders. A future release will connect this endpoint to the backend message store.</Warning>

### Errors

| Code | Description              |
| ---- | ------------------------ |
| 401  | Unauthorized             |
| 404  | Agent not found          |
| 500  | Failed to fetch messages |

## Get agent stats

```http theme={null}
GET /api/agents/:id/stats
```

Returns live service metrics when available, with a mock fallback.

### Response (live)

```json theme={null}
{
  "stats": {
    "agentId": "agent_123",
    "cpu": "0.15%",
    "memory": "128MiB / 2GiB",
    "memoryPercent": "6.25%",
    "network": "1.2kB / 3.4kB",
    "uptime": 86400000,
    "uptimeFormatted": "1d 0h",
    "status": "running",
    "pids": "12",
    "messagesProcessed": "N/A",
    "messagesPerHour": "N/A",
    "averageResponseTime": "N/A",
    "successRate": "N/A",
    "errorRate": "N/A"
  },
  "status": "ok"
}
```

### Response (mock fallback)

When the backend is unavailable, mock data is returned with `"status": "mock"`:

```json theme={null}
{
  "stats": {
    "agentId": "agent_123",
    "messagesProcessed": 1234,
    "messagesPerHour": 456,
    "averageResponseTime": 789,
    "uptime": 12345,
    "successRate": "95.42",
    "errorRate": "4.58",
    "timestamp": "2026-03-19T00:00:00Z"
  },
  "status": "mock"
}
```

## Agent lifecycle

Lifecycle operations are available at two endpoint patterns depending on which service you call:

* **Web proxy:** `/api/instance/:userId/{action}` — requires session authentication and proxies to the backend.
* **Backend direct:** `/api/agents/:id/{action}` — requires API key authentication.

Both patterns support the same actions. The examples below use the backend pattern.

<Note>All lifecycle operations require the Render API to be available. When the Render API is unreachable, these endpoints return `500` with an error message describing the failure. You can check availability using the [backend health endpoint](/api-reference/health#backend-health-check) — when the `docker` field is `unavailable`, lifecycle operations will fail. The API itself continues to serve non-lifecycle endpoints normally.</Note>

### Start agent

```http theme={null}
POST /api/agents/:id/start
```

Resumes a suspended agent service on Render.

```json theme={null}
{
  "success": true,
  "status": "running"
}
```

### Stop agent

```http theme={null}
POST /api/agents/:id/stop
```

Suspends the agent's Render service. The service retains its data and can be resumed later.

```json theme={null}
{
  "success": true,
  "status": "suspended"
}
```

### Restart agent

```http theme={null}
POST /api/agents/:id/restart
```

```json theme={null}
{
  "success": true,
  "status": "active",
  "healedLegacyModel": false,
  "healMessage": "",
  "openclawVersion": "2026.3.22"
}
```

| Field               | Type    | Description                                                          |
| ------------------- | ------- | -------------------------------------------------------------------- |
| `healedLegacyModel` | boolean | Whether a deprecated model was automatically migrated during restart |
| `healMessage`       | string  | Description of the migration performed (empty if none)               |
| `openclawVersion`   | string  | Current OpenClaw runtime version                                     |

### Update agent image

```http theme={null}
POST /api/agents/:id/update
```

Triggers an image update on the backend. Before replacing the service, the endpoint creates a backup of the agent's data. If the new image fails to start, the endpoint automatically rolls back to the previous image.

#### Request body

| Field   | Type   | Required | Description                                                               |
| ------- | ------ | -------- | ------------------------------------------------------------------------- |
| `image` | string | No       | Custom image to deploy. When omitted, the platform default image is used. |

#### Response

```json theme={null}
{
  "success": true,
  "status": "active",
  "image": "ghcr.io/openclaw/openclaw:2026.3.22",
  "previousImage": "ghcr.io/openclaw/openclaw:2026.3.12",
  "backupPath": "/backups/agent_123_2026-03-20",
  "openclawVersion": "2026.3.22"
}
```

| Field             | Type           | Description                                                                       |
| ----------------- | -------------- | --------------------------------------------------------------------------------- |
| `image`           | string         | New service image. The platform default is `ghcr.io/openclaw/openclaw:2026.3.22`. |
| `previousImage`   | string         | Previous service image before the update                                          |
| `backupPath`      | string \| null | Path to the pre-update backup archive                                             |
| `openclawVersion` | string         | Current OpenClaw runtime version                                                  |

<Note>When the new service fails to start, the endpoint reverts to `previousImage`. The caller still receives a `500` error, but the agent is restored to its prior working state. The pre-update backup remains available at `backupPath` for manual recovery if needed.</Note>

#### Errors

| Code | Description                                                                                         |
| ---- | --------------------------------------------------------------------------------------------------- |
| 400  | Invalid image name                                                                                  |
| 500  | Update failed. When automatic rollback succeeds, the agent continues running on the previous image. |

### Repair agent

```http theme={null}
POST /api/agents/:id/repair
```

Returns the backend response directly.

```json theme={null}
{
  "success": true,
  "message": "Agent repaired successfully"
}
```

### Reset agent memory

```http theme={null}
POST /api/agents/:id/reset-memory
```

Returns the backend response directly.

```json theme={null}
{
  "success": true,
  "message": "Memory reset successfully"
}
```

### Lifecycle error responses

Backend lifecycle endpoints return the following shape on failure:

```json theme={null}
{
  "error": "Error message describing the failure"
}
```

Web proxy lifecycle endpoints return a different error shape:

```json theme={null}
{
  "success": false,
  "status": "error"
}
```

| Code | Source    | Description                                                                             |
| ---- | --------- | --------------------------------------------------------------------------------------- |
| 401  | Both      | Unauthorized — missing or invalid authentication                                        |
| 403  | Web proxy | Forbidden — authenticated user does not own this agent instance                         |
| 500  | Backend   | Internal server error (for example, Render API unavailable or service operation failed) |
| 502  | Web proxy | Backend service unavailable                                                             |

## Get instance details

```http theme={null}
GET /api/instance/:userId
```

Returns the current status and metadata for an agent instance.

### Response

```json theme={null}
{
  "userId": "user_123",
  "status": "running",
  "startedAt": "2026-03-01T00:00:00Z",
  "subdomain": "user_123.agents.localhost",
  "url": "https://user_123.agents.localhost",
  "plan": "solo",
  "openclawVersion": "2026.2.17"
}
```

## Get instance stats

```http theme={null}
GET /api/instance/:userId/stats
```

Returns resource usage statistics for an agent instance.

### Response

```json theme={null}
{
  "userId": "user_123",
  "cpu": "0.15%",
  "memory": "128MiB",
  "status": "running",
    "plan": "solo",
    "openclawVersion": "2026.3.22"
}
```

## Get agent gateway token

```http theme={null}
GET /api/agents/:id/token
```

Returns the gateway token for the agent. If no token exists, a new cryptographically random token is generated using 32 bytes of entropy (returned as a 64-character hex string). Tokens generated by the service entrypoint (when the `OPENCLAW_GATEWAY_TOKEN` environment variable is not set) use 16 bytes (32 hex characters).

```json theme={null}
{
  "token": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2"
}
```

### Errors

| Code | Description         |
| ---- | ------------------- |
| 404  | Agent not found     |
| 500  | Failed to get token |

## Agent verification

Agents can be verified using multiple verification types: `eas` (Ethereum Attestation Service), `coinbase`, `ens`, or `webauthn`.

### Get verification status

```http theme={null}
GET /api/agents/:id/verification
```

<Note>The backend GET endpoint uses `/api/agents/:id/verification` while POST and DELETE use `/api/agents/:id/verify`. The web API proxies all three methods through `/api/agents/:id/verify`.</Note>

```json theme={null}
{
  "verified": false,
  "verificationType": null,
  "attestationUid": null,
  "verifierAddress": null,
  "verifiedAt": null,
  "metadata": null
}
```

### Verify agent

```http theme={null}
POST /api/agents/:id/verify
```

#### Request body

<Note>Requires `Content-Type: application/json` header.</Note>

| Field              | Type    | Required | Description                                                    |
| ------------------ | ------- | -------- | -------------------------------------------------------------- |
| `verificationType` | string  | Yes      | One of: `eas`, `coinbase`, `ens`, `webauthn`                   |
| `verified`         | boolean | No       | Whether the agent is verified (defaults to `true` via web API) |
| `attestationUid`   | string  | No       | Attestation UID from EAS                                       |
| `verifierAddress`  | string  | No       | Address of the verifying wallet                                |
| `metadata`         | object  | No       | Additional verification metadata                               |

<Note>The web API always sets `verified: true` on success. When calling the backend directly, you can pass `verified`, `verifierAddress`, and `metadata` explicitly.</Note>

#### Response

```json theme={null}
{
  "success": true,
  "verified": true,
  "verificationType": "eas",
  "attestationUid": "0x123...",
  "verifiedAt": "2026-03-19T00:00:00Z"
}
```

#### Errors

| Code | Description                                         |
| ---- | --------------------------------------------------- |
| 401  | Unauthorized (handled by authentication middleware) |
| 404  | Agent not found                                     |
| 500  | Failed to update verification                       |

### Remove verification

```http theme={null}
DELETE /api/agents/:id/verify
```

```json theme={null}
{
  "success": true
}
```

## Provision with channel tokens

```http theme={null}
POST /api/provision
```

Provisions a new agent with messaging channel tokens. Requires bearer token (API key) authentication. When a session is active, the user's email is automatically resolved from it. At least one channel token is required.

<Warning>This endpoint is subject to the general rate limit of 120 requests per minute per IP.</Warning>

The request is proxied to the backend provisioning service. When `MUX_TOKEN_ID` and `MUX_TOKEN_SECRET` are configured, the backend creates a real Mux live stream via the Mux API with public playback policy. When Mux credentials are not configured, placeholder streaming credentials are returned instead.

### Request body

| Field                  | Type   | Required    | Description                                                                                                                                                                                                           |
| ---------------------- | ------ | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `telegramToken`        | string | Conditional | Telegram bot token. At least one channel token is required.                                                                                                                                                           |
| `telegramUserId`       | string | No          | Telegram user ID for owner binding                                                                                                                                                                                    |
| `whatsappToken`        | string | Conditional | WhatsApp API token. At least one channel token is required.                                                                                                                                                           |
| `discordBotToken`      | string | Conditional | Discord bot token. At least one channel token is required.                                                                                                                                                            |
| `aiProvider`           | string | No          | AI provider (default: `openrouter`). Options: `openrouter`, `gemini`, `groq`, `anthropic`, `openai`. Each provider maps to a default model — see [AI provider defaults](#ai-provider-defaults) below.                 |
| `apiKey`               | string | No          | API key for the AI provider                                                                                                                                                                                           |
| `plan`                 | string | No          | Plan tier. Options: `solo`, `collective`, `label`, `network`. Defaults to `free` when omitted, which is not a valid plan and returns `400` with the message `Invalid plan`. A paid plan must be specified explicitly. |
| `email`                | string | No          | User email address. When omitted, the email is automatically populated from the authenticated session if one exists. The resolved email is forwarded to the backend in the `X-User-Email` header.                     |
| `stripeSubscriptionId` | string | No          | Stripe subscription ID from checkout                                                                                                                                                                                  |

<Note>When a session is active, the server resolves the user email from the session via `getServerSession`. If the `email` field is also present in the request body, the request body value takes precedence. The resolved email is sent to the backend provisioning service in the `X-User-Email` header.</Note>

<Warning>The following request fields are deprecated and no longer accepted: `whatsappPhoneNumberId`, `whatsappBusinessAccountId`, `discordGuildId`, `discordChannelId`.</Warning>

### Response

The proxy returns a filtered subset of the backend response:

```json theme={null}
{
  "success": true,
  "userId": "a1b2c3d4e5",
  "subdomain": "dj-a1b2c3d4e5.agentbot.raveculture.xyz",
  "url": "https://dj-a1b2c3d4e5.agentbot.raveculture.xyz",
  "streamKey": "sk-ab12-cd34-ef56",
  "liveStreamId": "x7k9m2p4q1"
}
```

<Note>The `/api/provision` proxy returns only `success`, `userId`, `subdomain`, `url`, `streamKey`, and `liveStreamId`. The full response shape from the backend provisioning service is shown below.</Note>

### Full backend response

When calling the backend provisioning service directly, the response includes additional fields.

<Warning>Channel tokens (`telegramToken`, `discordBotToken`, `whatsappToken`) are no longer included in the provision response. Tokens are write-only secrets — they are stored server-side but never returned to the caller.</Warning>

```json theme={null}
{
  "success": true,
  "userId": "a1b2c3d4e5",
  "agentId": "a1b2c3d4e5",
  "id": "a1b2c3d4e5",
  "aiProvider": "openrouter",
  "aiProviderConfig": {
    "model": "openai/gpt-4o-mini",
    "baseUrl": "https://openrouter.ai/api/v1",
    "requiresKey": true
  },
  "plan": "solo",
  "streamKey": "sk-ab12-cd34-ef56",
  "liveStreamId": "x7k9m2p4q1",
  "rtmpServer": "rtmps://live.mux.com/app",
  "playbackUrl": "https://image.mux.com/x7k9m2p4q1/playlist.m3u8",
  "subdomain": "dj-a1b2c3d4e5.agentbot.raveculture.xyz",
  "url": "https://dj-a1b2c3d4e5.agentbot.raveculture.xyz",
  "hls": {
    "playlistUrl": "https://image.mux.com/x7k9m2p4q1/playlist.m3u8"
  },
  "rtmp": {
    "server": "rtmps://live.mux.com/app",
    "key": "sk-ab12-cd34-ef56"
  },
  "status": "active",
  "createdAt": "2026-03-20T00:00:00Z",
  "metadata": {
    "channels": {
      "telegram": "enabled",
      "discord": "disabled",
      "whatsapp": "disabled"
    },
    "streaming": {
      "provider": "mux",
      "lowLatency": true,
      "resolution": "1920x1080",
      "bitrate": "5000k"
    }
  },
  "container": {
    "name": "agentbot-agent-a1b2c3d4e5",
    "status": "running",
    "port": 19000,
    "gatewayUrl": "http://127.0.0.1:19000"
  }
}
```

<Note>The `container` object is included when the backend successfully creates a service for the agent. If service creation fails (for example, when the Render API is unavailable), provisioning still succeeds and the `container` field is omitted. The agent can operate using API-side processing until the service becomes available. You can check Render API availability using the [backend health endpoint](/api-reference/health#backend-health-check).</Note>

| Field                  | Type   | Description                                                     |
| ---------------------- | ------ | --------------------------------------------------------------- |
| `container.name`       | string | Service container name                                          |
| `container.status`     | string | Service status (for example, `running`, `suspended`)            |
| `container.port`       | number | Host port mapped to the agent's internal gateway port (`18789`) |
| `container.gatewayUrl` | string | Local gateway URL in the format `http://127.0.0.1:<port>`       |

### Errors

| Code | Description                                                                                                                                                                                                                                                                             |
| ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400  | At least one channel token required (Telegram, WhatsApp, or Discord), or invalid `aiProvider` value                                                                                                                                                                                     |
| 400  | Invalid plan value. The `plan` field must be one of `solo`, `collective`, `label`, or `network`. Unrecognized values (including the default `free`) return this error.                                                                                                                  |
| 402  | Active subscription required. Returned when a valid plan is specified but no Stripe subscription ID is provided and the caller is not an admin or tester. The response body includes a `code` field set to `PAYMENT_REQUIRED`.                                                          |
| 402  | Agent limit reached for your plan. The response body includes a `code` field set to `AGENT_LIMIT_REACHED`, along with `current` (current agent count) and `limit` (maximum allowed) fields. Provisioning limits: `solo` 1, `collective` 3, `label` 10, `network` practically unlimited. |
| 500  | Internal server error                                                                                                                                                                                                                                                                   |
| 502  | Provisioning service unavailable or returned an error. All backend URLs failed or returned non-success responses.                                                                                                                                                                       |
| 503  | Provisioning is temporarily disabled (kill switch active)                                                                                                                                                                                                                               |

### AI provider defaults

Each `aiProvider` value maps to a default model and base URL. There are two model configurations: the **container config** (used by the agent's internal gateway) and the **provision response metadata** (`aiProviderConfig` field). These may differ.

#### Container config models

These models are configured inside the agent service at provisioning time and are used by the gateway's model fallback chain:

| Provider     | Primary model                 | Fallback model                           | Base URL                                                  |
| ------------ | ----------------------------- | ---------------------------------------- | --------------------------------------------------------- |
| `openrouter` | `moonshotai/kimi-k2.5`        | `openrouter/openai/gpt-4o-mini`          | `https://openrouter.ai/api/v1`                            |
| `gemini`     | `google/gemini-2.0-flash`     | `openrouter/anthropic/claude-sonnet-4-5` | `https://generativelanguage.googleapis.com/v1beta/models` |
| `groq`       | `groq/gemma2-9b-it`           | `openai/gpt-4o-mini`                     | `https://api.groq.com/openai/v1`                          |
| `anthropic`  | `anthropic/claude-sonnet-4-5` | `openai/gpt-4o`                          | `https://api.anthropic.com/v1`                            |
| `openai`     | `openai/gpt-4o`               | `openai/gpt-4o-mini`                     | `https://api.openai.com/v1`                               |
| `minimax`    | `MiniMax/MiniMax-Text-01`     | `openai/gpt-4o-mini`                     | `https://api.minimax.chat/v1`                             |

#### Provision response metadata models

The `aiProviderConfig` object returned in the provision response uses different default models:

| Provider     | Default model              | Base URL                                                  |
| ------------ | -------------------------- | --------------------------------------------------------- |
| `openrouter` | `openai/gpt-4o-mini`       | `https://openrouter.ai/api/v1`                            |
| `gemini`     | `gemini-2.0-flash`         | `https://generativelanguage.googleapis.com/v1beta/models` |
| `groq`       | `mixtral-8x7b-32768`       | `https://api.groq.com/openai/v1`                          |
| `anthropic`  | `claude-3-sonnet-20240229` | `https://api.anthropic.com/v1`                            |
| `openai`     | `gpt-4o`                   | `https://api.openai.com/v1`                               |
| `minimax`    | `MiniMax/MiniMax-Text-01`  | `https://api.minimax.chat/v1`                             |

Each provider includes a fallback model in the service config that is used automatically when the primary model is unavailable or returns an error.

<Note>`minimax` is available as a fallback in the provider configuration map but is not currently accepted as a value for the `aiProvider` request parameter. Passing `minimax` as `aiProvider` returns a `400` validation error. This provider may be enabled in a future release.</Note>

## Channel configuration

When an agent is provisioned, its channel configuration is generated based on the tokens provided. All channels share a set of defaults and each channel type has specific settings.

### Channel defaults

| Setting                  | Value       | Description                                                                 |
| ------------------------ | ----------- | --------------------------------------------------------------------------- |
| `groupPolicy`            | `allowlist` | Only explicitly allowed users can interact with the agent in group contexts |
| `heartbeat.showOk`       | `false`     | Suppress heartbeat OK messages                                              |
| `heartbeat.showAlerts`   | `true`      | Show heartbeat alert messages                                               |
| `heartbeat.useIndicator` | `true`      | Display a status indicator                                                  |

### Telegram channel settings

| Setting                   | Value                    | Description                                                  |
| ------------------------- | ------------------------ | ------------------------------------------------------------ |
| `dmPolicy`                | `allowlist` or `pairing` | `allowlist` when owner IDs are provided, `pairing` otherwise |
| `groups.*.requireMention` | `true`                   | Agent only responds in groups when mentioned                 |
| `historyLimit`            | `50`                     | Number of messages retained in context                       |
| `replyToMode`             | `first`                  | Reply threading mode                                         |
| `streaming`               | `partial`                | Enable partial message streaming                             |
| `retry.attempts`          | `3`                      | Maximum retry attempts                                       |
| `retry.minDelayMs`        | `400`                    | Minimum delay between retries                                |
| `retry.maxDelayMs`        | `30000`                  | Maximum delay between retries                                |
| `retry.jitter`            | `0.1`                    | Jitter factor for retry delays                               |

### Discord channel settings

| Setting            | Value                    | Description                                                  |
| ------------------ | ------------------------ | ------------------------------------------------------------ |
| `dmPolicy`         | `allowlist` or `pairing` | `allowlist` when owner IDs are provided, `pairing` otherwise |
| `dm.enabled`       | `true`                   | Accept direct messages                                       |
| `dm.groupEnabled`  | `false`                  | Group DMs are disabled                                       |
| `historyLimit`     | `20`                     | Number of messages retained in context                       |
| `streaming`        | `partial`                | Enable partial message streaming                             |
| `retry.attempts`   | `3`                      | Maximum retry attempts                                       |
| `retry.minDelayMs` | `500`                    | Minimum delay between retries                                |
| `retry.maxDelayMs` | `30000`                  | Maximum delay between retries                                |
| `retry.jitter`     | `0.1`                    | Jitter factor for retry delays                               |

### WhatsApp channel settings

| Setting                   | Value                    | Description                                                  |
| ------------------------- | ------------------------ | ------------------------------------------------------------ |
| `dmPolicy`                | `allowlist` or `pairing` | `allowlist` when owner IDs are provided, `pairing` otherwise |
| `groups.*.requireMention` | `true`                   | Agent only responds in groups when mentioned                 |
| `sendReadReceipts`        | `true`                   | Send read receipts for incoming messages                     |

### Group chat mention patterns

All channels that support group chat use the following default mention patterns: `@agent` and `agent`. The agent only responds in group conversations when one of these patterns is detected in the message.

## Tool profiles

Each agent is assigned a tool profile at provisioning time based on its plan tier. The tool profile determines which built-in tools the agent can use.

| Plan         | Tool profile | Description                                      |
| ------------ | ------------ | ------------------------------------------------ |
| `solo`       | `messaging`  | Chat-only tools suitable for messaging workflows |
| `collective` | `coding`     | Full development tools including code execution  |
| `label`      | `coding`     | Full development tools including code execution  |
| `network`    | `coding`     | Full development tools including code execution  |

<Note>The tool profile is set once at service creation and persists for the lifetime of the agent. Upgrading your plan does not automatically change the tool profile of existing agents — you need to reprovision the agent or use the [repair endpoint](#repair-agent) to apply the new profile.</Note>

All tool profiles deny `browser` and `canvas` tools inside agent services. The `coding` profile includes shell commands (`ls`, `cat`, `grep`, `curl`, `git`, `node`, `python3`, and others) while the `messaging` profile restricts the agent to chat-oriented capabilities.

## Deploy agent (backend)

```http theme={null}
POST /api/deployments
```

<Note>This is a backend-only endpoint. It deploys an agent as a Render web service and requires a `Content-Type: application/json` header. Requires bearer token authentication. Rate limited to 5 requests per minute per IP.</Note>

### Request body

| Field                  | Type      | Required | Description                                                   |
| ---------------------- | --------- | -------- | ------------------------------------------------------------- |
| `agentId`              | string    | Yes      | Unique agent identifier                                       |
| `config`               | object    | No       | Deployment configuration                                      |
| `config.telegramToken` | string    | Yes      | Telegram bot token                                            |
| `config.ownerIds`      | string\[] | No       | Telegram owner user IDs                                       |
| `config.aiProvider`    | string    | No       | AI provider (default: `openrouter`)                           |
| `config.apiKey`        | string    | No       | API key for the AI provider                                   |
| `config.plan`          | string    | No       | Plan tier. Options: `label`, `solo`, `collective`, `network`. |

### Response (201 Created)

```json theme={null}
{
  "id": "deploy-agent_123",
  "agentId": "agent_123",
  "subdomain": "agent_123.agents.localhost",
  "url": "https://agent_123.agents.localhost",
  "status": "active",
  "openclawVersion": "2026.3.22"
}
```

### Response (200 Already Active)

If the agent service is already running, returns the existing deployment details with the same shape as the 201 response.

### Errors

| Code | Description                                                                                                                                                                                                                                                |
| ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400  | `agentId is required`, `Invalid agentId`, or `telegramToken is required`                                                                                                                                                                                   |
| 401  | Unauthorized                                                                                                                                                                                                                                               |
| 500  | Deployment failed. When the Render API is not reachable, the error message indicates that provisioning is unavailable. Check the [backend health endpoint](/api-reference/health#backend-health-check) to verify Render API availability before deploying. |

## OpenClaw version (backend)

```http theme={null}
GET /api/openclaw/version
```

Returns the current OpenClaw runtime version. Requires bearer token authentication.

### Response

```json theme={null}
{
  "openclawVersion": "2026.3.22",
  "image": "ghcr.io/openclaw/openclaw:2026.3.22",
  "deployedAt": "2026-03-20T00:00:00Z"
}
```

## List instances (backend)

```http theme={null}
GET /api/openclaw/instances
```

Returns all running agent services. Requires bearer token authentication.

### Response

```json theme={null}
{
  "instances": [
    {
      "agentId": "agent_123",
      "name": "openclaw-agent_123",
      "image": "ghcr.io/openclaw/openclaw:2026.3.22",
      "status": "running",
      "createdAt": "2026-03-01T00:00:00Z",
      "version": "2026.3.13",
      "metadata": null
    }
  ],
  "count": 1
}
```

### Errors

| Code | Description              |
| ---- | ------------------------ |
| 401  | Unauthorized             |
| 500  | Failed to list instances |

## Get instance service stats (backend)

```http theme={null}
GET /api/openclaw/instances/:id/stats
```

Returns resource usage for a specific agent service. Requires bearer token authentication.

### Path parameters

| Parameter | Type   | Description |
| --------- | ------ | ----------- |
| `id`      | string | Agent ID    |

### Response

```json theme={null}
{
  "agentId": "agent_123",
  "cpu": "12.5%",
  "memory": "100MiB / 1GiB",
  "memoryPercent": "10.0%",
  "network": "1.2kB / 3.4kB",
  "blockIO": "0B / 0B",
  "pids": "12",
  "status": "running",
  "uptime": 86400000,
  "uptimeFormatted": "1d 0h",
  "timestamp": "2026-03-20T00:00:00Z"
}
```

## Agent interaction

```http theme={null}
GET /api/agent
POST /api/agent
```

Unified endpoint for interacting with agents. All requests require session authentication. The `userId` is always bound to the authenticated session and cannot be overridden by the client.

### GET actions

Pass the `action` query parameter to select the operation.

#### List endpoints

```http theme={null}
GET /api/agent
```

Returns available endpoints and version information when no action is specified.

```json theme={null}
{
  "apiVersion": "1.0.0",
  "agentbotVersion": "2026.3.1",
  "endpoints": {
    "GET /api/agent": "List endpoints",
    "GET /api/agent?action=health": "Health status",
    "GET /api/agent?action=sessions": "List sessions",
    "GET /api/agent?action=session&sessionId=xxx": "Get session details",
    "GET /api/agent?action=memory": "Get agent memory",
    "GET /api/agent?action=skills": "List available skills",
    "GET /api/agent?action=credentials": "List configured credentials",
    "POST /api/agent": "Send message to agent",
    "POST /api/agent?action=create-session": "Create new session",
    "POST /api/agent?action=update-skill": "Enable/disable skill"
  }
}
```

#### Health

```http theme={null}
GET /api/agent?action=health
```

```json theme={null}
{
  "status": "running",
  "version": "2026.3.1",
  "apiVersion": "1.0.0",
  "uptime": 86400,
  "model": "claude-sonnet-4-20250514",
  "channels": ["telegram"],
  "skills": [],
  "lastSeen": 1710806400000
}
```

#### List sessions

```http theme={null}
GET /api/agent?action=sessions
```

```json theme={null}
{
  "sessions": [
    {
      "id": "sess_abc123",
      "status": "active",
      "messageCount": 5,
      "createdAt": 1710806400000,
      "lastActivity": 1710810000000
    }
  ]
}
```

#### Get session

```http theme={null}
GET /api/agent?action=session&sessionId=sess_abc123
```

Returns the full session including messages.

#### Memory

```http theme={null}
GET /api/agent?action=memory
```

Returns the last 10 messages from the active session (truncated to 100 characters each).

```json theme={null}
{
  "memory": [
    { "role": "user", "content": "Hello, can you help me with..." },
    { "role": "assistant", "content": "Of course! Let me..." }
  ]
}
```

#### Skills

```http theme={null}
GET /api/agent?action=skills
```

Returns skills available on the agent instance.

#### Credentials

```http theme={null}
GET /api/agent?action=credentials
```

Returns which credentials are configured for the agent.

```json theme={null}
{
  "credentials": {
    "anthropic": false,
    "openai": false,
    "openrouter": true,
    "google": false,
    "telegram": true,
    "discord": false,
    "whatsapp": false
  }
}
```

### POST actions

Pass the `action` field in the request body.

#### Chat

```http theme={null}
POST /api/agent
```

| Field       | Type   | Required | Description                                                                               |
| ----------- | ------ | -------- | ----------------------------------------------------------------------------------------- |
| `action`    | string | No       | Set to `chat` or omit (default action)                                                    |
| `message`   | string | Yes      | Message to send to the agent                                                              |
| `sessionId` | string | No       | Session ID to continue. A new session is created if omitted and no active session exists. |

```json theme={null}
{
  "sessionId": "sess_abc123",
  "reply": "Agent is processing your request...",
  "timestamp": 1710810000000
}
```

#### Create session

| Field    | Type   | Required | Description      |
| -------- | ------ | -------- | ---------------- |
| `action` | string | Yes      | `create-session` |

```json theme={null}
{
  "sessionId": "sess_abc123",
  "status": "active"
}
```

#### Update skill

| Field     | Type    | Required | Description                                                                                   |
| --------- | ------- | -------- | --------------------------------------------------------------------------------------------- |
| `action`  | string  | Yes      | `update-skill`                                                                                |
| `skillId` | string  | Yes      | Skill ID to enable or disable                                                                 |
| `enabled` | boolean | No       | Whether to enable or disable the skill. Defaults to `false` (removes the skill) when omitted. |

```json theme={null}
{
  "success": true,
  "skillId": "browser",
  "enabled": true
}
```

#### Set credential

| Field    | Type   | Required | Description                                                               |
| -------- | ------ | -------- | ------------------------------------------------------------------------- |
| `action` | string | Yes      | `set-credential`                                                          |
| `key`    | string | Yes      | Credential key (for example, `anthropic`, `telegram`)                     |
| `value`  | string | No       | Credential value. When omitted, the credential is marked as unconfigured. |

```json theme={null}
{
  "success": true,
  "key": "anthropic",
  "configured": true
}
```

### Errors

| Code | Description                               |
| ---- | ----------------------------------------- |
| 400  | Invalid action or missing required fields |
| 401  | Unauthorized                              |
| 404  | Session not found                         |
| 500  | Internal error                            |

## Send message

```http theme={null}
POST /api/chat
```

Requires session authentication.

### Request body

| Field     | Type   | Required | Description        |
| --------- | ------ | -------- | ------------------ |
| `message` | string | Yes      | Message to send    |
| `topic`   | string | No       | Conversation topic |

```json theme={null}
{
  "message": "Hello!",
  "topic": "general"
}
```

### Response

```json theme={null}
{
  "id": "msg_123",
  "message": "Hello!",
  "topic": "general",
  "status": "sent",
  "timestamp": "2026-03-19T00:00:00Z",
  "reply": "Message received by agent"
}
```

### Errors

| Code | Description            |
| ---- | ---------------------- |
| 400  | Message required       |
| 401  | Unauthorized           |
| 500  | Failed to send message |

## List messages

```http theme={null}
GET /api/chat
```

Returns the message history. Requires session authentication.

### Response

```json theme={null}
{
  "messages": [],
  "count": 0
}
```

### Errors

| Code | Description  |
| ---- | ------------ |
| 401  | Unauthorized |
