API Reference

The Lemon Squeezy API is a REST API that has predictable resource-oriented URLs, returns valid JSON:API encoded responses and uses standard HTTP response codes, authentication, and verbs.


Quickstart

We have written a detailed Developer guide to help you get started with Lemon Squeezy and the API.

Read the Developer guide →

Find out what's new with the API from the API Changelog.


SDKs

Download packages for your app that make it easy to interface with the Lemon Squeezy API.

Official SDKs

Unofficial SDKs


Test mode

You can build and test a full API integration with Lemon Squeezy using test mode.

Any API keys created in test mode will interact with your test mode store data.

When you are ready to go live with your integration, make sure to create an API key in live mode and use that in your production application.


Making Requests

All API requests must be made over HTTPS to https://api.lemonsqueezy.com. Calls made over plain HTTP will fail. API requests without authentication will also fail.

The Lemon Squeezy API is compatible with the JSON:API spec. As per the spec, the following headers must be included with all requests to the API:

  • Accept: application/vnd.api+json
  • Content-Type: application/vnd.api+json

If you're attempting to make a request with a null Origin header (e.g. from a sandboxed iframe in a Figma plugin) then you can use the https://api-cors-anywhere.lemonsqueezy.com API proxy URL instead.


Resource Object Structure

All API responses follow the document structure outlined in the JSON:API spec. This means every response will contain a top-level data object/array which will contain one/many resource objects. Each resource object will contain the following properties:

  • type - The type of the resource (e.g. products, orders, etc.)
  • id - The id of the resource
  • attributes - An object representing the resources data

A resource object may also contain optional properties such as relationships, links and meta.


Authentication

The Lemon Squeezy API uses API keys to authenticate requests. You can view and manage your API keys in your account settings.

Note that API keys are live and test mode specific. A test mode API key will only return test mode data and vice versa.

Be sure to keep your API keys secure! Do not share your API keys in publicly accessible areas such as GitHub, client-side code, and so forth.

Generated API keys are valid for a year.

To authenticate requests, API keys must be included in the Authorization header as a Bearer token in the format:

Authorization: Bearer {api_key}

Unauthenticated requests will receive a 401 Unauthorized response.


Rate Limiting

To make it easier to determine if your application is being rate-limited, or is approaching that level, we add the following HTTP headers on our successful responses:

  • X-Ratelimit-Limit
  • X-Ratelimit-Remaining

There is a limit of 300 API calls per minute.

If you exceed the limit you will receive a 429 Too Many Requests response.


Errors

The Lemon Squeezy API uses conventional HTTP response codes to indicate the success or failure of an API request. In general, codes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted, an action failed, etc). Codes in the 5xx range indicate an error with our servers (these are rare).

A 4xx error will always contain valid JSON:API errors array in the response. Each error object will usually contain several fields that explain the error, including status, title, detail etc.

Some common error responses are listed below:

  • 400 Bad Request - Your request may be malformed
  • 401 Unauthorized - Your API key is wrong, or your user does not have access to this resource
  • 403 Forbidden - The record requested is hidden
  • 404 Not Found - The specified record could not be found
  • 405 Method Not Allowed - You tried to access a record with an invalid method
  • 422 Unprocessable Entity - The requested method cannot process for the record in question
  • 429 Too Many Requests - You have exceeded the API rate limit

Pagination

The Lemon Squeezy API uses page-based pagination for all “list” endpoints. The responses will contain valid JSON:API pagination objects in the response. This includes a top-level links object with (URL-encoded) first, last, next and prev links, like this:

{ ... "links": { "first": "https:\/\/api.lemonsqueezy.com\/v1\/orders?page%5Bnumber%5D=1&page%5Bsize%5D=10&sort=-createdAt", "last": "https:\/\/api.lemonsqueezy.com\/v1\/orders?page%5Bnumber%5D=5&page%5Bsize%5D=10&sort=-createdAt", "next": "https:\/\/api.lemonsqueezy.com\/v1\/orders?page%5Bnumber%5D=4&page%5Bsize%5D=10&sort=-createdAt", "prev": "https:\/\/api.lemonsqueezy.com\/v1\/orders?page%5Bnumber%5D=2&page%5Bsize%5D=10&sort=-createdAt" }, ... }

You can use links.next to continue through the pages of your query. If next is not in the links object, you have reached the last page (similarly, prev is not present on the first page of results).

The request also contains a pagination object in meta.page, which contains helpful pagination information for your current query:

{ "meta": { "page": { "currentPage": 3, "from": 21, "lastPage": 5, "perPage": 10, "to": 30, "total": 47 } }, ... }

Using this data, you can surface information like how many total results there are (meta.page.total) or how many pages there are (meta.page.lastPage).

To make custom paginated queries, use the page[size] parameter to determine how many results to return per page (default is 10, minimum is 1 and maximum is 100) and page[number] to determine which page to retrieve.

Request

GET /v1/orders?page[number]=3&page[size]=100

To help cut down on multiple requests, the Lemon Squeezy API supports the JSON:API spec for including related resources. Related resources can be included in the same response by using the include query parameter.

Request

The following request will include all Variants that belong to the Product with the ID 100:

GET /v1/products/100?include=variants

The response will contain a new top-level included array which will contain the related resources.

The following request will include a full Customer object for a Subscription:

GET /v1/subscriptions/30?include=customer

Related resources are returned in responses in a top-level included object.

{ "meta": { ... }, "jsonapi": { ... }, "links": { ... }, "data": [ {...}, {...}, {...} ], "included": [ { "type": "variants", "id": "1", "attributes": { "product_id": 1, "name": "Default", "slug": "537b22ba-fcc9-452a-9021-c3cabe3985cf", "description": "

This is the variant description.

", "price": 999, "is_subscription": true, "interval": "month", "interval_count": 1, "has_free_trial": false, "trial_interval": "day", "trial_interval_count": 30, "pay_what_you_want": false, "min_price": 0, "suggested_price": 0, "has_license_keys": false, "license_activation_limit": 5, "is_license_limit_unlimited": false, "license_length_value": 1, "license_length_unit": "years", "is_license_length_unlimited": false, "sort": 0, "status": "pending", "status_formatted": "Pending", "created_at": "2021-05-27T12:54:47.000000Z", "updated_at": "2021-07-14T11:25:24.000000Z", "test_mode": false }, "relationships": { "product": { "links": { "related": "https://api.lemonsqueezy.com/v1/variants/1/product", "self": "https://api.lemonsqueezy.com/v1/variants/1/relationships/product" } }, "files": { "links": { "related": "https://api.lemonsqueezy.com/v1/variants/1/files", "self": "https://api.lemonsqueezy.com/v1/variants/1/relationships/files" } }, "price-model": { "links": { "related": "https://api.lemonsqueezy.com/v1/variants/1/price-model", "self": "https://api.lemonsqueezy.com/v1/variants/1/relationships/price-model" } } }, "links": { "self": "https://api.lemonsqueezy.com/v1/variants/1" } }, {...}, {...} ] }

It's also possible to use nested queries to retrieve related objects without the parent object.

You can find nested query request URLs in each object's relationships object.

Request

This example queries all Variants for a specific Product:

GET /v1/products/100/variants

Filtering

List endpoints in our API can be filtered by related objects or object values using query parameters.

In the JSON:API spec, filters should be applied as follows:

?filter[{parameter}]={value}

Filtering subscriptions by product:

GET /v1/subscriptions?filter[product_id]=2

Filtering subscription invoices by subscription:

GET /v1/subscription-invoices?filter[subscription_id]=6

Filtering orders by customer email:

GET /v1/orders?filter[user_email][email protected]

Multiple filters:

GET /v1/subscription-invoices?filter[status]=open&filter[store_id]=11

Versioning

The Lemon Squeezy API includes the major version number as a prefix for all endpoints (e.g. /v1). While we reserve the right to make changes to the API as we see fit, we endeavour not to make any changes to the API that will break backwards compatibility.

In the rare case that we do need to break backwards compatibility, we will release a new major version of the API and deprecate the old version. This will give any integrations time to migrate to the new version.

Lemon Squeezy considers the following changes to be backwards-compatible:

  • Adding new API resources.
  • Adding new optional request parameters to existing API methods.
  • Adding new properties to existing API responses.
  • Changing the order of properties in existing API responses.
  • Adding new webhook event types.

Webhooks

Keep your application in sync with Lemon Squeezy by subscribing to webhook events.

Read how to set up webhooks.


Example App

If you're looking for some inspiration or guidance on how you might use our API, check out our example app created using Vue.js that demonstrates how you might use the API in your own apps.