developers
Point any OpenAI or Anthropic client at superbot and nothing else changes. Your program sends its normal requests, and superbot answers in the same dialect, from your own vendor keys, from credits, or from your full agent.
Prices and plans are on the pricing page; your local address is on the api console. To use superbot from Cursor, Continue, Claude Code and other clients, paste the base URL and caller key into that client’s settings.
75% less than Claude Opus 5.5
per 1M tokens, list prices
| Token type | superbot | Claude Sonnet 5.5 | Claude Opus 5.5 |
|---|---|---|---|
| Input | $1.00 | $2.00 list price | $4.00 list price |
| Output | $5.00 | $10.00 list price | $20.00 list price |
| Cache write | $1.25 | $2.50 list price | $5.00 list price |
| Cache read | $0.05 | $0.10 list price | $0.20 list price |
Claude prices are Anthropic’s list prices (5-minute cache write), read . superbot is not affiliated with Anthropic.
Base URL
One URL serves every client. The dialect is read from each request.
Every client
https://api.superbot.gg/v1
export OPENAI_BASE_URL="https://api.superbot.gg/v1"
export OPENAI_API_KEY="sbc_…"
export ANTHROPIC_BASE_URL="https://api.superbot.gg/v1"
export ANTHROPIC_API_KEY="sbc_…"Auth and scopes
Mint a caller key on the account page. The format is GitHub’s: sbc_, then 32 base64url characters, _ and 6 checksum characters, so a typo dies before the hash lookup. Send it as Authorization: Bearer sbc_… (any client’s default) or x-api-key: sbc_…. The API returns the plaintext once, at mint; the api console can copy a key minted since 2026-10-05 again from its Endpoint card, so roll an older key.
There are two kinds of key: a caller key (sbc_), which holds only the scopes you mint it with, and the one account key (sbk_), which covers the whole account; the model routes take a caller key and refuse the account key. The account key is not narrowed by scopes, and rotating it on the account page stops every client that uses the old key.
Every key carries a route (byo, credits or auto) and a mode (model or agent), and a request can override both:
curl -H "x-superbot-route: byo" -H "x-superbot-mode: agent" \
-H "x-superbot-session: my-thread" -H "x-superbot-engine: omni" \
"$ANTHROPIC_BASE_URL/messages" …Route byo is served by the account’s own linked provider logins, the ChatGPT, Claude or Grok subscription connected on the account page, and is not billed to credits. Those logins are the account holder’s personal vendor subscriptions, not a commercial API allocation. The vendor terms that govern them (OpenAI’s, Anthropic’s, xAI’s) cover personal use, not resale or serving third parties. A byo key handed to someone else spends the key owner’s subscription under terms that were not written for it. Point other people at credits, which serves the operator’s own metered allocation and bills per token, and keep byo for the account’s own clients and machines.
Set model: "superbot" for the agent: your whole superbot (skills, rules, MCP entries, device tools) through a plain client. That is for when no Helper is running, so a phone gets the full agent too, and tool activity streams as status lines.
A request that declares its own tools, the way Codex, Claude Code and Cursor do, is answered by the superbot model driving those tools: its tool calls come back in your dialect for your client to run. So is a call that caps its reply at 512 tokens or fewer, and a call that asks for structured output (a JSON object or a JSON schema), whose reply is the model’s output alone. Any other request is answered by your agent, and outside superbot’s own apps a card it draws comes back as plain markdown: a choice as a list, sources as a Sources: list. Send x-superbot-mode: agent to have your agent answer whatever the request carries; its cards then arrive as cards, not converted to plain markdown.
Set model: "superbot-omni": Superbot agent, run on your computer. Or keep the default model and send x-superbot-engine: omni on an agent call. Only omni is settable by a caller key: a caller key that sends any other x-superbot-engine value is ignored, not refused.
Scopes
Each key holds scopes, and an operation names the ones it needs; a key without one answers 403 insufficient_scope. Mint with one of three presets: Models, Read-only query or Full access. A key minted before scopes existed holds the Gateway preset, and a signed-in session is not narrowed by scopes.
| Scope | What it allows | Presets |
|---|---|---|
gateway:invoke | Call models through Superbot | Models, Full access |
usage:read | Read usage and spend | Models, Read-only query, Full access |
billing:read | Read the credit balance | Models, Read-only query, Full access |
keys:read | List caller keys | Read-only query, Full access |
keys:write | Mint, edit and revoke caller keys | Full access |
endpoints:read | Read custom endpoints and aliases | Read-only query, Full access |
endpoints:write | Change custom endpoints and aliases | Full access |
teams:read | Read teams and invites | Read-only query, Full access |
teams:write | Manage teams, members and invites | Full access |
devices:read | List devices | Read-only query, Full access |
devices:write | Remove devices | Full access |
runs:read | List and read cloud runs and their events | Full access |
runs:write | Start and cancel cloud runs | Full access |
mcp:invoke | Use the MCP tools on your relay Its endpoint is | Full access |
turns:read | Read turns and re-attach to their streams | Read-only query, Full access |
tools:invoke | Use the app's tools: images, audio, connectors, tool search | Full access |
Conversations
When your agent answers a call, superbot keeps its memory of the chat on the server, one thread per conversation. A call answered by the model alone, such as one that declares its own tools, keeps no such thread: the messages your client sends are the conversation. Name a conversation with the x-superbot-session: <id> header: letters, digits, _ and -, at most 59 characters. Every call that sends the same id continues the same thread, even when your client does not resend the earlier messages.
With no header, superbot reads the conversation id your client already sends: prompt_cache_key, metadata.session_id, metadata.conversation_id, a Responses conversation or an Anthropic metadata.user_id. Codex and Claude Code send these themselves, so the agent keeps each of their chats apart. With none of them, superbot keys the conversation on its first message, the first one the user wrote and not the reminder blocks a client wraps around it, so two chats that open with the same words share a thread. Name a session when that matters. The OpenAI user field is not a conversation id, and neither is a Responses previous_response_id.
A call that sends x-superbot-mode: agent is treated as one of superbot’s own apps: it reads only the header, and without one it shares a single thread per key.
Pagination
List routes take limit (1 to 100, default 20) with after_id or before_id. A page is {"object": "list", "data", "has_more", "first_id", "last_id"}. The Link: rel="next" header names the next page.
Errors
Account routes refuse with one envelope: error (the code below), message, doc_url (this table’s row) and request_id, plus param when one field is at fault. The gateway routes refuse in your dialect, OpenAI’s error.type/message envelope or Anthropic’s type: error one. They also answer 402 when the key’s budget or credits are spent (byo_url on the body). They answer 499 when the caller hung up (the agent turn keeps running). They answer 5xx with the upstream's own status, passed through in your dialect. A 502 or 504 that Superbot itself answers to a call made with a caller key or the account key reaches you as 503, the body unchanged, with x-superbot-origin-status naming the 502 or 504 it was (the CDN in front of the API replaces the body of a 502 or 504 and passes a 503). A provider's own status and the model router's own typed error keep theirs. When a status is your own vendor credential's answer (a BYO or custom-endpoint dial) the response also carries the header x-superbot-error-origin: vendor and origin: "vendor" with vendor_status inside the error object; a refusal without them is the gateway's own. Every gateway error object also carries error.source, where the problem is: request (your request or conversation, e.g. too long for the model), client (your client's key or setup), account (credits, plan or limits), superbot or model_server (ours: retry), or provider (an account you connected).
| Code | Status | What to change |
|---|---|---|
invalid_request | 400 | A parameter or body field is invalid; |
invalid_body | 400 | The body is not the JSON object this route expects. |
invalid_json | 400 | The body is not valid JSON. |
invalid_field | 400 | One field has the wrong type or value; |
missing_field | 400 | A required field is absent; |
invalid_cursor | 400 | The page cursor is not one this route issued; start again without it. |
invalid_name | 400 | The name is empty or too long. |
invalid_role | 400 | The role is not one of owner, admin, editor or member. |
invalid_window | 400 | The time range is reversed, malformed or longer than the route allows. |
key_required | 400 | A session must name the key to read with |
invalid_base | 400 | The endpoint base URL is not an http(s) URL. |
private_base | 400 | The endpoint base URL points at a private address, or at one the cloud does not dial (the message names it); use a URL that resolves to a public address. |
invalid route | 400 | The key route must be byo, credits or auto. |
invalid mode | 400 | The key mode must be model or agent. |
invalid_person | 400 | The |
not_a_person_key | 400 | person_name, person_email, person_group, prompt_history and paused_at edit a person, and this key was not minted for one; mint it with |
invalid_limit | 400 | monthly_usd on a person limit must be a number of US dollars from 0.01 to 100000, or null to lift the limit. |
invalid_alias | 400 | The alias body must be a JSON object describing the alias. |
invalid_vendor | 400 | The alias vendor must be a known model provider. |
invalid_model_id | 400 | The alias model_id must be a non-empty string. |
invalid_label | 400 | The label must be a string of at most 120 characters. |
invalid_custody | 400 | The alias custody must be 'envelope' or 'device-held'. |
invalid_token | 400 | The alias token is empty or malformed. |
unauthorized | 401 | Send a live caller key or session as |
insufficient_scope | 403 | The key lacks the scope in |
caller_key_forbidden | 403 | No caller key may call this route; use a signed-in session. |
caller_key_required | 403 | Only a caller key may call this route. |
incognito_key | 403 | An incognito key may read memory and persona but never write them; use a key that is not incognito, or drop the write. |
revoked_key | 403 | The key was revoked; mint a new one. |
key_paused | 403 | The key’s owner has paused this person; the key works again when the owner resumes them ( |
revoked | 409 | The key is already revoked and cannot be edited. |
forbidden | 403 | Your role on this team does not allow the change. |
key_not_owned | 403 | The key belongs to another account. |
not_found | 404 | No such resource on this account; check the id. |
unknown_team | 404 | No team with this id that you belong to. |
unknown_member | 404 | That account is not a member of this team. |
unknown_invite | 404 | No invite with this code. |
unknown_org | 404 | The team this invite names no longer exists. |
unknown_service | 404 | No shipped service document with this id. |
method_not_allowed | 405 | The route does not answer this HTTP method. |
conflict | 409 | The resource is not in a state that allows this change. |
person_has_no_live_keys | 409 | Every key of this person is revoked, so there is none to carry a monthly limit; mint the person a key with |
last_owner | 409 | A team keeps at least one owner; promote another member first. |
not_usable | 409 | The invite was already accepted, revoked or expired. |
invite_not_usable | 409 | The invite was already accepted, revoked or expired. |
invite_email_mismatch | 403 | The invite was sent to a different email address than this account’s. |
invite_needs_email | 403 | This account has no email address yet; add the invited address in Sign-in methods (/account#methods), then accept again. |
already_member | 409 | This account is already a member of the team. |
org_full | 409 | The team is at its member limit. |
own_device | 409 | A bearer cannot remove the device it is calling from. |
body too large | 413 | The body is over the route’s size cap. |
body_too_large | 413 | The body is over the route’s size cap. |
unsupported_media_type | 415 | Send the request body as application/json. |
rate_limited | 429 | Over the per-key request bucket; retry after |
internal_error | 500 | The server failed; retry, and quote |
spend report failed | 500 | The spend report could not be built; retry shortly. |
router_refused | 503 | Billing refused this limit (the message says why). Nothing was changed, so fix the cause and send the same call again. A caller key or the account key reads it as 503, and |
unavailable | 503 | A store behind the route is not ready; retry shortly. |
router_unavailable | 503 | Billing could not be reached to set this limit. Nothing was changed, so send the same call again in a moment. |
Rate limits
1200 requests/min per key, in a fixed-minute bucket, with x-ratelimit-remaining and x-ratelimit-reset on the 429. A keyed request is not counted against any per-IP bucket. Each key also carries its own daily and monthly token budgets.
Spend is metered per key on every dial, and the answer rows carry key_id and key_label. Incognito keys flag their rows (properties: {"incognito": true}) and skip the prompt and reply text.
Withheld
A caller key does what its scopes allow and nothing more. Minting keys and editing endpoints, teams and devices each need their write scope. A team key never holds more than gateway:invoke, usage:read, billing:read and teams:read. No scope unlocks these:
- Vault material: a secret only ever leaves through a dial to the vendor it belongs to.
- Billing changes: no top-up, no auto-recharge settings, no plan changes.
- Account and session management: no sign-in, no device pairing, no account deletion.
- Adapter registry and miss-queue writes.
- Control-socket methods and rooms administration.
Reference
Every operation, generated from the OpenAPI document. Each group has its own page, and every operation links its reference as markdown.
Gateway
OpenAI- and Anthropic-shaped model calls, answered in the dialect you dialed. Gateway as markdown
| Method | Path | Operation |
|---|---|---|
| GET | /v1/turns/{session} | Read a turn Needs |
| GET | /v1/turns/{session}/stream | Re-attach to a turn’s stream Needs |
| POST | /v1/chat/completions | Create a chat completion Needs |
| POST | /v1/responses | Create a response Needs |
| POST | /v1/messages | Create a message Needs |
| POST | /v1/messages/count_tokens | Estimate input tokens Any live key, caller keys only. markdown |
| GET | /v1/models | List models Any live key, caller keys only. markdown |
Usage & spend
What your keys and account spent: per request, per day, bucketed and across apps. Usage & spend as markdown
| Method | Path | Operation |
|---|---|---|
| GET | /v1/usage | Get usage over a window Needs |
| GET | /v1/usage/requests | List usage per request Needs |
| GET | /v1/usage/daily | Get usage per UTC day Needs |
| GET | /v1/usage/breakdown | Get usage bucketed and grouped Needs |
| GET | /v1/usage/export | Export usage rows Needs |
| GET | /v1/credits | Get the credit balance Needs |
| GET | /v1/spend | Get AI spend across apps Needs |
| GET | /v1/usage/report | Get a usage report Needs |
Keys
Mint, list, edit and revoke scoped caller keys. Keys as markdown
| Method | Path | Operation |
|---|---|---|
| GET | /v1/keys | List caller keys Needs |
| POST | /v1/keys | Create a caller key Needs |
| GET | /v1/keys/whoami | Get the calling key Any live key, caller keys only. markdown |
| PATCH | /v1/keys/{id} | Update a caller key Needs |
| DELETE | /v1/keys/{id} | Revoke a caller key Needs |
| POST | /v1/keys/{id}/rotate | Rotate a caller key Needs |
Endpoints
Custom OpenAI- or Anthropic-compatible endpoints and @mention aliases. Endpoints as markdown
| Method | Path | Operation |
|---|---|---|
| GET | /v1/upstreams | List custom endpoints Needs |
| POST | /v1/upstreams | Add a custom endpoint Needs |
| PATCH | /v1/upstreams/{slug} | Update a custom endpoint Needs |
| DELETE | /v1/upstreams/{slug} | Remove a custom endpoint Needs |
| POST | /v1/upstreams/{slug}/probe | Re-probe a custom endpoint Needs |
| GET | /v1/aliases | List @mention aliases Needs |
| PUT | /v1/aliases/{token} | Set an @mention alias Needs |
| DELETE | /v1/aliases/{token} | Delete an @mention alias Needs |
| GET | /docs/services/{service_id}.json | Get a service’s OpenAPI document No credential needed. markdown |
Teams
Teams, their members and their invites. Teams as markdown
| Method | Path | Operation |
|---|---|---|
| GET | /v1/org/{id}/audit | Export a team’s audit log Needs |
| GET | /v1/teams | List teams Needs |
| POST | /v1/teams | Create a team Needs |
| GET | /v1/teams/{team_id} | Get a team Needs |
| PATCH | /v1/teams/{team_id} | Update a team Needs |
| DELETE | /v1/teams/{team_id} | Delete a team Needs |
| GET | /v1/teams/{team_id}/members | List team members Needs |
| PATCH | /v1/teams/{team_id}/members/{user_id} | Change a member’s role Needs |
| DELETE | /v1/teams/{team_id}/members/{user_id} | Remove a team member Needs |
| GET | /v1/teams/{team_id}/invites | List pending team invites Needs |
| POST | /v1/teams/{team_id}/invites | Invite someone to a team Needs |
| DELETE | /v1/teams/{team_id}/invites/{code} | Revoke a team invite Needs |
| POST | /v1/teams/{team_id}/invites/{code}/resend | Resend a team invite Needs |
| POST | /v1/team_invites/{code}/accept | Accept a team invite Needs |
Devices
The devices paired to your account. Devices as markdown
| Method | Path | Operation |
|---|---|---|
| POST | /v1/devices/{device_id}/jobs | Run a job on an agent computer Needs |
| GET | /v1/devices/{device_id}/jobs/{job_id} | Read an agent computer job Needs |
| GET | /v1/devices/{device_id}/terminals/{terminal_id}/stream | Stream an agent computer terminal Needs |
| GET | /v1/pair/{user_code} | Preview an agent computer code Any live key, or a session. markdown |
| POST | /v1/pair/{user_code}/approve | Approve an agent computer code Any live key, or a session. markdown |
| POST | /v1/pair/{user_code}/deny | Decline an agent computer code Any live key, or a session. markdown |
| GET | /v1/devices | List devices Needs |
| GET | /v1/devices/{device_id} | Get a device Needs |
| PATCH | /v1/devices/{device_id} | Rename a device Needs |
| DELETE | /v1/devices/{device_id} | Unlink a device Needs |
Runs
Cloud agent runs: start one on a project, follow its events, cancel it, and get a signed webhook when it settles. Runs as markdown
| Method | Path | Operation |
|---|---|---|
| GET | /v1/runs | List cloud runs Needs |
| POST | /v1/runs | Start a cloud run Needs |
| GET | /v1/runs/projects | Find the project for a repository Needs |
| GET | /v1/runs/{run_id} | Get a cloud run Needs |
| GET | /v1/runs/{run_id}/events | Follow a run’s events Needs |
| POST | /v1/runs/{run_id}/cancel | Cancel a cloud run Needs |
| POST | /v1/runs/{run_id}/messages | Steer a running cloud run Needs |
Machine docs
Every page here has a markdown twin: add .md to its path.
/docs/openapi.json: OpenAPI 3.1, the canonical description./docs/openapi-3.2.json: the same as OpenAPI 3.2./docs/llms.txt: the API index for agents./docs/llms-full.txt: every operation as one markdown file./.well-known/api-catalog: the RFC 9727 catalog.
No operation matches this filter.