BillingWebhookKit

Deliver a digital download after Lemon Squeezy checkout

A checkout page proves payment intent, not safe fulfillment. Before sending a private ZIP, license file, or download link, verify the signed webhook, confirm the paid state, store an idempotency key, and publish enough checksum evidence for the buyer to trust the archive.

Read the delivery and support policy

Keep the paid archive private

A public GitHub Pages site can host the landing page, free sample, manifest, and status page. It should not host the paid ZIP itself. Publish a manifest with package version, file count, test count, byte size, SHA-256 checksum, and safety flags so buyers can verify the private download after checkout.

Fulfill only after the trusted paid event

For a one-time Lemon Squeezy product, fulfillment usually starts from a signed order_created webhook with a paid state and the expected product or variant. Do not send delivery email from an unsigned client redirect, stale checkout URL, or test-mode event that does not match production.

Signature Verify the exact raw body first

Read the raw request body once, compare the x-signature, then parse JSON and inspect trusted fields.

Paid state Check order, product, and variant

Match the expected live environment, product or variant ID, currency, and payment status before granting access.

Idempotency Store the processed event key

Use provider, event name, object type, and object ID so retries skip duplicate emails and duplicate license grants.

Evidence Attach a fulfillment report

Record checkout URL, order ID, event ID, delivery action, checksum, replay result, and rollback notes.

Use a minimal fulfillment gate

The implementation details vary by stack, but the release rule should stay constant: verify, decide, store, then deliver.

1. Receive Lemon Squeezy webhook
2. Verify x-signature against the exact raw body
3. Parse JSON after signature verification
4. Confirm event_name, paid status, product/variant, and currency
5. Insert processed_event idempotency key
6. If insert succeeds, create the private delivery action
7. If insert already exists, return 2xx without repeating side effects
8. Log secret-free evidence: order, event, checksum, and fulfillment result

Publish buyer-visible verification

A buyer should understand what they receive before paying and how to verify it after downloading. Link the product page to a public delivery/support policy, a package manifest, and a status page. Keep the actual archive private until the production checkout is live.

FAQ

Should a paid digital ZIP be public on GitHub Pages?

No. Keep the paid archive private. Publish only a manifest with file count, version, byte size, checksum, support policy, and safety notes so buyers can verify the download after checkout.

When should fulfillment run after Lemon Squeezy checkout?

Run fulfillment only after a signed webhook confirms a paid order or the equivalent trusted paid state. Store an idempotency key before sending download links, license files, or access grants.

How do I avoid duplicate delivery emails?

Persist a processed event key before side effects. Replayed deliveries should return success without sending another email, license file, private link, or access grant.

Turn fulfillment into a launch checklist

Use the free sample to inspect fake fixtures and local tests. Use the Pro Kit preview when you need copy-ready handlers, duplicate replay tests, package verification notes, and review reports for paid delivery.