Skip to content
On this page

Account

Billing & deposits

Prepaid micro-USD, transparent per-request pricing, and crypto top-ups through OxaPay.

New accounts start at $0.00. Every paid request requires a positive balance. There is no subscription and no minimum monthly spend.

Money units

All internal amounts are integer micro-USD: 1_000_000 micro = $1.00. Never do float math on balance_micro; display micro / 1e6. Prices in the catalog are USD per 1M tokens.

What a request costs

cost = network_fee + token_cost
token_cost = (prompt_tokens × price_prompt_per_m
+ completion_tokens × price_completion_per_m) / 1e6
× model.token_multiplier
(+ cached / cache-write adjustments)
cost_micro = ceil(token_micro) + network_fee_micro
  • Network fee is the model's fixed_price_micro (1000 = $0.001 on the seeded catalog). An account override can replace it: -1 uses the model default, 0 waives it, and >0 is a custom fee.
  • model.token_multiplier scales the billed token cost. It does not affect the quota counter.
  • users.token_multiplier is a separate account-level quota multiplier. It scales tokens_used only and does not change the amount billed.
  • Cache reads are discounted: 50% of input for openai, 10% for openai_compatible, and 10% for anthropic. Anthropic cache writes cost 1.25× input; other providers have no separate cache-write charge.
  • Provider total_tokens is used for quota. If the provider total exceeds prompt + completion, the excess is billed as extra input tokens.
  • BYOK makes token cost $0; the network fee still applies. Dedicated keys are billed normally.
  • price_overrides replace catalog prices for the account at billing time: {"model-id":[prompt_per_m, completion_per_m]}.

Balance gates and reservations

Before proxying a billable request, the backend reserves the worst-case estimate: fee + prompt tokens + max_tokens at the model's prices. The reservation is released when the request finishes, which prevents a burst of parallel requests from overdrawing the account.

ConditionStatusResponse
balance_micro <= 0 or insufficient402{ "error": "out of credit — top up via POST /deposits" }
token cap reached403{ "error": "account token quota exhausted" }
model not allowed403{ "error": "model '…' is not enabled for this key" }
key spend cap hit403"key daily quota exhausted" or "key monthly quota exhausted".

Create an invoice

POST/depositsJWT or API key

Bounds: $0.50 – $100,000. Returns 500 if payments are not configured.

curl -X POST https://api.relayrouter.org/deposits \
-H "Authorization: Bearer $JWT" \
-H 'content-type: application/json' \
-d '{"amount_usd":10}'

Open payment_url in a new tab. Credit is applied by the OxaPay webhook (POST /webhooks/oxapay, HMAC-SHA512 verified) or by a manual sync.

List invoices

GET/depositsJWT or API key

Returns the same objects, newest first. Status is pending, paying, completed, or an OxaPay status such as expired or failed. Only completed credits the balance.

Manual sync

POST/deposits/{id}/syncJWT or API key

Re-checks the invoice and credits if paid. Safe to poll; crediting is atomic and idempotent.

{ "status": "completed", "balance_micro": 10000000 }

A reasonable UX is to poll every 5 seconds for about 10 minutes, then fall back to a "refresh balance" action.

Currencies

GET/deposits/currenciesJWT or API key

Returns the OxaPay accepted list as { "currencies": [...] }. May return 400 if payments are not configured.

Side effects of a completed deposit

  • The balance is credited once, via an atomic pending → completed claim.
  • The account is marked verified (verified = 1; /auth/me shows email_verified: true).
  • The deposit IP is recorded for the anti-farm check.
  • A receipt email is sent if email is configured.
  • The first-party Discord bot may notify the user.

Worked examples

Assumptions: a model at $0.15 / $0.60 per 1M tokens, token_multiplier = 1.0, and fixed_price_micro = 1000. Prompt 5,000 tokens and completion 200 tokens.

tokens = 5000 × 0.15 / 1e6 + 200 × 0.60 / 1e6
= 0.00075 + 0.00012 = $0.00087
fee = $0.001
charged = ceil(870 micro) + 1000 micro = 1,870 micro = $0.00187
Per-account overrides and multipliers change the final amount. Treat /usage and usage_logs.cost_micro as the source of truth, not client-side arithmetic.