Change a subscription's plan
Moves a subscription to a different price. BillKit prices the switch, charges the difference against the existing mandate, and applies the new plan when that payment settles.
Parameters
| Parameter | Description |
|---|---|
| subscription_idstring · pathrequired | Id of the subscription, which starts sub_. |
| target_price_idstringrequired | Id of the price to move the subscription to. It and its product must be active, in the subscription's currency and not metered, and it must differ from the current price. |
Returns
The subscription as it stands right now, which is still on the old price. The switch is asynchronous: this call only mints the charge. When it settles you get subscription.updated, subscription.plan_changed and payment.succeeded. If it fails you get payment.failed and the plan does not change.
The price of the switch is a credit for the unused part of the current period, subtracted from the full new price. Preview it first if you want to show the customer the number before they commit.
Two changes are refused. An upgrade whose net charge would be under 100 minor units is too close to the
renewal, so it answers 409 state_conflict, and waiting bills the new rate anyway. A downgrade, where
the credit exceeds the cheaper price, answers 400 parameter_invalid with
reason: “plan_change_not_supported”: cancel at period end and start the cheaper plan with a new
checkout when it lapses.
The subscription must be active or past_due (a trialing one is refused with 409 state_conflict) and auto_renew with a mandate, the target price and its product must be active, the currency must match, and neither price may be metered.
While a renewal charge for the subscription is still settling the call returns 409 operation_pending, with the time to retry in the message. A past_due subscription returns 409 subscription_past_due: the unpaid period has to be paid first, through reauthorize_payment_method. If a chargeback or a decline marked the stored payment method as unusable, the call returns 409 state_conflict with reason: “no_active_mandate” until the customer replaces it. If Mollie refuses to create the proration charge, the call returns 402 with reason: “payment_refused”, nothing is charged and the plan does not change. If Mollie does not answer, the call returns 502 and the outcome is unknown: retry with the same Idempotency-Key.
Test it
Change the plan, then advance a test clock past the period end and read the invoice that falls out.
Errors
| Status | Cause |
|---|---|
| 400 | The request was refused (type: invalid_request_error): a required parameter is missing (parameter_missing), one failed validation (parameter_invalid) or is not one the operation takes (parameter_unknown), and param names it. |
| 401 | No credential, or one that does not authenticate. |
| 402 | The account is suspended (tenant_suspended), or the payment provider refused a charge or refund the call made (type: payment_error, code: payment_refused). |
| 403 | Authenticated, but not allowed: missing scope (insufficient_scope), a key of the wrong mode (mode_mismatch), or a refused origin. Needs the subscriptions:write scope. |
| 404 | No such object in this account and mode. |
| 409 | Conflicts with the object's current state (state_conflict, or a more specific code), or an operation still in flight (operation_pending). |
| 413 | The request body is larger than the API accepts. |
| 429 | Rate limited. Retry-After says when to try again. |
| 500 | Something failed on BillKit's side (type: api_error). Retry with the same Idempotency-Key. |
| 502 | The payment provider failed or did not answer. |
| 503 | Temporarily unable to serve. reason says whether the request was attempted. |
Other subscriptions operations
- List subscriptions GET /v1/subscriptions
- Retrieve a subscription GET /v1/subscriptions/{subscription_id}
- Cancel a subscription POST /v1/subscriptions/{subscription_id}/cancel
- Pause subscription POST /v1/subscriptions/{subscription_id}/pause
- Preview update subscription POST /v1/subscriptions/{subscription_id}/preview_update
- Reactivate subscription POST /v1/subscriptions/{subscription_id}/reactivate
- Reauthorize payment method POST /v1/subscriptions/{subscription_id}/reauthorize_payment_method
- Resume subscription POST /v1/subscriptions/{subscription_id}/resume
BillKit