Update a subscription
Update subscription-level settings, manage items (add/remove/modify), adjust quantities and prices, with control over proration timing and behavior for mid-cycle changes.
Update subscription fields
Update metadata, payment method, trial period, or discount on an active subscription without changing line items.
API
Python SDK
Updatable fields
Lifecycle impact: Changing cancel_at_period_end, trial_end, or trial_period_days triggers a re-evaluation of the subscription lifecycle and may reschedule automated actions.
Invoice impact: Changing coupon_id or promotion_code voids any pending renewal invoices to ensure correct pricing on the next billing cycle.
Update subscription items
Add, remove, or change items on a subscription. This is how you handle quantity changes, add-ons, and price swaps within the same billing interval.
Item operations
Combine multiple operations in a single request. All changes are applied atomically.
Proration behavior
The proration_behavior field is required and controls how mid-cycle changes are billed:
always_invoice: Creates an invoice immediately and attempts payment. Use when you want the customer to pay for the upgrade right away.create_prorations: Creates floating items (invoice_id=NULL) that are collected on the next renewal invoice. Use for deferred billing.none: No proration charges or credits are created. Items are updated immediately but no billing adjustment is made for the mid-cycle change.
Response fields
The response includes:
subscription_id: The updated subscription’s external IDinvoice_id: Created invoice ID (ifproration_behavior=always_invoice)payment_status: Payment result ("paid","processing","requires_action","failed","no_payment_method","skipped")payment_error: Error message if payment failedfloating_items_created: Count of floating items (ifproration_behavior=create_prorations)proration_amount_atom: Net proration amount in atomsvoided_invoice_ids: External IDs of voided pending renewal invoicesnew_renewal_invoice_id: External ID of replacement renewal invoice (if a voided invoice had active dunning)new_invoice_payment_status: Payment status of the replacement renewal invoice
Items must have the same billing interval as the subscription. To change a customer from monthly to annual billing, use the change plan endpoint instead.
Proration behavior
When items change mid-cycle, PaymentKit calculates the prorated difference. Control how proration is handled with the proration_behavior field:
Example: Immediate upgrade
Upgrade a customer from a basic plan to a pro plan and charge the prorated difference immediately:
The response includes the created invoice ID and payment status:
Payment status values:
paid: Payment succeededprocessing: Async payment (ACH/SEPA) submitted, awaiting confirmationrequires_action: Customer action required (e.g., 3D Secure authentication)failed: Payment failedno_payment_method: No payment method availableskipped: Payment processing disabled for this account
If payment fails, the payment_error field contains the error message.
Invoice voiding: When immediate updates are made, any pending renewal invoices (DRAFT, OPEN, or PAST_DUE) are automatically voided to ensure correct billing. The voided_invoice_ids field contains a list of the voided invoices. If the voided invoice had active dunning, a new renewal invoice is created with updated items, and its ID is returned in new_renewal_invoice_id.
Example: Deferred billing
Add an add-on that will be billed on the next renewal:
The response includes the count of floating items created:
Prorated line items are stored as floating items (with invoice_id set to null) and automatically included in the next renewal invoice.
Change subscription plan
Use the change-plan endpoint when you need to move items to different billing intervals or contract terms. This is the recommended approach for upgrades and downgrades that change the billing cycle.
Request fields
Proration behavior options
always_invoice: Create invoice immediately and attempt payment now. Use when you want the customer to pay for the upgrade immediately.create_prorations: Create floating items (invoice_id=NULL) that will be collected at the next renewal. Use for deferred billing.none: No proration, changes apply at next renewal only. Items are updated but no proration charges/credits are created.
How term-based splitting works
When items change to prices with different billing terms, PaymentKit automatically creates new subscriptions grouped by their terms:
Items are grouped by:
- Billing interval (month, year, etc.)
- Billing interval count (every 1 month, every 3 months, etc.)
- Contract length (12 cycles, indefinite, etc.)
- Auto-renew setting
Item actions
Each item mapping requires an action field and additional fields depending on the action:
Items NOT included in the request stay unchanged on the original subscription.
Example: Monthly to annual upgrade
Upgrade a customer from monthly (1,000/yr) billing with immediate payment:
API
Python SDK
The response includes details about the plan change:
Response fields
Created subscription fields
Each subscription in created_subscriptions includes:
In this example:
- The customer receives a $50 credit for unused time on the monthly plan
- The customer is charged $1,000 for the annual plan
- The net invoice is $950
- The original subscription is cancelled (all items moved)
- A new annual subscription is created
Example: Add items during plan change
Add a new item while upgrading to a different plan:
Example: Partial plan change
Change only some items while keeping others unchanged:
Items not included in the request remain on the original subscription with their current billing terms.
Example: Deferred billing with create_prorations
Upgrade a plan but defer billing to the next renewal:
With create_prorations, proration amounts are calculated but stored as floating line items (invoice_id=NULL). They will be included in the next renewal invoice rather than creating an immediate invoice.
Example: Pay-before-change flow
Require payment before applying the plan change. This ensures the customer stays on their original plan if payment fails:
With pay_before_change: true:
- New subscriptions are created in
incompletestate - items are added but not yet active - Original subscription remains unchanged - items are NOT deactivated and the subscription is NOT cancelled until payment succeeds
- A 402 Payment Required response is returned with the
invoice_idto collect - Collect the invoice separately to complete the plan change:
- If payment succeeds: Items on the original subscription are deactivated, the original subscription is cancelled (if empty), and new subscriptions are activated automatically
- If payment fails or requires action (e.g., 3D Secure): The customer stays on their original subscription with no disruption
pay_before_change: true requires proration_behavior: "always_invoice". Without an invoice, there is nothing to collect payment on.
Pending invoice handling
When you modify a subscription, PaymentKit automatically voids any pending renewal invoices to ensure the next invoice reflects the updated configuration.
What gets voided:
- Only renewal invoices (
billing_reason: "subscription_cycle") - With status
draft,open, orpast_due - Proration invoices (
billing_reason: "subscription_update") are never voided
The response includes the voided invoice IDs:
Handling active dunning:
If a voided invoice has active dunning (failed payment with scheduled retries), PaymentKit uses a two-phase approach to ensure the replacement invoice has the correct subscription items:
-
Phase 1 - Void old invoice:
- Marks the old invoice as
void - Marks the dunning state as
invoice_voided
- Marks the old invoice as
-
Phase 2 - Create replacement invoice (after item changes are applied):
- Creates a new renewal invoice with the updated subscription items
- Finalizes the invoice to
openstatus - The dunning system automatically picks up the new invoice for collection
This ensures customers are always billed the correct amount for their current subscription configuration, even when dunning is in progress.
Preview upcoming invoice
Before making changes, preview what the next invoice will look like:
This is a read-only operation that computes what the next renewal invoice will be without creating anything in the database. No invoice numbers are claimed, no billing cycles are decremented, and no events are emitted.
The response includes:
- subscription: Complete subscription details including all items and pricing
- upcoming_invoice: Preview of the next billing cycle invoice with:
- Line items (descriptions, quantities, amounts, period dates)
- Amount breakdowns (subtotal, tax, total, due amount)
- Due date (calculated from
net_dpayment terms) - Billing period (period_start, period_end)
- Currency and collection method
Example response: