Connect onboarding
Keylight Connect is the zero-plumbing path to selling licenses. One OAuth click links your Stripe account, and Keylight handles checkout sessions, webhook delivery, and license minting on your behalf. This page walks through everything you need to do — before clicking, during the OAuth flow, and after — to be ready to take your first payment.
What Connect does for you
Section titled “What Connect does for you”- OAuth link — one click authorizes Keylight to create checkout sessions on your Stripe account.
- Hosted checkout sessions — call
POST /api/:tenantId/checkoutto get a Stripe checkout URL. No Stripe SDK or webhook code on your side. - Automatic license minting —
checkout.session.completedevents arrive at Keylight directly and mint a license for the key type the customer purchased. - Outbound
license.createdwebhook — Keylight POSTs the raw key to a URL you control so you can email it to the customer. Connect-only.
What you’ll pay
Section titled “What you’ll pay”Keylight takes a 0.5% platform fee out of every Stripe Connect transaction, deducted from your payout via Stripe’s application_fee_amount. The customer always pays the full sticker price; the fee is on your side.
| License price | Platform fee |
|---|---|
| $9.99 | 5¢ |
| $29 | 15¢ |
| $49 | 25¢ |
| $99 | 50¢ |
| $199 | $1.00 |
This is separate from your Keylight plan subscription (Starter / Plus / Pro), and separate from Stripe’s own card-processing fees (~2.9% + 30¢, deducted on Stripe’s side).
Before you start
Section titled “Before you start”You need:
- A Stripe account. If you don’t have one, Stripe will offer to create it during the OAuth flow. Account country, business verification, and payout method are configured on Stripe’s side — Keylight has no opinion on any of that.
- A Keylight plan that includes Connect. Free plan accounts see an upgrade prompt instead of the Connect button. Starter, Plus, and Pro plans all include it.
- At least one product with at least one key type. Create these first under Apps → New app → Key Types so the post-Connect price wizard has something to map.
- Prices set on each key type you want to sell. A key type without
priceInCentsandpriceCurrencywon’t get a Stripe price, and any checkout request for that key type will return422.
You don’t use Stripe Payment Links
Section titled “You don’t use Stripe Payment Links”A common point of confusion: with Connect, you do not create or share Stripe Payment Links to sell licenses. Payment Links can’t carry the per-purchase metadata Keylight needs to mint the right license (tenant_id, key_type_id, customer_email) and would bypass the platform fee. The supported flow is your backend → Keylight’s checkout API → one-time Stripe Checkout URL → customer, covered in step 5 below. Keylight handles the Stripe Product and Price for you (auto-created when you set a price on a key type), so the only thing you build on your side is the “Buy” button + the call to POST /api/:tenantId/checkout.
Setting it up
Section titled “Setting it up”1. Click “Connect Stripe”
Section titled “1. Click “Connect Stripe””From your dashboard: Settings → Integrations → Connect Stripe. You’ll be redirected to Stripe’s OAuth authorize page. Sign in to your Stripe account (or create one), confirm the connection, and Stripe will redirect you back.
The OAuth scope is read_write on your Stripe account — Keylight can create products, prices, checkout sessions, and customers, and read account state. You can revoke it any time from Stripe’s dashboard under Connected applications, or from Keylight via Settings → Integrations → Disconnect.
2. Save your Checkout API key
Section titled “2. Save your Checkout API key”Right after the OAuth callback succeeds, Keylight shows your Checkout API key exactly once — a 64-character hex string. Copy it before leaving the page.
3a520045a7d6a2d01eaa60880f5f9a356a66f86a3f7c978d7f85726e29a72485Keylight stores only the SHA-256 hash; the plaintext is never retrievable. If you lose it, generate a new one from Settings → Integrations → Rotate checkout API key (the old hash becomes invalid the moment you rotate).
This key authenticates your sales backend → Keylight, not Keylight → Stripe (that’s already handled by the OAuth grant). It is a server-to-server credential — never put it in client-side code.
3. Finish the price setup wizard (if shown)
Section titled “3. Finish the price setup wizard (if shown)”If any of your key types didn’t have a Stripe price ID at the time of connection, Keylight redirects you to the Stripe price setup wizard. It creates a Stripe Product and Price on your connected account for each priced key type. One submit, done. If all key types already had a price, you skip this step and land back on the integrations tab.
4. (Recommended) Configure your license-delivery webhook
Section titled “4. (Recommended) Configure your license-delivery webhook”Under Settings → Integrations, set the License webhook URL. Keylight POSTs the raw license key to this URL after every successful purchase so you can email it to the customer:
{ "event": "license.created", "tenant_id": "your-tenant", "key": "ACME-XXXX-XXXX-XXXX-XXXX", "product_id": "pro", "key_type_id": "lifetime", "customer_email": "buyer@example.com", "session_id": "cs_test_..."}The request includes an X-Keylight-Signature HMAC header signed with the webhook secret Keylight reveals once at setup. Verify it on your endpoint before trusting the payload.
If you don’t set this URL, licenses still mint correctly, but you’ll need another way to deliver keys to customers (e.g., having them log into your dashboard).
5. Wire your sales backend
Section titled “5. Wire your sales backend”When a customer clicks Buy on your site, your backend calls Keylight:
curl -X POST https://api.keylight.dev/api/your-tenant-id/checkout \ -H "Authorization: Bearer <your-checkout-api-key>" \ -H "Content-Type: application/json" \ -d '{ "product_id": "pro", "key_type_id": "lifetime", "success_url": "https://yourapp.com/thanks", "cancel_url": "https://yourapp.com/pricing", "customer_email": "buyer@example.com" }'Response: { "url": "https://checkout.stripe.com/..." }. Redirect the customer there. Stripe handles the card form; Keylight handles everything after the payment lands.
Rate limit: 20 checkouts per account per minute.
Sandbox vs production
Section titled “Sandbox vs production”When you click Connect Stripe, Keylight asks you whether to connect to Production (your real Stripe account — real charges) or Sandbox (Stripe’s test environment — test cards only, no real money). Use Sandbox to wire up your checkout → webhook → license flow end-to-end before going live.
Once you’re ready, click Switch to live in the Stripe Integration card. Keylight disconnects the sandbox, redirects you through Stripe OAuth for your real account, and walks you through recreating prices on the live side. It’s a single click on your end.
Switching to live is one-way. Once your account is connected in live mode, there is no “switch back to sandbox” button — that’s deliberate. The risk of accidentally leaving production in test mode (and silently failing every purchase) is too high. If you genuinely need to test against Stripe again after going live, disconnect entirely from Settings → Integrations → Disconnect and reconnect via the Sandbox button. You’ll have a fresh sandbox account ID and will need to redo price setup.
When to use manual mode instead
Section titled “When to use manual mode instead”Use Manual webhook mode if you need to:
- Operate a shared Stripe account across many sellers with custom routing logic.
- Customize the checkout session beyond what Keylight’s Connect endpoint exposes (e.g., custom Stripe metadata, Stripe Tax integration with your own configuration).
- Avoid giving Keylight any access to your Stripe account.
In manual mode, you mint checkout sessions yourself and forward checkout.session.completed events to Keylight’s per-tenant webhook endpoint. There’s no platform fee in manual mode (because Keylight isn’t on the payment path), but you write all the Stripe-integration code.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Likely cause |
|---|---|
| ”Stripe Connect requires a Starter, Plus, or Pro plan” after clicking | You’re on Free. Upgrade in Account → Billing, then retry. |
| Stripe authorize page says “Invalid client_id” | Operator-side: the platform’s STRIPE_CONNECT_CLIENT_ID isn’t set or is from the wrong mode. Contact your Keylight operator. |
| Stripe authorize page says “redirect_uri_mismatch” | Operator-side: https://app.keylight.dev/stripe/callback isn’t whitelisted in the platform’s Stripe OAuth settings. Contact your Keylight operator. |
| OAuth completes but returns 500 | Likely the price setup wizard URL — try navigating to /dashboard/<your-tenant-id>/stripe/setup directly. The connection is already saved. |
401 on POST /api/.../checkout | Wrong or missing Checkout API key. Rotate it under Settings → Integrations. |
409 on POST /api/.../checkout | Tenant isn’t connected to Stripe (or was disconnected). Reconnect from the integrations tab. |
422 on POST /api/.../checkout | The key type has no Stripe price set. Set priceInCents on the key type and re-run the setup wizard. |
| Checkout completes but no license arrives | Stripe webhook signature mismatch. Confirm with the operator that STRIPE_CONNECT_WEBHOOK_SECRET matches the active Connect endpoint in Stripe. |
license.created never fires | licenseWebhookUrl not set, or your endpoint returned 5xx. Keylight logs the failure but does not retry — check your server logs. |
| Wanted to switch back to Sandbox after going live — no button shown | Intentional. Disconnect from Settings → Integrations → Disconnect, then click Connect to Sandbox (test) on the empty integration card. You’ll get a fresh sandbox account and will need to redo price setup. |
Related
Section titled “Related”- How payments flow — the full sequence diagram from Buy click to active license.
- Test mode — wire up the flow with test cards before going live.
- Manual webhook mode — DIY alternative if Connect doesn’t fit.
- Billing & plans — the other Stripe account (Keylight billing you for your plan).