Developer guide

Taking payments

Taking payments with Lemon Squeezy means sending customers to a checkout. Our checkout pages let your customers purchase one-off and subscription products using various payment methods including cards, PayPal and Apple Pay.

To integrate with Lemon Squeezy, you need to send customers to a checkout and then after payment is complete save the customer and order data to your system.

About checkout URLs

You can create checkouts for every product and variant you create in your Lemon Squeezy store.

Say you have a subscription product with two variants, for example a monthly subscription and a yearly subscription. Each of these two variants have a unique checkout URL, which you should send your customer to in order to make a purchase.

A checkout URL looks like this:

https://[STORE].lemonsqueezy.com/checkout/buy/[VARIANT_ID]

When sharing a checkout URL you can specify whether you want to use a hosted checkout, which loads the checkout in a browser window, or our checkout overlay, which will load the checkout over the current page. When integrating into apps, the checkout overlay keeps the experience more streamlined.

Though it's possible to use a custom domain for your storefront, checkout URLs will always be served from https://[STORE].lemonsqueezy.com. We are actively working on adding to support custom domains on checkout URLs.

Note that shareable checkout URLs contain /checkout/buy/. When these links are opened in a browser they are converted to "carts" and the URL will then contain /checkout/?cart=. These cart URLs cannot be shared because they are single use and unique to a customer. Make sure you share checkout URLs rather than cart URLs.

By default, checkout URLs can be used indefinitely and are safe to be stored/cached on the merchant side. It is possible to create expiring checkout URLs using the API.


How to create checkouts

There are two ways to create checkouts for your products.

Creating checkouts from the Lemon Squeezy admin

The first way is from the Products page in Lemon Squeezy.

Click on the “Share” option when viewing a product and you’ll see a settings panel for creating a checkout link.

You can select between using the hosted and overlay checkouts plus show and hide different parts of the page.

When you’re done, copy the URL and use it in your app or website.

Creating checkouts with the API

The second way to create checkout URLs is by using the Checkouts API endpoint. By using our API, you can create checkouts on-demand and with more flexibility.

To create a checkout with the API, send a POST request with your desired configuration. You have the same options as in the Share panel, plus a range of customisation options.

The most basic request contains required relationships to the store and variant. The following request will create a checkout for a specified variant:

curl -X "POST" "https://api.lemonsqueezy.com/v1/checkouts" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}' -d $'{ "data": { "type": "checkouts", "relationships": { "store": { "data": { "type": "stores", "id": "2" } }, "variant": { "data": { "type": "variants", "id": "2" } } } } }'

You can find your store ID from Settings > Stores.
Variant IDs can be copied from product dropdown menus (...) using the "Copy ID" option, or from the API using the list all variants endpoint.

The response from this request looks like this:

{ "jsonapi": { "version": "1.0" }, "links": { "self": "https://api.lemonsqueezy.com/v1/checkouts/d42dda93-592a-4016-9d9a-d6ca5c6b86c0" }, "data": { "type": "checkouts", "id": "d42dda93-592a-4016-9d9a-d6ca5c6b86c0", "attributes": { "store_id": 2, "variant_id": 2, "custom_price": null, "product_options": { "name": "", "description": "", "media": [], "redirect_url": "", "receipt_button_text": "", "receipt_link_url": "", "receipt_thank_you_note": "", "enabled_variants": [] }, "checkout_options": { "embed": false, "media": true, "logo": true, "desc": true, "discount": true, "dark": false, "subscription_preview": true, "button_color": "#7047EB" }, "checkout_data": { "email": "", "name": "", "billing_address": [], "tax_number": "", "discount_code": "", "custom": [], "variant_quantities": [] }, "expires_at": null, "created_at": "2023-02-02T11:43:07.000000Z", "updated_at": "2023-02-02T11:43:07.000000Z", "test_mode": false, "url": "https://my-store.lemonsqueezy.com/checkout/custom/d42dda93-592a-4016-9d9a-d6ca5c6b86c0?signature=ac6ca41510f0cedaa5ce65144a0bab2c69ab6b35902592e52b69803c51b2dbb4" }, "relationships": { "store": { "links": { "related": "https://api.lemonsqueezy.com/v1/checkouts/d42dda93-592a-4016-9d9a-d6ca5c6b86c0/store", "self": "https://api.lemonsqueezy.com/v1/checkouts/d42dda93-592a-4016-9d9a-d6ca5c6b86c0/relationships/store" } }, "variant": { "links": { "related": "https://api.lemonsqueezy.com/v1/checkouts/d42dda93-592a-4016-9d9a-d6ca5c6b86c0/variant", "self": "https://api.lemonsqueezy.com/v1/checkouts/d42dda93-592a-4016-9d9a-d6ca5c6b86c0/relationships/variant" } } }, "links": { "self": "https://api.lemonsqueezy.com/v1/checkouts/d42dda93-592a-4016-9d9a-d6ca5c6b86c0" } } }

The data.attributes.url in the response is the unique URL for your specific checkout request.

A common flow for using a checkout URL would be to send an API request to generate a checkout when a customer clicks a "Buy" button in your app. After receiving the response, you could then redirect the customer to the URL.

Alternatively, you could create a checkout during or right after page load and insert the URL in a "Buy" button, ready for the customer to click. However, we don't recommend doing this on high-traffic pages unless you are caching the response.

However you decide to do it, once the checkout URL is available to your customer, they can start buying your products! 🚀


Advanced checkouts

We have added the ability to make some more customisations and personalisation in checkouts. This can be done with query parameters in a URL or with some extra attributes when using the checkouts API.

Checkout overlays

By default the URLs from the Share option in your dashboard and created using the API will load the Lemon Squeezy checkout in a full browser window.

It's possible to set up a more streamlined version, with the checkout appearing over your site or application, meaning that the customer never leaves the page.

In the dashboard when sharing a product, click on the "Checkout Overlay" option and then paste the provided code into your web page.

This code includes Lemon.js, our mini library for handling checkout actions. Whenever a link with the CSS class lemonsqueezy-button is clicked, the checkout will appear over the current page instead of opening in the full browser window, making it feel a part of your site.

If you're creating checkouts using the API, you can also use Lemon.js for loading your checkout URLs in an overlay. Make sure you include the script on your page, then once you have created the checkout, use LemonSqueezy.Url.Open() to create the overlay:

const checkoutUrl = response['data']['attributes']['url']; LemonSqueezy.Url.Open(checkoutUrl);

You can also use Lemon.js to open the "update payment method" URL in an overlay and to listen for checkout events like a successful order.

Pre-fill customer information

To make it easier for your customers to check out, you can pre-fill names, emails, addresses and discount codes in the checkout.

If you already have a checkout URL, you can easily append query string parameters like this:

https://[STORE].lemonsqueezy.com/checkout/buy/[VARIANT_ID] ?checkout[email][email protected] &checkout[name]=Luke Skywalker

With the API you can add values in a checkout_data object in your request. The same example above would be:

curl -X "POST" "https://api.lemonsqueezy.com/v1/checkouts" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}' -d $'{ "data": { "type": "checkouts", "attributes": { "checkout_data": { "email": "[email protected]", "name": "Luke Skywalker" } }, "relationships": { ... } } }'

The full list of attributes that can be passed to checkout_data can be found in the Create a checkout docs.

Passing custom data

You can pass custom data to checkout, which you can then access later in webhooks and API calls. This data is never shown to customers so is perfect for linking checkouts to users or sessions from within your product.

You can add custom data to checkout URLs with query string parameters:

https://[STORE].lemonsqueezy.com/checkout/buy/[VARIANT_ID] ?checkout[custom][user_id]=123

With the API, you can add custom data using a custom object within checkout_data, like this:

curl -X "POST" "https://api.lemonsqueezy.com/v1/checkouts" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}' -d $'{ "data": { "type": "checkouts", "attributes": { "checkout_data": { "custom": { "user_id": 123 } } }, "relationships": { ... } } }'

This object will then be returned as meta.custom_data in all Order, Subscription and License key related webhook events.

{ "meta": { "event_name": "subscription_created", "custom_data": { "user_id": 123 } }, "data": { "type": "subscriptions", ... } }

Customise the checkout design

When you share a product from inside Lemon Squeezy, you will see options to show and hide certain parts of the checkout. The options you choose will be reflected in the URL that is generated. You can also edit these manually on any checkout URL.

Here's how to create a checkout overlay with the logo hidden and a dark grey button:

https://[STORE].lemonsqueezy.com/checkout/buy/[VARIANT_ID] ?embed=1 &logo=0 &button_color=%23111111

Note that the # symbol used in the hex colour needs to be URL-encoded as %23 (#111111 becomes %23111111).

It's also possible to edit the checkout design on-the-fly with the API using a checkout_options object. The same example from above would look like this:

curl -X "POST" "https://api.lemonsqueezy.com/v1/checkouts" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}' -d $'{ "data": { "type": "checkouts", "attributes": { "checkout_options": { "embed": true, "dark": true, "logo": false, "button_color": "#111" } }, "relationships": { ... } } }'

View all checkout_options attributes in the Create a checkout docs.

Custom pricing

Sometimes you may want to offer one of your products at special prices for certain customers. With the API, you can do this on-demand.

Simply add a custom_price value and that price will override the product’s usual price when the customer visits the checkout (this price does not include tax, which may be added at checkout).

The custom_price value must be in the currency’s smallest unit i.e. 599 would mean $5.99 for USD and ¥599 for JPY.

curl -X "POST" "https://api.lemonsqueezy.com/v1/checkouts" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}' -d $'{ "data": { "type": "checkouts", "attributes": { "custom_price": 599 }, "relationships": { ... } } }'

Custom pricing is not available using query string parameters on checkout URLs.

For subscriptions, the custom_price you set will be retained for all future renewals unless the customer is moved to another plan (product); in this case the new product’s price will override and replace the custom price you set in the initial checkout.

Override product details

In addition to overriding a product’s price at checkout, you also have the option to change some of a product’s other values (this customisation is only available for checkouts created using the API).

With the API, product_options can change basically all the fields that you used to create the initial product, like name, description, media, redirect URL and even which variants should be shown.

curl -X "POST" "https://api.lemonsqueezy.com/v1/checkouts" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}' -d $'{ "data": { "type": "checkouts", "attributes": { "product_options": { "name": "Unique subscription for Dave", "redirect_url": "https://myapp.com/welcome/?user=dave123", "receipt_button_text": "Go to your account" } }, "relationships": { ... } } }'

View all product_options attributes in the Create a checkout docs.

Expiring checkout URLs

The final option we’ll go into in this guide is to create checkout URLs which expire at a certain time. This is useful if you only want to offer a product (or customised product) for a certain period.

Simply set a date in the expires_at attribute and Lemon Squeezy will invalidate the checkout after that date, preventing unwanted purchases.

curl -X "POST" "https://api.lemonsqueezy.com/v1/checkouts" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}' -d $'{ "data": { "type": "checkouts", "attributes": { "expires_at": "2023-04-30T23:59:59.000000Z" }, "relationships": { ... } } }'

As noted earlier, checkout URLs without an expires_at value can be used indefinitely and are safe to be stored/cached on the merchant side.


After the checkout

The checkout itself isn’t the only important part of a purchase for your customers. What happens after taking payment is also crucial to get right, and we offer you a number of options to create the perfect flow for your app or product.

The confirmation modal

After a successful payment, your customer will be shown a confirmation message.

The text and button in the confirmation is fully customisable from a product's settings panel.

Redirects

If you’re integrating Lemon Squeezy into your app, maybe you want to redirect the user to their billing page or a custom welcome page after purchase.

By default the button in the confirmation will take users to their My Orders page.

You can change this button's URL by changing the "Button link" option in the Confirmation modal settings:

If you're creating checkouts with the API, simply add a product_options.redirect_url in your request to change the button's link:

curl -X "POST" "https://api.lemonsqueezy.com/v1/checkouts" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}' -d $'{ "data": { "type": "checkouts", "attributes": { "product_options": { "redirect_url": "https://myapp.com" } }, "relationships": { ... } } }'

If you add a custom button URL, the customer will see a "Continue" button instead of the default "View Order" button. If you've customised the "Button text" value in the Confirmation modal settings, your custom button text will be used instead.

Editing receipts

You can customise the copy and the button in the receipt emails sent to your customers.

Here's an example receipt:

By default your customer will see a "View Order" button but this is easily configurable for each product from the edit product side panel.

Receipts can be customised when editing products in Lemon Squeezy:

You can also achieve the same result with the API by adding attributes to the product_options object when creating checkouts:

curl -X "POST" "https://api.lemonsqueezy.com/v1/checkouts" -H 'Accept: application/vnd.api+json' -H 'Content-Type: application/vnd.api+json' -H 'Authorization: Bearer {api_key}' -d $'{ "data": { "type": "checkouts", "attributes": { "product_options": { "receipt_button_text": "Go to your account", "receipt_link_url": "https://myapp.com/account/", "receipt_thank_you_note": "Thank you for signing up! Click on the button to access your account.", } }, "relationships": { ... } } }'

Saving checkout and subscription data in your database

It's important that you store Lemon Squeezy data in your own database so that you can easily reference objects later and use the API to get more details.

For orders, you could listen for order_created webhooks or use the data returned in the Lemon.js Checkout.Success event. Store the order id from Order objects to be able to make future requests for orders in the API.

For subscriptions, you could listen for subscription_created and subscription_updated webhook events and store subscription ids. (Handily, the subscription_created event will return the order_id, so there’s no need to listen to the order_created event if you’re selling subscriptions and also want to store the order ID).

You should also record the product_id and variant_id, which will help should you need to change subscription plans in the future.

Store the first_subscription_item.id if you are using usage-based billing, so you can create usage records. It's also recommended to store first_subscription_item.quantity so you can show your customers their current usage.

Store the customer_id if you want to query customer data in the future.

For the best user experience, store and display the status, trial_ends_at, renews_at, ends_at, card_brand and card_last_four values from a Subscription object so that you can display up-to-date information about a subscription in your user’s billing page.

We also recommended to store a subscription object's urls.update_payment_method value, which provides a simple URL for customers to update their payment method during their subscription.

Previous
Getting started with the API