Skip to main content

Exchange

Map credits into one another.

The exchange table maps credits to one another through a common base currency — the rune. It's what allows a pool of abstract credits to drain across multiple discrete entitlements, and what enables Limitr to compute per-customer margin without external tooling.


The rune

Every value in the exchange table is expressed relative to the rune. By default, 1 rune = 1 USD. You don't need to define the rune explicitly — it's automatically set as:

exchange:
rune:
value: 1
currency: usd

All other exchange pairs chain back to the rune. Limitr resolves any conversion by walking the chain: credit A → credit B → rune.


Schema

exchange:
grant_strategy: string # 'expires_first' | 'cheapest_first' | 'valuable_first'. Default: 'expires_first'.
rune:
value: float # Always 1 by convention.
currency: string # 'usd' or another terminal currency.
<credit-id>:
value: float # How many units of `currency` does 1 unit of this credit equal?
currency: string # The credit ID or terminal currency this pair prices into.

Each exchange pair has two fields:

value — The multiplier. Must be ≥ 0. Represents how many units of currency one unit of this credit is worth.

currency — The credit ID or terminal currency this pair prices into. Use 'rune' to price directly in runes. Use another credit's ID to chain through it.

Matching price to exchange

Setting a credit's exchange value equal to its price.amount keeps the two in sync and makes the policy easier to maintain. Chains let you adjust the relationship between abstract and discrete credits independently of the base price.


How resolution works

Limitr resolves conversions by walking the chain from the source credit toward rune, multiplying values at each step. If a cycle is detected, the conversion returns null.

For credits with a flat pricing model and a defined price.amount, an explicit exchange entry is optional — Limitr uses the credit's price as its rune value automatically. Adding an explicit entry overrides this.

Example:

exchange:
rune: { value: 1, currency: usd }
ai_credit: { value: 1.25, currency: rune }
sonnet_input: { value: 0.000004, currency: ai_credit }
sonnet_output: { value: 0.00002, currency: ai_credit }

To find how many sonnet_input tokens 1 ai_credit buys:

1 ai_credit / 0.000004 = 250,000 input tokens

Grant strategy

When a customer has multiple grants eligible to cover overage, grant_strategy controls which is consumed first.

StrategyBehavior
expires_firstThe grant with the earliest expiry is consumed first. Prevents credit from going to waste. Default.
cheapest_firstThe grant with the lowest rune value per unit is consumed first. Preserves higher-value grants.
valuable_firstThe grant with the highest rune value per unit is consumed first.
exchange:
grant_strategy: expires_first
rune: { value: 1, currency: usd }
# ...

Multi-step chains

Exchange chains can be arbitrarily deep. A common pattern is a two-level chain: an abstract customer-facing credit → a discrete model credit → rune.

exchange:
rune: { value: 1, currency: usd }
ai_credit: { value: 1.25, currency: rune }
sonnet_input: { value: 0.000004, currency: ai_credit }
sonnet_output: { value: 0.00002, currency: ai_credit }
haiku_input: { value: 0.000001, currency: ai_credit }
haiku_output: { value: 0.000005, currency: ai_credit }

When a customer's ai_credit grant is drawn against a sonnet_input overage, Limitr walks sonnet_input → ai_credit → rune to determine how much grant balance to deduct.


Exchange and grants

The exchange table is what makes grants work across different credit types. A grant is denominated in one credit (e.g. ai_credit). An entitlement limit is denominated in another (e.g. sonnet_input). When overage occurs on a soft-limit entitlement, Limitr:

  1. Finds the best eligible grant per grant_strategy
  2. Uses the exchange table to convert the overage amount from the entitlement's credit into the grant's credit
  3. Deducts from the grant balance
  4. Fires meter-overage only if no grants remain to cover the overage

See Topups & Grants for grant lifecycle and Enforcement for the full event flow.


SDK

policy.creditExchange()

Converts a value from one credit to another using the exchange table. Returns null if no path exists between the two credits.

// How many sonnet input tokens does 10 ai_credits buy?
const tokens = await policy.creditExchange('ai_credit', 'sonnet_input', 10);
// → 2,500,000

// Returns null if no path exists
const result = await policy.creditExchange('sonnet_input', 'unrelated_credit', 1);
// → null