Documentation

Stripe integration

The shortest path from "your customer hit pay" to "your customer has a working license" is one Stripe webhook configured against KeyStack. This guide takes about 10 minutes.

What it does

When a Stripe checkout.session.completed event fires:

  1. KeyStack matches the Stripe price/product to a license plan you've configured.
  2. KeyStack dedupes / creates a customer from the Stripe Customer.
  3. KeyStack mints a license key using that plan.
  4. The key is written back as metadata on the Stripe Customer (so you can see it in the Stripe dashboard).
  5. KeyStack emails the customer with their key (using your branding).
  6. KeyStack records an order.created event in the audit log.

Step 1 — Add a Stripe key

KeyStack only needs your restricted key with read access to Customers + Charges + Checkout Sessions + write access to Customer metadata. Generate it from Stripe → Developers → API keys → Create restricted key.

In KeyStack: Settings → Billing → Stripe → Connect. Paste the key.

Step 2 — Map prices to plans

For each Stripe price you sell, choose which KeyStack license plan it should mint:

Stripe PriceKeyStack Plan
price_pro_monthlymonthly-pro
price_pro_yearlyyearly-pro
price_lifetimelifetime-pro

You can change this mapping at any time.

Step 3 — Add the webhook in Stripe

In Stripe → Developers → Webhooks → Add endpoint, set:

  • URL: https://api.keystack.dev/v1/webhooks/stripe/<your-org-slug>
  • Events: checkout.session.completed, customer.subscription.deleted, charge.refunded

KeyStack will reject events whose signature doesn't match the webhook secret you'll see one screen later — paste that secret into Settings → Billing → Stripe → Webhook secret.

Step 4 — Test with a real test-mode purchase

Use a Stripe test card and complete a checkout. Within 1–2 seconds you should see:

  • A new license in the dashboard.
  • An email landing in your inbox (Mailhog locally, real provider in prod).
  • An entry in the Audit log tagged order.created.

If something doesn't show up, head to Settings → Webhooks → Deliveries and inspect the failed deliveries. Click Replay to retry.

Advanced

  • Sub-products: if a single Stripe checkout maps to multiple keys, configure quantity-based plan rules in Settings → Billing → Stripe → Plan rules.
  • Refunds: Stripe charge.refunded events automatically freeze the matching license. You decide whether to revoke or keep frozen for re-activation.
  • Subscription deletion: customer.subscription.deleted events expire the license at the period end.

The hosted Stripe → KeyStack webhook described above is on our roadmap. For today the cleanest pattern is:

  1. Add an endpoint on your own backend that receives Stripe's checkout.session.completed.
  2. Verify Stripe's signature.
  3. Look up the corresponding KeyStack plan code from the price.id.
  4. Call POST /v1/issue on KeyStack with the customer's email + plan code.
  5. Email the customer the returned license key.

Less infra to share, no secret-of-a-secret, and you can run any custom logic before issuing (e.g. fraud checks, gift codes, bundling).