BillingWebhookKit

Webhook entitlement decision matrix

Payment webhook bugs often happen after signature verification, when the handler decides whether to grant access, extend a renewal, deliver a license, schedule cancellation, or ignore an event.

Open the free matrix builder

Decision matrix

Event State Handler decision Write model Regression test
order_createdpaidGrant one-time accesspurchase entitlement + processed eventPaid order grants exactly once under duplicate replay.
order_createdpending, failed, refundedHold or revoke accessorder audit record, no active entitlementUnpaid or refunded order does not grant access.
license_key_createdcreatedDeliver license keylicense entitlement with redacted key referenceLicense delivery is idempotent and masks the key in logs.
subscription_createdactive or trialingActivate subscriptionsubscription entitlement + current periodSubscription create maps customer to the correct plan.
subscription_payment_successpaidExtend renewalinvoice payment + renewed entitlement windowRetrying the same invoice does not extend twice.
subscription_cancelledends_at presentSchedule cancellationsubscription status + scheduled access endCancellation keeps access until the configured end date.
payment_failedpast_due or failedPause risky side effectsdunning state, no destructive deleteFailed payment does not erase entitlement history.
unknown_eventunmappedQuarantine and acknowledgeraw event sample + alertUnknown events are stored for review and do not run side effects.

Release rule

Verify the signature first, persist an idempotency key, then run the entitlement decision once. Duplicate deliveries should return success without repeating the side effect.

What to test in CI

Every row should have a fixture and a duplicate replay test. The most important checks are paid order grants once, unpaid order grants nothing, renewal extends once, cancellation respects the end date, and unknown events are quarantined without customer-facing side effects.

FAQ

Should a webhook grant access before signature verification?

No. Verify the raw-body signature first, persist a stable idempotency key, then run the entitlement decision exactly once.

Should duplicate payment webhooks extend subscriptions twice?

No. Duplicate deliveries should return success after confirming the idempotency key already ran, without repeating license delivery, access grants, emails, or renewal extension.

Use the free sample before wiring production checkout

Download a public sample pack with fake Lemon Squeezy fixtures, signature tests, contract checks, duplicate replay tests, and CI skeletons. The Pro Kit preview shows the full paid package structure without exposing the private archive.