Managing subscriptions - Polar

Change the plan

Switch a subscription to a different recurring product — the standard upgrade or downgrade flow.

cURL

curl --request PATCH \
  --url https://api.polar.sh/v1/subscriptions/{subscription_id} \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
    "product_id": "<new_product_id>",
    "proration_behavior": "prorate"
  }'

Python

polar.subscriptions.update(
    id="<subscription_id>",
    subscription_update={
        "product_id": "<new_product_id>",
        "proration_behavior": "prorate",
    },
)

Read more in Proration.

Change the number of seats

For seat-based subscriptions, update how many seats the customer is paying for. Like plan changes, when the seat count actually takes effect depends on the proration behavior: immediate with invoice or prorate, scheduled for the next cycle with next_period.

cURL

curl --request PATCH \
  --url https://api.polar.sh/v1/subscriptions/{subscription_id} \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{ "seats": 25, "proration_behavior": "invoice" }'

Apply or change a discount

Attach a discount to an active subscription, or remove the current one by passing null. The change is applied to the next billing cycle — it doesn’t retroactively re-bill the current period.

cURL

curl --request PATCH \
  --url https://api.polar.sh/v1/subscriptions/{subscription_id} \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{ "discount_id": "<discount_id>" }'

Manage the trial

You can add, extend, or end a trial on any subscription:

cURL

curl --request PATCH \
  --url https://api.polar.sh/v1/subscriptions/{subscription_id} \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{ "trial_end": "2026-06-01T00:00:00Z" }'

Reschedule the next renewal

If you need to move a subscription’s renewal date — for example, to align several subscriptions on the same day, or to extend the current period as a goodwill gesture — you can set a new current_billing_period_end. The new date has to be in the future, and this operation isn’t available on revoked subscriptions. If the subscription is scheduled to cancel at period end, its ends_at moves with the new date: it ends then instead of on the original period end.

cURL

curl --request PATCH \
  --url https://api.polar.sh/v1/subscriptions/{subscription_id} \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{ "current_billing_period_end": "2026-07-15T00:00:00Z" }'

Pause and resume

Pausing stops billing without ending the subscription. Use it for seasonal plans or account “freezes”, where a customer steps away for a while and comes back to the same subscription and payment method.

Pause at period end

Calling pause sets pause_at_period_end = true. The subscription stays active and keeps its benefits until its current_period_end, then it moves to the paused status: benefits are revoked and no further orders are generated. Pausing never charges the customer and never takes effect mid-period. Pass an optional resumes_at date to schedule an automatic resume. It has to be after the current period end. Leave it out to pause indefinitely and resume by hand later.

cURL

curl --request PATCH \
  --url https://api.polar.sh/v1/subscriptions/{subscription_id} \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
    "pause_at_period_end": true,
    "resumes_at": "2026-11-01T00:00:00Z"
  }'

You can only pause a subscription that’s active, with no pending cancellation or pause. To cancel a scheduled pause before it takes effect, set pause_at_period_end back to false.

cURL

curl --request PATCH \
  --url https://api.polar.sh/v1/subscriptions/{subscription_id} \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{ "pause_at_period_end": false }'

Resume

Resuming a paused subscription takes effect right now: status moves back to active, a new billing period starts from the resume date, and the customer is charged immediately. The payment method stays on file, so there’s no second checkout. An automatic resume on the resumes_at date does exactly the same thing.

cURL

curl --request PATCH \
  --url https://api.polar.sh/v1/subscriptions/{subscription_id} \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{ "resume": true }'

Cancel or revoke

Polar distinguishes between canceling and revoking a subscription. Both end the customer’s access eventually — the difference is when.

Cancel at period end

Calling cancel (or toggling “Cancel at period end” in the dashboard) sets cancel_at_period_end = true and schedules the subscription to end on its current_period_end. Until then:

This is the gentler option and the one customers trigger themselves from the Customer Portal. It’s also what satisfies the “cancel the way you signed up” requirement in jurisdictions like California’s Automatic Renewal Law.

cURL

curl --request PATCH \
  --url https://api.polar.sh/v1/subscriptions/{subscription_id} \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
    "cancel_at_period_end": true,
    "customer_cancellation_reason": "too_expensive"
  }'

You can optionally record a cancellation reason and comment — useful for tracking churn. The supported reasons are too_expensive, missing_features, switched_service, unused, customer_service, low_quality, too_complex, and other.

Revoke immediately

Revoking ends the subscription right now: status moves to canceled, ended_at is set to the current time, and all benefits are revoked. There’s no refund — if you need to issue one, do it separately from Refunds. Use this when access needs to stop immediately — a terms-of-service violation, a chargeback, or an explicit customer request.

cURL

curl --request DELETE \
  --url https://api.polar.sh/v1/subscriptions/{subscription_id} \
  --header 'Authorization: Bearer <TOKEN>'

Revoking is irreversible. If you want the option to reverse the decision, cancel at period end instead.

Uncancel

If a subscription is set to cancel at period end and hasn’t ended yet, you (or the customer) can reverse the decision. The cancel_at_period_end flag is cleared, ends_at and canceled_at are unset, and the subscription goes back to renewing normally.

cURL

curl --request PATCH \
  --url https://api.polar.sh/v1/subscriptions/{subscription_id} \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{ "cancel_at_period_end": false }'

Uncancelling is not possible once the subscription has actually ended.

What customers can do

The Customer Portal exposes a subset of these actions to the customer, gated by your portal settings:

Everything else on this page is merchant-only: revoking a subscription, applying or changing a discount, extending or ending a trial, and rescheduling the renewal date are not exposed to customers.