Skip to content

How Money Flows

FORA never touches money. It follows the OpenRTB model: the protocol handles authorization and logging, while actual settlement happens outside the protocol through existing billing infrastructure.

The chain works like this:

Provider -> Exchange operator -> AI Company (the agent's account holder)
  1. The Exchange (operated by an Exchange operator, provider, or third party) handles all billing through its pluggable Billing Adapter
  2. The Exchange operator invoices the AI company via its existing system (monthly invoicing, prepaid balance, etc.). A purchase made through a Broker is billed to the agent’s own account, as a direct one is
  3. The Exchange operator pays the provider via its existing revenue-share agreement

The billing_id in a TransactionResponse is an invoice line item, not a payment confirmation. Settlement happens offline, same as programmatic advertising.

PricingModel is the charging structure only — a closed set of three. The open-ended metering basis (“per what”) lives in Pricing.unit as a vocabulary, so per-access / per-token / per-fetch / per-page / per-minute / per-record are all PER_UNIT with a different unit.

ModelDescriptionRSL Equivalent
PRICING_MODEL_FREENo charge (state explicitly; absent Pricing ≠ free)free
PRICING_MODEL_PER_UNITRate per Pricing.unit (metering basis: accesses, tokens, fetches, pages, minutes, records, …)crawl / use / inference / training / metered purchase
PRICING_MODEL_FLATOne-time flat fee; rate is the total, no unitone-time purchase

A PER_UNIT price is metered. A PER_UNIT offer may carry an estimated_quantity in its unit, or none; whether to state one is the publisher’s decision. The purchase charges estimate × rate, or one unit’s rate without an estimate, and the charge is final. A disagreement about the quantity consumed is a dispute. See Charging a metered purchase.

A subscription is FREE + a subscription:* scope (settled off-protocol). Attribution and contribution are Obligations, not pricing models. There is no revenue-share model — settlement is off-protocol.

Providers set their preferred pricing model and rate in their RSL file. The Exchange operationalizes these into live Offers. RSL pricing serves as a price ceiling (public declaration); private pricing between provider and Exchange may be lower.

Different pricing models make direct comparison difficult. An article priced at $0.05 per access is not directly comparable to a resource priced at $0.00002 per token.

unit_cost normalizes all pricing to a per-unit basis, analogous to eCPM in advertising. It is stated in the comparison unit of the content type: tokens for text, seconds for audio and video, pages for documents, records for data.

unit_cost = price of one purchase / size of the resource in the comparison unit

The denominator is the size of the resource, not estimated_quantity. estimated_quantity is always counted in the offer’s own Pricing.unit, so it is the comparison size only when the offer is priced in the comparison unit. A price per access has an estimate in accesses — one access — never a token count.

For example:

  • Article at $0.05 per access (unit: "accesses", estimated_quantity: 1), 3,300 tokens long: unit_cost = $0.05 / 3,300 = $0.00001515 per token
  • Per-token pricing at $0.00002 (unit: "tokens"): unit_cost = $0.00002 per token, the rate itself
  • Per-page at $0.10 (unit: "pages", estimated_quantity: 15): unit_cost = $0.10 per page, the rate itself
  • Audio at $0.50 per minute (unit: "minutes", estimated_quantity: 45): unit_cost = $0.50 / 60 = $0.0083 per second

The Broker uses unit_cost to compare offers across Exchanges and pricing models, selecting the most cost-effective option regardless of how the provider originally priced it.

Every Offer in a ResourceResponse includes both the native pricing and the computed unit_cost value. Here the article priced per access:

{
"pricing": {
"model": "PRICING_MODEL_PER_UNIT",
"rate": "0.05",
"currency": "USD",
"unit_cost": "0.00001515",
"estimated_quantity": 1,
"unit": "accesses"
}
}

The purchase charges estimate × rate = 1 × $0.05, and the charge is final. Its usage report counts accesses too (consumed_quantity: 1, consumed_unit: "accesses").

Each Exchange declares a base_currency in its manifest (ISO 4217 code, e.g., “USD”, “EUR”). All unit_cost values in offers from that Exchange are denominated in this currency. This enables cross-exchange price comparison by the Broker without requiring currency conversion at query time.

The protocol supports two billing patterns:

The default model. Each transaction is independently authorized and billed:

  1. Agent sends ExecuteTransaction with a selected offer
  2. Exchange calls BillingAdapter.Authorize(requester, amount) — checks the requester’s balance/credit
  3. If authorized, Exchange issues a signed URL and records the transaction
  4. The AI company is invoiced for the sum of all transactions

When an AI company has a subscription deal with an Exchange:

  1. During DiscoverResources, the Exchange detects the requester’s subscription and includes a subscription offer with rate=0 and subscription_id
  2. The Broker prefers subscription offers (zero marginal cost)
  3. During ExecuteTransaction, the Exchange skips BillingAdapter.Authorize (already paid under subscription) but checks quota
  4. Usage reporting is still mandatory — providers need consumption data for subscription renewals

Subscription transactions include a subscription_unit_value field that carries the per-unit cost even though cost.amount is 0. This enables financial attribution: the AI company can track the value of resources consumed against the subscription’s total prepaid amount.

Two enforcement layers prevent overspend, mirroring how OpenRTB prevents advertiser overspend:

  • Agent/Broker-side: RequestConstraints.max_unit_cost — the agent will not accept offers above this threshold. BrokerService.Resolve may filter out offers that would exceed the agent’s budget (max_price, and period_budget for its budget_scope) and answers a URI left with none with OFFER_ABSENCE_REASON_BUDGET_EXCEEDED. How the budget is computed is the Broker’s own behaviour, not part of the protocol. Resolve never charges.
  • Exchange-side: The Exchange operator’s Billing Adapter checks the requester’s balance or credit before authorizing each item. An item the requester cannot afford is denied in the response body (DENIAL_REASON_INSUFFICIENT_BALANCE), also when it is the only item.

Each Exchange independently tracks per-requester balance. The Broker keeps its own view of spend for budget filtering, but the Exchange is authoritative for “can this requester afford this transaction.” Currency conversion is out of scope for this version: totals are never summed across currencies.

Here is a concrete transaction with dollar amounts.

Setup:

  • Provider: TechCrunch (Hearst Media)
  • Article: “AI Regulation: What Providers Need to Know” (2,500 words, ~3,300 tokens)
  • RSL price ceiling: $0.08 per crawl
  • SSP-Alpha private pricing: $0.05 per article (below RSL ceiling)
  • Requester: Anthropic (Claude), with a registered account at SSP-Alpha (account handle acct_7f3e21c9 — an opaque value minted by the Exchange at registration, meaningless on its own)
  • Anthropic has an annual subscription with Hearst via SSP-Alpha

What happens:

StepActionCost
1Claude queries SSP-Alpha via DiscoverResources$0
2SSP-Alpha returns two offers: per-request ($0.05) and subscription ($0.00)—
3Broker selects subscription offer (zero marginal cost)$0.00
4ExecuteTransaction — subscription quota checked (850,000 tokens remaining), 3,300 deducted$0.00
5Signed URL issued, Claude fetches article from CDN—
6Usage report filed: 3,150 actual tokens consumed—

Financial attribution:

  • cost.amount: $0.00 (subscription)
  • subscription_unit_value.amount: $0.05 (the per-article value for accounting)
  • Anthropic tracks: $0.05 drawn against prepaid subscription balance

Without the subscription, the per-request path would have charged $0.05 for this article, with a unit_cost of $0.00001515 per token.

When an agent files a successful dispute via DisputeTransaction, the resolution may include a credit:

ResolutionWhenEffect
CREDITCDN delivery failure, content hash mismatch, size anomalyFull transaction amount credited back to agent’s balance
PARTIAL_CREDITToken count discrepancy corroborated by CDN sizeProrated credit based on discrepancy
REDELIVERYTransient failure, content still availableNew signed URL issued, no credit
REJECTEDInsufficient evidence, fabricated claimsNo credit, dispute pattern logged

Credits are applied to the agent’s balance with the Exchange. They reduce the next invoice — same as ad-tech billing discrepancy adjustments. The protocol does not prescribe how credits are settled between Exchange operator and provider; that follows the existing revenue-share agreement.

One field provides cost transparency even when the per-request charge is zero:

  • subscription_unit_value: Carried on subscription transactions where cost.amount is $0. Shows the per-unit value for financial attribution — the AI company can track the value of resources consumed against its prepaid subscription balance.

A Broker’s fee has no field. It is additive and disclosed out of band, never folded into the offer price the Exchange signed, so the agent sees what it pays for the resource and what it pays for brokerage (see Selection Engine).

Three independent records ensure transaction integrity:

  1. CDN access logs (provider controls): every signed URL access with transaction ID, agent ID, timestamp
  2. Exchange transaction log (Exchange operator controls): every billing_id issued with cost, requester, offer snapshot (including Ed25519 exchange signature for non-repudiation)
  3. Usage reports (agent files): what the agent actually did with the resource (token count, function, citation)

All three records must agree. Discrepancies are resolved offline, like ad-tech billing discrepancy resolution (~5-10% tolerance).