Cancellation and upgrade for shopify billing api subs

How can we create a subs using appSubscriptionCreate such that the cancellation is deferred upto end of billing cycle but the upgrade is immediate i.e. the old subs is cancelled immediately and prorated upgrade plan starts. Given, that this subs behavior is handled by replacementBehavior but that can have only one behavior.

And the docs mentions that this behavior of appSubscriptionCancel is also handled by `replacementBehavior`


appSubscriptionCancel

mutation

Cancels an active app subscription, stopping future billing cycles. The cancellation behavior depends on the replacementBehavior setting

replacementBehavior

AppSubscriptionReplacementBehavior

Default:STANDARD

The replacement behavior when creating an app subscription for a merchant with an already existing app subscription.

Hide enum values

APPLY_IMMEDIATELY

Cancels the merchant’s current app subscription immediately and replaces it with the newly created app subscription.

APPLY_ON_NEXT_BILLING_CYCLE

Defers canceling the merchant’s current app subscription and applying the newly created app subscription until the start of the next billing cycle. This value is ignored if the new app subscription is using a different currency than the current app subscription, in which case the new app subscription is applied immediately.

STANDARD

Cancels the merchant’s current app subscription immediately and replaces it with the newly created app subscription, with the exception of the following scenarios where replacing the current app subscription will be deferred until the start of the next billing cycle.

  1. The current app subscription is annual and the newly created app subscription is annual, using the same currency, but is of a lesser value.

  2. The current app subscription is annual and the newly created app subscription is monthly and using the same currency.

  3. The current app subscription and the newly created app subscription are identical except for the discount value.

Hey @Jaspreet_Singh - thanks for reaching out.

Cancellation and upgrades are actually handled by two separate mutations, so you shouldn’t need a single replacementBehavior value to cover both cases.

For upgrades (replacing the current sub with a higher plan), you’d use appSubscriptionCreate with replacementBehavior: APPLY_IMMEDIATELY. This should cancel the old sub right away and start the new one, with proration applied.

For cancellations (merchant just wants to cancel, no new plan), you’d use the appSubscriptionCancel mutation instead. When you call this without prorate: true, the subscription is cancelled but the merchant has already paid through the current billing period - so access continues until currentPeriodEnd. The sub just won’t auto-renew for the next cycle.

So the flow would look something like:

  1. Merchant upgrades → call appSubscriptionCreate with the new plan and replacementBehavior: APPLY_IMMEDIATELY
  2. Merchant cancels → call appSubscriptionCancel (with prorate: false which is the default)

The replacementBehavior enum on appSubscriptionCreate is usually only useful when you’re creating a new subscription to replace an existing one - it shouldn’t come into play for standalone cancellations.

Sharing the docs for reference in case it’s help too:

Hope this helps! Let me know if I can clarify anything on our end here.

For upgrades (replacing the current sub with a higher plan), you’d use appSubscriptionCreate with replacementBehavior: APPLY_IMMEDIATELY. This should cancel the old sub right away and start the new one, with proration applied.

how does proration work in detail for shopify subs?

Hey @Jaspreet_Singh :waving_hand: great question.

When a merchant upgrades to a higher-priced plan mid-cycle via appSubscriptionCreate with replacementBehavior: APPLY_IMMEDIATELY, we calculate the prorated charge based on what the merchant has already paid, the cost difference between the plans, and the time left in the current billing cycle.

The formula looks like this:

plan1_cost + (plan2_cost - plan1_cost) * (cycle_days_left / total_cycle_days) = total_cost

So for example, if a merchant starts a 30-day cycle on a $5.00 plan and upgrades to a $15.00 plan on day 15, they’d be charged $10.00:

$5.00 + ($15.00 - $5.00) * (15/30) = $10.00

For downgrades, it works the other way around. The merchant gets a prorated credit for the unused portion of the higher plan:

(plan2_cost - plan1_cost) * (cycle_days_left / total_cycle_days) = credit

So if a merchant is on a $20.00 plan and downgrades to $10.00 on day 15, they’d get a $5.00 credit:

($20.00 - $10.00) * (15/30) = $5.00

The docs cover this in more detail here: About subscription billing

Hope this helps! Let me know if I can clarify anything on our end here.