# Management

Dynamic provider and key management via crabctl CLI, admin API, and OpenAPI docs.

CrabLLM supports dynamic management of providers and API keys at runtime — no restart required. You can use the `crabctl` CLI or call the admin API directly.

## [Install](/content/docs/crabllm/features/management#install/index.html)

```
cargo install crabllm crabctl
```

Both binaries are installed from the same workspace. `crabctl` talks to a running gateway over HTTP.

## [Admin token](/content/docs/crabllm/features/management#admin-token/index.html)

All management operations require a bearer token. Configure it in your TOML:

```
admin_token = "${CRABLLM_ADMIN_TOKEN}"
```

Pass it to crabctl via `--token` or the `CRABCTL_TOKEN` environment variable.

## [Crabctl CLI](/content/docs/crabllm/features/management#crabctl-cli/index.html)

### [Global flags](/content/docs/crabllm/features/management#global-flags/index.html)

| Flag      | Env var         | Description                             |
|-----------|------------------|-----------------------------------------|
| `--url`   | `CRABCTL_URL`    | Gateway URL (e.g. `http://localhost:5632`) |
| `--token` | `CRABCTL_TOKEN`  | Admin bearer token                     |
| `--json`  | —                | Output raw JSON instead of formatted tables |

### [Key management](/content/docs/crabllm/features/management#key-management/index.html)

```
crabctl keys list
crabctl keys create my-key --models gpt-4o,claude-sonnet-4-20250514 --rpm 60 --tpm 100000
crabctl keys get my-key
crabctl keys update my-key --rpm 120
crabctl keys delete my-key
```

Keys created via the API are "dynamic" — they're stored in the configured [storage backend](/content/docs/crabllm/features/storage/index.html) and persist across restarts (with SQLite or Redis). Keys defined in TOML cannot be modified or deleted via the API.

### [Provider management](/content/docs/crabllm/features/management#provider-management/index.html)

```
crabctl providers list
crabctl providers create my-openai \
  --kind openai \
  --api-key "$OPENAI_API_KEY" \
  --models gpt-4o,gpt-4o-mini \
  --weight 2
crabctl providers get my-openai
crabctl providers update my-openai --weight 5
crabctl providers delete my-openai
```

When you create a provider with `--kind openai`, `--kind ollama`, or `--kind custom` and omit `--models`, CrabLLM auto-fetches the model list from the provider's `/models` endpoint.

Dynamic providers are hot-loaded — the routing registry rebuilds immediately. No restart.

### [Operational queries](/content/docs/crabllm/features/management#operational-queries/index.html)

```
crabctl usage                          # all usage
crabctl usage --key my-key             # usage for one key
crabctl usage --model gpt-4o           # usage for one model

crabctl budget                         # budget status per key

crabctl logs                           # recent audit logs
crabctl logs --key my-key --limit 50   # filtered logs
crabctl logs --since 1713200000000     # logs after epoch ms

crabctl cache clear                    # clear response cache
```

## [Admin API](/content/docs/crabllm/features/management#admin-api/index.html)

All endpoints require `Authorization: Bearer {admin_token}`.

### [Keys](/content/docs/crabllm/features/management#keys/index.html)

| Method | Path                     | Description                          |
|--------|-------------------------|--------------------------------------|
| `POST` | `/v1/admin/keys`        | Create a key                        |
| `GET`  | `/v1/admin/keys`        | List all keys                       |
| `GET`  | `/v1/admin/keys/{name}` | Get one key                         |
| `PATCH`| `/v1/admin/keys/{name}` | Update a key (JSON Merge Patch)    |
| `DELETE`| `/v1/admin/keys/{name}`| Delete a key                        |

Create request body:

```
{
  "name": "team-a",
  "models": ["gpt-4o", "claude-sonnet-4-20250514"],
  "rate_limit": { "rpm": 60, "tpm": 100000 }
}
```

The response includes the generated secret key (`sk-...`). Store it — it's only shown once.

### [Providers](/content/docs/crabllm/features/management#providers/index.html)

| Method | Path                           | Description                            |
|--------|--------------------------------|----------------------------------------|
| `POST` | `/v1/admin/providers`          | Create a provider                     |
| `GET`  | `/v1/admin/providers`          | List all providers                    |
| `GET`  | `/v1/admin/providers/{name}`   | Get one provider                      |
| `PATCH`| `/v1/admin/providers/{name}`   | Update a provider (JSON Merge Patch) |
| `DELETE`| `/v1/admin/providers/{name}` | Delete a provider                     |

Create request body:

```
{
  "name": "openai-backup",
  "kind": "openai",
  "api_key": "sk-...",
  "models": ["gpt-4o"],
  "weight": 1,
  "max_retries": 3,
  "timeout": 30
}
```

### [Operational](/content/docs/crabllm/features/management#operational/index.html)

| Method | Path              | Description                                   |
|--------|------------------|-----------------------------------------------|
| `GET`  | `/v1/usage`      | Token usage per key/model                     |
| `GET`  | `/v1/budget`     | Budget status per key                         |
| `GET`  | `/v1/logs`       | Audit logs (filterable by key, model, time range) |
| `DELETE`| `/v1/cache`      | Clear response cache                          |

### [TOML vs dynamic](/content/docs/crabllm/features/management#toml-vs-dynamic/index.html)

Resources defined in TOML take precedence. They appear in list responses (with `source: "config"`) but cannot be updated or deleted via the API. Dynamic resources (created via API or crabctl) have `source: "dynamic"` and persist in the configured storage backend.

## [OpenAPI / Scalar docs](/content/docs/crabllm/features/management#openapi--scalar-docs/index.html)

CrabLLM serves interactive API documentation out of the box:

- **`/docs`** — Scalar UI for browsing and testing all endpoints
- **`/openapi.json`** — raw OpenAPI 3.1 spec

Enabled by default. Disable with:

```
openapi = false
```

You can also export the spec from the CLI:

```
crabllm openapi --format json > openapi.json
crabllm openapi --format html > docs.html
```
