Skip to content

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.

  • OAuth link — one click authorizes Keylight to create checkout sessions on your Stripe account.
  • Hosted checkout sessions — call POST /api/:tenantId/checkout to get a Stripe checkout URL. No Stripe SDK or webhook code on your side.
  • Automatic license minting — checkout.session.completed events arrive at Keylight directly and mint a license for the key type the customer purchased.
  • Outbound license.created webhook — Keylight POSTs the raw key to a URL you control so you can email it to the customer. Connect-only.

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 pricePlatform fee
$9.995¢
$2915¢
$4925¢
$9950¢
$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).

You need:

  1. 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.
  2. Any Keylight plan. Stripe Connect is available on Free as well as paid plans; payments are not paywalled.
  3. 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.
  4. Prices set on each key type you want to sell. A key type without priceInCents and priceCurrency won’t get a Stripe price, and any checkout request for that key type will return 422.

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.

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.

Right after your first live OAuth connection succeeds, Keylight shows your Checkout API key exactly once — a 64-character hex string. Copy it before leaving the page.

3a520045a7d6a2d01eaa60880f5f9a356a66f86a3f7c978d7f85726e29a72485

Keylight 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).

Reconnecting Stripe or switching to a different connected account preserves the existing Checkout API key. It does not rotate or reveal the credential again; use the explicit rotation action when you intend to replace it.

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.

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).

When a customer clicks Buy on your site, your backend calls Keylight:

Terminal window
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.

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.

The Sandbox option appears only when the Keylight operator has configured the complete test Connect stack: the test client ID, test platform secret key, and test webhook signing secret. If Sandbox is absent, contact the operator; a partially configured test environment is deliberately not offered. Production Connect and manual Stripe continue to work independently.

Once you’re ready, click Switch to live in the Stripe Integration card. Keylight redirects you through OAuth for your live account and walks you through creating live prices. Your sandbox connection and test prices remain available, so you can continue rehearsing purchases without disturbing production.

Live and sandbox are separate slots. Disconnecting sandbox removes only its test accounts and catalogs; live checkout remains connected. A full disconnect removes both environments and any per-app Connect accounts, but preserves your Checkout API key for a later reconnect. Rotate that key separately if it may have been exposed.

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.

For operators: subscribe both live and test Connect webhook endpoints to charge.dispute.closed, alongside checkout, refund, renewal, and deauthorization events. Only terminal lost disputes revoke access; open and won disputes preserve it.

SymptomLikely cause
”Stripe Connect requires a Starter, Plus, or Pro plan” after clickingYou’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 500Likely the price setup wizard URL — try navigating to /dashboard/<your-tenant-id>/stripe/setup directly. The connection is already saved.
401 on POST /api/.../checkoutWrong or missing Checkout API key. Rotate it under Settings → Integrations.
409 on POST /api/.../checkoutTenant isn’t connected to Stripe (or was disconnected). Reconnect from the integrations tab.
422 on POST /api/.../checkoutThe key type has no Stripe price set. Set priceInCents on the key type and re-run the setup wizard.
Checkout completes but no license arrivesStripe webhook signature mismatch. Confirm with the operator that STRIPE_CONNECT_WEBHOOK_SECRET matches the active Connect endpoint in Stripe.
license.created never fireslicenseWebhookUrl not set, or your endpoint returned 5xx. Keylight logs the failure but does not retry — check your server logs.
Sandbox checkout is unavailable after going liveConfirm the Sandbox slot is still connected and that the app has a Sandbox price under Prices. Live and Sandbox connections coexist.