Recurring
Subscriptions, plans, add-ons, and discounts. Compose them into recurring billing schedules for vaulted customers.
Recurring billing is built from four building blocks: add-ons and discounts modify an amount; plans package those modifiers with a base amount, cadence, and duration; subscriptions attach a plan to a vaulted customer. You can mix and match — the fields that define billing cadence live on both plans and subscriptions, so a subscription can override anything its plan specifies.
Add-ons
An add-on adds an amount or a percentage to a recurring charge. Either use amount (cents) or percentage (in thousandths of a percent — 43440 = 43.44%). Not both.
Create add-on
| Field | Type | Description |
|---|---|---|
name | string | Display name. |
description | string | Free-text description. |
amount | integer | Flat amount in cents. 100 = $1.00. Either amount or percentage. |
percentage | integer | 0 or .1%–100%, expressed in thousandths. Either amount or percentage. |
duration | integer | Billing-cycle count. 0 means "until cancelled". |
Get add-on by ID
List add-ons
Update add-on
Same body as create.
Delete add-on
Discounts
Identical shape to add-ons, but subtracts instead of adds. Create / Get / List / Update / Delete follow the same pattern.
| Action | Method | Endpoint |
|---|---|---|
| Create | POST | /api/recurring/discount |
| Get by ID | GET | /api/recurring/discount/{discount_id} |
| List | GET | /api/recurring/discounts |
| Update | POST | /api/recurring/discount/{discount_id} |
| Delete | DELETE | /api/recurring/discount/{discount_id} |
Fields match the add-on set: name, description, amount or percentage, duration.
Plans
A plan is a reusable template. It names the base amount, the billing cadence, the duration, and any add-ons or discounts that travel with it.
Create plan
| Field | Type | Required | Description |
|---|---|---|---|
name | string | required | Display name. |
description | string | optional | Free-text. |
amount | integer | required | Base amount in cents. |
billing_cycle_interval | integer | required | Run the billing cycle every X months. |
billing_frequency | string | required | monthly, twice_monthly, or daily. |
billing_days | string | required | Day(s) of the month. Comma-separated for twice_monthly (e.g. "1,15"). Use "0" for the last day of the month. |
charge_on_day | boolean | optional | When true, billing day is set to today. |
duration | integer | optional | Number of billings. 0 means "until cancelled". |
add_ons | array | optional | Each entry has an id plus optional overrides (name, description, amount, duration). |
discounts | array | optional | Same shape as add_ons, for discount references. |
Get plan by ID
List plans
Update plan
Same fields as create, with one addition:
| Field | Type | Description |
|---|---|---|
update_subscriptions | boolean | When true, apply the new amount to every active subscription using this plan. |
Delete plan
Subscriptions
Subscriptions bind a plan to a customer, lock in a cadence and a start date, and produce recurring transactions. Subscription fields override plan fields when both are present.
Create subscription
| Field | Type | Required | Description |
|---|---|---|---|
plan_id | string | optional | Plan to inherit from. |
description | string | optional | Free-text description. |
customer.id | string | required | Vaulted customer ID. |
customer.payment_method_type | string | optional | card or ach. Defaults to the customer's default type. |
customer.payment_method_id | string | conditional | Specific vault payment method to charge. Required if payment_method_type is set. |
customer.billing_address_id | string | optional | Specific billing address. |
customer.shipping_address_id | string | optional | Specific shipping address. |
amount | integer | required | Charge amount in cents. |
billing_cycle_interval | integer | required | Every X months. |
billing_frequency | string | required | monthly, twice_monthly, daily. |
billing_days | string | required | Same semantics as plans. |
charge_on_day | boolean | optional | Sets billing day to today when true. |
duration | integer | optional | Number of billings. 0 means "until cancelled". |
next_bill_date | string | optional | YYYY-MM-DD. The next charge date. |
add_ons / discounts | array | optional | Same shape as on plans. |
Get subscription by ID
Search subscriptions
Query with the usual {operator, value} shape for string fields and {start_date, end_date} for dates.
| Field | Type |
|---|---|
plan_id | QuerySearchString |
customer.id | QuerySearchString |
next_bill_date | QuerySearchDateRange |
expiration_date | QuerySearchDateRange |
status | QuerySearchString |
limit / offset | integer (0–100 / any) |
Update subscription
Same shape as create.
Change subscription status
Status transitions are separate GET endpoints. Each returns the updated subscription.
| Action | Endpoint |
|---|---|
| Pause | GET /api/recurring/subscription/{id}/status/paused |
| Mark past due | GET /api/recurring/subscription/{id}/status/past_due |
| Cancel | GET /api/recurring/subscription/{id}/status/cancelled |
| Activate | GET /api/recurring/subscription/{id}/status/active — accepts query param next_bill_date (YYYY-MM-DD). |
| Complete | GET /api/recurring/subscription/{id}/status/completed |