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:

  1. Prerequisites: getting an API key
  2. JSON account APIs: /v1/models, /v1/me
  3. LLM endpoints: quick reference with examples
  4. Setting up agents and harnesses

Prerequisites

Get an API key

  1. 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.
  2. Note the account token shown on the landing page (in the account_token cookie). You'll need it to return to this account from another browser.
  3. 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/me endpoint does not return key secrets. Use the dashboard to retrieve them.)
  4. 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:

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.

Source: Claude Code environment variables

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>"

Source: Zed, Use API Access (OpenAI/Anthropic-compatible)

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:

  1. Set the base URL to your Dollar Store Tokens host (/v1 for OpenAI, bare host for Anthropic).
  2. Set the API key to your sk_... value.
  3. Pick a model from GET /v1/models.

Tools in this category (config not individually verified here):

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