Developer guide

Managing subscriptions with the API

On this page, we'll go through how you can handle things like changing plans, cancelling and pausing subscriptions with the Lemon Squeezy API.

Creating subscriptions

Read the Taking payments page to find out how to create checkouts and let customers sign up to your subscriptions products.

Saving product data in your database

In the Saving checkout and subscription data in your database section of this guide, we went through the data that should be saved locally in your app. To be able to let customers switch between plans in your app, you need to store a list of your Lemon Squeezy products.

The easiest way to get product and variant data into your app is by manually calling the list all variants endpoint whenever you edit or add products (alternatively you could set up a background job to fetch data more regularly).

We recommend you save data like the product_id, variant_id, name and price values so you can display them in your app.

Changing plans

To change a subscription’s product, make a PATCH request to the individual subscription endpoint with the new variant ID.

curl -X "PATCH" "https://api.lemonsqueezy.com/v1/subscriptions/{subscription_id}" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}' -d $'{ "data": { "type": "subscriptions", "id": "{subscription_id}", "attributes": { "variant_id": {variant_id}, } } }'

The subscription will be instantly moved to the new product variant and you will be able to verify this by checking the response (which will contain a subscription object).

You can also manage subscription plans in the dashboard.

Handling proration

When a subscription’s plan (variant) is changed, proration will occur. Proration is the term used for calculating the difference between payment totals and lengths, making sure the customer is charged correctly for the time they spend across different products.

For example, if a customer moves from a $19/month plan to a $99/month plan, a prorated amount will be charged based on the new $99 plan relative to how much time they have already spent on the $19 plan.

By default, this extra amount will be added to the next renewal.

There are two options you can use to determine how proration is handled when changing plans.

The first option is "invoice_immediately": true, which will create a new invoice during the plan change. The invoice total will be zero if there is nothing to pay (the customer is changing to a lower-priced plan). If the invoice total is greater than zero, a payment of the difference will be attempted.

You can disable proration completely by adding "disable_prorations": true to your request. When using this option, the customer will not be charged a prorated amount and will simply move to the new plan's price at their next renewal.

If used together in the same request, disable_prorations will always override invoice_immediately.

Note that the change of plan on the Subscription is always immediate, regardless of the proration option applied.

curl -X "PATCH" "https://api.lemonsqueezy.com/v1/subscriptions/{subscription_id}" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}' -d $'{ "data": { "type": "subscriptions", "id": "{subscription_id}", "attributes": { "variant_id": {variant_id}, "disable_prorations": true } } }'

API reference

This is how API proration options compare to the options listed in the Manage Subscription panel in the dashboard:

  • Changing plans without invoice_immediately or disable_prorations is the same as "Apply changes with proration" (the default)
  • Using "invoice_immediately": true is the same as "Apply changes with proration and invoice immediately"
  • Using "disable_prorations": true is the same as "Apply changes without proration"

Cancelling and resuming subscriptions

To cancel subscriptions, send a DELETE request to the individual subscription endpoint. In the response, you will get an updated subscription object, with cancelled set to true and status set to cancelled.

curl -X "DELETE" "https://api.lemonsqueezy.com/v1/subscriptions/{subscription_id}" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}'

If a subscription is cancelled mid billing period (either by the customer or by the store owner), it will enter a “grace period” before it expires at the next scheduled renewal date (refected in a subscription's ends_at value). The customer should still have access to your app or product until this date because they have paid for that time period.

During this cancelled grace period, it’s possible to resume the subscription with a quick API call with cancelled set to false.

curl -X "PATCH" "https://api.lemonsqueezy.com/v1/subscriptions/{subscription_id}" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}' -d $'{ "data": { "type": "subscriptions", "id": "{subscription_id}", "attributes": { "cancelled": false, } } }'

If a subscription is resumed like this, the subscription is changed back to active and the original payment schedule will continue.

However, if a subscription is cancelled and then reaches its next renewal date (ends_at) without being resumed, it will instead expire (its status will change to expired). When a subscription is in the expired state, your customer should no longer have access to your app and the subscription is no longer resumable.

API reference

Pausing and unpausing subscriptions

Pausing a subscription is a great option if you want to keep a subscription active but pause regular payment collection. Maybe this is because your app will be inaccessible for a temporary period or you will be on holiday during a service-based retainer. Alternatively you may want to let your customers pause subscriptions if they won’t be able to make full use of your product for a certain period of time.

A paused subscription with have a status of paused.

To pause a subscription, send a PATCH request containing a pause object:

curl -X "PATCH" "https://api.lemonsqueezy.com/v1/subscriptions/{subscription_id}" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}' -d $'{ "data": { "type": "subscriptions", "id": "{subscription_id}", "attributes": { "pause": { "mode": "free", "resumes_at": "2023-06-30T00:00:00.000000Z" } } } }'

There are two mode values you can use when pausing a subscription. Both stop payment collection temporarily. Use free if you want to offer your product or service for free. Use void if you can't provide your services for the period in question.

In the request you can also specify an optional resumes_at value, which will unpause the subscription automatically on a certain date.

To manually unpause a paused subscription, make a PATCH request with pause set to null. Similarly to resuming a cancelled subscription, the subscription will be changed to active and payment collection will resume on its original schedule.

curl -X "PATCH" "https://api.lemonsqueezy.com/v1/subscriptions/{subscription_id}" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}' -d $'{ "data": { "type": "subscriptions", "id": "{subscription_id}", "attributes": { "pause": null } } }'

API reference

Updating billing details

Letting your customers update their payment details during a subscription is an essential feature, especially when cards expire or if payments fail for any reason.

We provide a signed URL in every Subscription-related API request and webhook event in urls.update_payment_method, which customers can use to easily update their billing details. We suggest you make this URL easily available to your customers, for example in your app’s billing pages.

{ "type": "subscriptions", "id": "1", "attributes": { ... "urls": { "update_payment_method": "https://my-store.lemonsqueezy.com/subscription/1/payment-details?expires=1674045831&signature=31cf3c83983a03a6cf92e4ec3b469fc044eace0a13183dcb1d7bc0da3bad6f31", "customer_portal": "https://my-store.lemonsqueezy.com/billing?expires=1674045831&signature=82ae290ceac8edd4190c82825dd73a8743346d894a8ddbc4898b97eb96d105a5" } ... } }

Note: If you have a custom domain set up, update_payment_method will contain your custom domain.

For security, the URLs returned by the API expire after 24 hours. You will need to query the subscription over the API for a refreshed URL.

To make the URL open in a more seamless overlay on top of your app (similar to the checkout overlay) use Lemon.js to open the URL with the LemonSqueezy.Url.Open() method.

Note: During our payment recovery process any subscriptions with failed payments will have four retries before entering the (optional) dunning flow. After each payment retry and for each of the dunning series emails, we will send the same URL to the customer to update their billing details.

Changing the billing date

You can easily change the billing date of a subscription by specifying a billing_anchor value in a request:

curl -X "PATCH" "https://api.lemonsqueezy.com/v1/subscriptions/{subscription_id}" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}' -d $'{ "data": { "type": "subscriptions", "id": "{subscription_id}", "attributes": { "billing_anchor": 1, } } }'

By default, a subscription’s billing_anchor will match the date the customer initially signed up, but you can easily change it to any other day of the month. As an example, some businesses like to charge all customers on the first of each month.

When changing the billing_anchor value of a subscription, a proration will occur to make sure the customer is not overcharged or undercharged when the length of their billing period changes.

Note: If the current month doesn’t contain the day that matches your billing_anchor (for example, if the billing_anchor is 31 and the month is November), the customer will be charged on the last day of the month.

You can use null or 0 to easily change the billing anchor to the current date. Doing this will also remove any active trial period.

API reference

Update a subscription's quantity

Go to the Usage-based billing page to find out how to update a subscription's quantity or usage.

Previous
Staying in sync with webhooks