Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.authforge.cc/llms.txt

Use this file to discover all available pages before exploring further.

The supported way to sell licenses through Lemon Squeezy is Commerce: paste your signing secret in the dashboard, map variants to license templates, and AuthForge verifies webhooks, deduplicates events, issues keys, and can email buyers for you. This guide walks through that setup. If you instead need to host your own webhook handler (custom checkout flows, bundles, or anything Commerce does not cover), use the Custom integration guide and call the Developer API directly when an order clears.

Prerequisites

  • An AuthForge account with an app created
  • A Lemon Squeezy store with at least one product + variant

How it maps to AuthForge

Lemon Squeezy goes through the same Commerce pipeline as Stripe; ingress verifies signatures, inserts into the inbound event ledger, enqueues onto SQS, and a worker creates the license. The only differences are the signature header, the event names, and the identifier Lemon Squeezy assigns to each price.
Lemon Squeezy eventCommerce action
order_createdCreate license
subscription_payment_successExtend license on renewal
subscription_cancelledRevoke license
subscription_expiredRevoke license
order_refundedRevoke license
subscription_payment_refundedRevoke license
AuthForge matches incoming events to a mapping by the Lemon Squeezy variant ID (the equivalent of a Stripe price). Every variant you sell that should issue a license needs one mapping row.

Setup

Commerce lives under Dashboard → Commerce and is account-global. You map Lemon Squeezy variants to specific apps inside the mappings table.

1. Create an AuthForge app

Commerce delivers licenses into an app. If you don’t have one yet, open Dashboard → Applications → New application first, then come back.

2. Connect your Lemon Squeezy store

AuthForge stores both secrets encrypted in DynamoDB under a KMS key we never export.

2a. Register the webhook endpoint in Lemon Squeezy

On the Commerce page, AuthForge shows a webhook URL of the form:
https://api.authforge.cc/billing/webhook/lemon/<your-user-id>
Copy it. In the Lemon Squeezy dashboard:
  1. Go to Settings → Webhooks → New webhook.
  2. Paste the URL from AuthForge into Callback URL.
  3. Enter a signing secret (any random high-entropy string; you’ll paste the same value into AuthForge in the next step).
  4. Select the events AuthForge should receive:
    • order_created; required for purchases
    • subscription_payment_success; subscription renewals
    • subscription_cancelled; subscription cancellations
    • subscription_expired; subscription lapsing
    • order_refunded; refunds
    • subscription_payment_refunded; subscription refunds
  5. Save.

2b. Paste the signing secret

Back on the AuthForge Commerce page, paste the same signing secret into the Lemon Squeezy signing secret field. In the Lemon Squeezy dashboard, go to Settings → API → Create API key. Paste the token into the AuthForge Lemon Squeezy API key field. The API key is a fallback: Lemon Squeezy usually includes variant and product IDs on webhook payloads, but if an event ever lands without them (rare, but possible for some subscription lifecycle events), AuthForge uses this key to fetch the order/subscription and look them up. Without it, events that lack a variant are logged as skipped · api_key_required_for_line_items and no license is issued. Click Connect Lemon Squeezy. You should now see a green Connected chip next to the Lemon Squeezy section.

3. Map variants to license templates

Still on the Commerce page, under Product mappings, click New mapping:
  1. Pick Lemon Squeezy as the provider (only visible when you have more than one provider connected).
  2. Pick the AuthForge app to deliver licenses into.
  3. Paste the Lemon Squeezy variant ID. You can find it in Lemon Squeezy under Products → open a product → Variants: each variant has a numeric ID.
  4. Choose What kind of product is this?:
    • One-time purchase (lifetime or fixed length): leave Access length blank for a perpetual key, or enter days for a fixed-term license from a single payment. Renewal invoices do not extend the license—use a non-recurring variant for true one-time sales.
    • Subscription; auto-renews and extends the license: set Billing period to one billing cycle (30 for monthly, 365 for yearly). The same mapping covers initial purchase, every renewal, and cancellations/refunds.
    • Add-on; extends an existing customer’s license: for top-up SKUs only. Set days to the number of days to add.
    • Revocation product: almost never needed. Cancel/refund/dispute events already revoke automatically through the main mapping.
  5. Set the duration in days (blank = lifetime) and HWID slots per key.
  6. Optionally add license variables that get stamped onto every license this mapping creates. Your SDK exposes them as licenseVariables after the user logs in; use this for plan tier, feature flags, seat counts, etc.
  7. Leave Respect quantity on unless you always want exactly one key per order regardless of what the buyer actually purchased.
Save. Everything else; renewals, cancellations, refunds; flows through the same mapping automatically. One mapping per variant ID is enough: AuthForge stamps the Lemon Squeezy customer and subscription IDs on the license at create time so future renewal and cancellation events target the correct license, even when one customer holds multiple subscriptions.

Testing the integration

  1. In the Lemon Squeezy dashboard, open your webhook and click Send test event with order_created.
  2. Refresh Dashboard → Commerce → Recent events. You should see the event with provider lemon and state processed (or skipped with a clear reason if something is misconfigured).
  3. Check the relevant app’s Licenses tab; the new key should be there, with the buyer’s email attached and ready for the self-service portal.
Common failure states and what they mean:
  • skipped · no_mapping_for_price; the variant ID on the event does not match any mapping for this merchant. Add a mapping or correct the one you have.
  • skipped · api_key_required_for_line_items; the payload lacked a variant ID and no Lemon Squeezy API key is stored. Save an API key and Lemon Squeezy will redeliver the event on its next retry, or send a fresh test event.
  • failed; an unexpected error during license creation. The Commerce worker bumps retryCount and SQS will redeliver. Persistent failures end up in the DLQ (alarmed).

Next steps