Billing Events (Lemon Squeezy)
Synapse receives subscription lifecycle events from Lemon Squeezy via webhooks. These events update your workspace's plan, limits, and billing status.
Webhook Endpoint
This endpoint is secured by an HMAC-SHA256 signature in the x-signature header. See Signature Verification for details.
Events
| Event | Description | Synapse Action |
|---|---|---|
subscription_created | New subscription created after checkout | Update plan, set limits, store LS customer/subscription IDs, set renewal date |
subscription_updated | Plan changed or renewal date updated | Update plan and limits if plan changed, update renewal date |
subscription_cancelled | Subscription cancelled by owner | Logged only -- access continues until current period ends |
subscription_expired | Subscription period ended after cancellation | Downgrade to free plan, clear LS subscription fields, reset limits |
subscription_payment_failed | Recurring payment attempt failed | Logged as warning. Lemon Squeezy handles retry/dunning automatically. |
Payload Schema
Lemon Squeezy webhooks use a standard envelope with meta and data sections:
Key Fields
| Field | Location | Description |
|---|---|---|
meta.event_name | Envelope | The event type identifier |
meta.custom_data.tenant_id | Envelope | Synapse workspace UUID (set at checkout time) |
meta.custom_data.plan_id | Envelope | Plan identifier (e.g., starter, growth) |
data.id | Data | Lemon Squeezy subscription ID |
data.attributes.customer_id | Data | Lemon Squeezy customer ID |
data.attributes.status | Data | Subscription status (active, cancelled, expired, etc.) |
data.attributes.renews_at | Data | Next renewal date (ISO 8601) |
data.attributes.ends_at | Data | Subscription end date (set on cancellation) |
Event Details
subscription_created
Fired when a workspace owner completes checkout and payment succeeds.
Synapse action:
tenants.planupdated to the purchased plan (e.g.,growth)- Plan limits synced:
monthly_email_limit,contacts_limit,monthly_events_limit,data_retention_days tenants.ls_customer_idandtenants.ls_subscription_idstoredtenants.ls_current_period_endset fromrenews_at- Workspace status set to
active
subscription_updated
Fired when a subscription is modified (plan change, renewal date update).
Synapse action:
- If the plan changed and status is
active, updatetenants.planand sync limits - Update
tenants.ls_current_period_endfromrenews_at
subscription_cancelled
Fired when the workspace owner cancels their subscription.
Synapse action:
- Logged only. The workspace retains full access until the current billing period ends.
- When the period ends, Lemon Squeezy fires
subscription_expired.
Cancellation does not immediately downgrade the workspace. The owner keeps their current plan until the period end date shown in the billing page.
subscription_expired
Fired when a cancelled subscription's billing period ends.
Synapse action:
tenants.plandowngraded tofree- Limits reset to free-tier values
tenants.ls_subscription_idandtenants.ls_current_period_endclearedtenants.ls_customer_idpreserved (for future checkouts)
subscription_payment_failed
Fired when a recurring payment attempt fails.
Synapse action:
- Logged as a warning. No plan or limit changes.
- Lemon Squeezy handles automatic retry and dunning (payment failure emails to the customer).
Retry Behavior
The webhook handler always returns 200 OK with {"received": true}. This prevents Lemon Squeezy from retrying indefinitely. Internal processing failures are logged and alerted via Sentry.
Signature Verification
Lemon Squeezy signs every webhook request with an HMAC-SHA256 signature in the x-signature header. The signature is computed over the raw request body using your webhook secret.
See Signature Verification for more examples and best practices.