Billing & Settlement
How OpenTela billing works — seller asks, buyer credit, per-request caps, and settlement through the API market's billing gateway.
OpenTela has a single billing rail: the API market (the billing gateway at
api.opentela.ai). Sellers publish their minimum fee as asks, buyers fund a
credit account and cap spend per request, and the gateway meters actual
usage and settles against the buyer's credit. There is no peer-to-peer payment
path: nodes never sign transfers to each other.
The legacy direct-transfer settlement was removed
Earlier versions of this document described a peer-to-peer settlement system
(rates.yaml with price_per_1000 rates, head/worker CRDT reconciliation, and
head-signed SPL transfers between consumer and provider wallets). That rail was
removed — billing.enabled / OF_BILLING_ENABLED now fails fast at startup
with a pointer here. If you are migrating an old deployment: delete the
billing: and rates: blocks from cfg.yaml, and move to the market flow
below. Running both rails on the same traffic double-billed buyers, which is
why the old path was retired rather than kept alongside.
The market model
Seller (worker node) Buyer (head node)
──────────────────── ──────────────────
publishes asks ── market ──> resolves live asks +
(askpublish, every 2m) price book affordable peers
(X-Otela-Allowed-Peers)
▲ │
│ withdraw earnings │ forwards request
│ (POST /manage/billing/withdrawals) ▼
│ gateway meters usage and
┌───────────────────────────────────────────────────────┐
│ billing gateway (api.opentela.ai) │
│ reserve → meter → settle against buyer credit │
└───────────────────────────────────────────────────────┘-
Sellers set their minimum fee. Each provider publishes per-million-token asks (input / cached-input / output) with the reference ask-publisher:
askpublish \ -api https://api.opentela.ai \ -control-token "$INTERNAL_CONTROL_TOKEN" \ -peer-key-file ~/.opentela/identity.key \ -asks asks.jsonAsks carry a server-assigned 5-minute TTL; the republish loop (default 2m) keeps them live. See ask publication for the asks file format.
-
Buyers fund credit. Credit is backed by OTELA deposits into the treasury. Acquire OTELA, then top up from the tokens dApp billing tab (a wallet → treasury transfer the deposit watcher credits) or via
POST /manage/billing/topup. -
Buyers cap spend per request. Account-level caps are managed on the wallet page (
PATCH /manage/billing/preferences); a caller can additionally cap any single request with the max-fee headers:X-Max-Input-Price-Per-Million: 100 X-Max-Cached-Input-Price-Per-Million: 50 X-Max-Output-Price-Per-Million: 200A peer whose live ask exceeds a capped dimension is excluded from that request's affordable set. See frontend integration for the full header semantics.
-
The gateway meters and settles. For each served request the gateway reserves conservatively, meters actual usage, and settles the exact amount against the buyer's credit ledger, crediting the seller's account. Sellers withdraw earnings via the manage API.
Price-aware routing
The gateway stamps the cheapest affordable peers (cheapest-first) into
X-Otela-Allowed-Peers on every forwarded request. The mesh head consumes that
order: with routing.price_weight_decay set (env
OF_ROUTING_PRICE_WEIGHT_DECAY), selection is weighted toward the cheapest
affordable peers, and retries deterministically prefer the next-cheapest
allowed peer. See Routing.
Local usage tracking (observability)
Worker services report usage through response headers:
X-Usage-Tokens: 1234
X-Usage-GPU-Ms: 5000The head extracts these (X-Usage-*) and keeps local per-request records
(Badger-backed, keyed by request ID). These records do not move money —
they are the node's local accounting trail for observability and dispute
evidence. The authoritative meter and settlement live in the billing gateway.
Where things live
| Concern | Where |
|---|---|
| Publish / update asks | askpublish → POST /internal/pricing (5-min TTL) |
| Fund credit | tokens dApp billing tab or POST /manage/billing/topup |
| Per-request caps | X-Max-*-Price-Per-Million headers |
| Account caps | PATCH /manage/billing/preferences |
| Balance & usage history | GET /manage/billing, GET /manage/billing/deposits |
| Seller pricing surface | cloud console → Instances → Pricing (GET /manage/billing/asks) |
| Withdraw earnings | POST /manage/billing/withdrawals |
| Design & phases | docs/billing-design.md |
Last updated on