Field manual
Docs
Cosmo speaks the OpenAI chat wire. Base URL https://www.cosmocompute.dev, a ck_live_ key, any model in the catalog. The full surface is the OpenAPI document.
QuickstartPOST/v1/chat/completions
Sign in with a wallet on the dashboard and mint a key. One signature, no deposit. Then:
curl https://www.cosmocompute.dev/v1/chat/completions \
-H "Authorization: Bearer ck_live_..." \
-H "Content-Type: application/json" \
-d '{
"model": "mistralai/mistral-nemo",
"messages": [{"role": "user", "content": "Hello"}]
}'Model ids are vendor/model, from GET /v1/models. The ids in these examples were read from this deployment's catalog just now.
Try it
The same catalog, live from this page. No key needed.
Models and routingGET/v1/models
GET /v1/models lists every world with its price per million tokens and its context length. Three ids are policies rather than models: Cosmo picks the world.
"model": "cosmo/auto" balanced: price, measured speed and measured quality
"model": "cosmo/auto:cheap" cheapest
"model": "cosmo/auto:fast" fastest time to first tokenGive models as a list and Cosmo tries each in turn on a 429, a 5xx or a dropped connection. A saved preset works as a model id too: preset/<name>. The x-cosmo-model response header always names what answered.
{
"model": "mistralai/mistral-nemo",
"models": ["inclusionai/ling-3.0-flash"],
"messages": [{"role": "user", "content": "Hello"}]
}Streaming
"stream": true gives server sent events in the OpenAI chunk format, ending with data: [DONE]. The last chunk carries usage.
curl -N https://www.cosmocompute.dev/v1/chat/completions \
-H "Authorization: Bearer ck_live_..." \
-H "Content-Type: application/json" \
-d '{
"model": "inclusionai/ling-3.0-flash",
"stream": true,
"messages": [{"role": "user", "content": "Count to five"}]
}'Anthropic wirePOST/v1/messages
The Anthropic messages format over the same catalog, keys and credits. Authenticate with x-api-key or a bearer token. max_tokens is required.
curl https://www.cosmocompute.dev/v1/messages \
-H "x-api-key: ck_live_..." \
-H "Content-Type: application/json" \
-d '{
"model": "inclusionai/ling-3.0-flash",
"max_tokens": 512,
"messages": [{"role": "user", "content": "Hello"}]
}'CreditsGET/api/credits
Keys are free, and a lifetime free allowance covers the first requests of an account that has never deposited; past it, 402 free_allowance_exhausted. A funded account whose balance cannot cover a request's worst case cost answers 402, insufficient_credits.
Stablecoins only, no cards: send USDC or USDT on an accepted network (Base and Arbitrum One by default) to the address GET /api/credits reports, then claim the transfer by its transaction hash. It is credited exactly once.
# with the wallet session cookie
curl https://www.cosmocompute.dev/api/credits/deposit \
-H "Content-Type: application/json" \
-d '{"txHash": "0x...", "chain": "base"}'Or bring your own OpenRouter, OpenAI or Anthropic key at POST /api/provider-keys. Those requests bill your provider account, spend no credits, and come back with x-cosmo-byok: 1.
Headers
| Header | On | Meaning |
|---|---|---|
| x-cosmo-model | response | The model that answered, after routing and fallback. This is what was billed. |
| x-cosmo-upstream | response | The adapter that served it: openai, anthropic, or openrouter. |
| x-cosmo-byok | response | 1 when your own provider key served it, so no credits were spent. |
| x-cosmo-request-id | response | This deployment's id for the call. |
| retry-after | response | Seconds until a full window rolls over, on a 429. |
| x-cosmo-session | request | A label that groups requests in your logs and usage. |
| x-cosmo-cache | request | on to serve a repeated, non streaming request from store. Echoed as hit or miss. |
| x-cosmo-route | request | A JSON directive that steers an autopilot choice: policy, weights, constraints. |
Errors
OpenAI shaped: {"error": {"message", "type"}}. Branch on type.
| type | Status | When |
|---|---|---|
| invalid_request_error | 400, 404 | Bad body or unknown model id. |
| request_too_large | 413 | The body is over the size cap. |
| authentication_error | 401 | No key, a revoked key, or no session. |
| rate_limit_error | 429 | The per key or per IP window is full. See retry-after. |
| spend_cap_exceeded | 429 | The account's monthly spend cap is reached. |
| free_allowance_exhausted | 402 | A keyed account that never deposited has spent the free allowance. |
| insufficient_credits | 402 | A funded account whose balance cannot cover the request's worst case cost. |
| policy_violation | 403 | The model is off this key's allowlist, the key lacks the scope, or the caller's address is off its IP allowlist. |
| policy_exceeded | 402, 403 or 429 | A per key daily or monthly limit is spent, or an organization's shared balance is empty. |
| upstream_unavailable | 502, 503 | No provider for that model, or every candidate failed. |
Limits
60 requests per minute per key. The anonymous consoles, the tester above included, get 10 per minute per IP address and 1024 output tokens. Output is capped at 4096 tokens per request: a larger max_tokens is clamped, not refused. Limits answer 429 with retry-after.
Endpoints
Everything under /v1 takes the key. Everything under /api takes the wallet session, is public, or takes the key where the row says so. The rest is in the OpenAPI document.
| POST/v1/chat/completions | Completions, OpenAI wire. |
| GET/v1/models | The catalog, with prices and context lengths. |
| POST/v1/messages | Completions, Anthropic wire. |
| POST/v1/embeddings | Embeddings. |
| GET/api/openapi | The whole surface, generated from the code. |
| GET/api/auth/nonce | A nonce to sign. Then POST /api/auth/verify with the signature for a session. |
| GET/api/keys | Your keys. POST mints one; it is shown once. |
| GET/api/credits | Balance, ledger and the deposit address. POST /api/credits/deposit claims a transfer. |
| POST/api/provider-keys | Attach your own OpenRouter, OpenAI or Anthropic key. |
| GET/api/usage | What you spent, by model and by day. GET /api/logs lists requests. |
| GET/api/presets | Saved defaults, used as preset/<name> in the model field. GET /api/aliases: short names. |
| POST/api/webhooks | budget.threshold, key.created, key.revoked, price.change, alert.triggered, alert.resolved; HMAC signed. |
| GET/api/traces | The flight recorder: one span per request, bodies only when you opt in. |
| POST/api/router/explain | The routing decision for a request, without sending it. Takes the key. |
| GET/api/tokens | A token estimate for a prompt. A heuristic, and it says so. |
| GET/api/health | Liveness, with the database. |
SDKs
Five clients under packages/ in the repository, a Go SDK among them. The SDKs take a base URL option; the CLI, the MCP server and the Go SDK read COSMO_BASE_URL.
npm i @cosmocompute/sdk # TypeScript
pip install cosmo-compute # Python, sync and async
npm i -g @cosmocompute/cli # cosmo login, models, chat, usage, keys
npm i -g @cosmocompute/mcp # the catalog and chat as MCP tools