Rate tables provide structured lookup pricing - a grid of rates indexed by one or more dimensions. Use rate tables for complex pricing that depends on multiple variables like geography, volume tier, customer segment, or contract term.
Example: A shipping rate table with dimensions for weight range, origin country, and destination country.
List rate tables
Lists the rate tables of the caller's organization. Archived tables are not listed.
Required scope: price.read (Read prices).
query Parameters
includeExtra data to add to the response: scheduled_versions. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. scheduled_versions is sent without being asked until 2026-11-30; after that date it is sent only when named here.
limitPage size (default 50, max 200)
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: slug, name or created_at, each with an optional :asc/:desc suffix (default slug:asc). An unknown value is rejected. Cursors are bound to the ordering that issued them, so changing sort mid-walk needs a fresh first page.
has_scheduled_versionFilter by whether the entity has a version scheduled to publish (true or false). A scheduled version is a FROZEN version row a pending catalog.publish_version Change is bound to; the entity itself stays draft, published or archived and its working draft stays free for immediate changes.
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 rate tables › Responses
OK
Create a rate table
Creates a rate table in the caller's organization. It starts as a draft: fill its working draft with PUT /rate-tables/{id}/draft/content, and formulas can read it once that draft is published.
Required scope: price.write (Write prices).
query Parameters
includeExtra data to add to the response: scheduled_versions. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. scheduled_versions is sent without being asked until 2026-11-30; after that date it is sent only when named here.
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 rate table › Request Body
nameDisplay name for the table.
on_missing_keyBehaviour when no entry matches: 'error', 'zero', or 'default_value'.
slugURL-safe unique identifier formulas reference this table by.
table_typeMatching mode: 'lookup' (exact key match) or 'bracket' (numeric range match).
currencyISO 4217 currency for the entry values; defaults to the org's preferred currency when omitted.
default_value^-?\d+(\.\d+)?$The value returned on a miss, a formula operand; required when on_missing_key=default_value.
descriptionOptional description of the table's purpose.
requires_continuous_coverageWhen true, published versions may not leave a gap in the effective-date timeline.
Create a rate table › Responses
Created
Get a rate table
Returns the rate table: its slug, matching mode, the missing-key policy of the version in force and that version as head_version. The rows of a version are read with GET /rate-tables/{id}/versions/{version}.
Required scope: price.read (Read prices).
path Parameters
idRate table ID
query Parameters
includeExtra data to add to the response: scheduled_versions. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. scheduled_versions is sent without being asked until 2026-11-30; after that date it is sent only when named here.
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 rate table › Responses
OK
Delete a rate table (draft only)
Deletes a rate table that has never been published, with its working draft. A published table is refused (400); archive it with PATCH /rate-tables/{id} {"status": "archived"}.
Required scope: price.write (Write prices).
path Parameters
idRate table 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.
Delete a rate table (draft only) › Responses
No Content
Update a rate table
Updates a rate table. A new name, description or coverage rule applies at once. A new missing-key policy or default value goes into the table's working draft and changes no lookup until that draft is published (POST /changes with operation catalog.publish_version and subject_kind=rate_table). {"status": "archived"}, sent alone, archives the table.
Required scope: price.write (Write prices).
path Parameters
idRate table ID
query Parameters
includeExtra data to add to the response: scheduled_versions. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. scheduled_versions is sent without being asked until 2026-11-30; after that date it is sent only when named here.
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 rate table › Request Body
default_value^-?\d+(\.\d+)?$New default value, a formula operand; omit to leave unchanged.
descriptionNew description; omit to leave unchanged.
nameNew display name; omit to leave unchanged.
on_missing_keyNew missing-key behaviour ('error', 'zero', or 'default_value'); omit to leave unchanged.
requires_continuous_coverageNew continuous-coverage requirement; omit to leave unchanged.
statusarchived archives the table and every version of it: lookups keep the rates for the periods before the archive, and nothing can publish to it again. Refused (409) while a live price reads the table. Archiving is final. Send status alone; a table that has never been published is deleted with DELETE instead.
Update a rate table › Responses
OK
Archive a rate table (terminal)
Deprecated: use PATCH /rate-tables/{id} instead. Removed on 2026-11-30.
Archives the table and every version of it, and returns 200 with the archived rate table. Refused (409) while a live price reads the table. Use PATCH /rate-tables/{id} with {"status": "archived"} instead.
Required scope: price.write (Write prices).
path Parameters
idRate table ID
query Parameters
includeExtra data to add to the response: scheduled_versions. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. scheduled_versions is sent without being asked until 2026-11-30; after that date it is sent only when named here.
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.
Archive a rate table (terminal) › Responses
OK
Get the open working draft
The entity's ONE working draft: its row id, the version it publishes as, when it was opened, the version it is authored on top of, and a counted summary of what is staged. data is null when nothing is staged — a state, not an error.
Required scope: price.read (Read prices).
path Parameters
idEntity 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 the open working draft › Responses
OK
Open the working draft on a chosen base
Opens the working draft if none is open, and records which version it is authored on top of: the live head (omit base_version_id) or one of the entity's scheduled versions. Re-basing an open draft keeps its edits — the delta is the author's intent and is never rewritten — and re-materialises them over the new base. A publish of a draft based on a scheduled version cannot be scheduled to fire before that version does.
Required scope: price.write (Write prices).
path Parameters
idEntity 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.
Open the working draft on a chosen base › Request Body
base_version_idThe version the working draft is authored on top of — the live head, or one of the entity's scheduled versions. Omit for the head.
Open the working draft on a chosen base › Responses
OK
Discard the open working draft
Archives the working draft with reason 'discarded'. The live entity is untouched: nothing pointed at the draft and it was never on the billing timeline. 404 when nothing is staged, which is a different answer from a successful discard and is reported as one.
Required scope: price.write (Write prices).
path Parameters
idEntity 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.
Discard the open working draft › Responses
No Content
Replace what the working draft contains
States what the draft should CONTAIN; the server derives the change against the draft's base and validates the result. A child the body omits is removed from the draft. Opens the working draft on the head when none is open.
Required scope: price.write (Write prices).
path Parameters
idEntity 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.
Replace what the working draft contains › Request Body
The rows this version should carry: exact-match lookup keys or numeric brackets.
on_missing_keyWhat a lookup does when no row matches.
currencyISO 4217 currency the values are in when a formula reads them as money.
default_value^-?\d+(\.\d+)?$The value a miss is served with when on_missing_key is 'default_value'.
Replace what the working draft contains › Responses
OK
List a rate-table's version timeline
The entity's versions in the order they fired and will fire: history, head, scheduled releases, working draft. Published and scheduled rows are returned by default; pass include=all for the draft and the archived rows. Same row shape as /versions.
Required scope: price.read (Read prices).
path Parameters
idEntity UUID
query Parameters
includeSet to 'all' to include the working draft and archived rows.
limitPage size (default 100, max 200)
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.
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 a rate-table's version timeline › Responses
OK
List rate-table versions
Returns version rows for the entity, keyset-paginated (default 100, max 200 per page). The status filter accepts draft, scheduled, published, archived; the default excludes draft. include=usage_count adds how many records use each version; sort=version:desc lists the newest first.
Required scope: price.read (Read prices).
path Parameters
idEntity UUID
query Parameters
includeExtra data to add to the response: usage_count. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400.
statusLifecycle status filter (repeatable / comma-separated): draft, scheduled, published, archived. Default excludes draft.
archived_reasonNarrow archived rows by reason (repeatable / comma-separated): canceled, discarded, errored, superseded
sortOrder: version:asc (the default) lists the versions in the order they fired and will fire; version:desc lists the highest number first, versions without a number (the working draft, archived rows) last.
limitPage size (default 100, max 200)
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.
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 rate-table versions › Responses
OK
Get the currently active rate-table version
Deprecated: use GET /rate-tables/{id}/versions/{version} instead. Removed on 2026-11-30.
Returns the rate-table version in force now, with its entries; 404 while the table has never been published. The same version is GET /rate-tables/{id}/versions/{version} with the number of the table's head_version.
Required scope: price.read (Read prices).
path Parameters
idRate table 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.
Get the currently active rate-table version › Responses
OK
Get a rate-table version snapshot
The version's own fields plus the common version header. {version} is the number, or the word 'draft' for the open working draft.
Required scope: price.read (Read prices).
path Parameters
idEntity UUID
versionThe version number, or the word 'draft' for the open working draft.
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 rate-table version snapshot › Responses
OK
Name or annotate a rate-table version
Sets the version's release_name and/or release_note. These are display metadata, not content: editing them never creates a new version and is allowed on published versions. An absent field is left unchanged; null clears it; an empty string is refused. It answers the version row without the data envelope; from 2026-11-30 it answers {"data": …} like every other operation.
Required scope: price.write (Write prices).
path Parameters
idEntity UUID
versionThe version number, or the word 'draft'.
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.
Name or annotate a rate-table version › Request Body
release_nameNew name; null clears it. Absent leaves it unchanged.
release_noteNew note; null clears it. Absent leaves it unchanged.
Name or annotate a rate-table version › Responses
OK
created_atWhen the row was opened — for a draft when editing started, for a release when it was armed.
effective_fromeffective_toidThe catalog_versions row id. A client selecting a version writes this, never the number.
originWho made this version: manual (an operator published it), scheduled_release (a scheduled publish fired), cascade (republished automatically because something it depends on published).
published_atstatusThe row's own state: draft, scheduled, published or archived.
versionThe version's display number, or 0 for a row that is not on the chain (a working draft, an archived row).
archived_reasonWhy an archived row left the timeline: canceled, discarded or superseded.
For origin=cascade: what caused this version.
What the version does differently from the version it replaced; from is absent for the entity's first version. Sent only with include=diff (plans and products).
Who published the version — the same actor the audit trail names: an operator, an API key, or the system for a cascade. Absent on a version not yet published and on one published before publishers were recorded.
rank1-based position in the entity's queue of scheduled versions — the order they will fire. Present only on scheduled rows.
recorded_atWhen the publish was captured, on the wall clock (its audit row). published_at is the operation's instant — a sandbox's test clock — and effective_from when it governs. Sent with include=diff on published versions that have an audit row.
release_nameOperator-given name of this version, shown beside its number.
release_noteFree-text note about this version.
scheduled_change_idThe pending catalog.publish_version Change that will publish this version — reschedule or cancel it there.
scheduled_forWhen this scheduled version is due to publish. Present only on a scheduled row.
usage_countPresent only with ?include=usage_count.
Compare two rate-table versions
Every cell that differs between two versions, with the value on each side. ?against= takes 'head' (the default), another version number, or 'draft'. The comparison is of the two versions' STORED grids — nothing is recomputed at read time.
Required scope: price.read (Read prices).
path Parameters
idEntity UUID
versionThe version number, or the word 'draft'.
query Parameters
againstWhat to compare against: 'head' (the default) for the live version, or another version number, or 'draft'.
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.
Compare two rate-table versions › Responses
OK
Export rate-table version entries as CSV
Streams the version's entries as CSV with columns lookup_key, range_min, range_max, value, addressed by version number (the same key GET /rate-tables/{id}/versions/{version} returns). Suitable for round-tripping back through the import endpoint.
Required scope: price.read (Read prices).
path Parameters
idRate table ID
versionVersion number
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.
Export rate-table version entries as CSV › Responses
CSV body
Preview what else publishing this version would publish
The entities that will publish BECAUSE this one does — a plan that tracks this product's latest, say — each with the cells its next head would carry that its current one does not. Derived on every read and never frozen: something that starts following tomorrow appears tomorrow.
Required scope: price.read (Read prices).
path Parameters
idEntity UUID
versionThe version number, or the word 'draft' for the open working draft.
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.
Preview what else publishing this version would publish › Responses
OK
Forecast the impact of superseding this rate-table version
Who is using the version in force today, and what a publish over it would move. pinnable reports whether holding a version is possible for this entity at all — it is false for tax rules, which are dated rather than pinned, so a caller must not render a pinned count for them. republishes_consumers is the cross-entity fan-out (publishing a price formula republishes every ACTIVE product whose head tiers reference it), and live_readers counts consumers billing off the live head, who move as soon as the publish lands. Read-only, and uncached: this is read at the moment money changes.
Required scope: price.read (Read prices).
path Parameters
idEntity UUID
versionVersion number (positive integer)
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.
Forecast the impact of superseding this rate-table version › Responses
OK
List rate-table version referrers
Offset-paginated drill-down of the referrers of one type for one version of the entity.
Required scope: price.read (Read prices).
path Parameters
idEntity UUID
versionVersion number (positive integer)
query Parameters
typeReferrer type to list (required)
limitPage size (default 50, max 200)
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.
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 rate-table version referrers › Responses
OK
Get rate-table version usage summary
Referrer counts for one version of the entity, grouped by referrer type. Powers the version-switcher hover card.
Required scope: price.read (Read prices).
path Parameters
idEntity UUID
versionVersion number (positive integer)
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 rate-table version usage summary › Responses
OK