Advanced Pricing Models (recipes)
What this is
Copyable pricing patterns that go beyond the UI. Each recipe shows when to use it, a minimal price shape, and links to related concepts. Use these as starting points and adapt to your product.
When to use it
- You need multi‑component pricing that the UI doesn’t support yet
- You want hybrid models (base + usage), seat bundles, or mixed cycles
- You need BPS‑style transaction pricing or custom minimum‑spend behavior
Recipe 1: Hybrid – base + usage with free allowance
Use when you want a predictable base fee and pay‑as‑you‑go beyond an included allowance.
Minimal price shape (trimmed)
{
"dsl_version": 1,
"components": [
{
"type": "fixed",
"label": "Pro – Base",
"amount_cents": 2900,
"recurrence_rule": "RRULE:FREQ=MONTHLY;INTERVAL=1"
},
{
"type": "usage",
"label": "API calls overage",
"unit_label": "call",
"metric_id": "met_api_calls_30d",
"unit_cost_cents": 1,
"recurrence_rule": "RRULE:FREQ=MONTHLY;INTERVAL=1"
}
]
}
How it works
- Create a numeric feature
api-calls
and metric that counts calls in the billing window. 2) Create a credit definition for the included allowance (e.g., 10,000 per month). 3) Add theusage
component for overage. During billing, usage within credits is free; beyond credits is charged by this component.
Gotchas
- Ensure the metric’s
eventName
matches the events you send - Link the credit definition to the same feature slug used by the metric
- Keep RRULEs in UTC; avoid
TZID
See also
Recipe 2: Seat‑based (per‑unit) with conceptual proration
Use when you charge per active seat/member, optionally with a minimum seat count.
Minimal price shape (trimmed)
{
"dsl_version": 1,
"components": [
{
"type": "per_unit",
"label": "Seats",
"unit_label": "seat",
"amount_cents": 1000,
"metric_id": "met_seat_count",
"recurrence_rule": "RRULE:FREQ=MONTHLY;INTERVAL=1"
}
]
}
How it works
Track seats in your app (organization members) using a seat‑count metric (referenced by metric_id
). Bill counting the current seat count at each cycle. If you need an included seat allowance, combine with a usage feature and credits; otherwise rely on per‑unit only.
Proration (conceptual)
Proration can be modeled by adding a one‑time fixed adjustment when seats change mid‑cycle, or by charging immediately via bill_immediately
components on add‑seat flows. Exact pro‑rating rules are product‑specific.
Gotchas
- Align UI seat count with what you bill (source of truth)
- If you mix seats and usage, keep component cycles consistent
See also
Recipe 3: BPS on transaction volume (API)
Use when you charge a percentage of processed volume (e.g., 1%). Implement by defining a metric that sums volume in whole dollars and a usage
component with per‑dollar cost equal to the percentage.
Minimal shape (trimmed)
{
"dsl_version": 1,
"components": [
{
"type": "usage",
"label": "Processing fee (1%)",
"unit_label": "USD",
"metric_id": "met_volume_usd_30d",
"unit_cost_cents": 1,
"recurrence_rule": "RRULE:FREQ=MONTHLY;INTERVAL=1"
}
]
}
If your metric returns dollars, unit_cost_cents: 1
= $0.01 per $1 = 1%.
Minimum spend (advanced)
Commonly you want charge = max(minimum, bps_charge)
. Today this requires API‑driven adjustments (e.g., add a fixed base for the minimum and apply a plan‑level monetary credit for the difference when bps_charge exceeds the minimum). Treat this as an advanced pattern and test carefully.
Gotchas
- Ensure the metric scales to the unit label (dollars vs cents)
- Avoid double‑counting refunds or reversals in your event stream
See also
Recipe 4: Mixed cycles (multi‑component, different RRULEs)
Use when you need different components on different billing cycles (e.g., monthly base, yearly seat bundle, monthly usage).
Minimal shape (trimmed)
{
"dsl_version": 1,
"components": [
{
"type": "fixed",
"label": "Base (monthly)",
"amount_cents": 1500,
"recurrence_rule": "RRULE:FREQ=MONTHLY;INTERVAL=1"
},
{
"type": "per_unit",
"label": "Seats (yearly)",
"unit_label": "seat",
"amount_cents": 9000,
"metric_id": "met_seat_count",
"recurrence_rule": "RRULE:FREQ=YEARLY;INTERVAL=1"
},
{
"type": "usage",
"label": "AI tokens (monthly)",
"unit_label": "1k tokens",
"metric_id": "met_tokens_30d",
"unit_cost_cents": 25,
"recurrence_rule": "RRULE:FREQ=MONTHLY;INTERVAL=1"
}
]
}
Each component maintains its own cycle and appears separately in subscription details and invoices.
Gotchas
- Don’t mix timezones in RRULEs; always use pure UTC
- Keep metric timeframes aligned to each component’s cycle when computing usage
See also
How the UI wires this
- The Create Plan UI can scaffold usage‑based features: it creates the metric (simple COUNT/SUM from your event), creates plan‑scoped credit definitions, and when you add a usage price it links the credit definition to that usage component and aligns renewals to the billing cycle.
- For seat‑based pricing, the UI generates a seat‑count metric and references it from
per_unit
components so billing reflects active seats. - Publishing to pricing tables is handled for you when you enable “show in pricing table”.
UI vs API
- UI: Base fees, simple per‑unit, and standard usage patterns
- API: BPS, minimum spend logic, mixed cycles, complex adjustments
Common pitfalls
- Missing metric linkage for usage components → no overage computed
- Mis‑scaled metrics (cents vs dollars) in BPS patterns
- RRULEs with
TZID
or invalid cadence - Assuming minimum‑spend max logic exists by default — implement via API