How payments flow
Whichever Stripe mode you use, the sequence is the same: someone pays, Stripe fires a webhook, Keylight mints a license, your customer gets the key.
This page walks through each step for the Connect path (the recommended one). Manual webhook mode follows the same shape but with your own checkout + webhook plumbing in front.
The path
Section titled “The path”Step 1 - your server creates a checkout session
Section titled “Step 1 - your server creates a checkout session”You call POST /api/:tenantId/checkout with a Bearer token (the Checkout API Key, separate from the SDK key) and a JSON body:
{ "product_id": "pro", "key_type_id": "lifetime", "success_url": "https://yourapp.com/thanks", "cancel_url": "https://yourapp.com/pricing", "customer_email": "buyer@example.com"}Keylight:
- Authenticates your Checkout API key (SHA-256 compare against
tenant.checkoutApiKeyHash). - Checks your account’s lifecycle state allows new licenses.
- Looks up the key type’s
stripePriceId(created when you set a price on that key type). - Creates a Stripe checkout session on your connected account with a 0.5% platform fee deducted from your payout (charged via Stripe’s
application_fee_amount).
Returns { url } - redirect the customer there.
Rate limit: 20 checkouts per account per minute. Exceeding returns 429.
Step 2 - customer pays on Stripe
Section titled “Step 2 - customer pays on Stripe”Normal Stripe checkout. Nothing Keylight-specific happens here. On success, Stripe redirects the customer to success_url and fires a checkout.session.completed event on the platform’s Connect webhook endpoint.
Step 3 - Keylight’s Connect webhook mints the license
Section titled “Step 3 - Keylight’s Connect webhook mints the license”Stripe posts the event to POST /api/stripe/webhook/connect. Keylight:
- Verifies the
Stripe-Signatureheader againstSTRIPE_CONNECT_WEBHOOK_SECRET. - Looks up your account by
event.account(the connected Stripe account ID). - Reads
session.metadata.product_idto pick the product. - Mints a fresh license with the correct key type’s activation limit and duration.
- Stores the
LicenseRecordin Postgres + Durable Object.
If you have configured a License Webhook URL in Settings → Integrations, Keylight also fires an outbound license.created webhook to that URL with the raw key in the payload:
{ "id": "5d3c7e02-2b78-4f1a-b3a4-7d2f6c2e8b9d", "created": 1714669200, "version": "2026-05-01", "event": "license.created", "tenant_id": "acme", "key": "ACME-XXXX-XXXX-XXXX-XXXX", "product_id": "pro", "key_type_id": "lifetime", "customer_email": "buyer@example.com", "session_id": "cs_live_..."}Your receiver verifies the X-Keylight-Signature HMAC header using the webhook secret Keylight showed you at setup. Once verified, you email the key to the customer (or whatever else your post-purchase flow does).
See the full Webhooks overview for signature-verification snippets in Node/Python/Go, retry behavior, the deliveries log, and the full list of events Keylight can send (activation, deactivation, expiry, refund, renewal).
Step 4 - customer activates
Section titled “Step 4 - customer activates”The customer launches your app, pastes the key, and the SDK calls /activate. First activation consumes one slot; subsequent launches re-use the cached Ed25519 lease. See How it works for the SDK’s side of the handshake.
What can go wrong
Section titled “What can go wrong”| Symptom | Likely cause |
|---|---|
401 on /api/checkout | Wrong or missing Checkout API key |
409 on /api/checkout | Tenant not connected to Stripe; reconnect via Connect |
422 on /api/checkout | Key type has no Stripe price set; fix in Products → Key types |
checkout.session.completed fired but no license | Webhook signature failed; check STRIPE_CONNECT_WEBHOOK_SECRET wasn’t rotated |
license.created never arrives | License Webhook URL isn’t configured, or every retry failed — check Dashboard → Webhooks for the delivery row and its last_status. Keylight retries 1m/5m/30m, then gives up. |
Related
Section titled “Related”- Connect onboarding - the one-click OAuth link.
- Manual webhook mode - DIY alternative.
- Billing & plans - the other Stripe account (Keylight billing you).