OpenTela
Tutorial

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         │
  └───────────────────────────────────────────────────────┘
  1. 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.json

    Asks carry a server-assigned 5-minute TTL; the republish loop (default 2m) keeps them live. See ask publication for the asks file format.

  2. 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.

  3. 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: 200

    A peer whose live ask exceeds a capped dimension is excluded from that request's affordable set. See frontend integration for the full header semantics.

  4. 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: 5000

The 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

ConcernWhere
Publish / update asksaskpublish → POST /internal/pricing (5-min TTL)
Fund credittokens dApp billing tab or POST /manage/billing/topup
Per-request capsX-Max-*-Price-Per-Million headers
Account capsPATCH /manage/billing/preferences
Balance & usage historyGET /manage/billing, GET /manage/billing/deposits
Seller pricing surfacecloud console → Instances → Pricing (GET /manage/billing/asks)
Withdraw earningsPOST /manage/billing/withdrawals
Design & phasesdocs/billing-design.md
Edit on GitHub

Last updated on

On this page