Taking Payments

Learn how to integrate Lemon Squeezy’s checkout system into your app or product, from creating checkout URLs to handling post-purchase processes and managing customer data.


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.

Integrating with Lemon Squeezy involves two key steps: directing customers to a checkout page, and then capturing and storing customer and order data in your system once the payment is processed.

Checkout URLs

For each product and variant in your Lemon Squeezy store, you can generate unique checkout URLs.

Let’s consider an example: imagine you have a subscription product with two variants - a monthly plan and an annual plan. Each variant will have its own distinct checkout URL. You’ll direct customers to the appropriate URL to complete their purchase.

The structure of a checkout URL is as follows:

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.

Shareable Checkout URLs vs. Cart URLs

When a customer opens a checkout URL in their browser, it’s converted to a “cart” URL:

  • The URL changes to contain /checkout/?cart=
  • This cart URL is unique to that customer and single-use only!
  • Cart URLs cannot be shared or reused. They will not work for other customers.

How to create checkouts

There are two ways to create checkouts for your products:

Creating checkouts from the Lemon Squeezy dashboard

  1. Log into your Lemon Squeezy dashboard and navigate to Products.
  2. Click on the “Share” link when viewing a product and you’ll see a panel containing options for creating a checkout URL.
Lemon Squeezy: Share Product Panel

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 using the Lemon Squeezy API

The second way to create a checkout URL 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 Product” panel, plus a range of customization 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"
        }
      }
    }
  }
}'

The response to this request is a Checkout object.

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.

Advanced checkouts

Our checkout system offers additional customization and personalization options. You can apply these customizations in two ways:

  • By adding query parameters to checkout URLs
  • By including additional attributes when using the Checkouts API

Checkout overlays

Lemon Squeezy offers two checkout display options:

  • Hosted Checkout (Default): Checkout URLs generated from your dashboard’s Share option or via the API open in a new browser tab.
  • Checkout Overlay: This option displays the checkout process in an iframe, over your existing website or application, keeping customers on your page.

To implement the “Checkout Overlay” from your Lemon Squeezy Dashboard:

  1. From your Lemon Squeezy dashboard, navigate to the product sharing settings.
  2. Select the “Checkout Overlay” option.
  3. Copy the provided code snippet.
  4. Paste this code into your web page.
Lemon Squeezy: Checkout Overlay Copy Code

This code includes Lemon.js, our mini JS 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.

Lemon Squeezy: Checkout Overlay

Lemon.js

If you’re creating checkouts using the API, you can 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 the LemonSqueezy.Url.Open() method to create the overlay:

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

To get the “Checkout Overlay” URL using the Lemon Squeezy API see the embed attribute in checkout customization options.

Pre-fill customer information

You can pre-populate the checkout fields with customer information, making the process quicker and more convenient for your customers. The pre-fillable fields include:

  • Name
  • Email address
  • Billing address
  • Tax number
  • Discount codes
  • Quantities

To add this information to an existing checkout URL, append query string parameters. For example:

https://[STORE].lemonsqueezy.com/checkout/buy/[VARIANT_ID]
?checkout[email][email protected]
&checkout[name]=John Doe
&checkout[billing_address][country]=US
&checkout[billing_address][state]=NY
&checkout[billing_address][zip]=10121
&checkout[tax_number]=123456789
&checkout[discount_code]=10PERCENTOFF

If you are using API to create checkouts pass a JSON object inside checkout_data.

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": "John Doe"
      }
    },
    "relationships": {
      ...
    }
  }
}'

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 it’s perfect for linking checkouts to users or sessions from within your product.

Custom data can be passed to checkout URLs with query string parameters. For example, if you want to pass user_id of value 123 to the checkout, you can do it like so:

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

Checkout page customization

Lemon Squeezy allows you to customize the appearance of your checkout page via:

  • Dashboard: When sharing a product, you’ll find options to show or hide specific elements. These choices are automatically reflected in the generated URL.
  • Query params: Manually adjust any checkout URL to customize its appearance.

Here’s an example of creating a checkout overlay with a hidden logo 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 color needs to be URL-encoded as %23, #111111 becomes %23111111.

Custom pricing

You might occasionally want to provide special pricing for certain customers. With the API, you can easily set these custom prices on demand.

To do this, add a custom_price value in your API request. This custom price will override the product’s standard price at checkout. Note that this price excludes tax, which may be added during the checkout process.

For example:

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": {
      ...
    }
  }
}'

Override product details

Beyond overriding a product’s price at checkout, you can also modify other product attributes using the API (this customization is exclusive to API-created checkouts).

The product_options object in the API allows you to update the fields used during the product creation process, including name, description, media, redirect URL, and the variants to be displayed.

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": {
      ...
    }
  }
}'

Expiring Checkout URLs

The final option in this guide is to create checkout URLs that expire at a specific time. This feature is useful if you want to offer a product (or customized product) for a limited period.

To set this up, simply add a date in the expires_at attribute. Lemon Squeezy will invalidate the checkout after that date, preventing any further 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": {
      ...
    }
  }
}'

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.

Lemon Squeezy: The Confirmation Modal

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:

Lemon Squeezy: Redirects

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://example.com/dashboard"
      }
    },
    "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 customized the “Button text” value in the “Confirmation” modal settings, your custom button text will be used instead.

Lemon Squeezy: Redirect Overlay

Editing receipts

You can customize the copy and the button in the receipt emails sent to your customers. Here’s an example receipt:

Lemon Squeezy: 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 customized when editing products in Lemon Squeezy:

Lemon Squeezy: Customize ReceiptLemon Squeezy: Customize Receipt

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://example.com/dashboard/",
        "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

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

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.


That’s all. By following this guide, you’ll be well-equipped to integrate Lemon Squeezy’s checkout system into your app or product, ensuring a smooth, customizable, and efficient payment process for your customers.


Was this page helpful?