Billing
Plans, subscription, invoices, usage.
11 endpoints.
GET /v1/billing/plansGET /v1/billing/subscriptionPOST /v1/billing/checkoutPOST /v1/billing/change-planPOST /v1/billing/change-plan/previewPOST /v1/billing/cancelPOST /v1/billing/resumeGET /v1/billing/invoicesGET /v1/billing/portalPOST /v1/billing/webhooks/{provider}GET /v1/usage
GET
/v1/billing/plansPublic plan list (no auth)
No key needed
Responses
- 200Successful Response
PlanOut[]
GET
/v1/billing/subscriptionBilling Subscription
Needs a key or a dashboard session
Responses
- 200Successful Response
SubscriptionOut
POST
/v1/billing/checkoutBilling Checkout
Needs a key or a dashboard session
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key | header | string | null | no | Unique per logical write (8-255 chars). Retries with the same key are safe. · pattern ^[A-Za-z0-9_\-:.]{8,255}$ |
Request body application/json CheckoutRequest
| Name | Type | Required | Description |
|---|---|---|---|
plan_code | string | yes | max length 32 |
interval | "month" | "year" | no | default "month" |
quantity | integer | no | Plans sold by size (Enterprise): blocks of `sizing.block_products` products, 1 to 40. 1 for every other plan.default 1 · min 1 · max 40 |
Responses
- 200Successful Response
RedirectUrl
POST
/v1/billing/change-planUpgrade or downgrade with proration
Needs a key or a dashboard session
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key | header | string | null | no | Unique per logical write (8-255 chars). Retries with the same key are safe. · pattern ^[A-Za-z0-9_\-:.]{8,255}$ |
Request body application/json ChangePlanRequest
| Name | Type | Required | Description |
|---|---|---|---|
plan_code | string | yes | max length 32 |
interval | "month" | "year" | no | default "month" |
quantity | integer | no | Plans sold by size (Enterprise): blocks of `sizing.block_products` products, 1 to 40. 1 for every other plan.default 1 · min 1 · max 40 |
Responses
- 200Successful Response
SubscriptionOut
POST
/v1/billing/change-plan/previewWhat a plan change charges today (nothing changes)
Needs a key or a dashboard session
Request body application/json ChangePlanRequest
| Name | Type | Required | Description |
|---|---|---|---|
plan_code | string | yes | max length 32 |
interval | "month" | "year" | no | default "month" |
quantity | integer | no | Plans sold by size (Enterprise): blocks of `sizing.block_products` products, 1 to 40. 1 for every other plan.default 1 · min 1 · max 40 |
Responses
- 200Successful Response
ChangePlanPreview
POST
/v1/billing/cancelBilling Cancel
Needs a key or a dashboard session
Request body application/json CancelRequest
| Name | Type | Required | Description |
|---|---|---|---|
at_period_end | boolean | no | Must be true: a store's plan runs to the end of the paid period (no refunds). false is refused with 403 cancel_now_not_allowed; only the super-admin console can end a plan now.default true |
reason | string | null | no | max length 500 |
Responses
- 200Successful Response
SubscriptionOut
POST
/v1/billing/resumeKeep my plan: undo a cancel at period end before the period ends
Needs a key or a dashboard session
Responses
- 200Successful Response
SubscriptionOut
GET
/v1/billing/invoicesBilling Invoices
Needs a key or a dashboard session
Responses
- 200Successful Response
InvoiceOut[]
GET
/v1/billing/portalProvider portal (card, invoices)
Needs a key or a dashboard session
Responses
- 200Successful Response
RedirectUrl
POST
/v1/billing/webhooks/{provider}Payment provider webhooks (signature checked, no API key)
No key needed
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
provider | path | "paddle" | "stripe" | "mock" | yes |
Responses
- 200Successful Response
map<string, boolean>
GET
/v1/usageUsage this period vs the plan
Needs a key or a dashboard session
Responses
- 200Successful Response
UsageOut
Data shapes on this page
PlanOut
| Name | Type | Required | Description |
|---|---|---|---|
code | string | yes | |
name | string | yes | |
price_month_cents | integer | null | yes | |
price_year_cents | integer | null | yes | |
currency | string | yes | |
products_limit | integer | null | yes | null = custom |
searches_limit | integer | null | yes | Searches per month (Enter). Suggest is never billed. |
features | object | yes | |
overage | object | yes | |
trial_days | integer | yes | |
sizing | PlanSizing | null | no | Set when the plan is bought by catalog size. |
PlanSizing
A plan bought by catalog size: price per month = graduated tiers on the number of blocks.
| Name | Type | Required | Description |
|---|---|---|---|
block_products | integer | yes | Products in one block (the plan's products_limit). |
max_blocks | integer | yes | Most blocks sold online. Above that: talk to sales. |
searches_per_extra_block | integer | yes | Searches per month added by each block after the first. |
tiers | PriceTier[] | yes |
PriceTier
| Name | Type | Required | Description |
|---|---|---|---|
up_to | integer | null | yes | Last block of this tier. null = every block after the tiers before. |
month_cents | integer | yes | Price per block per month in this tier. Yearly = 10 x. |
SubscriptionOut
| Name | Type | Required | Description |
|---|---|---|---|
plan_code | string | yes | |
interval | "month" | "year" | yes | |
status | "trialing" | "active" | "past_due" | "paused" | "canceled" | "incomplete" | yes | |
provider | "paddle" | "stripe" | "mock" | "manual" | yes | |
trial_ends_at | string (date-time) | null | no | |
current_period_start | string (date-time) | null | no | |
current_period_end | string (date-time) | null | no | |
cancel_at_period_end | boolean | no | default false |
quantity | integer | no | Blocks of a plan sold by size (Enterprise); 1 for other plans.default 1 |
CheckoutRequest
| Name | Type | Required | Description |
|---|---|---|---|
plan_code | string | yes | max length 32 |
interval | "month" | "year" | no | default "month" |
quantity | integer | no | Plans sold by size (Enterprise): blocks of `sizing.block_products` products, 1 to 40. 1 for every other plan.default 1 · min 1 · max 40 |
RedirectUrl
| Name | Type | Required | Description |
|---|---|---|---|
url | string | yes |
ChangePlanRequest
| Name | Type | Required | Description |
|---|---|---|---|
plan_code | string | yes | max length 32 |
interval | "month" | "year" | no | default "month" |
quantity | integer | no | Plans sold by size (Enterprise): blocks of `sizing.block_products` products, 1 to 40. 1 for every other plan.default 1 · min 1 · max 40 |
ChangePlanPreview
What POST /v1/billing/change-plan with the same body would charge today. Nothing changes.
| Name | Type | Required | Description |
|---|---|---|---|
plan_code | string | yes | |
interval | "month" | "year" | yes | |
quantity | integer | no | default 1 |
proration | "prorate_now" | "prorate_next_invoice" | yes | prorate_now: an upgrade, the difference is charged now. prorate_next_invoice: a downgrade, the credit goes on the next invoice. |
known | boolean | yes | False: the amount is not known (see `reason`); confirm without an amount. |
amount_minor | integer | null | no | Charged today in minor units (cents): the provider's amount for the plan change (tax included) plus add-on bundles at their list price. 0 = nothing is charged today. |
tax_minor | integer | null | no | |
currency | string | null | no | |
reason | "provider_has_no_preview" | "provider_error" | "addon_price_unknown" | null | no | Why the amount is not known. None when `known` is true. |
CancelRequest
| Name | Type | Required | Description |
|---|---|---|---|
at_period_end | boolean | no | Must be true: a store's plan runs to the end of the paid period (no refunds). false is refused with 403 cancel_now_not_allowed; only the super-admin console can end a plan now.default true |
reason | string | null | no | max length 500 |
InvoiceOut
| Name | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
status | string | yes | |
currency | string | yes | |
total_minor | integer | yes | |
tax_minor | integer | yes | |
hosted_url | string | null | no | |
pdf_url | string | null | no | |
issued_at | string (date-time) | yes | |
paid_at | string (date-time) | null | no |
UsageOut
| Name | Type | Required | Description |
|---|---|---|---|
period_start | string (date) | yes | |
period_end | string (date) | yes | |
plan_code | string | null | yes | null = the store has no plan yet (see TenantOut.billing_state). |
metrics | UsageMetric[] | yes | |
overage_estimate_cents | integer | yes | |
daily | UsageDay[] | yes | |
notices | "80_percent" | "100_percent"[] | no |
UsageMetric
| Name | Type | Required | Description |
|---|---|---|---|
metric | "search" | "translated_product" | "products_indexed" | yes | |
used | integer | yes | |
limit | integer | null | yes | |
percent | number | null | yes |
UsageDay
| Name | Type | Required | Description |
|---|---|---|---|
day | string (date) | yes | |
searches | integer | yes | |
suggests_not_billed | integer | yes | |
translated_products | integer | yes |