Skip to content

Documentation

Start in one prompt.

ScaledThought is agent-first: your agent signs up and does the work, and you get a dashboard for billing, keys and teammates when you want it. Everything here is written for you and for the agent. The API is OpenAI-compatible: most OpenAI SDK code works by changing the base URL and key.

Quickstart

1

Easiest: ask your agent

Paste this into Claude Code, Codex, Cursor or any agent that can run commands. It reads /llms.txt and runs the setup steps.

Deep links into apps you have installed. Claude and Claude Code are trademarks of Anthropic; Codex is a trademark of OpenAI. ScaledThought is not affiliated with or endorsed by either.

Not affiliated with or endorsed by Anthropic, OpenAI, Cursor or any model publisher. Claude, Claude Code, Codex, Cursor, OpenAI and model names are trademarks of their owners.

2

Or run one command

Creates an account in the US region, writes ST_API_KEY and ST_BASE_URL to .env, and lists the models live there. Safe to re-run: with a key already present it just reports the account. The Canada region is coming soon; until it opens, its API doesn't answer and --region ca fails with network_error.

shell
npx -y scaledthought@0.3 init --region us
3

Buy credits

Every call is paid from prepaid credits, $20 to $2,000 per top-up, at most $2,000 per 24 hours and 2 open approval links at a time. The agent asks for a top-up and sends the approval_url it gets back to its human, who pays by card. Until the credits land, calls return 402 insufficient_credits. More in Credits & approval.

shell
npx -y scaledthought@0.3 billing topup --amount-usd 20
4

Make your first call

curl "$ST_BASE_URL/chat/completions" \
  -H "Authorization: Bearer $ST_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "model": "deepseek-v4-1-flash",
    "messages": [{"role": "user", "content": "Hello"}]
  }'

Authentication

Send your key as a bearer token. Keys are scoped to one region and can carry their own budget. The base URL is your region's host, saved to .env as ST_BASE_URL: https://api.us.scaledthought.com/v1 (Canada's https://api.ca.scaledthought.com/v1 is coming soon).

headers
Authorization: Bearer $ST_API_KEY
Content-Type: application/json

Chat completions

POST /v1/chat/completions accepts the OpenAI request shape. Use a model id from npx -y scaledthought@0.3 models --live or /pricing.

curl "$ST_BASE_URL/chat/completions" \
  -H "Authorization: Bearer $ST_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "model": "deepseek-v4-1-flash",
    "messages": [{"role": "user", "content": "Hello"}]
  }'

Streaming

Set stream: true to receive server-sent events in the OpenAI delta format.

stream = client.chat.completions.create(
    model="deepseek-v4-1-flash",
    messages=[{"role": "user", "content": "Write a haiku about open weights"}],
    stream=True,
)
for chunk in stream:
    print(chunk.choices[0].delta.content or "", end="")

Tool calling

Pass tools in the OpenAI format. Models that support tool calling return standard tool_calls. Support and quality vary by model, so check a model's card before relying on it.

Python
resp = client.chat.completions.create(
    model="deepseek-v4-1-flash",
    messages=[{"role": "user", "content": "Weather in Toronto?"}],
    tools=[{
        "type": "function",
        "function": {
            "name": "get_weather",
            "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]},
        },
    }],
)
print(resp.choices[0].message.tool_calls)

Structured output

Use response_format with a JSON schema. On models that support it, output is constrained to the schema during decoding. Validate the result before relying on it.

Python
resp = client.chat.completions.create(
    model="deepseek-v4-1-flash",
    messages=[{"role": "user", "content": invoice_text}],
    response_format={
        "type": "json_schema",
        "json_schema": {"name": "invoice", "schema": {
            "type": "object",
            "properties": {"vendor": {"type": "string"}, "total": {"type": "number"}},
            "required": ["vendor", "total"],
        }},
    },
)

Responses API & Codex

POST $ST_BASE_URL/responses speaks the OpenAI Responses API, so clients that use only that protocol, such as Codex, can use ScaledThought as their model provider. It takes input (a string, or messages, function_call and function_call_output items), instructions, function and custom (freeform) tools, tool_choice, max_output_tokens, text.format for JSON output and stream: true (Responses events, ending with response.completed or response.incomplete with its usage, or response.failed with an error).

It is stateless. We store no responses, so send the whole conversation in input every turn (Codex does) and leave out previous_response_id, which returns 400 invalid_request; store is always false. Hosted tools such as file search return 400; a web search tool is ignored. Requests without max_output_tokens get a cap of what the model's context leaves after your prompt, at most 32,768 tokens.

Billing is the same as chat completions: per token, from the usage the model server reports, paid from your credits.

# ~/.codex/config.toml
model = "deepseek-v4-1-flash"  # or a model id from `npx -y scaledthought@0.3 models --live`
model_provider = "scaledthought"

[model_providers.scaledthought]
name = "ScaledThought"
base_url = "https://api.us.scaledthought.com/v1"  # your ST_BASE_URL
env_key = "ST_API_KEY"
wire_api = "responses"
model_catalog_url = "https://api.us.scaledthought.com/v1/codex/models"  # same host (and region) as base_url

Codex reads ST_API_KEY from the environment, so load ./.env into the shell first. wire_api = "responses" is required: ScaledThought serves Codex over the Responses API.

model_catalog_url tells Codex the context windows of the models live in your region, so it compacts long sessions in time, and gives it its apply_patch editing tool. It is built from the live models on every request; Codex sends your key with it, so keep it on the same host as base_url (your region's).

Models & benchmarks

GET /v1/models lists the model ids live in your region, in OpenAI's format. That list is the truth about what you can call. GET /v1/models/{id} returns one model's pricing, context length, release date, benchmark scores and live status, so an agent can choose without a human reading a web page. To search and filter, use npx -y scaledthought@0.3 models --live or the MCP tool models_search. For people, /pricing lists every model live in the US with its price, from the same API.

curl "$ST_BASE_URL/models"
curl "$ST_BASE_URL/models/deepseek-v4-1-flash"

Regions & retention

Every key is pinned to its region. The US region is open now; Canada (ca) is coming soon; its API doesn't answer until it opens. Requests are served and logged, and account and usage records stored, only in that country. Card payments for every region are processed by Stripe in the US. Prompts and completions are not stored after the response is returned, and are never used for training. Batch and fine-tuning files are erased after 30 days, or sooner with DELETE /v1/files/{id}. Every response carries x-st-region and x-st-data-retention: none. See security (or /security.json) and the Privacy Policy.

Keys & budgets

Agents can create scoped keys with hard daily spending limits. When a budget is hit, calls return 402 instead of spending more. A revoked key stops working within about 30 seconds.

npx -y scaledthought@0.3 keys create --name support-bot --budget-usd 40

Scopes are inference, read, keys, billing. A key can only give a new key scopes it has itself (otherwise 403 scope_not_allowed). Expiry: send expires_in (like "30d") or expires_at, up to 365 days; after that the key gets 401 key_expired. A key never outlives the key that created it.

Sub-agent keys: with child: true the new key records the calling key as its parent. Its daily budget fits in what the parent has left today, its rate limits and expiry are no higher than the parent's, and it can manage only its own sub-keys. Revoking a key revokes every key below it.

Rotation: POST /v1/keys/{id}/rotate mints a replacement with the same name, scopes, budget and limits, returned once. The old key keeps working for grace (default 24h, "0" to "7d"). Self-revocation: DELETE /v1/keys/self revokes the calling key and its sub-agent keys, with no scope needed, so an agent that suspects a leak can act at once.

npx -y scaledthought@0.3 keys create --name sub-agent --child --scopes inference --budget-usd 2 --expires-in 12h
npx -y scaledthought@0.3 keys rotate key_… --grace 24h
npx -y scaledthought@0.3 keys revoke-self

More on how keys and data are protected: security.

Credits & approval

Usage is paid from prepaid credits, $20 to $2,000 per top-up, at most $2,000 per 24 hours and 2 open approval links at a time. The agent asks for a top-up ($20 by default) and gets back an approval_url: a funding page where its human confirms or changes the amount, can turn on auto-reload, and pays by card. The credits land once the payment is confirmed, and we email a receipt. Nothing is ever charged without that approval. Credits don't expire. When they run out, requests return 402 insufficient_credits with the balance and the amount needed.

npx -y scaledthought@0.3 billing topup --amount-usd 20

Auto-reload is optional and recommended: when the balance drops below a threshold (default $5), the saved card adds a set amount (default $20), so the agent never stalls. The human turns it on on the funding page of any top-up, or without buying anything through an auto-reload setup link (billing auto-reload setup), where they save a card. Loads are limited to $2,000 per 24 hours. Turning it on or raising any limit needs a new approval; turning it off or lowering it doesn't. If a reload is declined, auto-reload switches itself off and the next 402 tells the agent to get a new link. billing status shows the balance and any pending top-ups; billing transactions lists every purchase, reload and charge.

npx -y scaledthought@0.3 billing topup --amount-usd 20 --auto-reload-below 5 --auto-reload-amount 20
npx -y scaledthought@0.3 billing auto-reload setup --below 5 --amount 20   # no purchase: they save a card
npx -y scaledthought@0.3 billing auto-reload off

Notices & webhooks

Responses can carry x-st-notice with comma-separated codes: low_balance (a paid account whose balance is under $5). An agent that sees one should tell its human what to approve. GET /v1/account, MCP account_status,status and doctor show the same codes with the words to relay.

Webhooks push the same signals instead: balance.low, key.expiring and budget.exhausted. Endpoints must be public https URLs on port 443. Each POST carries x-st-signature: t=…,v1=…, an HMAC-SHA256 of <t>.<raw body> keyed with the endpoint's signing secret, which is shown once when you add it. Deliveries go to your URL wherever it is hosted, even outside your account's region, and carry only id, type, created_at, region, account_id and data: ids, integer micro-dollar amounts, day counts and timestamps, never prompts, names or emails. data per event: balance.low {balance_micros, threshold_micros}, key.expiring {key_id, expires_at}, budget.exhausted {scope, key_id, budget_micros, spent_today_micros, resets_at}. Failed deliveries are retried with backoff for about two days.

npx -y scaledthought@0.3 webhooks add https://hooks.example.com/st --events balance.low,budget.exhausted

Optional request headers: x-st-app names your app in usage records (not published), and x-st-session keeps one conversation on the same replica so its cached prefix is reused (memory only, never stored). In Canada, requests never overflow to another country: when every replica of a model is busy a request waits briefly, then gets 429 capacity_exhausted with Retry-After.

Batch inference

Upload a JSONL file of requests and get results at 50% of the normal price. Batches run in a 24-hour completion window and typically finish within it, but finishing in time isn't promised. The Files and Batches endpoints follow OpenAI's, so client.batches.create works. Every line is validated up front, so a bad file fails within seconds.

batch_file = client.files.create(file=open("requests.jsonl", "rb"), purpose="batch")
batch = client.batches.create(
    input_file_id=batch_file.id,
    endpoint="/v1/chat/completions",
    completion_window="24h",
)
# later
batch = client.batches.retrieve(batch.id)
results = client.files.content(batch.output_file_id).text

Embeddings

POST /v1/embeddings with an embedding model (find one with models --live --modality embedding). Input can be a string or an array of strings.

Python
vecs = client.embeddings.create(model="<embedding-model-id>", input=["open weights", "served hot"])

Fine-tuning

Train a LoRA adapter on your own examples. The result is a private model id that only your account can call, served on the same replicas as its base model and billed at the base model's per-token price. Only base models running on our own GPUs in your region can be trained, and adapters can't be downloaded. Training is billed per 1M training tokens (dataset tokens × epochs); the job response includes an estimate before anything runs. Paid from prepaid credits. See pricing.

f = client.files.create(file=open("examples.jsonl", "rb"), purpose="fine-tune")
job = client.fine_tuning.jobs.create(model="<base-id>", training_file=f.id, suffix="triage")
# poll
job = client.fine_tuning.jobs.retrieve(job.id)
resp = client.chat.completions.create(model=job.fine_tuned_model, messages=[...])

MCP server

Remote MCP on your region's API host: https://api.us.scaledthought.com/mcp (Canada's https://api.ca.scaledthought.com/mcp is coming soon; Streamable HTTP, 2026-07-28 spec). Authenticate with your API key as a bearer token. MCP can't create accounts: sign up with npx -y scaledthought@0.3 init or POST /v1/accounts first, then npx -y scaledthought@0.3 mcp prints the exact command and config for your region. The agent gets these tools:

npx -y scaledthought@0.3 mcp
account_status
Region, spend, credit balance, auto-reload, key count and notices (tell your human about each). Call it first.
account_settings
Read or change account settings. ad_measurement: false opts the account out of ad measurement; any key can do it.
keys_manage
List, create, rotate or revoke keys (action: list | create | rotate | revoke | revoke_self). create and rotate return the full key once; create takes scopes, expires_in, child (a sub-agent key) and lives_in (where it will be stored); rotate takes grace. revoke_self revokes the key in use.
budget_manage
Set or clear a key's hard daily budget (USD) and rate limits.
webhooks
Signed HTTPS callbacks for balance.low, key.expiring and budget.exhausted (action: add | list | remove). add returns signing_secret once.
models_search
Models with prices, context, benchmarks and live status in your region (live_only, category, search).
benchmarks_get
Our own per-task scores and speed for one model.
usage_query
Requests, tokens and cost over the last N days, by model, day or key.
billing_topup
With amount_usd (and optional auto_reload): an approval_url for your human to buy credits. action: status | transactions | auto_reload_off.
fine_tuning
List, get, cancel fine-tuning jobs and their events; list your fine-tuned models.
docs_search
Where the docs, llms.txt and your base URL are.

CLI

Run it as npx -y scaledthought@0.3 <command>. Output is JSON whenever stdout isn't a terminal (or with --json), and errors are one JSON line on stderr with code, message and hint. Nothing prompts. Keys come from ST_API_KEY or ./.env, never from flags.

init --region us
Account and key in the US. Writes ST_API_KEY and ST_BASE_URL to .env. Safe to re-run. Canada (ca) is coming soon.
init --account Acme
In a new folder on a machine with saved accounts: use that account with a new project key (init asks which when there are several). --new-account makes a separate account; --no-save keeps the key out of this machine's credential store.
login --region us
Connect to an existing account: prints a code your human types on the dashboard's connect page (opened in their browser). Then run login --wait.
login --wait
Waits about 90 s for your human to approve the code, then writes a new key to .env (never printed). Re-run on authorization_pending.
login --code -
Use a connect line made on the dashboard (its stl_ code on stdin, out of shell history): already approved, works once for 15 minutes.
use "Side project"
Point this folder at another account saved on this machine: a new project key in .env; the folder's old project key is revoked.
init --region us --source a-rd
The same, recording the campaign code of the scaledthought.com/go/<code> link that brought you (optional). An invalid code is dropped with a warning.
models --live
Models serving in your region now, newest first, with prices. Filter with --category or --search. The US list is also on /pricing.
models <id>
Pricing, context, benchmarks and live status for one model.
chat -m <id> "prompt"
Send one message to a model id from models --live.
account
Region, spend and credit balance.
account ad-measurement off
Opt out of ad measurement: nothing about the account is ever sent to an ad platform. on turns it back on.
keys create --name <name> --budget-usd 5
New key with a hard daily budget in USD. The key is printed once.
keys create --name <name> --expires-in 30d --scopes inference,read
A key that expires (at most 365d) with a subset of your key's scopes.
keys create --name <name> --child --budget-usd 2
A sub-agent key: scopes, budget, rate limits and expiry within your key's; revoked when your key is.
keys list
Your keys (prefixes only).
keys rotate <id> --grace 24h
Replace a key: the new key is printed once; the old one keeps working for the grace period (0 to 7d).
keys revoke <id>
Revoke a key and its sub-agent keys. They stop working within about 30 seconds.
keys revoke-self
Revoke the key you are using now (and its sub-agent keys), e.g. if it may have leaked. Irreversible.
keys put github --repo <owner/repo> --budget-usd 2
Put a new sub-agent key straight into a platform's secret store as ST_API_KEY, through its own CLI with the key on stdin (never printed). Destinations: github, vercel, fly, cloudflare, gcp, aws, k8s, doppler. The key is named after the place and records where it lives (lives_in). If storing fails, the new key is revoked.
keys rotate --all --push --grace 1h
Rotate every key that keys put stored somewhere and put each replacement in the same place; the old keys stop after the grace period. Prints no keys. One key: keys rotate <id> --push.
connect opencode
Point an OpenAI-compatible tool at ScaledThought: opencode and aider get the base URL and their own sub-agent key in their config (files 0600, key never printed); cursor and continue get steps for your human.
usage --days 7 --by model
Requests, tokens and cost by model, day or key.
billing status
Credit balance, auto-reload, pending top-ups.
billing topup --amount-usd 20
Buy prepaid credits ($20 to $2,000 per top-up, at most $2,000 per 24 hours and 2 open approval links at a time; default 20): opens the funding page in your human's browser, where they confirm the amount, can turn on auto-reload and pay.
billing wait
Returns as soon as your human pays the open top-up, with the new balance. Polls about 90 seconds a run; run it again on topup_pending.
billing topup --amount-usd 20 --auto-reload-below 5 --auto-reload-amount 20
Top up with auto-reload pre-selected on the funding page (your human can untick it).
billing auto-reload setup --below 5 --amount 20
Turn auto-reload on without buying anything: opens a page where your human saves a card. Then billing wait.
billing auto-reload off
Turn auto-reload off. No approval needed.
billing transactions
The credit ledger: purchases, auto-reloads, usage, batches, fine-tuning, refunds.
batches create requests.jsonl
Upload a JSONL file and start a batch at 50% off. Needs prepaid credits.
fine-tune create examples.jsonl --model <base-id>
Upload a dataset and start a LoRA job. Needs prepaid credits.
webhooks add https://hooks.example.com/st --events balance.low,budget.exhausted
Get a signed POST when the balance is low, a key is about to expire or a budget is spent (default: every event). Prints signing_secret once.
webhooks list
Your webhook endpoints.
webhooks remove <id>
Delete a webhook endpoint.
doctor
Checks the key in .env, its region, the account and its credit, and lists notices to tell your human.
mcp
Prints the `claude mcp add` command and JSON config for your region.
dashboard --page billing
Opens your human's dashboard (overview, billing, keys, members, connect) in their browser. If they aren't signed in, one click emails them a link.
members
Who can sign in to the account's dashboard: email, role (owner or member), status.
status
Per-model health in your region over the last hour, plus your account's notices when a key is set.

API reference

POST /v1/accounts
Create an account in this host's region. Returns api_key (once) and base_url. No auth. Optional source: the campaign code from a /go/<code> link.
POST /v1/chat/completions
Chat, tools, JSON output, streaming. OpenAI-compatible.
POST /v1/responses
The OpenAI Responses API (Codex): function and custom tools, streaming. Stateless: send the whole conversation each turn; previous_response_id isn't supported.
POST /v1/completions
Raw text completion.
POST /v1/embeddings
Embeddings for embedding models.
GET /v1/models
Model ids live in this region (OpenAI list format). No auth.
GET /v1/models/{id}
One model: pricing, context, benchmarks and live_in_region. No auth.
GET /v1/models/{id}/benchmarks
Our own per-task scores and speed.
GET /v1/account
Plan, region, balance, spend, key count and notices (low_balance) with notice_text to relay to your human.
PATCH /v1/account
Account settings: {"ad_measurement": false} opts out of ad measurement (any key); true needs the keys or billing scope.
GET /v1/keys
List keys.
POST /v1/keys
Create a key: scopes (a subset of yours), daily_budget_usd, rate limits, expires_in or expires_at (max 365d), child: true for a sub-agent key, lives_in (where it will be stored, display only).
POST /v1/keys/{id}/rotate
Replace a key. The new key is returned once; the old one works for grace (default 24h, 0 to 7d).
PATCH /v1/keys/{id}
Change a key's name, daily budget, rate limits or lives_in (null clears it).
DELETE /v1/keys/{id}
Revoke a key and its sub-agent keys.
DELETE /v1/keys/self
The calling key revokes itself and its sub-agent keys. No scope needed.
GET /v1/usage
Requests, tokens and cost (days, group_by).
GET /v1/billing
Credit balance, auto-reload, pending top-ups and recent transactions.
POST /v1/billing/topup
Buy credits: {amount_usd, auto_reload?} returns an approval_url for your human.
GET /v1/billing/topups/{id}
One top-up's status (open, paid, expired, failed).
PATCH /v1/billing/auto-reload
Disable or lower auto-reload. Raising it needs a new top-up approval.
GET /v1/billing/transactions
The credit ledger, newest first (cursor).
POST /v1/webhooks
Add a webhook: {url (public https, port 443), events}. Returns signing_secret once. Billing scope; at most 5.
GET /v1/webhooks
Your webhook endpoints (status, last success and failure).
DELETE /v1/webhooks/{id}
Delete a webhook endpoint.
POST /v1/files
Upload JSONL (purpose=batch or fine-tune).
POST /v1/batches
Start a batch. GET /v1/batches/{id} to poll, POST /v1/batches/{id}/cancel to stop.
POST /v1/fine_tuning/jobs
Start a LoRA job from an uploaded purpose=fine-tune file.
GET /v1/status
Per-model health in this region, last hour.
POST /v1/dashboard/link
A URL for your human's dashboard (optional page), the owners, and a message to relay. billing or keys scope.
POST /v1/device/codes
Ask to connect to an existing account. No key. Returns device_code (secret), user_code for your human to type at verification_url, expires_in, interval.
POST /v1/device/token
Collect the key once approved: {device_code}, or {connect_code} (stl_…) for a dashboard connect line. 428 authorization_pending until then; one key per code, with the approver's scopes.
GET /v1/members
Who can sign in to the dashboard (email, role, status). read scope.

Rate limits

Limits are per key. Over the limit, calls return 429 rate_limit_exceeded with a Retry-After header in seconds. Until the account's first credit purchase, keys can lower their limits but not raise them.

New account
Requests / min: 60
Tokens / min: 200,000
Spend: Until the first credit purchase: up to 5 keys
Prepaid credits
Requests / min: 3,000
Tokens / min: 5,000,000
Spend: Credits your human buys, $20 to $2,000 per top-up, $2,000 per 24 h
Scale
Requests / min: Custom
Tokens / min: Custom
Spend: Talk to us

Errors

API errors are {"error":{"message","type","code"}}. CLI errors add a hint and exit non-zero.

400
Code: invalid_request
What to do: Fix the field named in message. Don't retry unchanged.
400
Code: invalid_body
What to do: Fix the field named in message. Don't retry unchanged.
400
Code: invalid_json
What to do: Send valid JSON with `content-type: application/json`.
401
Code: invalid_api_key
What to do: Key missing, mistyped or revoked. Load ST_API_KEY from .env; don't create a new account.
401
Code: missing_api_key
What to do: Send `Authorization: Bearer $ST_API_KEY`.
401
Code: key_expired
What to do: The key's expires_at has passed. Use another key, or create a new one with a key that has the keys scope.
400
Code: invalid_expiry
What to do: expires_in or expires_at must be in the future and at most 365 days ahead. Send one, not both.
400
Code: expiry_exceeds_parent
What to do: A key can't outlive the key that creates it. Ask for at most max_expires_at from the body.
403
Code: scope_not_allowed
What to do: Ask only for scopes your own key has (allowed_scopes in the body).
400
Code: budget_exceeds_parent
What to do: A sub-agent key's daily budget must fit in what its parent has left today (max_daily_budget_usd in the body).
400
Code: limit_exceeds_parent
What to do: A sub-agent key's rate limits and budget can't exceed its parent's (or, when it changes itself, its own).
400
Code: key_depth_exceeded
What to do: Sub-agent keys nest at most 16 levels. Create the key from a key higher up.
404
Code: key_not_found
What to do: No such key on this account, or (for a sub-agent key) it's outside the keys you created.
409
Code: key_not_active
What to do: Only an active key can be rotated. Create a new key instead.
402
Code: budget_exceeded
What to do: This key's daily budget is spent. Resets 00:00 UTC. Tell your human; don't retry now.
402
Code: insufficient_credits
What to do: The credit balance can't cover the request (the body has balance_usd and required_usd). Run `billing topup --amount-usd 20` and send your human the approval_url.
402
Code: daily_cap_exceeded
What to do: An operator-set daily cap on this account is reached. Resets 00:00 UTC. Tell your human.
402
Code: credits_required_for_batches
What to do: Batches are paid from prepaid credits. Run `billing topup --amount-usd 20`, then retry once your human approves.
402
Code: credits_required_for_fine_tuning
What to do: Fine-tuning is paid from prepaid credits. Run `billing topup --amount-usd 20`, then retry once your human approves.
409
Code: too_many_pending_topups
What to do: The account already has 2 unpaid approval links. Ask your human to pay one (`billing status` lists them), or wait for them to expire.
409
Code: daily_topup_limit
What to do: Top-ups are limited to $2,000 per account per rolling 24 hours, open links and auto-reloads included. Retry with at most available_usd from the body, or wait.
403
Code: approval_required
What to do: Turning auto-reload on or raising it needs your human. Run `billing auto-reload setup --below <usd> --amount <usd>` (a link your human approves; nothing is bought) and give them the approval_url. Disabling or lowering needs no approval.
402
Code: free_tier_key_limit
What to do: Accounts that haven't bought credits have 5 active keys. Revoke one (`keys revoke <id>`) or buy credits.
402
Code: free_tier_limit
What to do: Accounts that haven't bought credits can't raise budgets or rate limits. Buy credits first (`billing topup --amount-usd 20`).
409
Code: fine_tuning_requires_self_hosted
What to do: This base model isn't served on our own GPUs in your region, so it can't be fine-tuned here. Pick another base model.
409
Code: model_not_live
What to do: That model isn't served in your region yet. Pick one from `models --live`.
400
Code: invalid_video_url
What to do: video_url must be a public https URL or a data:video/mp4 (webm, mov) URL within the size limit.
403
Code: insufficient_scope
What to do: This key lacks the scope. Use the default key from init.
403
Code: account_suspended
What to do: Stop. Tell your human to email hello@scaledthought.com.
404
Code: model_not_found
What to do: Not live here. Pick an id from `models --live` or `GET $ST_BASE_URL/models`.
404
Code: not_found
What to do: Wrong path. ST_BASE_URL already ends in /v1; append /chat/completions.
421
Code: wrong_region
What to do: The key belongs to the other region. Use the `base_url` in the error body; remove any hard-coded host.
429
Code: rate_limit_exceeded
What to do: Wait `Retry-After` seconds, then retry.
429
Code: capacity_exhausted
What to do: Canada: every replica of the model is busy and Canadian requests never overflow to another country. Wait `Retry-After` seconds and retry with backoff, or use another model.
400
Code: invalid_webhook_url
What to do: Webhook URLs must be public https endpoints on port 443 (no other port, no private, loopback or internal hosts). Fix the URL.
409
Code: too_many_webhooks
What to do: An account has at most 5 webhook endpoints. Remove one (`webhooks remove <id>`) first.
404
Code: webhook_not_found
What to do: No such webhook on this account. List them with `webhooks list`.
503
Code: webhooks_unavailable
What to do: Webhooks aren't enabled in this region yet. Poll `GET /v1/account` for `notices` instead.
502
Code: upstream_error
What to do: Transient. Retry with backoff, or use another model from `models --live`.
503
Code: region_not_open
What to do: The Canada region isn't open yet. Check with your human that US hosting is acceptable, then use `init --region us` and the US host.
503
Code: service_unavailable
What to do: Transient. Retry in a few seconds.
exit 1
Code: no_key
What to do: No ST_API_KEY in the environment or ./.env. For an existing account run `login`; for a new one, `init --region us`.
exit 1
Code: key_exists
What to do: login: this folder already has a key. Use it, or pass --force to replace it.
428
Code: authorization_pending
What to do: login --wait: your human hasn't typed the code yet. Run it again (codes last 10 minutes).
410
Code: expired_token
What to do: The connect code expired. Run `login` again for a new one.
409
Code: already_claimed
What to do: A connect code works once. Run `login` again (or ask for a new connect line).
403
Code: access_denied
What to do: Your human denied the connection. Ask them before trying again.
exit 1
Code: region_mismatch
What to do: A key from the other region already exists here. Use it, or ask your human before creating a second account elsewhere.
exit 1
Code: wrong_region_endpoint
What to do: ST_BASE_URL / ST_API_URL points at the other region. Unset it. Nothing was sent.
exit 1
Code: network_error
What to do: Couldn't reach the API. Check the network, then retry.
exit 1
Code: bad_region
What to do: Use `--region us`. Canada (`ca`) is coming soon.
exit 2
Code: usage_error
What to do: Unknown command, flag or missing argument. Run the command with --help.

Agent view · paste this into your agent

Opens your agent with the prompt typed. You press Enter.

Deep links into apps you have installed. Claude and Claude Code are trademarks of Anthropic; Codex is a trademark of OpenAI. ScaledThought is not affiliated with or endorsed by either.

Agents can read the whole site as markdown at scaledthought.com/llms.txt.