diff --git a/services/www/src/docs/content/console/budgets.mdx b/services/www/src/docs/content/console/budgets.mdx new file mode 100644 index 00000000000..0e0ec33e514 --- /dev/null +++ b/services/www/src/docs/content/console/budgets.mdx @@ -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 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. | diff --git a/services/www/src/docs/content/console/byok.mdx b/services/www/src/docs/content/console/byok.mdx new file mode 100644 index 00000000000..60aa60251f1 --- /dev/null +++ b/services/www/src/docs/content/console/byok.mdx @@ -0,0 +1,132 @@ +--- +title: "BYOK" +description: "Call your own provider connections 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. + +```bash +curl -X POST "https://opencode.ai/inference/custom/conn_.../chat/completions" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "model": "deepseek-chat", + "messages": [{ "role": "user", "content": "Say hi" }] + }' +``` + +## Connect a provider + +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. + +```text +https://opencode.ai/inference/custom/ +``` + +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 `` 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. + +```text +Authorization: Bearer +``` + +Console also reads the key from `x-api-key`, `api-key`, or `x-goog-api-key`, so provider SDKs work when pointed at the +Console API URL. + +## Endpoints + +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 | +| -------------------- | --------------------------------- | +| Chat Completions | `/chat/completions` | +| Responses API | `/responses` | +| Anthropic Compatible | `/messages` | +| Google Generative AI | `/models/:generateContent` | + +Send the model ID as it appears on the provider page. When a model has a different API ID upstream, Console rewrites it. +Requests for models that are not enabled on the connection are rejected. + +### Chat Completions + +```bash +curl -X POST "https://opencode.ai/inference/custom/conn_.../chat/completions" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "model": "deepseek-chat", + "messages": [{ "role": "user", "content": "Say hi" }] + }' +``` + +### Responses API + +```bash +curl -X POST "https://opencode.ai/inference/custom/conn_.../responses" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "model": "gpt-5.4", + "input": "Say hi" + }' +``` + +### Anthropic Compatible + +`max_tokens` is required. + +```bash +curl -X POST "https://opencode.ai/inference/custom/conn_.../messages" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "model": "claude-sonnet-4-6", + "max_tokens": 1024, + "messages": [{ "role": "user", "content": "Say hi" }] + }' +``` + +### Google Generative AI + +The model and method are part of the path. Replace `:generateContent` with `:streamGenerateContent` to stream the +response. + +```bash +curl -X POST "https://opencode.ai/inference/custom/conn_.../models/gemini-3.1-pro:generateContent" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "contents": [{ "parts": [{ "text": "Say hi" }] }] + }' +``` + +## 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 + +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. In [usage exports](/console/usage), BYOK rows have +`billing_source` set to `byok` and a zero `cost_micro_cents`. diff --git a/services/www/src/docs/content/console/go.mdx b/services/www/src/docs/content/console/go.mdx index 6518f0620b7..08811f68c1b 100644 --- a/services/www/src/docs/content/console/go.mdx +++ b/services/www/src/docs/content/console/go.mdx @@ -11,7 +11,7 @@ It is designed primarily for international users and provides stable global acce ## How it works -1. Sign in to the [OpenCode console](https://console.opencode.ai), subscribe to Go, add your billing details, and copy your API key. +1. Sign in to the [OpenCode console](https://opencode.ai/console), subscribe to Go, add your billing details, and copy your API key. 2. Run `/connect` in the TUI, select **OpenCode Go**, and paste your API key. ```text @@ -132,7 +132,7 @@ The estimates are also based on the following prices per 1M tokens and the month -You can track your current usage in the [console](https://console.opencode.ai). +You can track your current usage in the [console](https://opencode.ai/console). If you reach the usage limit, you can continue using the free models. diff --git a/services/www/src/docs/content/console/inference.mdx b/services/www/src/docs/content/console/inference.mdx new file mode 100644 index 00000000000..f119838e120 --- /dev/null +++ b/services/www/src/docs/content/console/inference.mdx @@ -0,0 +1,99 @@ +--- +title: "Inference API" +description: "Call OpenAI, Anthropic, and Gemini-compatible models through Console inference with one authentication header." +--- + +Console inference serves OpenAI, Anthropic, and Gemini-compatible APIs from `https://opencode.ai/inference`. Send a +JSON `POST` request to the endpoint that matches the model's API family. + +```bash +curl -X POST "https://opencode.ai/inference/openai/v1/chat/completions" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "model": "kimi-k2.6", + "messages": [{ "role": "user", "content": "Say hi" }] + }' +``` + +## Authentication + +Replace `` with a service account key created in the [Console](https://opencode.ai/console). Paid models +require the header; free chat models can be called without it. + +```text +Authorization: Bearer +``` + +## Endpoints + +| API | Path | +| ----------------------- | --------------------------------------------------------- | +| OpenAI Chat Completions | `/inference/openai/v1/chat/completions` | +| OpenAI Responses | `/inference/openai/v1/responses` | +| Anthropic Messages | `/inference/anthropic/v1/messages` | +| Gemini | `/inference/google/v1beta/models/:generateContent` | + +Each model is served by one API family. See the [model endpoints](/console/models#endpoints) table, or fetch the live +list: + +```bash +curl https://opencode.ai/inference/v1/models +``` + +### OpenAI Chat Completions + +Open models such as `kimi-k2.6`, `glm-5.1`, `minimax-m2.7`, and the free models use the Chat Completions API. + +```bash +curl -X POST "https://opencode.ai/inference/openai/v1/chat/completions" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "model": "glm-5.1", + "messages": [{ "role": "user", "content": "Say hi" }] + }' +``` + +### OpenAI Responses + +GPT models use the Responses API. + +```bash +curl -X POST "https://opencode.ai/inference/openai/v1/responses" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "model": "gpt-5.5", + "input": "Say hi" + }' +``` + +### Anthropic Messages + +Claude and Qwen models use the Messages API. `max_tokens` is required. + +```bash +curl -X POST "https://opencode.ai/inference/anthropic/v1/messages" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "model": "claude-sonnet-4-6", + "max_tokens": 1024, + "messages": [{ "role": "user", "content": "Say hi" }] + }' +``` + +### Gemini + +Gemini models take the model and method in the path. Replace `:generateContent` with `:streamGenerateContent` to +stream the response. + +```bash +curl -X POST "https://opencode.ai/inference/google/v1beta/models/gemini-3.1-pro:generateContent" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "contents": [{ "parts": [{ "text": "Say hi" }] }] + }' +``` diff --git a/services/www/src/docs/content/console/models.mdx b/services/www/src/docs/content/console/models.mdx index 942daa97555..cdde72f9101 100644 --- a/services/www/src/docs/content/console/models.mdx +++ b/services/www/src/docs/content/console/models.mdx @@ -11,7 +11,7 @@ instead. For a subscription with included usage, see [OpenCode Go](/console/go). ## How it works -1. Sign in to the [console](https://console.opencode.ai), add your billing details and credits, and copy your API key. +1. Sign in to the [console](https://opencode.ai/console), add your billing details and credits, and copy your API key. 2. Run `/connect` in the TUI, choose the OpenCode pay-as-you-go provider, and paste your API key. ```text diff --git a/services/www/src/docs/content/console/usage.mdx b/services/www/src/docs/content/console/usage.mdx new file mode 100644 index 00000000000..ca6b385406a --- /dev/null +++ b/services/www/src/docs/content/console/usage.mdx @@ -0,0 +1,146 @@ +--- +title: "Usage API" +description: "Export usage records as CSV for a workspace, member, service account, or model." +--- + +Export usage records as CSV for a workspace, member, service account, or model. Use the versioned endpoint in scripts, +reporting jobs, and billing integrations. + +## Quick start + +Create a service account API key in the [Console](https://opencode.ai/console). This endpoint accepts service account +keys only; user session tokens are rejected. + +```bash +export CONSOLE_URL="https://opencode.ai/console" +export SERVICE_API_KEY="oc_sk_..." +``` + +Export the last seven days of workspace usage: + +```bash +curl --fail-with-body --get \ + "${CONSOLE_URL}/api/v1/usage/export" \ + --header "Authorization: Bearer ${SERVICE_API_KEY}" \ + --header "Accept: text/csv" \ + --data-urlencode "scope=organization" \ + --data-urlencode "range=7d" \ + --output "usage-organization-7d.csv" +``` + +A successful request writes `usage-organization-7d.csv`. Remove `--output` to print the CSV in your terminal instead. + +## Endpoint and scopes + +```text +GET /api/v1/usage/export +``` + +Every request requires `scope` and `range`. Supported ranges are `24h`, `7d`, and `30d`. They start at midnight UTC +rather than being rolling windows. The full range is returned as a single streamed CSV file, regardless of size. + +| Scope | Additional parameters | Result | +| ----------------- | ---------------------- | ---------------------------------------- | +| `organization` | None | All usage in the workspace. | +| `member` | `user_email` | Usage attributed to one member. | +| `service_account` | `service_account_id` | Usage attributed to one service account. | +| `model` | `provider` and `model` | Usage for one provider and model pair. | + + + Member, service account, and model filters are mutually exclusive. Extra filters return HTTP 400 instead of being + silently ignored. + + +## Export examples + +One member: + +```bash +curl --fail-with-body --get \ + "${CONSOLE_URL}/api/v1/usage/export" \ + --header "Authorization: Bearer ${SERVICE_API_KEY}" \ + --header "Accept: text/csv" \ + --data-urlencode "scope=member" \ + --data-urlencode "range=24h" \ + --data-urlencode "user_email=alice@example.com" \ + --output "usage-member-24h.csv" +``` + +One service account: + +```bash +curl --fail-with-body --get \ + "${CONSOLE_URL}/api/v1/usage/export" \ + --header "Authorization: Bearer ${SERVICE_API_KEY}" \ + --header "Accept: text/csv" \ + --data-urlencode "scope=service_account" \ + --data-urlencode "range=30d" \ + --data-urlencode "service_account_id=svcacct_..." \ + --output "usage-service-account-30d.csv" +``` + +One provider and model: + +```bash +curl --fail-with-body --get \ + "${CONSOLE_URL}/api/v1/usage/export" \ + --header "Authorization: Bearer ${SERVICE_API_KEY}" \ + --header "Accept: text/csv" \ + --data-urlencode "scope=model" \ + --data-urlencode "range=7d" \ + --data-urlencode "provider=anthropic" \ + --data-urlencode "model=claude-sonnet-4-5" \ + --output "usage-model-7d.csv" +``` + +Provider is the provider catalog key, such as `anthropic`, `deepseek`, or `opencode`. A valid filter with no matching +records still returns HTTP 200 with a header-only CSV file. + +## CSV response + +Results are newest first. Empty optional values are blank cells. `cost_micro_cents` is the amount charged by Console +in microcents, where 100,000,000 equals one dollar. Managed-inference usage carries its charge; free, BYOK, and +unclassified legacy usage have a zero charge. + +Organization and member exports include [Websearch](/console/websearch) charges. Search rows identify `web-search` in +the `service` column and leave provider, model, and token fields blank. Model and provider filters select inference +records only. + +
+ +| Field | Description | +| ------------------------- | -------------------------------------------------------------------------------------------------------- | +| `id` | Unique record ID. New service records use a `service:` prefix; inference and historical IDs are numeric. | +| `user_email` | Current email of the member that generated the usage, when applicable. | +| `service_account_name` | Current name of the service account that generated the usage, when applicable. | +| `app` | Client app title, or its referrer when no title was reported. | +| `provider` | Provider catalog key, such as `openai`, `anthropic`, `deepseek`, or `opencode`. | +| `model` | Model identifier reported for the request. | +| `input_tokens` | Number of input tokens consumed. | +| `output_tokens` | Number of output tokens generated. | +| `reasoning_tokens` | Number of reasoning tokens reported by the provider. | +| `cache_read_tokens` | Number of input tokens read from the provider cache. | +| `cache_write_5m_tokens` | Number of tokens written to a five-minute cache. | +| `cache_write_1h_tokens` | Number of tokens written to a one-hour cache. | +| `reasoning_mode` | Reasoning mode used, such as `effort`, `adaptive`, `budget`, or `disabled`. | +| `reasoning_effort` | Provider-specific reasoning effort value, when supplied. | +| `reasoning_budget_tokens` | Requested reasoning-token budget, when supplied. | +| `reasoning_source` | Source from which the reasoning configuration was derived. | +| `billing_source` | How the request was funded, such as `managed-inference`, `credit`, `byok`, or `free`. | +| `cost_micro_cents` | Amount charged by Console in microcents. Divide by 100,000,000 to convert to USD. | +| `created_at` | When the usage was recorded, as an ISO 8601 UTC timestamp. | +| `service` | Service identifier, currently `web-search`. Blank for model requests. | +| `quantity` | Number of billable operations represented by the record; normally one. | + +
+ +## Errors + +| Status | Meaning | +| ------ | ------------------------------------------------------------------------------------ | +| `400` | Missing parameters, invalid values, or filters that do not match the selected scope. | +| `401` | Missing, invalid, expired, or revoked service API key. | +| `403` | The authenticated service account is not allowed to read usage. | + +Curl uses `--fail-with-body` in these examples so authentication and validation failures produce a non-zero exit code +while preserving any error response. diff --git a/services/www/src/docs/content/console/websearch.mdx b/services/www/src/docs/content/console/websearch.mdx index ff1e7aedea8..f16db32eb70 100644 --- a/services/www/src/docs/content/console/websearch.mdx +++ b/services/www/src/docs/content/console/websearch.mdx @@ -9,7 +9,7 @@ Each successful search costs **$0.01** and counts toward the workspace balance a ## Enable -1. Sign in to the [Console](https://console.opencode.ai) as a workspace owner or admin. +1. Sign in to the [Console](https://opencode.ai/console) as a workspace owner or admin. 2. Open **Settings** > **General**. 3. Turn on **Hosted web search**. diff --git a/services/www/src/docs/content/providers.mdx b/services/www/src/docs/content/providers.mdx index dc87fb98be8..22588741113 100644 --- a/services/www/src/docs/content/providers.mdx +++ b/services/www/src/docs/content/providers.mdx @@ -17,7 +17,7 @@ Run `/connect`, choose a provider, and enter its credentials. Then run `/models` ## Go [OpenCode Go](/console/go) is an optional subscription for coding models tested by the OpenCode team. Subscribe in the -[console](https://console.opencode.ai), copy your API key, then connect it as **OpenCode Go**. +[console](https://opencode.ai/console), copy your API key, then connect it as **OpenCode Go**. ```text /connect diff --git a/services/www/src/docs/lib/navigation.ts b/services/www/src/docs/lib/navigation.ts index 676b047b8f8..31557189148 100644 --- a/services/www/src/docs/lib/navigation.ts +++ b/services/www/src/docs/lib/navigation.ts @@ -141,6 +141,15 @@ export const docsSections: DocsSection[] = [ { title: "Go", slug: "console/go" }, ], }, + { + title: "API", + items: [ + { title: "Inference", slug: "console/inference" }, + { title: "BYOK", slug: "console/byok" }, + { title: "Usage", slug: "console/usage" }, + { title: "Budgets", slug: "console/budgets" }, + ], + }, ], }, ]