Skip to main content

Credits

Units your pricing is built on.

Every entitlement limit is denominated in a credit. Every meter tracks consumption in a credit's units. Every margin calculation runs through a credit's overhead_cost and price.


Discrete vs abstract

Discrete credits map to something real: an AI input token, a GPU second, a megabyte of storage. They carry overhead_cost (what it costs you, per unit) and price (what you charge, per unit). This is what makes per-customer margin tracking accurate.

Abstract credits are conceptual units — "AI Credits", "messages", "reports". No cost attached directly. They map to discrete credits through the exchange table. Use them when you want a customer-facing unit that doesn't expose per-token or per-MB pricing, or when you want a single credit pool to drain across multiple discrete entitlements.

Both types use the same schema. The distinction is whether you define overhead_cost, price, and stof_units.


Schema

credits:
<credit-id>:
description: string # Optional. Human-readable description.
label: string # Human-facing label. Default: 'Credit'.
unit: string # Singular unit label. Default: 'credit'.
overhead_cost: float # Cost per unit (in runes). Default: 0.
pricing_model: string # 'flat' | 'tiered' | 'volume' | 'stairstep'. Default: 'flat'.
price: # Required if pricing_model is 'flat'. Null otherwise.
amount: float # Price per unit (in runes).
tiers: # Required if pricing_model is tiered/volume/stairstep.
- up_to: float # Upper bound (exclusive). Omit on the last tier for infinity.
price:
amount: float
stof_units: string # Unit type for this credit. Default: 'float'.
resets: bool # Whether this credit's meter can reset. Default: false.

Fields

description

Optional. Appears in event payloads and customer state objects. Useful for debugging and support tooling.

label

Human-facing label. Shown in the Cloud dashboard and available in the customer object for UI display.

unit

Singular label for one unit of this credit. Used in display contexts.

overhead_cost

What this credit costs you per unit, expressed in runes (1 rune = 1 USD by default). Must be ≥ 0. Used by customerMarginSnapshot() to compute cost-to-serve. The more accurately this reflects your actual provider cost, the more accurate your margin data.

pricing_model

Controls how overage is billed on soft-limit entitlements. Must be one of:

ModelBehavior
flatA single price per unit applied uniformly. Requires price.amount. Default.
tieredGraduated pricing — each consumption band has its own per-unit rate, applied only to units within that band. Requires tiers.
volumeTotal consumption determines a single per-unit rate, applied retroactively to all units. Requires tiers.
stairstepTotal consumption determines which band you're in; you pay that band's flat fee regardless of where within the band you land. Requires tiers.

price

Required when pricing_model is 'flat'. Must be null for all other pricing models.

price:
amount: 0.000004 # per unit, in runes

tiers

Required when pricing_model is 'tiered', 'volume', or 'stairstep'. A list of price tier objects. The last tier must omit up_to to represent infinity. Tiers are validated and sorted at policy load time.

tiers:
- up_to: 100000
price: { amount: 0.000006 }
- up_to: 1000000
price: { amount: 0.000005 }
- # last tier: no up_to = infinity
price: { amount: 0.000004 }

stof_units

The unit type for this credit. When set, Limitr automatically converts values passed to allow() or increment() into the credit's canonical units before metering.

stof_units: MB # allow('user', 'storage', '2GB') → meters 2000
stof_units: min # allow('user', 'gpu_min', '42seconds') → meters 0.7
stof_units: int # token counts — no unit conversion, integer
stof_units: float # (default) no conversion performed

Valid units include SI storage (B, KB, MB, GB, TB, KiB, MiB, GiB, TiB), time (ms, s, min, hr, day), and others defined in the Stof runtime.

Unit conversion

Entitlement limit values are not auto-converted. Set stof_units to the unit you want the limit expressed in, and pass values in compatible units when calling allow().

resets

Whether meters for this credit can reset on a schedule. When true, the reset schedule is defined on the entitlement limit (limit.resets, limit.reset_inc) — not on the credit itself. This flags the credit as reset-capable; the entitlement limit controls when.


Examples

Discrete: AI token credit with flat pricing

credits:
sonnet_input:
description: Claude Sonnet 4 input tokens
overhead_cost: 0.000003 # $3.00 per 1M tokens (your cost)
pricing_model: flat
price:
amount: 0.000004 # $4.00 per 1M tokens (customer price) → $1 margin per 1M
stof_units: int
resets: true

Discrete: storage with tiered pricing

credits:
gb_storage:
description: Object storage
overhead_cost: 0.00002
pricing_model: tiered
tiers:
- up_to: 10
price: { amount: 0.023 }
- up_to: 50
price: { amount: 0.022 }
-
price: { amount: 0.021 }
stof_units: GB

Abstract: customer-facing credit pool

credits:
ai_credit:
description: AI Credits
label: AI Credit
unit: credit
# No overhead_cost, no price, no stof_units
# Maps to discrete credits via the exchange table

SDK

policy.credit()

Returns the credit record for a given credit ID.

const credit = await policy.credit('sonnet_input');
// { description, label, overhead_cost, pricing_model, price, stof_units, resets }

policy.creditFor()

Returns the credit record for the credit backing a specific entitlement. id can be a plan ID or a customer ID.

const credit = await policy.creditFor('user_123', 'chat_input');

policy.creditExchange()

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

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

policy.remainingCredit()

Returns the total remaining balance of a specific credit across all of a customer's grants, after exchange conversion. Does not include entitlement meter state.

const remaining = await policy.remainingCredit('user_123', 'ai_credit');