Skip to main content
/api/v1/subscription/update changes amounts on the subscription the customer already has, and can only lower them. Everything else — a different cycle, a higher price, a different plan, a different currency — is a plan change through /api/v1/subscription/change. This page is the plan-change contract. Amount-only changes are in Subscription amounts & per-period scheduling.

What does a plan change actually do?

It does not edit the existing subscription. It creates a new subscription, has the customer authorise it, and retires the old one.
  1. You call /api/v1/subscription/change with the original subscription’s originSubscriptionRequest plus a complete description of the new plan and a fresh subscriptionRequest.
  2. Waffo creates the new subscription and returns a subscriptionAction containing a webUrl. You send the customer there to authorise the new plan.
  3. When the customer authorises and the first charge of the new plan succeeds, the change commits: the new subscription becomes ACTIVE and the original is retired.
  4. Waffo pushes SUBSCRIPTION_CHANGE_NOTIFICATION to the notifyUrl you sent on the change request. /api/v1/subscription/change/inquiry returns the same view on demand.
So the answer to “can I just edit the customer’s existing plan” is no — there is no endpoint that rewrites the cycle, the period count or the plan on a live subscription. The customer has to re-authorise, because the mandate they originally gave was for the old terms. subscriptionId changes. Key your own records on the new subscriptionId from the moment the change commits, and keep the old one only for history.

Do I have to hand the customer a payment page, or can it be silent?

You have to hand them a page. The change is authorised by the customer at checkout — that is what subscriptionAction.webUrl is for. There is no server-to-server plan change that reuses the existing mandate. Plan for the customer abandoning it: until they authorise, nothing has changed and the original subscription keeps billing normally.

What are the change statuses?

CLOSED is deliberately one bucket for every non-success ending — the customer’s payment failed, the authorisation window ran out, or you replaced this change with a newer one. It is not a distinct “timed out” versus “declined” signal, so do not branch on it as though it were. What to do when you see CLOSED: nothing automatic. The original subscription is still there and still billing. If the customer still wants the new plan, raise a new change request; do not retry the old one, and do not reuse its subscriptionRequest.

What is remainingAmount, and who works it out?

remainingAmount is required on every change request, and it is a value you compute. Waffo does not calculate proration and has no proration field — see the proration section of the amounts page. What Waffo does with it: it holds the figure as a credit balance on the change, in the change request’s currency, and draws it down against the new subscription’s charges. When a charge it was drawn against is closed rather than collected, or draws down less than was reserved, the unused part is returned to the balance rather than lost. Practical rules:
  • It is your number. If you want “the customer paid for 30 days and used 12”, you do that arithmetic and send the result.
  • Send it in the change request’s currency. It is not converted for you.
  • It is a credit against future charges, not a refund. If the customer is owed money back rather than credit forward, refund the original charge instead — see Refunds.
  • remainingAmount also comes back on /api/v1/subscription/change/inquiry, so you can read what is left rather than tracking it yourself.

Can a plan change also switch the currency, or the payment method?

Yes to both — a change request describes the new subscription from scratch, so these are just fields on it: Because remainingAmount is expressed in the change request’s currency, a currency switch means you must express the carry-over in the new currency. Waffo will not convert an old-currency balance for you. Nothing is inherited from the old subscription. Anything you do not restate is gone, including the per-period amount plan — restate scheduledAmounts in the change request if a price ramp should survive.

Can one change request carry several plans?

productInfoList is a list, and each entry describes a plan. Treat it as the shape for one plan the customer is moving to: the subscription that results has one cycle, one period count and one amount, so a request describing two different cycles has no coherent meaning. If a customer is genuinely buying two things on different cycles, that is two subscriptions.

Does the old subscription stop immediately, or at the end of the period?

Both exist, and you choose with startTime: The second row is how you build “the upgrade takes effect next cycle” without double-billing and without writing a scheduler. It is also the only end-of-period retirement Waffo performs — /api/v1/subscription/cancel is always immediate, which is covered on the hosted management page. Two constraints on startTime for a change:
  • It must not be earlier than the original subscription’s next scheduled charge. A start time inside the period the customer has already paid for is rejected.
  • The general creation limits still apply: strictly in the future, at most 365 days out, and inside the validity window of the agreement that will carry the new subscription.
While a change with a future start is pending, the original subscription’s renewal is held rather than allowed to fire, so the customer is not charged for a period they are about to leave. Call /api/v1/subscription/change again with the plan they actually want. Waffo settles the pending change for you as part of that call: the unpaid charge on the pending new subscription is cancelled, that new subscription is closed as replaced, the pending change moves to CLOSED, and the original subscription is released so the new change can be built on it. You do not need support to clear it, and you do not need a separate cancel call — there is no “cancel change” endpoint precisely because the next change does it. The important caveat: settlement can fail, and when it does the new change is not created. You get one of these instead, and the pending change is still the live one: A0048 and A0049 are easy to confuse. A0048 means the money is moving, stop and wait for the answer; A0049 means we do not yet know, ask again. Retrying on A0048 will not help, and treating A0049 as fatal will leave a customer stuck.

Can I change amounts and the plan in the same breath?

No, and they are mutually exclusive while either is in flight. Waffo serialises update, change and cancel per subscription: while one is being processed, the others are rejected with A0055 (“The subscription is being modified, please retry later”). A0055 is retryable. If you re-price in bulk, treat it as backpressure rather than a failure — but do not fire an update and a change at the same subscription concurrently and expect both to land.

What happens to per-period amounts and trials on the new plan?

Nothing carries over. The new subscription’s amount, trialPeriodAmount, numberOfTrialPeriod and scheduledAmounts come entirely from the change request. Omit scheduledAmounts and the new subscription bills every period at the new amount. One thing to think about before granting a trial on an upgrade: the trial period numbering restarts, because this is a new subscription. A customer who already had your trial gets it again if you configure one.

Which record is authoritative?

/api/v1/subscription/change/inquiry, keyed on the new subscriptionRequest plus originSubscriptionRequest. It returns the change status, subscriptionAction while authorisation is still pending, the current remainingAmount, and the full new-plan description you sent. SUBSCRIPTION_CHANGE_NOTIFICATION tells you when to look; the inquiry tells you what is true. Persist the new subscriptionId from it, and switch your entitlement to the new subscription only once the change reads SUCCESS.

Where do I look next?