LedgerBee Developer
  • Getting started
  • Conventions
  • Products
  • Advisor firms
  • Configuration
  • API Reference
Subscriptions
    OverviewAssign a subscriptionData modelLifecycle & statusesBilling & cadenceProrationUsage commitmentsReporting usageMonthly revenue & unbilled usageChange flowsParent & childAdd-onsBilling groupsWebhooks
Payment flowCard paymentsProducts & PricingDiscountsProduct Entitlements
Billing documents
Accounting
WebhooksPartner-Hosted Checkout
Customer Portal
Subscriptions

Change flows

A subscription changes through a set of flows. Most are queued from the LedgerBee operator app or the customer portal. Over the API you can create product changes, cancellations, add-ons and billing-group changes, and read or cancel a queued plan replacement, product change, direction change or cancellation.

FlowWhat it doesActivatesWhere today
Replace planSwaps the plan; settles any overlapat the next billing boundaryUI
Direction changeSwitches advance ⇄ arrearsnext boundaryUI
Cadence changeSwitches among the plan's alternative cadencesnext boundary (doesn't stack)UI
Change productsChanges quantities, prices and line descriptions, and adds or removes product lineson effectiveDatePublic API + UI
Pause / resumeSuspends billing, then resumesimmediately / on resume dateUI
Cancel / churnEnds the subscription, and its add-ons with itper strategy (below)Public API + UI
Add an add-onCreates a subscription that bills on this one's invoicethe parent's next billing date after todayPublic API + UI
Form a billing groupBills several of one customer's subscriptions on one shared invoicethe lead's next billing datePublic API + UI
Join a billing groupAdds a subscription to an existing group's shared invoicethe group's next billing datePublic API + UI
Leave a billing groupReturns a subscription to its own invoiceat once; bills alone from its next billing datePublic API + UI

Each flow appends a version or segment. A plan replacement or products edit re-bills the affected partial period and carries its own prorationBehavior to settle it. A queued, not-yet-active flow is a scheduled change you can read or cancel over the API (below).

Change products

POST /v1/subscriptions/{id}/product-changes changes a subscription's products from effectiveDate. The subscription keeps its id and is not cancelled, so revenue reports record the change as that subscription's revenue going up or down rather than as one subscription ending and another starting.

TerminalCode
curl -X POST https://api.ledgerbee.com/api/v1/subscriptions/{id}/product-changes \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "effectiveDate": "2026-11-01", "products": [ { "priceId": "0190…", "quantity": 12, "customPrice": "89.00" } ] }'

products is every product line the subscription has from effectiveDate. A price the subscription carries changes that line, a price it does not carry adds a line, and a price you leave out of the list is removed. The full request schema is in the API Reference.

Field on a lineOmittednull
quantityKeeps the line's quantity. A new line bills a quantity of 1; a new usage-metered line bills what is used.Not accepted
customPriceKeeps the line's priceBills the list price
descriptionKeeps the line's invoice textRemoves it

A line's dimensions and prepaid usage commitment always carry over unchanged.

The same request changes the discount records the subscription references from effectiveDate: discountIds is the full set, in the order they apply ([] removes them all), and discountEndDates sets or clears an end date per discount ([{ "discountId": "0190…", "endsAt": "2027-01-01" }]). A change that sends either may leave products out, and the products stay as they are.

Timing and settlement

effectiveDateResult
A future dateThe change is queued, listed under scheduled changes as edit_products until it takes effect, and can be cancelled there.
TodayThe change takes effect at once.
An earlier dateThe change takes effect at once, from that date. The earliest date accepted is the day the subscription's current terms took effect: its start date, or the date of the last change that has taken effect.

On a subscription billed in arrears, the invoice at the end of the period bills each part of the period at the terms in force, by days. A change effective on the 11th of a 31-day month bills 10/31 of the period at the old terms and 21/31 at the new ones.

On a subscription billed in advance, prorationBehavior settles the part of the period after effectiveDate. The modes are listed under Proration. Omitted, it is create_prorations: the difference goes on the next regular invoice.

Errors

StatusCodeCause
400SUBSCRIPTION_EDIT_PRODUCTS_NO_CHANGESThe products and discounts from effectiveDate would be the same as before it.
400DISCOUNT_END_DATE_NOT_REFERENCEDdiscountEndDates names a discount the subscription does not reference after the change.
400SUBSCRIPTION_CANNOT_SET_QUANTITY_FOR_USAGE_BASEDA line sets quantity or customPrice on a usage-metered price. Leave both out on those lines.
400SUBSCRIPTION_PRODUCT_ALREADY_ADDEDA price is listed twice.
400SUBSCRIPTION_CARD_BELOW_MINIMUMThe subscription is charged to a card, and the change would take its regular invoice below the smallest amount the card can be charged.
400SUBSCRIPTION_REPLACE_PLAN_EFFECTIVE_DATE_OUT_OF_RANGEeffectiveDate is before the day the current terms took effect, or after the subscription's end date.
400SUBSCRIPTION_MUTATION_SUPERSEDES_PREBILLED_PERIODThe subscription has been invoiced in advance for a period that has not started yet, and effectiveDate is on or before that period's start. Pick a date inside the period, or after it.
400SUBSCRIPTION_REPLACE_PLAN_REQUIRES_ACTIVE_SUBSCRIPTIONThe subscription is not active, in trial, or scheduled to start; for example, it is paused or cancelled.
404SUBSCRIPTION_CUSTOMER_SUBSCRIPTION_NOT_FOUNDThe id is not a subscription of the company the key belongs to.

When a card-charged subscription is already below that amount before the change, the change is saved and the subscription's automatic card payment is switched off. Its next invoice is paid by bank transfer.

Cancel

POST /v1/subscriptions/cancel ends a subscription:

TerminalCode
curl -X POST https://api.ledgerbee.com/api/v1/subscriptions/cancel \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "id": "0190…", "strategy": "end_of_cycle" }'
StrategyEffect
end_of_cycleCancels at the end of the current billing period.
immediatelyCancels now; optionally set refundBehavior (below).
specific_dateCancels on effectiveDate (required for this strategy).
clear_scheduleRemoves a previously scheduled cancellation, leaving it running.

An immediate cancel can issue a refund via refundBehavior:

refundBehaviorBehavior
noneNo refund is issued.
last_invoiceRefund the full amount of the last paid invoice.
proratedRefund the prorated amount for unused time since the last invoice.

On a subscription that bills on a billing group, last_invoice is refused with 400 SUBSCRIPTION_BILLING_GROUP_REFUND_LAST_INVOICE_NOT_SUPPORTED: the last paid invoice is the group's and covers other subscriptions. Use prorated or none. The same refusal answers on an add-on and on a subscription with add-ons, whose last invoice carries the add-ons' lines. Cancelling a group member ends that member; the other members keep billing on the group.

Cancelling a subscription that has add-ons cancels its add-ons with it. The response adds cascadedAddonSubscriptionIds: on immediately, the add-ons that ended now; on end_of_cycle and specific_date, the add-ons that will end with it, as they stand when the request is made; on clear_schedule, []. An immediate cancellation of such a subscription can also answer SUBSCRIPTION_ADDON_CASCADE_MEMBER_NOT_CHURNABLE (an add-on's status blocks it; details.addonSubscriptionId names it), SUBSCRIPTION_ADDON_CASCADE_SET_CHANGED (an add-on was added or removed while the request ran; nothing was changed, retry) or SUBSCRIPTION_ADDON_CASCADE_MIXED_CREDITED_INVOICES (the refund would credit more than one invoice; cancel with refundBehavior: none, or cancel the add-ons first).

A scheduled cancellation (end_of_cycle / specific_date) is itself a queued change — clear it before it activates with clear_schedule or via scheduled-changes below.

Read or cancel a queued change

A queued plan replacement, products edit, direction change, or future cancellation is a scheduled change that hasn't activated. List them:

TerminalCode
curl https://api.ledgerbee.com/api/v1/subscriptions/{id}/scheduled-changes \ -H "x-api-key: YOUR_API_KEY"
Code
[ { "changeId": "0190…", "kind": "replace_plan", "effectiveDate": "2026-07-01", "planId": "0190…", "subscriptionName": "Pro" } ]

kind is one of replace_plan, edit_products, change_direction, or churn. Cancel one by its changeId (DELETE …/scheduled-changes/{changeId}); the rest of the subscription is unaffected and the response is the current state.

changeId is ephemeral — valid only until the change activates or is cancelled. Always re-list rather than caching it.

Last modified on November 6, 2026
Monthly revenue & unbilled usageParent & child
On this page
  • Change products
    • Timing and settlement
    • Errors
  • Cancel
  • Read or cancel a queued change
JSON