Documentation

Developer documentation

Tokenly is a drop-in replacement for the OpenAI and Anthropic APIs. Point your SDK at Tokenly, change the key — and everything else works as before. Below: how to send your first request, how authentication works, ready-to-use code samples and streaming.

Quick start

Quick start

Three steps to your first request. If you already use the OpenAI or Anthropic SDK, only the base URL and the key change.

  1. Create an API key in your dashboard — you can copy it any time from the API keys page.
  2. Top up your balance with a card, SBP or cryptocurrency — Tokenly is prepaid.
  3. Set the base URL and the key in your SDK and send your first request.
Base URL https://tokenly.plus/api/v1

Keys live on the API keys page; the current model slugs are in the model catalogue.

curl
curl https://tokenly.plus/api/v1/chat/completions \ -H "Authorization: Bearer $TOKENLY_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-5.5", "messages": [{"role": "user", "content": "Hello!"}] }'
Authentication

Authentication

Every request is authenticated with an API key passed in the Authorization header as a Bearer token. One key routes to every provider — the provider is chosen by the model in the request body.

HTTP
# works on every endpointAuthorization: Bearer sk-disc-... # native alternative accepted by /api/v1/messagesx-api-key: sk-disc-...

You can copy an API key at any time from the API keys page. Keep it secret and revoke any compromised key there.

Error codes

  • 401Invalid or disabled key
  • 402Insufficient balance
  • 404Unknown model
  • 503Provider unavailable or server busy
Endpoints

Endpoints

Pick the endpoint that matches your model's provider dialect — the model in the request body decides which upstream provider the request is routed to.

Endpoint Dialect Providers
POST /api/v1/chat/completions OpenAI Chat Completions OpenAI, Gemini, Anthropic
POST /api/v1/responses OpenAI Responses OpenAI
POST /api/v1/messages Anthropic Messages Anthropic
GET /api/v1/models OpenAI Models —
GET /api/v1/balance Tokenly —
Balance

Check balance

Fetch your current prepaid balance programmatically with the same API key you use for requests — handy for dashboards, low-balance alerts or a pre-flight check in CI before a big job.

curl
curl https://tokenly.plus/api/v1/balance \ -H "Authorization: Bearer $TOKENLY_KEY"
Response
{ "balance": "12.34567890", "currency": "USD"}

balance is a decimal string in US dollars at full precision. This endpoint is never funds-gated, so you can poll it even at a zero or negative balance to decide when to top up.

Code examples

Code examples

The API is fully compatible with the OpenAI and Anthropic SDKs. Pick your stack — the only change is the base URL and the key.

from openai import OpenAI client = OpenAI( api_key="sk-disc-...", # your Tokenly key base_url="https://tokenly.plus/api/v1", # ← the only change) resp = client.chat.completions.create( model="gpt-5.5", messages=[{"role": "user", "content": "Hello!"}],)
from anthropic import Anthropic client = Anthropic( api_key="sk-disc-...", # your Tokenly key base_url="https://tokenly.plus/api", # ← the only change) msg = client.messages.create( model="claude-opus-5", max_tokens=1024, messages=[{"role": "user", "content": "Hello!"}],)
import OpenAI from "openai"; const client = new OpenAI({ apiKey: process.env.TOKENLY_KEY, baseURL: "https://tokenly.plus/api/v1", // ← the only change}); const resp = await client.chat.completions.create({ model: "gemini-3.1-pro", messages: [{ role: "user", content: "Hello!" }],});
curl https://tokenly.plus/api/v1/chat/completions \ -H "Authorization: Bearer $TOKENLY_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-5.5", "messages": [{"role": "user", "content": "Hello!"}] }'
Streaming

Streaming

Streaming is supported on every endpoint. Add "stream": true to the request body and the response arrives as a Server-Sent Events (SSE) stream — exactly as it does with the provider directly.

curl -N https://tokenly.plus/api/v1/chat/completions \ -H "Authorization: Bearer $TOKENLY_KEY" \ -H "Content-Type: application/json" \ -d '{ "stream": true, "model": "gpt-5.5", "messages": [{"role": "user", "content": "Hello!"}] }'
stream = client.chat.completions.create( model="gpt-5.5", stream=True, messages=[{"role": "user", "content": "Hello!"}],) for chunk in stream: print(chunk.choices[0].delta.content or "", end="")

Billing is metered from the final stream chunk, so a streamed request costs the same as a non-streamed one.

Request cost

Request cost

Every successful response tells you exactly what the request cost: Tokenly adds usage.cost to the usage object — the amount debited from your balance, in US dollars. No need to recompute it from token counts and the price list.

Response
{ "id": "chatcmpl-...", "choices": [ ... ], "usage": { "prompt_tokens": 1000, "completion_tokens": 100, "cost": 0.0045 }}
Endpoint Regular response Streaming
/api/v1/chat/completions usage.cost usage.cost in the final chunk that carries usage
/api/v1/responses usage.cost response.usage.cost in the response.completed event
/api/v1/messages usage.cost usage.cost in the message_delta event

cost is a number in US dollars rounded to 8 decimal places — exactly the amount recorded in your statistics. Failed requests cost nothing and are returned as is, without cost.

Integrations

Integrations

Tokenly speaks the native Anthropic and OpenAI dialects, so tools built against those APIs work after changing two settings. Below are ready-to-paste configurations.

Claude Code CLI

Claude Code talks to the Anthropic Messages API, so pointing it at Tokenly takes a single settings file — no plugin, no local proxy. Requests are billed at Tokenly prices and show up in your statistics like any other API call.

  1. Create an API key in your dashboard and copy it.
  2. Open ~/.claude/settings.json (create the file if it does not exist).
  3. Paste the configuration below, put your key into ANTHROPIC_AUTH_TOKEN and restart claude.
Settings file ~/.claude/settings.json
settings.json
{ "env": { "ANTHROPIC_AUTH_TOKEN": "sk-disc-...", "ANTHROPIC_BASE_URL": "https://tokenly.plus/api", "ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-5", "ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-5", "ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-haiku-4.5", "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1" }, "model": "opus"}
Key What it does
ANTHROPIC_AUTH_TOKEN Your Tokenly API key. Claude Code sends it as a Bearer token on every request.
ANTHROPIC_BASE_URL The Tokenly gateway. Note there is no /v1 at the end — Claude Code appends /v1/messages itself.
ANTHROPIC_DEFAULT_OPUS_MODEL Which catalogue model the opus alias resolves to.
ANTHROPIC_DEFAULT_SONNET_MODEL Which catalogue model the sonnet alias resolves to.
ANTHROPIC_DEFAULT_HAIKU_MODEL Which catalogue model the haiku alias resolves to — Claude Code uses it for background tasks.
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC Turns off non-essential calls to Anthropic's own servers so all traffic goes through Tokenly.
model The alias Claude Code starts with. You can switch at any time with the /model command.

Any model from the model catalogue works here — just swap in the slugs you want. Models are resolved by exact slug, so write the identifier exactly as it appears in the catalogue.

OpenCode

OpenCode reaches Tokenly through its OpenAI-compatible provider adapter, so it is a matter of one block in the config — and both Anthropic and OpenAI models end up under a single provider, on one key and one balance.

  1. Create an API key in your dashboard and copy it.
  2. Open ~/.config/opencode/opencode.json (or opencode.json in the project root, for a per-project setup).
  3. Add the provider block below, put your key into apiKey and pick the models you need under models.
Config file ~/.config/opencode/opencode.json
opencode.json
{ "$schema": "https://opencode.ai/config.json", "provider": { "tokenly": { "npm": "@ai-sdk/openai-compatible", "name": "Tokenly", "options": { "baseURL": "https://tokenly.plus/api/v1", "apiKey": "sk-disc-..." }, "models": { "claude-opus-5": { "name": "Claude Opus 5", "attachment": true, "modalities": { "input": ["text", "image"], "output": ["text"] } }, "gpt-5.6-sol": { "name": "GPT-5.6 Sol", "attachment": true, "modalities": { "input": ["text", "image"], "output": ["text"] } } } } }}
Field What it does
provider.tokenly The provider id. Models appear in the picker under this prefix — for example tokenly/claude-opus-5.
npm The OpenAI-compatible adapter OpenCode loads for the provider. Leave it as is.
options.baseURL The Tokenly gateway. Unlike Claude Code, the /v1 belongs here — OpenCode appends only /chat/completions.
options.apiKey Your Tokenly API key.
models The models available in the picker. Each key is a catalogue slug; name is only the display label.

Both dialects go through one provider: Anthropic, OpenAI and Gemini models alike are served by /api/v1/chat/completions. Add as many models from the model catalogue as you like — the key of each entry must match the catalogue slug exactly.

Codex

Codex (the CLI and the VS Code extension) talks to Tokenly natively: it pulls the model list from the gateway on startup, so Tokenly models show up right in its model picker.

  1. Create an API key in your dashboard and export it in your shell profile: export TOKENLY_KEY=sk-disc-...
  2. Open ~/.codex/config.toml — the CLI and the VS Code extension share it.
  3. Add the block below and restart Codex (or reload VS Code). Pick a model with /model or in the extension's picker.
Config file ~/.codex/config.toml
config.toml
model = "gpt-5.5"model_provider = "tokenly" [model_providers.tokenly]name = "Tokenly"base_url = "https://tokenly.plus/api/v1"wire_api = "responses"supports_websockets = false [model_providers.tokenly.auth]command = "sh"args = ["-c", "echo $TOKENLY_KEY"]

Codex works over the Responses API, so the picker lists OpenAI models only. Pass the key through the auth command as shown — with env_key Codex does not load our model list and offers its built-in models, which the gateway does not know. model and model_provider must come before the first [section] of the file.