Stripe integration

Connect your own Stripe account and SoftLicense issues, renews, suspends and revokes licenses from your checkouts and subscriptions. SoftLicense only ever needs a restricted read key, never a secret key.

Setup

  1. In Stripe, go to Developers → Webhooks and add a destination pointing at the workspace URL shown in Integrations → Stripe. Select these events: checkout.session.completed invoice.paid customer.subscription.updated customer.subscription.deleted charge.refunded
  2. Create a restricted API key with read access to Checkout Sessions, Subscriptions, Invoices, Customers, Charges.
  3. Paste the webhook signing secret and the restricted key into Integrations → Stripe.
  4. Map each Stripe price to a SoftLicense policy.

What happens

Stripe eventSoftLicense action
checkout.session.completedLooks up the session's line items. For each mapped price, creates (or finds) the customer by email and issues one license per quantity. Subscriptions expire at the billing period end plus the policy grace. The key is emailed if license emails are enabled.
invoice.paidExtends the license tied to the subscription to the new period end and reinstates it if it was suspended.
customer.subscription.updatedpast_due, unpaid, paused → suspend. active, trialing → reinstate and refresh the expiry.
customer.subscription.deletedPer mapping: revoke immediately or let the license expire at period end.
charge.refundedPer mapping: revoke or ignore. Only full refunds count.

Reliability

  • Events are acknowledged immediately, stored with their id (duplicates are dropped) and processed in the background. Every event and its outcome is listed on the Stripe page with a replay button.
  • SoftLicense re-fetches sessions, subscriptions and invoices with your key rather than trusting the event body, and handles both pre- and post-2025 Stripe API shapes.
  • Unmapped prices are reported as ignored with a one-click “map this price” shortcut.

Testing locally

stripe listen --forward-to localhost:3000/api/integrations/stripe/<workspace-id>
stripe trigger checkout.session.completed

Use the whsec_… printed by stripe listen as the signing secret and an rk_test_… restricted key.