A price defines the monetary amount charged for a product within a plan. Prices support multiple currencies, billing periods, and pricing models - from simple flat fees to complex tiered and formula-based calculations.
Pricing models:
- Flat - a fixed amount per billing period (e.g., $49/month)
- Per-unit - a fixed amount multiplied by quantity (e.g., $10/seat)
- Tiered - different rates at different volume thresholds (e.g., $0.10/unit for 0–1,000, $0.08/unit for 1,001–10,000)
- Volume - the tier that contains the total quantity determines the rate for all units
- Graduated - each tier's rate applies only to units within that tier's range
- Formula - a mathematical expression evaluated at billing time (see Price Formulas)
Key concepts:
- Effective date - prices can be scheduled to take effect in the future
- Country code - geo-specific pricing for different markets
- Currency - each price is denominated in a single currency; use multiple prices for multi-currency support
List prices
Returns a paginated list of prices. Supports the unified field.op=value filter grammar (see /docs/pagination).
query Parameters
created_atFilter on created_at (date-time). Operators: eq, gt, gte, lt, lte — dot grammar, e.g. created_at.gt=value; a bare created_at=value means eq.
currencyFilter on currency (string). Operators: eq, in — dot grammar, e.g. currency.in=value; a bare currency=value means eq. A bare comma-separated value is in-sugar: currency=a,b means currency.in=a,b.
keyFilter on key (string). Operators: eq, in — dot grammar, e.g. key.in=value; a bare key=value means eq. A bare comma-separated value is in-sugar: key=a,b means key.in=a,b.
kindFilter on kind (enum). Operators: eq, in — dot grammar, e.g. kind.in=value; a bare kind=value means eq. A bare comma-separated value is in-sugar: kind=a,b means kind.in=a,b. Legal values: BASE, PLAN_OVERRIDE.
updated_atFilter on updated_at (date-time). Operators: eq, gt, gte, lt, lte — dot grammar, e.g. updated_at.gt=value; a bare updated_at=value means eq.
limitPage size. Values above the server-side cap are clamped (standard default 50, cap 200; a few document-heavy lists use larger windows). Invalid values fall back to the default.
cursorOpaque continuation token from the previous response's pagination.cursor. Omit for the first page. Cursors are stateless and do not expire, but are only valid for the list and filters that produced them.
sortOrdering: created_at, with an optional :asc/:desc suffix (default created_at:desc). An unknown value is rejected. Cursors are bound to the ordering that issued them, so changing sort mid-walk needs a fresh first page.
product_idFilter by product UUID (sugar for product_id.eq). Filterable fields (product_id, plan_id, status, currency, key, kind, created_at, updated_at) accept apifilter operator suffixes
plan_idFilter by plan UUID (sugar for plan_id.eq); also supports plan_id.in
statusFilter by status (sugar for status.eq); also supports status.ne, status.in
viewValue view: draft (working-draft values) or head (published only)
product_version_idPin values to a product version
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List prices › Responses
OK
Create a price
Creates a new price. If FormulaID is not provided, a formula is auto-created from the Amount field.
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Create a price › Request Body
currencyISO 4217 currency for the list price and tier amounts.
list_price^-?\d+(\.\d+)?$ · requiredList price, MAJOR units, in the currency field.
product_idThe product to attach this price to.
country_codeCountry to scope this price to; omit to match any country.
Arbitrary dimension key/values that further scope the price.
display_nameCustomer-facing label for this price / price_key.
effective_fromOptional explicit publish timestamp; defaults to now.
effective_toOptional timestamp at which this price version stops being effective.
is_set_priceMarks this as the set price covering every effective key of the product's key set; requires a keyed product and a null price_key.
kindResolution scope: BASE or PLAN_OVERRIDE. Defaults to the most specific scope implied by the ids present. A price is a CATALOG row; a rate agreed with one customer is a subscription negotiated price, not a price.
Free-form key/value metadata to attach to the price.
plan_idPlan to scope a PLAN_OVERRIDE to; required (with plan_version) for kind=PLAN_OVERRIDE, forbidden otherwise.
plan_versionThe exact plan version the PLAN_OVERRIDE pins to; required for kind=PLAN_OVERRIDE.
price_keyKeyed variant this price covers on a keyed product; 1-64 chars matching [a-zA-Z0-9._-].
The tier ladder in ascending up_to order; omit it for a flat price, which then needs a non-zero list_price.
valid_fromCustomer-facing start of the price's applicability window; distinct from effective_from.
valid_toCustomer-facing end of the price's applicability window; distinct from effective_to.
Create a price › Responses
Created
Compute a price
Evaluates a formula expression with variable bindings. Accepts either an inline expression or a reference to a stored formula by ID.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Compute a price › Request Body
debugWhen true, the response includes a step-by-step evaluation trace.
expressionAd-hoc expression to evaluate; either this or formula_id is required.
formula_idA stored formula to evaluate; either this or expression is required.
Variable bindings supplied to the evaluation, keyed by variable name.
Compute a price › Responses
OK
Resolve a price
Resolves the most specific price for the given dimensions.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Resolve a price › Request Body
product_idProduct whose price to resolve.
quantity^-?\d+(\.\d+)?$ · requiredQuantity to price; must be positive. Drives the tier walk and formula tier_quantity binding.
at_timePoint in time to resolve at; the cascade honours each price's valid_from/valid_to against this instant. Defaults to now.
country_codeCountry context; country-specific prices outrank generic ones.
currencyCurrency to pin the resolution to; filters the cascade to prices in this currency rather than converting. SEND THIS whenever the product is priced in more than one currency: currency is not a ranking term in the cascade, so an unpinned resolve over a multi-currency slot picks a stable but arbitrary row (and that row becomes the FX source). A pin the catalog cannot satisfy is not an error - it degrades to the catalog currency and converts into the pinned one, reporting conversion_applied plus original_currency and exchange_rate.
customer_idThe customer this resolution is for. It scopes currency preference and the audit record; it does not select a price — the catalog has no customer-scoped prices.
Dimension values used to match a price's custom_dimensions scope.
plan_idPlan scope; when set, plan_version is required and PLAN_OVERRIDE rows for that plan become eligible.
plan_versionThe exact plan version PLAN_OVERRIDE rows must match; required when plan_id is set.
price_keyKeyed variant to resolve on a keyed product; falls back to the set price when no exact key price exists.
Named numeric/string variables supplied to tier formulas and rate expressions during resolution.
subscription_idSubscription context for the resolution, when resolving for an existing sub.
Resolve a price › Responses
OK
Get a price
Returns a single price enriched with owning-product context (product name, quantity source, referenced cost keys).
path Parameters
idPrice UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Get a price › Responses
OK
Remove a price
Removes the price from the owning product's working draft: the draft records the removal and the price leaves billing at the release that carries it. Discarding the draft puts the price back, and every already-published version goes on listing it — a version's price list is its own revision set, not the head's. A price that has never been released is hard-deleted instead. Returns 204; an unknown price is 404.
path Parameters
idPrice UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Remove a price › Responses
No Content
Update a price
Merge-patch update: only supplied fields change. Prices carry no publish controls — the edit lands in the owning product's working draft and reaches billing when the product is next published; to schedule a price change, schedule the product version. Currency changes are validated against the workspace's catalog currency allowlist.
path Parameters
idPrice UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Update a price › Request Body
country_codeCountry scope to set on the price; omit to leave unchanged.
currencyISO 4217 currency to change the price to; omit to keep the existing currency.
Arbitrary dimension key/values that further scope the price.
display_nameCustomer-facing label for this price / price_key.
list_price^-?\d+(\.\d+)?$List price, MAJOR units, in the price's currency (the currency field when set, else the price's existing currency).
Free-form key/value metadata to attach to the price.
Replacement tier ladder; null carries the previous version's tiers forward, an empty array clears them.
Update a price › Responses
OK
Restore a removed price
Undoes a removal that has not been released yet: the price is added back to the owning product's working draft, on the same id and with the head's values. Refused (409) when the current head does not carry the price — there is nothing to restore it from; add a new price instead.
path Parameters
idPrice UUID
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Restore a removed price › Responses
OK