Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions services/www/src/docs/content/console/api/budgets.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
title: "Budgets API"
description: "Read effective monthly budgets for every workspace member and manage each member's custom budget."
---

Read effective monthly budgets for every workspace member and manage each member's custom budget from an integration.

## Quick start

Create a [service account](/console/api#service-accounts) API key with **All** permissions in the [Console](https://opencode.ai/console).
Inference-only keys cannot access budget data or change limits.

```bash
export CONSOLE_URL="https://opencode.ai/console"
export SERVICE_API_KEY="oc_sk_..."
```

List member budgets:

```bash
curl --fail-with-body \
"${CONSOLE_URL}/api/v1/budgets/members" \
--header "Authorization: Bearer ${SERVICE_API_KEY}" \
--header "Accept: application/json"
```

## List member budgets

```text
GET /api/v1/budgets/members
```

The response includes every current member, ordered by email. A limit with source `custom` is a member override;
source `default` is inherited from the workspace default. A null limit and source mean the member is unlimited.

```json
[
{
"user_id": "user_...",
"email": "alice@example.com",
"limit_micro_cents": "7525000000",
"spent_micro_cents": "1250000000",
"exceeded": false,
"resets_at": "2026-10-01T00:00:00.000Z",
"source": "custom",
"updated_at": "2026-09-03T12:00:00.000Z"
}
]
```

Monetary response fields are decimal strings in microcents so integrations do not lose precision. There are
100,000,000 microcents per US dollar. Spend and reset timestamps cover the current UTC calendar month. `updated_at` is
null when there is no custom member override.

## Set a custom budget

```text
PUT /api/v1/budgets/members/:user_id
```

Set a $75.25 monthly budget for one member:

```bash
curl --fail-with-body --request PUT \
"${CONSOLE_URL}/api/v1/budgets/members/user_..." \
--header "Authorization: Bearer ${SERVICE_API_KEY}" \
--header "Content-Type: application/json" \
--data '{"budget_dollars":75.25}'
```

`budget_dollars` accepts a non-negative US-dollar amount with at most two decimal places. The PUT is idempotent and
returns HTTP 204. Use the member ID returned by the list operation.

## Return to the workspace default

```text
DELETE /api/v1/budgets/members/:user_id
```

Remove the custom override:

```bash
curl --fail-with-body --request DELETE \
"${CONSOLE_URL}/api/v1/budgets/members/user_..." \
--header "Authorization: Bearer ${SERVICE_API_KEY}"
```

Deleting an override does not delete the member. The member inherits the workspace default budget afterward, or
becomes unlimited when the workspace has no default. Repeating the request is safe and returns HTTP 204.

## Errors

| Status | Meaning |
| ------ | -------------------------------------------------------- |
| `400` | Invalid member ID or budget amount. |
| `401` | Missing, invalid, expired, or revoked service API key. |
| `403` | The API key does not have permission to manage budgets. |
| `404` | The member is not in the workspace bound to the API key. |
166 changes: 166 additions & 0 deletions services/www/src/docs/content/console/api/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
---
title: "API Overview"
description: "Authenticate with the OpenCode Console API using service account keys or user tokens."
---

The Console API lets integrations read workspace configuration and manage budgets. Paths are relative
to the Console base URL.

```bash
export CONSOLE_URL="https://opencode.ai/console"
export SERVICE_API_KEY="oc_sk_..."

curl --fail-with-body "${CONSOLE_URL}/api/v2/config" \
--header "Authorization: Bearer ${SERVICE_API_KEY}"
```

| API | Endpoints |
| ----------------------------------- | ------------------------------------------ |
| [Inference](/console/api/inference) | `https://opencode.ai/inference/...` |
| [Providers](/console/api/providers) | `https://opencode.ai/inference/custom/...` |
| [Budgets](/console/api/budgets) | `/api/v1/budgets/members` |
| [Config](#workspace-config) | `GET /api/v2/config` |

## Service accounts

Integrations authenticate with a service account: a non-human member of the workspace with its own API keys, usage,
and [budget](/console/budgets#service-account-budgets). Owners and admins manage them from **Keys**.

1. Open **Keys** and click **Add Service Account**, then name it, for example `CI Pipeline`.
2. Open the service account and click **Add API Key**.
3. Choose a **Key name**, **Permissions**, and an optional **Expiry date**, then click **Create key**.
4. Copy the key. It is shown only once.

```text
oc_sk_1a2b3c4d5e6f_...
```

Send the key as a bearer token. It is bound to one workspace, so no workspace header is needed.

```text
Authorization: Bearer oc_sk_...
```

### Permissions

| Permission | Allows |
| -------------- | --------------------------------------------------------------------------------------------------------------- |
| Inference only | [Inference](/console/api/inference) and [Providers](/console/api/providers) requests, and `GET /api/v2/config`. |
| All | Everything above, plus the Console API with admin access, except managing models. |

Some actions always require a person signed in to the Console, even with an **All** key: inviting members, changing
roles, removing members, and creating or revoking keys.

### Revoke keys

Open the service account and revoke a key from **API Keys**. Removing the service account revokes all its keys.
Automations using a revoked or expired key get HTTP `401` immediately.

## User tokens

User tokens act as a signed-in person with their workspace role. Send the token with an `x-org-id` header naming the
workspace.

```bash
curl --fail-with-body "${CONSOLE_URL}/api/v2/config" \
--header "Authorization: Bearer ${USER_TOKEN}" \
--header "x-org-id: org_..."
```

Tokens from the [device flow](#device-flow) are bound to the workspace chosen during sign-in and do not need the
header. A different `x-org-id` returns `403`.

## Device flow

OpenCode signs in with the OAuth device authorization grant (RFC 8628). Other CLIs can use the same flow.

1. Request a device code. Send `supports_org_scope=true` to bind the token to a workspace.

```bash
curl --fail-with-body "${CONSOLE_URL}/auth/device/code" \
--data "client_id=my-cli" \
--data "supports_org_scope=true"
```

The response includes `device_code`, `user_code`, `verification_uri_complete`, `expires_in` (600 seconds), and
`interval` (5 seconds).

2. Open `verification_uri_complete` in a browser. It is a path such as `/console/device?user_code=...`, relative to
`https://opencode.ai`. The person signs in, picks a workspace, and approves.

3. Poll for the token every `interval` seconds with the same `client_id`.

```bash
curl --fail-with-body "${CONSOLE_URL}/auth/device/token" \
--data "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
--data "device_code=..." \
--data "client_id=my-cli"
```

Until approval the response is `400` with `authorization_pending`. On success it returns `access_token`,
`refresh_token`, `expires_in`, and `org_id`.

4. Refresh before the access token expires. The workspace binding is preserved.

```bash
curl --fail-with-body "${CONSOLE_URL}/auth/device/token" \
--data "grant_type=refresh_token" \
--data "refresh_token=..." \
--data "client_id=my-cli"
```

Each refresh token can be used once. Reusing an old refresh token revokes the whole session.

## Workspace config

`GET /api/v2/config` returns the providers and models available to the workspace in the OpenCode V2
[config](/config) format. OpenCode loads it after `/connect`.

```bash
curl --fail-with-body "${CONSOLE_URL}/api/v2/config" \
--header "Authorization: Bearer ${SERVICE_API_KEY}"
```

```json
{
"providers": {
"opencode": {
"name": "OpenCode",
"env": ["OPENCODE_CONSOLE_TOKEN"],
"package": "aisdk:@ai-sdk/openai-compatible",
"settings": {
"baseURL": "https://opencode.ai/inference/openai/v1",
"apiKey": "{env:OPENCODE_CONSOLE_TOKEN}"
},
"headers": { "x-opencode-org-id": "org_..." },
"models": {
"kimi-k2.6": { "name": "Kimi K2.6" }
}
}
}
}
```

| Field | Description |
| ----------------------- | -------------------------------------------------------------------------------- |
| `providers` | Console, Go, and connected providers, each with its gateway settings and models. |
| `websearch` | Hosted [web search](/console/websearch), for members when enabled. |
| `mcp` | The Console MCP server, for members. |
| `experimental.policies` | Workspace [policy](/policies#console) statements. |

Every key permission level and member role can read the config.

## Errors

Errors return JSON with a `_tag` naming the error.

```json
{ "_tag": "Forbidden" }
```

| Status | Meaning |
| ------ | ---------------------------------------------------------------------------------------- |
| `400` | `OrgRequired`: a user token was sent without `x-org-id`. |
| `401` | Missing, invalid, expired, or revoked credential. |
| `403` | Wrong workspace, missing permission, or an **Inference only** key on a Console endpoint. |
| `404` | The workspace does not exist or was deleted. |
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ curl -X POST "https://opencode.ai/inference/openai/v1/chat/completions" \

## Authentication

Replace `<token>` with a service account key created in the [Console](https://opencode.ai/console). Paid models
Replace `<token>` with a [service account key](/console/api#service-accounts) created in the [Console](https://opencode.ai/console). Paid models
require the header; free chat models can be called without it.

```text
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
title: "BYOK"
description: "Call your own provider connections through the Console gateway with a Console key."
title: "Providers API"
description: "Call the providers connected to your workspace through the Console gateway with a Console key."
---

Bring your own key (BYOK) connects a provider account you already pay for to your workspace. Console stores the
provider credential and gives each connection one gateway URL. Members and integrations call that URL with a Console
key and never handle the provider secret.
Every [provider](/console/providers) connected to your workspace is served through the Console gateway at its own
URL. OpenCode uses it automatically after `/connect`; call it directly to use the same providers from your own tools.
Console adds the provider credential before forwarding, so the provider secret never leaves the workspace.

```bash
curl -X POST "https://opencode.ai/inference/custom/conn_.../chat/completions" \
Expand All @@ -17,29 +17,18 @@ curl -X POST "https://opencode.ai/inference/custom/conn_.../chat/completions" \
}'
```

## Connect a provider
## Provider URL

1. In the [Console](https://opencode.ai/console), open **Providers** and click **Connect Provider**.
2. Pick a provider from the catalog and paste its API key, or click **Add Custom Provider** for any other endpoint.
3. Copy the **Console API URL** from the provider page.
Copy the **Console API URL** from the provider's page under **Providers**.

```text
https://opencode.ai/inference/custom/<connection_id>
```

Catalog providers come with their models preconfigured. Custom providers need a few more fields:

| Field | Description |
| ---------- | --------------------------------------------------------------------------------- |
| Base URL | Where Console forwards requests, for example `https://api.deepseek.com/v1`. |
| API schema | Chat Completions, Responses API, Anthropic Compatible, or Google Generative AI. |
| Auth mode | Bearer, API key header, or Custom header, plus the credential to send. |
| Models | The model IDs members can request, with optional pricing used for usage tracking. |

## Authentication

Replace `<token>` with a service account key created in Console. Console swaps it for the connection's credential
before forwarding, so the provider secret stays in the workspace.
Replace `<token>` with a [service account key](/console/api#service-accounts) created in Console. Console swaps it for
the connection's credential before forwarding.

```text
Authorization: Bearer <token>
Expand All @@ -53,7 +42,7 @@ Console API URL.
Append the provider's API path to the Console API URL. Console forwards the request to the connection's base URL and
returns the provider response unchanged.

| API schema | Path |
| Format | Path |
| -------------------- | --------------------------------- |
| Chat Completions | `/chat/completions` |
| Responses API | `/responses` |
Expand Down Expand Up @@ -116,16 +105,7 @@ curl -X POST "https://opencode.ai/inference/custom/conn_.../models/gemini-3.1-pr
}'
```

## Use in OpenCode

Members do not need the gateway URL. Connections appear as providers in OpenCode for everyone who connects to the
workspace with `/connect`, and `/models` lists their enabled models.

```text
/connect
```

## Usage and limits
## Usage

The provider bills you for the tokens. Console records every request and, using the pricing configured on the model,
counts it toward workspace and member monthly limits.
Requests count toward [budgets](/console/budgets) using the pricing set on each model. The provider
bills you for the tokens.
Loading
Loading