> ## Documentation Index
> Fetch the complete documentation index at: https://docs.clawup.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Public API

> Call ClawUp programmatically with API keys and the OpenAPI spec

ClawUp exposes a public HTTP API so you can build integrations, CLIs, and automation on top of your account — without scraping the dashboard. The API is described by a machine-readable **OpenAPI 3.1** spec, so you can also generate a client SDK in your language of choice.

> **Status:** Draft v1. The spec covers authentication, the read-only catalogs (plans, models, runtimes, tools, team templates), **agent and team management** (list / create / get / update / delete), and **agent chat** (OpenAI-compatible, with streaming). More endpoints are added over time. Documented endpoints are stable — we only add fields, never rename or remove them, without a version bump.

## Base URL

```
https://api.clawup.org
```

Every endpoint lives under `/api/v1/`.

## The OpenAPI spec

The full machine-readable spec is served straight from the backend and always matches the live API (it's generated from the server code, so it never drifts):

```
GET https://api.clawup.org/openapi.json
```

Point any OpenAPI tool at that URL to explore endpoints or generate a typed client:

```bash theme={null}
# Generate a TypeScript client
npx @openapitools/openapi-generator-cli generate \
  -i https://api.clawup.org/openapi.json \
  -g typescript-fetch \
  -o ./clawup-client
```

## Authentication

All API calls authenticate with an **API key** passed as a Bearer token:

```
Authorization: Bearer cu_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
```

A key grants the same access as your account, so treat it like a password.

### Creating an API key

1. Sign in at [clawup.org](https://clawup.org).
2. Go to **Account → API Keys**.
3. Click **Create key**, choose the **permissions** the key should grant and an optional expiry, then confirm.
4. Click **Reveal** to show the key, then **Copy** it.

Keys are **hidden by default** and shown only when you reveal them. You can **Revoke** a key at any time — revoked keys stop working immediately.

> Keys are prefixed `cu_`. Older keys with an `eb_` prefix continue to work.

### Permissions (scopes)

Each key grants a set of `<resource>:<action>` scopes, chosen when you create it:

| Scope          | Grants                                  |
| -------------- | --------------------------------------- |
| `agents:read`  | List and read agents; read chat history |
| `agents:write` | Create, update, and delete agents       |
| `agents:chat`  | Send chat messages to an agent          |
| `teams:read`   | List and read teams                     |
| `teams:write`  | Create, update, and delete teams        |

New keys default to **read-only** (`agents:read`, `teams:read`). A request made with a key that lacks the scope a route requires returns `403 SCOPE_FORBIDDEN`. (Browser/session logins from the dashboard are unrestricted.)

## Quick example

Verify your key by fetching your own account:

```bash theme={null}
curl https://api.clawup.org/api/v1/auth/me \
  -H "Authorization: Bearer cu_your_key_here"
```

```json theme={null}
{
  "id": "0553776e-62bf-49be-ad29-4ab320a6afc3",
  "email": "you@example.com",
  "credit_balance_cents": 0,
  "is_node_admin": false,
  "created_at": "2026-05-06T07:14:56.272Z",
  "last_login_at": "2026-05-06T07:14:56.272Z",
  "login_count": 1
}
```

## Chat with an agent

The chat endpoint is **OpenAI-compatible**, so you can point any OpenAI client (or a raw `curl`) at it. Use the agent's id in the path. Requires the `agents:chat` scope.

```bash theme={null}
curl https://api.clawup.org/api/v1/agents/AGENT_ID/chat \
  -H "Authorization: Bearer cu_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openclaw",
    "messages": [{ "role": "user", "content": "Hello!" }]
  }'
```

Use `"model": "openclaw"` to route to the agent's own configured model. Only the last `user` message is sent — earlier turns are loaded from the agent's stored transcript on the server.

### Streaming

Set `"stream": true` to receive a `text/event-stream` of OpenAI `chat.completion.chunk` frames, terminated by `data: [DONE]`:

```bash theme={null}
curl -N https://api.clawup.org/api/v1/agents/AGENT_ID/chat \
  -H "Authorization: Bearer cu_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "model": "openclaw", "messages": [{ "role": "user", "content": "Hello!" }], "stream": true }'
```

Read the stored transcript with `GET /api/v1/agents/AGENT_ID/chat` (requires `agents:read`).

## Available endpoints (v1)

| Method | Path                       | Scope          | Description                                                |
| ------ | -------------------------- | -------------- | ---------------------------------------------------------- |
| GET    | `/api/v1/auth/me`          | —              | The currently authenticated user                           |
| GET    | `/api/v1/plans`            | —              | Subscription plans and their limits                        |
| GET    | `/api/v1/models`           | —              | Provider × model catalog                                   |
| GET    | `/api/v1/runtime/images`   | —              | Available runtime types and images                         |
| GET    | `/api/v1/tools`            | —              | MCP tool catalog                                           |
| GET    | `/api/v1/teams/templates`  | —              | Built-in team templates                                    |
| GET    | `/api/v1/agents`           | `agents:read`  | List your agents                                           |
| POST   | `/api/v1/agents`           | `agents:write` | Create an agent                                            |
| GET    | `/api/v1/agents/{id}`      | `agents:read`  | Get one agent                                              |
| PUT    | `/api/v1/agents/{id}`      | `agents:write` | Update an agent                                            |
| DELETE | `/api/v1/agents/{id}`      | `agents:write` | Delete an agent                                            |
| POST   | `/api/v1/agents/{id}/chat` | `agents:chat`  | Chat with an agent (OpenAI-compatible; supports streaming) |
| GET    | `/api/v1/agents/{id}/chat` | `agents:read`  | Chat history                                               |
| GET    | `/api/v1/teams`            | `teams:read`   | List your teams                                            |
| POST   | `/api/v1/teams`            | `teams:write`  | Create a team                                              |
| GET    | `/api/v1/teams/{id}`       | `teams:read`   | Get one team                                               |
| PUT    | `/api/v1/teams/{id}`       | `teams:write`  | Update a team                                              |
| DELETE | `/api/v1/teams/{id}`       | `teams:write`  | Delete a team                                              |

See `https://api.clawup.org/openapi.json` for the authoritative, always-current list, request/response schemas, and which endpoints require authentication.

## Errors

Errors use a consistent JSON shape:

```json theme={null}
{ "error": "AUTH_401", "message": "missing or invalid credentials" }
```

The `error` field is a stable string code (e.g. `AUTH_401`); `message` is human-readable and may change. A `401` means the key is missing, invalid, expired, or revoked. A `403 SCOPE_FORBIDDEN` means the key is valid but lacks the scope the route requires — mint a key with the right permission (see [Permissions](#permissions-scopes)).

## Versioning

Every route is under `/api/v1/`. Breaking changes ship as a new version (`/api/v2/`) and the old version keeps working during a deprecation window. Within a version, we only add optional request fields and additive response fields.
