Lemon Squeezy uses webhooks to notify your application when an event happens in your store. Webhooks are particularly useful for asynchronous events like when a license key is created or when a subscription expires.
About webhooks
Creating webhooks
Webhooks require three elements to function:
A callback URL - This is the URL that Lemon Squeezy will send a POST request to when an event is triggered.
A signing secret - This is a secret (usually a random string) between 6 and 40 characters that will be used to sign each request. You should validate against this secret on each incoming webhook so you can verify that the request came from Lemon Squeezy.
A list of events - This is a list of events that will trigger this webhook.
Recent webhooks sent from your store are logged on the webhooks settings page. You can see which events have been sent, the full payloads of each request and also resend webhooks if you need to.
Testing webhooks
When in test mode, you can set up and test a full webhook integration.
Lemon Squeezy will send webhooks for each event that happens in your test mode store just like it would in live mode.
For more manual testing, you can also simulate webhook events for any test mode subscriptions. Simply choose a subscription event you'd like to receive a webhook for and send it manually to your app from your Lemon Squeezy admin.
Test and live mode webhooks are kept separate within your account, meaning a test mode webhook will only be triggered for test mode data and vice versa.
Tip: To make it easier to check the data that is sent via webhooks, you can use a tool like webhook.site.
Webhook requests
When a webhook event occurs in Lemon Squeezy, a POST request will be sent to the configured webhook URL.
Return a 200 response to show that the webhook was successfully captured. If the response status is anything else, the webhook will be retried up to three more times using an exponential backoff strategy (e.g. 5 secs, 25 secs, 125 secs) at which point the request will be considered failed and will no longer be retried.
The webhook body will be a JSON:API resource object that relates to the event (e.g. “order” events will be sent an order object, “subscription” events will be sent a subscription object, etc).
The request headers will include:
A Content-Type header set to application/json.
An X-Event-Name header with the name of the event that triggered the webhook.
An X-Signature header containing the request signature. Read on for information about verifying signatures.
If a webhook is configured to send a request to an HTTPS URL, the SSL certificate of the URL will be verified before sending the request.
If you have added custom data to your checkout, you will find a custom_data object inside the meta field for all Order, Subscription and License key related events.
To ensure that webhook requests are coming from Lemon Squeezy, you will be asked to enter a signing secret when creating your webhook. The secret can be anything you want but is normally a random string between 6 and 40 characters in length.
When the webhook request is sent, Lemon Squeezy will use the signing secret to generate a hash of the payload and send the hash in the X-Signature header of the request. You can use the same secret to calculate the hash in your application and check it against the request signature to verify that the hashes match.
Examples
Lemon Squeezy uses a HMAC hex digest to compute the hash. Calculating the hash is different in each programming language.
Occurs when a subscription's data is changed or updated. This event can be used as a "catch-all" to make sure you always have access to the latest subscription data.
Occurs when a subscription is cancelled manually by the customer or store owner. The subscription enters a "grace period" until the next billing date, when it will expire. It is possible for the subscription to be resumed during this period.
Occurs when a subscription has ended after being previously cancelled, or once dunning has been completed for past_due subscriptions. You can manage how long to wait before the system marks deliquent subscriptions as expired. More info
Occurs when a subscription has a successful payment after a failed payment. A subscription_payment_success event will always be sent alongside a subscription_payment_recovered event.
We suggest subscribing to these events as a minimum so that your application will have the latest data.
If you sell one-off products:
order_created - This event lets you know when new orders are placed.
If you sell subscriptions:
subscription_created - This event lets you know when new subscriptions are created.
subscription_payment_success - This event lets you save billing histories for your subscribing customers.
subscription_updated - This event keeps your application up-to-date with all changes to a subscription.
Events sent during a subscription's lifecycle
Different events will be triggered at various events during a subscription's life.
You can see that subscription_updated is fired at every event after the initial payment. In most cases, subscribing to more granluar events like subscription_resumed or subscription_expired events as well as subscription_updated is not necessary.
Example 1: A typical flow of events
Initial order is placed:
order_created
subscription_created
subscription_payment_success
license_key_created (if licenses are enabled on the subscription product)
Successful renewal payment:
subscription_payment_success
subscription_updated
Payment method updated by customer:
subscription_updated
Subscription manually cancelled by the customer or store owner:
subscription_cancelled
subscription_updated
Subscription expires when the cancelled subscription reaches the ends_at date:
subscription_expired
subscription_updated
Example 2: With payment failures
Initial order is placed:
order_created
subscription_created
subscription_payment_success
license_key_created (if licenses are enabled on the subscription product)
Below are a few examples of webhook event data. You will notice that the data in the payload is one of the objects listed above, plus some meta and the usual relationships and links.