Skip to main content
This page covers how much is charged in each billing period: configuring different amounts per period, changing amounts on a live subscription, and what Waffo does (and does not) do about mid-period price changes. For creation-time validation and status values see Subscription Creation & Validation FAQ. For deferred starts, payment methods and retries see Subscription Lifecycle & Payment Method Management and the Subscription FAQ.

What does scheduledAmounts mean in the subscription request?

scheduledAmounts is an optional list inside productInfo that lets you charge a different amount in specific billing periods instead of the same amount every period. Each entry has exactly two fields:
That subscription charges 9.90 in period 1, 49.90 in period 2, and 99.90 in every period from 3 to 12. Periods you do not list simply fall back to amount, and the listed periods do not have to be consecutive — listing only periods 1 and 5 is valid. You can set scheduledAmounts when you create the subscription and change it later with /api/v1/subscription/update.

Is period counted from the first period, or from the first period after the trial?

From the first period of the subscription. period is an absolute, 1-based index over every billing period, and trial periods are included in that count. This matters when a trial exists: if you configure a 2-period trial, then period: 1 and period: 2 address the two trial periods, and the first period at the regular price is period: 3. There is no offset applied anywhere: Waffo looks up the period number of the charge it is about to create and reads scheduledAmounts with that exact number. To see where a live subscription currently is, read productInfo.currentPeriod from /api/v1/subscription/inquiry — the stored plan comes back in the same response as productInfo.scheduledAmounts, so you can always confirm which period numbers are still in the future before you send an update.

How does Waffo decide the amount for each period?

Three inputs are consulted in this order; the last rule that matches wins: So a scheduledAmounts entry overrides the trial amount for that period. If you want the trial to be billed at trialPeriodAmount, do not list the trial period numbers in scheduledAmounts. This is the first thing to check when a charge does not match what you expected: work out the period number of the charge, then walk the three rules in order.

What are the exact limits on scheduledAmounts?

Two details worth calling out because they are commonly assumed the other way round:
  • Amounts are decimal strings in the currency’s normal unit, not minor units. "9.90", not "990". Extra decimal places are rejected, not rounded.
  • amount: "0" passes field validation, so a free period is expressible — but the value still has to satisfy the minimum amount on your agreement, so whether 0 is accepted depends on your contract.

Can I raise the next period’s subscription amount directly?

No — not through /api/v1/subscription/update. By default that endpoint rejects any increase. This is enforced on all three amount fields: The per-period baseline is the currently stored scheduled amount for that same period, or the subscription’s amount if that period is not in the stored plan. That closes the obvious loophole: you cannot lower a period first and then raise it back in a second call, because the second call is compared against the value you just wrote. Violations come back as a parameter error whose message names what was rejected (amount is not allowed to increase, trialPeriodAmount is not allowed to increase, or scheduledAmounts.amount is not allowed to increase for period N). To charge more, either use /api/v1/subscription/change and move the user to a new plan, or — where the increase is a seat add-on — send the update with a topupInfo block: that path collects the difference for the current period immediately and is allowed to raise amount from the next period (see the proration table below). Plain increases through update are not open to accounts generally; if you believe your integration needs them, raise it with integration support rather than designing around it.

How do I set prorate?

There is no proration field, and Waffo does not calculate proration. If you are looking for a prorate / proration_behavior parameter, it does not exist — neither on /subscription/update nor on /subscription/change. Here is what actually happens in each case, so you can decide what to implement on your side: In short: amount changes are period-boundary events, and any money that should move because a change landed mid-period is yours to compute and yours to collect.

What exactly does /subscription/update change, and when does it take effect?

It changes amounts only, from the next billing period onward. It can change: amount, productInfo.trialPeriodAmount, productInfo.scheduledAmounts — individually or together. At least one of the three must be present, otherwise the request is rejected. It does not change: the plan, periodType, periodInterval, the number of periods remaining, the billing date, or the payment method. It does not trigger proration and it does not create a new subscription. Timing: the new values apply from the next period. A charge for the current period that has already been generated or is already in flight is not affected. The response tells you the period number the change lands on:

When is an amount update rejected outright?

The last row means updates are serialized per subscription. If you are re-pricing many subscriptions, treat a “being modified, please retry later” response as retryable rather than as a failure.

If I send scheduledAmounts in an update, does it merge with the existing plan?

No — the list you send replaces the stored plan as a whole. It is not a patch: periods present in the old plan but absent from your request stop having a scheduled amount and fall back to amount. Two consequences to design for:
  • Always send the complete set of future periods you want priced, not just the ones you are changing.
  • Because an update may only address periods after the current one, entries for already-charged periods are dropped from storage when you replace the plan. That is expected and does not change any charge that already happened.
Sending an empty array, or omitting the field, is treated as no change — it does not clear the plan. There is no way to clear a scheduled-amount plan through /subscription/update; to get back to a single flat amount, list every remaining future period at the amount you want, or move the user to a new plan with /subscription/change.

What happens to scheduledAmounts when I upgrade or downgrade?

Nothing is inherited. /subscription/change creates a new subscription, and that new subscription’s amount and scheduledAmounts come entirely from the change request. If you omit scheduledAmounts there, the new subscription has no per-period plan at all and every period is billed at the new amount. So if a tiered price ramp should survive an upgrade, you have to restate it in the change request.

Will the end user be told that the amount changed?

Yes — Waffo emails the subscriber after a successful amount update. The mail carries the previous amount, the new amount, the previous and new per-period plans, and the period number the change takes effect from. Two operational caveats:
  • The email is sent only if the amount-change notification is enabled for your account and product. If it is switched off, nothing is sent to the user.
  • Sending is best-effort and asynchronous: a mail failure does not roll back the amount change. The API response is the record of what changed.

Does Waffo send me a webhook when an amount update succeeds?

Yes. After a successful /subscription/update, Waffo pushes SUBSCRIPTION_UPDATE_NOTIFICATION to the notifyUrl stored on the subscription. For a plain amount change it is sent as soon as the update is committed; for a seat add-on (see below) it is sent once the top-up charge succeeds and the new amount is applied. The payload is the subscription as the inquiry API returns it, so it already reflects the new amounts. To keep your own records aligned:
  • Treat the /subscription/update response as the primary record — read newAmount, newScheduledAmounts and nextEffectivePeriod from it and store them. The webhook confirms the same change asynchronously and is the signal to use when the change was committed outside your immediate request path (the top-up case).
  • Keep listening to the per-period notification and the subscription payment order notification for the actual charged amount of each period — those reflect what was really taken, which is the number you should reconcile against.

Which subscriptions can use per-period amounts at all?

Per-period amounts and /subscription/update are available on subscriptions where Waffo drives the billing schedule. For some payment methods the payment method itself drives the schedule; those subscriptions reject scheduledAmounts at creation and are not eligible for amount updates. If a creation call comes back saying scheduled amounts are not supported for the subscription, that is why — the fix is a different payment method, not a different request shape.