Skip to main content
This page covers the API. For the billing logic behind it, see Billing changes. For the same change in the app, see Subscriptions.
POST /v1/subscriptions/{id}/units sets a subscription’s unit count. It needs the subscriptions:write scope. Send the new total, not the difference. Saasybill decides what the change costs and where to bill it, using the same rules as the Update Units dialog in the app. You choose whether to prorate.
Units are for a plan’s recurring fee. A plan with no recurring fee (no_base_fee) has no units, and the request is refused. Metered usage isn’t set as units. Report it as events instead.

Request fields

proration_behaviour and effective_date are refused unless prorate is true.

What happens

Saasybill classifies the new total against the units already paid for this period.

Increasing units

Prorated amounts follow the proration formula: the difference in value, multiplied by the days remaining, divided by the days in the period.
If you increase units without prorating, proration is unavailable for further increases until the next renewal. A prorated request in that state is refused with 422.

Decreasing units

A decrease never raises a document. The subscription’s units update straight away, but the customer has paid for the period, so the lower amount is billed from the next renewal. Send prorate: false, or omit it.

Volume plans

On a volume plan, a unit increase that crosses into a cheaper band re-prices every unit, and the total can fall. Saasybill raises a prorated credit note instead of an invoice.
  • prorate can’t be false for this change. It answers 422 proration_required.
  • The credit is always issued immediately, so proration_behaviour is fixed to charge_immediately.
  • The credit note is held as a credit balance on the subscription and applied to future invoices. change.credit_note holds its id.

Units already paid for

Units at or below the number already paid for this period are never charged twice. If a customer drops from 10 to 8 units and then returns to 10, nothing more is billed until renewal.

When proration is fixed

proration_behaviour is fixed to charge_immediately when:
  • the subscription is in its final period, because there is no renewal to charge at
  • the renewal invoice has already been created, because there is no renewal invoice left to add to

After the renewal invoice is created

Saasybill creates a renewal invoice ahead of the renewal date, set by Invoice Creation Date in Company Settings. Once that has happened, a unit change touches two periods: the current one, and the next one that’s already been invoiced. Then a document has to carry the change. You choose it per request with document, or once for the organisation. Before the renewal invoice exists, document is refused. After it exists, document is optional.

Set a default for the organisation

Amending changes a document the customer may already hold, so the default is separate. An owner or admin can change it under Developer Settings, then Configuration. The setting is called Changes After Invoicing. A document in the request always wins over the setting.
If the setting is Amend and the renewal invoice can no longer be changed, for example because it has a payment or credit on it, Saasybill raises a separate invoice instead. It doesn’t refuse the request. The response says so in change.document_fallback_reason. A request that names amend itself is refused in that case, and the error says why.
A sandbox doesn’t copy the setting. Set it again in the sandbox.
With amend, change.renewal_invoice is the updated renewal invoice. With separate, change.invoice is the new invoice. change.document tells you which happened.

The response

The response is the updated subscription with a change object.
renewal_value in the response is what the next renewal will bill at the new units.

Example

Send an Idempotency-Key built from your own change event. The key is optional here, but a retried seat change without one could be applied twice.

When a change is refused

A unit change is refused with 422 when it breaks a rule. See the unit change codes for each.
If your platform sends the current total on every sync, treat units_unchanged as success. The subscription already has the units you wanted.
A 409 xero_accounts_not_mapped means an admin needs to map the Xero accounts on the Integrations tab before units can change.