Field manual
Docs
Antimatter speaks the OpenAI chat wire. Base URL https://useantimatter.com, an am_live_ key, any model in the catalog. The full surface is the OpenAPI document. What Antimatter is, and what it is not, is in the whitepaper.
QuickstartPOST/v1/chat/completions
Sign in with a wallet on the dashboard and mint a key. One signature, no deposit. Then:
curl https://useantimatter.com/v1/chat/completions \
-H "Authorization: Bearer am_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: Antimatter picks the world.
"model": "antimatter/auto" balanced: price, measured speed and measured quality
"model": "antimatter/auto:cheap" cheapest
"model": "antimatter/auto:fast" fastest time to first tokenGive models as a list and Antimatter 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-antimatter-model response header always names what answered.
{
"model": "mistralai/mistral-nemo",
"models": ["inclusionai/ling-3.0-flash-vl"],
"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://useantimatter.com/v1/chat/completions \
-H "Authorization: Bearer am_live_..." \
-H "Content-Type: application/json" \
-d '{
"model": "inclusionai/ling-3.0-flash-vl",
"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://useantimatter.com/v1/messages \
-H "x-api-key: am_live_..." \
-H "Content-Type: application/json" \
-d '{
"model": "inclusionai/ling-3.0-flash-vl",
"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. Where the deployment runs the holder perk, a signed in wallet that holds the stated amount of $ANTI on Robinhood Chain widens the free allowance; GET /api/credits says by how much.
Stablecoins only, no cards: send USDC or USDT on an accepted network (Base and Arbitrum One by default, and Solana) to the address GET /api/credits reports, then claim the transfer by its transaction hash, or on Solana by its signature with a short message signed by the sending wallet. It is credited exactly once.
# with the wallet session cookie
curl https://useantimatter.com/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-antimatter-byok: 1.
Headers
| Header | On | Meaning |
|---|---|---|
| x-antimatter-model | response | The model that answered, after routing and fallback. This is what was billed. |
| x-antimatter-upstream | response | The adapter that served it: openai, anthropic, or openrouter. |
| x-antimatter-byok | response | 1 when your own provider key served it, so no credits were spent. |
| x-antimatter-request-id | response | This deployment's id for the call. |
| x-antimatter-overhead-ms | response | The gateway's own time before the request left for the upstream, in milliseconds. |
| retry-after | response | Seconds until a full window rolls over, on a 429. |
| x-antimatter-session | request | A label that groups requests in your logs and usage. |
| x-antimatter-cache | request | on to serve a repeated, non streaming request from store. Echoed as hit or miss. |
| x-antimatter-route | request | A JSON directive that steers an autopilot choice: policy, weights, constraints. |
Names from before the rename still work: request headers named x-cosmo-*, model ids starting cosmo/, and keys starting ck_live_. Answers carry only thex-antimatter- names.
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 addresses. POST /api/credits/deposit claims a transfer, on an EVM network or on Solana. |
| 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 ANTIMATTER_BASE_URL.
npm i @antimatter-compute/sdk # TypeScript
pip install antimatter-compute # Python, sync and async
npm i -g @antimatter-compute/cli # antimatter login, models, chat, usage, keys
npm i -g @antimatter-compute/mcp # the catalog and chat as MCP tools