Skip to main content

What proration does

When a customer switches plans mid-cycle, Recurso doesn’t wait for the next renewal to make things fair. It settles the difference immediately:
  • Credits the unused portion of what they already paid on the current plan.
  • Charges the new plan, prorated for the time left in the cycle.
The difference between the two is the net amount — a charge on an upgrade, a credit on a downgrade.
Every amount is in the currency’s smallest unit (cents, paise) and the proration is time-based — computed from the seconds remaining in the cycle, not whole days. Each side is truncated (never rounded up) to a whole minor unit.

The formula

For a plan change at time t inside a cycle running [start, end]:
Both sides use the same remaining / total fraction — the unused time you’re crediting is exactly the remaining time you’re charging for. A positive net is billed now; a negative net becomes a credit note.

Worked example

A customer on 20/moupgradesto20/mo** upgrades to **50/mo on day 10 of a 30-day cycle. Prices are stored in minor units: $20.00 → 2000, $50.00 → 5000.
The customer is invoiced 20.00immediatelyforthericherplanovertheremaining20days.Reversetheprices(a20.00** immediately for the richer plan over the remaining 20 days. Reverse the prices (a **50 → 20downgrade)atthesamepointandnetis20 downgrade**) at the same point and `net` is **−20.00 — Recurso issues a credit note for that amount. The table below shows the net for the same two plans at different points in the cycle (30-day cycle, $20 ↔ $50):
Tax isn’t shown above because it depends on the customer’s location and the plan’s HSN/tax code. The API applies it on top of the net: a charge is taxed on the new plan’s code, and a downgrade credit reverses the tax originally collected (so GST is refunded correctly). See tax_amount in the preview response.

Coupons: prorated at the price actually paid

If the subscription carries a coupon and the current period’s invoice was discounted, both sides of the formula use the discounted prices, not the list prices. The credit refunds what the customer actually paid for the unused time, and the charge matches what a renewal on the new plan would bill inside this discounted period. Worked example — the same $20 → $50 upgrade at day 15, but with a 50%-off coupon applied this period:
Without this, a discounted subscription would be credited unused time at list price — on a deep discount, a downgrade could return more account credit than the customer ever paid. Periods billed without the discount (a once coupon after its first period, a repeating coupon past its window) prorate at list prices, exactly as above. The preview endpoint reflects whichever applies, so what you show the customer is always what they’ll be charged or credited.

Previewing from the API

You never have to compute this yourself. Ask Recurso for the exact breakdown — no writes, no side effects — before you commit a plan change:
The response is the read-only breakdown — every field in the currency’s smallest unit:
preview-change is a dry run — it computes and returns numbers but changes nothing. The identical proration runs when you actually switch plans via PATCH /subscriptions/:id, so the previewed total_amount is exactly what the customer is billed.

Notes on the math

  • Truncation, not rounding. Each side (credit, charge) is truncated to a whole minor unit independently. This is deliberate and matches the ledger — the net can be off by at most one minor unit from a rounded calculation, and it never over-charges.
  • Time-based, not day-based. Real proration uses seconds remaining in the cycle. The examples above use days for legibility; the ratio is identical.
  • Same-price switches net to zero. Moving between two equally-priced plans mid-cycle bills nothing — the credit and charge cancel exactly.

Next steps

Subscriptions

The upgrades and downgrades that trigger proration

Revenue recognition

How prorated amounts recognize