Subscription Management using the Lemon Squeezy API

Learn how to effectively manage subscriptions using the Lemon Squeezy API, including changing plans, cancelling, pausing, and resuming subscriptions.


This guide covers essential subscription management tasks using the Lemon Squeezy Subscriptions API. You’ll learn how to programmatically change subscription plans, handle cancellations, implement pausing and resuming functionality, and manage other key aspects of your subscription-based service.

Creating subscriptions

Read the “Taking payments” guide to learn how to create checkouts and let customers sign up to your subscription products.

Saving product data in your database

To enable plan switching within your app, you need to store your Lemon Squeezy product data locally. This builds on the information covered in the “Saving checkout and subscription data in your database” section of the “Taking payments” guide, where we discussed essential data to store in your app.

To populate your app with product and variant data, you have two main options:

  • Manually call the list all variants endpoint whenever you edit or add products.
  • Set up a background job to fetch this data regularly.

We recommend storing the following key information for each variant:

  • product_id
  • variant_id
  • name
  • price

Storing these details allows you to easily display and manage product information within your app.

Changing plans

To change a subscription’s plan (variant):

  1. Send a PATCH request to the specific subscription endpoint
  2. Include the new variant ID in the request body.
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).

Handling proration

When changing a subscription’s plan (variant), proration occurs by default.

For example:

  • A customer moves from a $19/month plan to a $99/month plan
  • A prorated amount is charged based on the time already spent on the $19 plan
  • By default, this extra amount is added to the next renewal

You have two options to control how proration is handled:

  1. "invoice_immediately": true
  • Creates a new invoice during the plan change
  • If the new plan is cheaper, the invoice total will be zero
  • If the new plan is more expensive, an immediate payment for the difference is attempted
  1. "disable_prorations": true
  • Completely disables proration
  • The customer moves to the new plan’s price at the next renewal without any additional charges

Important notes:

  • If both options are used in the same request, disable_prorations overrides invoice_immediately
  • The plan change takes effect immediately, regardless of the proration option chosen
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
    }
  }
}'

Cancelling and resuming subscriptions

To cancel a subscription:

  1. Send a DELETE request to the specific subscription endpoint.
  2. The response will contain an updated Subscription object with:
    • cancelled set to true
    • status set to "cancelled"

Grace period

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.

Resuming a subscription in grace period

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.

Expired subscriptions

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).

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.

Pausing a subscription

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"
      }
    }
  }
}'

When pausing a subscription, you can choose between two mode values:

  • free: Use this when you want to offer your product or service at no cost during the pause period.
  • void: Use this when you cannot provide your services during the pause period.

You can also optionally pass resumes_at to specify a date to automatically unpause the subscription.

Manually unpausing a paused subscription

  1. Send a PATCH request to the specific subscription endpoint.
  2. Include pause attribute with null value.

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
    }
  }
}'

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"
    }
    ...
  }
}

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.

Update payment method modal

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.

Changing the billing date

  1. Send a PATCH request to the specific subscription endpoint.
  2. Include billing_anchor attribute.
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.

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.

For more information please refer to the API reference

Update a subscription’s quantity

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


And that’s it! You’re now equipped to set up, manage, and modify subscriptions using the Lemon Squeezy API, enabling you to provide a flexible and user-friendly subscription experience for your customers.


Was this page helpful?