Usage
How to call Dollar Store Tokens's JSON APIs and point agents, editors, and harnesses at it.
Dollar Store Tokens exposes three LLM wire APIs (OpenAI Chat Completions, OpenAI
Responses, Anthropic Messages) plus two JSON account APIs
(/v1/models, /v1/me). Anything that speaks OpenAI or Anthropic can
talk to Dollar Store Tokens unchanged. Set the base URL, set the API key, pick a
model.
This doc covers:
- Prerequisites: getting an API key
- JSON account APIs:
/v1/models,/v1/me - LLM endpoints: quick reference with examples
- Setting up agents and harnesses
Prerequisites
Get an API key
- Open the Dollar Store Tokens dashboard (this site) in a browser. A new account is auto-provisioned on first visit. No signup, no email, no KYC.
- Note the account token shown on the landing page (in the
account_tokencookie). You'll need it to return to this account from another browser. - In the API Keys panel, create a key. The plaintext
sk_...secret is shown immediately and is always retrievable later from the same panel. (The JSON/v1/meendpoint does not return key secrets. Use the dashboard to retrieve them.) - Deposit Monero to the address shown on the landing page to fund the account.
Base URL
The OpenAI-compatible paths live under /v1 (/v1/chat/completions, /v1/responses,
/v1/models); the Anthropic path is /v1/messages.
JSON account APIs
These endpoints return JSON for programmatic access: scripts,
dashboards, and agents that need to discover models or check balance
without scraping HTML. /v1/models is public (no auth);
/v1/me requires an API key (Authorization: Bearer sk_... or
x-api-key: sk_...).
GET /v1/models
OpenAI-compatible model list. Use this to discover which model IDs Dollar Store Tokens can route. OpenAI-compatible clients (Codex, Zed, omp, OpenAI SDK) call this automatically when configured with Dollar Store Tokens as their base URL. No authentication required.
curl https://dollarstoretokens.com/v1/models
{
"object": "list",
"data": [
{
"id": "gpt-4o",
"display_name": "GPT-4o",
"object": "model",
"created": 0,
"owned_by": "dollarstoretokens",
"input_rate": "692500",
"output_rate": "4155000",
"cache_read_rate": "138500",
"cache_write_rate": "969500",
"price_index": 0.0,
"max_context_window": 128000,
"max_output_tokens": 16384,
"supports_vision": false,
"supports_tools": false,
"tps": 42.5,
"ttft_ms": 680
}
]
}
| Field | Type | Description |
|---|---|---|
id |
string | Model ID. Pass this as model in LLM requests |
display_name |
string | Human-readable model name for model selectors |
object |
string | Always "model" (OpenAI shape) |
owned_by |
string | Always "dollarstoretokens" |
input_rate |
string | Input rate, micro-USD per 1M tokens |
output_rate |
string | Output rate, micro-USD per 1M tokens |
cache_read_rate |
string | Cache-read rate, micro-USD per 1M tokens |
cache_write_rate |
string | Cache-write rate, micro-USD per 1M tokens |
price_index |
number | Relative price 0โ1 (0 = cheapest available) |
max_context_window |
number|null | Max context tokens from the model card, or null when the official source does not state it |
max_output_tokens |
number|null | Max output tokens from the model card, or null when unknown |
supports_vision |
boolean|null | Whether the model accepts image inputs, or null when unknown |
supports_tools |
boolean|null | Whether the model supports tool/function calling, or null when unknown |
tps |
number|null | Tokens/sec on active routes, null if none yet |
ttft_ms |
number|null | Time-to-first-token ms, null if none yet |
The list is filtered the same way as the /models HTML page: only
models currently available and cheaper than the official API are
listed.
GET /v1/me
Returns the calling API key's account: balance, deposit address, live XMR/USD rate, and API key metadata. Useful for scripts that monitor balance or automate deposits. Requires an API key.
Auth errors: missing/invalid key โ 401 with
{"error":"invalid_api_key"}; disabled key โ 403 with
{"error":"api_key_disabled"}; frozen account โ 403 with
{"error":"account_frozen"}.
curl https://dollarstoretokens.com/v1/me \
-H "Authorization: Bearer sk_<your-key>"
{
"account": {
"id": "a1b2c3d4-...",
"balance": {
"micro_usd": "100000000",
"usd": "100.00"
},
"deposit_address": "85FyTtygFivGveVa5kwAZ..."
},
"rate": {
"usd_per_xmr": 172.40
},
"api_keys": [
{
"id": "key-uuid-...",
"name": "my-codex-key",
"prefix": "sk_1a2b3c4d"
}
]
}
| Field | Type | Description |
|---|---|---|
account.id |
string | Account UUID |
account.balance.micro_usd |
string | Balance in micro-USD (1/1,000,000 USD) |
account.balance.usd |
string | Human-readable USD string |
account.deposit_address |
string|null | Monero subaddress for deposits, null if not allocated |
rate.usd_per_xmr |
number|null | USD per 1 XMR, null if unavailable |
api_keys[].id |
string | Key UUID |
api_keys[].name |
string | Human-given key name |
api_keys[].prefix |
string | Key prefix (first characters) |
Key secrets are not returned here. Retrieve them from the cookie-authed dashboard, which shows them at creation.
Python: check balance and list models
import requests
BASE = "https://dollarstoretokens.com"
HEADERS = {"Authorization": "Bearer sk_<your-key>"}
# List available models (public, no auth needed)
models = requests.get(f"{BASE}/v1/models").json()
for m in models["data"]:
print(f"{m['id']:30} in={m['input_rate']} out={m['output_rate']} ctx={m['max_context_window']}")
# Check your balance (requires auth)
me = requests.get(f"{BASE}/v1/me", headers=HEADERS).json()
print(f"Balance: ${me['account']['balance']['usd']} ({me['account']['balance']['micro_usd']} micro-USD)")
print(f"Deposit: {me['account']['deposit_address']}")
JavaScript / TypeScript: balance watcher
const BASE = "https://dollarstoretokens.com"
const HEADERS = { Authorization: `Bearer ${process.env.DOLLARSTORETOKENS_KEY}` }
async function pollBalance() {
const res = await fetch(`${BASE}/v1/me`, { headers: HEADERS })
if (!res.ok) throw new Error(`/v1/me ${res.status}`)
const me = await res.json()
const microUsd = BigInt(me.account.balance.micro_usd)
const usd = Number(microUsd) / 1_000_000
console.log(`balance: $${usd.toFixed(2)}`)
console.log(`rate: 1 XMR = $${me.rate.usd_per_xmr}`)
return usd
}
setInterval(pollBalance, 30_000)
LLM endpoints
Quick reference. Full request/response shapes are documented in
09-api-reference.md.
| Endpoint | Method | Path | Format | Auth header |
|---|---|---|---|---|
| Chat Completions | POST | /v1/chat/completions |
OpenAI | Authorization: Bearer |
| Responses | POST | /v1/responses |
OpenAI Responses | Authorization: Bearer |
| Messages | POST | /v1/messages |
Anthropic | Authorization: Bearer or x-api-key |
All three accept stream: true for SSE. Cache affinity is derived
automatically from the conversation's stable prefix. No special
header needed. Cache expires after 1 hour of inactivity.
Chat Completions
curl https://dollarstoretokens.com/v1/chat/completions \
-H "Authorization: Bearer sk_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is the capital of France?"}
],
"stream": false
}'
Responses
curl https://dollarstoretokens.com/v1/responses \
-H "Authorization: Bearer sk_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o",
"input": "What is the capital of France?",
"stream": false
}'
Messages (Anthropic)
curl https://dollarstoretokens.com/v1/messages \
-H "x-api-key: sk_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-20250514",
"messages": [{"role": "user", "content": "Hello!"}],
"max_tokens": 1024
}'
Setting up agents and harnesses
Every tool below uses the same three values:
- Base URL:
https://dollarstoretokens.com(your Dollar Store Tokens host) - API key:
sk_...(from the dashboard) - Model: any ID from
GET /v1/models
Pick the wire API that matches your tool: OpenAI-compatible tools use
/v1/chat/completions (or /v1/responses); Anthropic-compatible
tools use /v1/messages.
Claude Code
Claude Code reads ANTHROPIC_BASE_URL and ANTHROPIC_API_KEY from the
environment. Point it at Dollar Store Tokens and it will call /v1/messages.
Shell:
export ANTHROPIC_BASE_URL="https://dollarstoretokens.com"
export ANTHROPIC_API_KEY="sk_<your-key>"
claude
Settings file (~/.claude/settings.json):
{
"env": {
"ANTHROPIC_BASE_URL": "https://dollarstoretokens.com",
"ANTHROPIC_API_KEY": "sk_<your-key>"
}
}
Then pick a Claude model in-session with /model claude-sonnet-4-20250514 (or any model from GET /v1/models).
Claude Code sends the x-api-key header, which Dollar Store Tokens accepts.
Codex CLI
Codex reads ~/.codex/config.toml. Define a custom model provider
pointing at Dollar Store Tokens and select it. Dollar Store Tokens speaks the OpenAI Responses
API at /v1/responses and Chat Completions at /v1/chat/completions.
# ~/.codex/config.toml
model = "gpt-4o"
model_provider = "dollarstoretokens"
[model_providers.dollarstoretokens]
name = "dollarstoretokens"
base_url = "https://dollarstoretokens.com/v1"
env_key = "DOLLARSTORETOKENS_API_KEY"
wire_api = "responses"
Then export the key and run:
export DOLLARSTORETOKENS_API_KEY="sk_<your-key>"
codex
For Chat Completions instead of Responses, set wire_api = "chat".
To override for a single run without editing config:
codex --model gpt-4o --config model_provider='"dollarstoretokens"'
Source: Codex advanced configuration, custom model providers
Zed
Zed supports OpenAI-compatible and Anthropic-compatible providers
in settings.json. Add Dollar Store Tokens as an OpenAI-compatible provider
(if you use Chat Completions / Responses) or an Anthropic-compatible
provider (if you use Messages).
OpenAI-compatible (uses /v1/chat/completions):
{
"language_models": {
"openai_compatible": {
"dollarstoretokens": {
"api_url": "https://dollarstoretokens.com/v1",
"available_models": [
{
"name": "gpt-4o",
"display_name": "GPT-4o (Dollar Store Tokens)",
"max_tokens": 128000,
"max_output_tokens": 16384
}
]
}
}
}
}
Anthropic-compatible (uses /v1/messages):
{
"language_models": {
"anthropic_compatible": {
"dollarstoretokens": {
"api_url": "https://dollarstoretokens.com",
"available_models": [
{
"name": "claude-sonnet-4-20250514",
"display_name": "Sonnet (Dollar Store Tokens)",
"max_tokens": 200000,
"max_output_tokens": 8192
}
]
}
}
}
}
Enter the API key in the provider settings UI (agent: open settings)
or set the generated environment variable:
export DOLLARSTORETOKENS_API_KEY="sk_<your-key>"
Oh My Pi (omp)
omp keeps provider definitions in ~/.omp/agent/models.yml and model
roles in ~/.omp/agent/config.yml. There are two parts: registering
the provider (with price tracking), and routing roles to it.
1. Install the price-tracking extension
omp's built-in openai-models-list discovery fetches model IDs from
GET /v1/models but does not read pricing โ it hardcodes every
discovered model as free. To get real cost-per-token display in omp's
/models view, install this extension. It fetches /v1/models,
converts the micro-USD rates to omp's USD-per-million cost format,
and registers each model with live pricing. omp caches the result
(24 h TTL) and refreshes automatically.
Save this file as ~/.omp/agent/extensions/dollarstoretokens-pricing.ts:
import type { ExtensionAPI } from "@oh-my-pi/pi-coding-agent";
const BASE_URL = "https://dollarstoretokens.com";
export default function (pi: ExtensionAPI) {
pi.registerProvider("dollarstoretokens", {
baseUrl: `${BASE_URL}/v1`,
api: "openai-completions",
fetchDynamicModels: async (apiKey) => {
const headers = apiKey ? { Authorization: `Bearer ${apiKey}` } : {};
const res = await fetch(`${BASE_URL}/v1/models`, { headers });
if (!res.ok) throw new Error(`/v1/models ${res.status}`);
const { data } = (await res.json()) as {
data: Array<{
id: string;
input_rate: string;
output_rate: string;
cache_read_rate: string;
cache_write_rate: string;
max_context_window: number | null;
max_output_tokens: number | null;
supports_vision: boolean | null;
}>;
};
return data.map((m) => ({
id: m.id,
name: m.id,
reasoning: false,
input: m.supports_vision === true ? ["text", "image"] : ["text"],
cost: {
input: Number(m.input_rate) / 1_000_000,
output: Number(m.output_rate) / 1_000_000,
cacheRead: Number(m.cache_read_rate) / 1_000_000,
cacheWrite: Number(m.cache_write_rate) / 1_000_000,
},
contextWindow: m.max_context_window ?? 128000,
maxTokens: m.max_output_tokens ?? 8192,
}));
},
});
}
The extension reads the same /v1/models endpoint documented above.
Rates are micro-USD per 1M tokens (e.g. "692500" = $0.6925/1M); the
extension divides by 1,000,000 to convert to omp's USD-per-million
format. The https://dollarstoretokens.com shown above is your Dollar Store Tokens
host โ the usage page fills it in automatically from your deployment
configuration.
To pass an API key to the extension, set it in models.yml under the
same provider id:
providers:
dollarstoretokens:
apiKey: sk_<your-key>
2. Route roles to Dollar Store Tokens
~/.omp/agent/config.yml: route a role to Dollar Store Tokens:
modelRoles:
default: dollarstoretokens/gpt-4o
slow: dollarstoretokens/claude-sonnet-4-20250514:medium
The role format is <provider-id>/<model>[:<thinking-level>]. For the
Anthropic API (anthropic-messages), thinking levels map to budget
tokens.
Generic OpenAI SDK
The OpenAI SDK (Python, TypeScript, etc.) accepts a base_url and
api_key. Point it at Dollar Store Tokens and it will call
/v1/chat/completions and /v1/models.
Python:
from openai import OpenAI
client = OpenAI(
base_url="https://dollarstoretokens.com/v1",
api_key="sk_<your-key>",
)
# Discover models
models = client.models.list()
print([m.id for m in models.data])
# Chat
resp = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello!"}],
)
print(resp.choices[0].message.content)
# Streaming
for chunk in client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Count to 5."}],
stream=True,
):
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)
TypeScript / Node:
import OpenAI from "openai"
const client = new OpenAI({
baseURL: "https://dollarstoretokens.com/v1",
apiKey: process.env.DOLLARSTORETOKENS_KEY,
})
const resp = await client.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "Hello!" }],
})
console.log(resp.choices[0].message.content)
Environment variables (tools that auto-detect OpenAI):
export OPENAI_API_KEY="sk_<your-key>"
export OPENAI_BASE_URL="https://dollarstoretokens.com/v1"
Generic Anthropic SDK
The Anthropic SDK accepts base_url and api_key. Point it at Dollar Store Tokens
and it will call /v1/messages.
Python:
from anthropic import Anthropic
client = Anthropic(
base_url="https://dollarstoretokens.com",
api_key="sk_<your-key>",
)
resp = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
)
print(resp.content[0].text)
# Streaming
with client.messages.stream(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[{"role": "user", "content": "Count to 5."}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
TypeScript / Node:
import Anthropic from "@anthropic-ai/sdk"
const client = new Anthropic({
baseURL: "https://dollarstoretokens.com",
apiKey: process.env.DOLLARSTORETOKENS_KEY,
})
const resp = await client.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello!" }],
})
console.log(resp.content[0].text)
Environment variables (tools that auto-detect Anthropic):
export ANTHROPIC_API_KEY="sk_<your-key>"
export ANTHROPIC_BASE_URL="https://dollarstoretokens.com"
curl
A single-shot helper that lists models, checks balance, and sends a chat request:
#!/usr/bin/env bash
set -euo pipefail
BASE="${DOLLARSTORETOKENS_BASE:-https://dollarstoretokens.com}"
AUTH="Authorization: Bearer ${DOLLARSTORETOKENS_KEY:?set DOLLARSTORETOKENS_KEY}"
echo "=== models ==="
curl -fsS "$BASE/v1/models" | jq -r '.data[].id'
echo "=== balance ==="
curl -fsS "$BASE/v1/me" -H "$AUTH" | jq '.account.balance, .rate'
echo "=== chat ==="
curl -fsS "$BASE/v1/chat/completions" \
-H "$AUTH" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4o","messages":[{"role":"user","content":"hi"}]}' \
| jq -r '.choices[0].message.content'
Other OpenAI/Anthropic-compatible tools
Any tool that lets you set a custom base URL and API key will work. The pattern is always:
- Set the base URL to your Dollar Store Tokens host (
/v1for OpenAI, bare host for Anthropic). - Set the API key to your
sk_...value. - Pick a model from
GET /v1/models.
Tools in this category (config not individually verified here):
- OpenClaw: set the OpenAI base URL and API key in its provider config.
- Hermes: set
OPENAI_BASE_URL/OPENAI_API_KEY(or the Anthropic equivalents) in its environment. pi: if it readsOPENAI_BASE_URL/ANTHROPIC_BASE_URL, point it at Dollar Store Tokens the same way as the generic SDKs above.- Continue, Aider, Cursor, GitHub Copilot CLI, OpenWebUI, LiteLLM: all support custom OpenAI-compatible base URLs.
If a tool only accepts an OpenAI key and base URL, use the OpenAI
endpoints (/v1/chat/completions, /v1/responses, /v1/models).
If it only accepts Anthropic config, use /v1/messages (Dollar Store Tokens
accepts x-api-key as a fallback to Authorization: Bearer).
Tips
- Cache affinity: automatic. Multi-turn conversations stay on the same upstream, preserving prompt-cache hits and lowering TTFT. No header needed. Cache expires after 1 hour of inactivity.
- Streaming: always prefer
stream: truefor interactive use; tokens arrive as the upstream emits them with no buffering. - Balance checks: poll
/v1/meno more than once every 30s. The dashboard's/account/livefragment uses the same cadence. - Model discovery:
GET /v1/modelsreflects currently available models, cheaper than the official API. If a model you expect is missing, it is either unavailable or not cheaper than the official API. Check/modelson the dashboard for the full picture. - Key secrets: retrievable from the cookie-authed dashboard at any
time. The JSON
/v1/meendpoint does not return them. If you need a key secret programmatically, retrieve it from the dashboard.