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.
| Flow | What it does | Activates | Where today |
|---|---|---|---|
| Replace plan | Swaps the plan; settles any overlap | at the next billing boundary | UI |
| Direction change | Switches advance ⇄ arrears | next boundary | UI |
| Cadence change | Switches among the plan's alternative cadences | next boundary (doesn't stack) | UI |
| Change products | Changes quantities, prices and line descriptions, and adds or removes product lines | on effectiveDate | Public API + UI |
| Pause / resume | Suspends billing, then resumes | immediately / on resume date | UI |
| Cancel / churn | Ends the subscription, and its add-ons with it | per strategy (below) | Public API + UI |
| Add an add-on | Creates a subscription that bills on this one's invoice | the parent's next billing date after today | Public API + UI |
| Form a billing group | Bills several of one customer's subscriptions on one shared invoice | the lead's next billing date | Public API + UI |
| Join a billing group | Adds a subscription to an existing group's shared invoice | the group's next billing date | Public API + UI |
| Leave a billing group | Returns a subscription to its own invoice | at once; bills alone from its next billing date | Public 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.
Code
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 line | Omitted | null |
|---|---|---|
quantity | Keeps the line's quantity. A new line bills a quantity of 1; a new usage-metered line bills what is used. | Not accepted |
customPrice | Keeps the line's price | Bills the list price |
description | Keeps the line's invoice text | Removes 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
effectiveDate | Result |
|---|---|
| A future date | The change is queued, listed under scheduled changes as edit_products until it takes effect, and can be cancelled there. |
| Today | The change takes effect at once. |
| An earlier date | The 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
| Status | Code | Cause |
|---|---|---|
400 | SUBSCRIPTION_EDIT_PRODUCTS_NO_CHANGES | The products and discounts from effectiveDate would be the same as before it. |
400 | DISCOUNT_END_DATE_NOT_REFERENCED | discountEndDates names a discount the subscription does not reference after the change. |
400 | SUBSCRIPTION_CANNOT_SET_QUANTITY_FOR_USAGE_BASED | A line sets quantity or customPrice on a usage-metered price. Leave both out on those lines. |
400 | SUBSCRIPTION_PRODUCT_ALREADY_ADDED | A price is listed twice. |
400 | SUBSCRIPTION_CARD_BELOW_MINIMUM | The subscription is charged to a card, and the change would take its regular invoice below the smallest amount the card can be charged. |
400 | SUBSCRIPTION_REPLACE_PLAN_EFFECTIVE_DATE_OUT_OF_RANGE | effectiveDate is before the day the current terms took effect, or after the subscription's end date. |
400 | SUBSCRIPTION_MUTATION_SUPERSEDES_PREBILLED_PERIOD | The 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. |
400 | SUBSCRIPTION_REPLACE_PLAN_REQUIRES_ACTIVE_SUBSCRIPTION | The subscription is not active, in trial, or scheduled to start; for example, it is paused or cancelled. |
404 | SUBSCRIPTION_CUSTOMER_SUBSCRIPTION_NOT_FOUND | The 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:
Code
| Strategy | Effect |
|---|---|
end_of_cycle | Cancels at the end of the current billing period. |
immediately | Cancels now; optionally set refundBehavior (below). |
specific_date | Cancels on effectiveDate (required for this strategy). |
clear_schedule | Removes a previously scheduled cancellation, leaving it running. |
An immediate cancel can issue a refund via refundBehavior:
| refundBehavior | Behavior |
|---|---|
none | No refund is issued. |
last_invoice | Refund the full amount of the last paid invoice. |
prorated | Refund 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:
Code
Code
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.