A B2B SaaS subscription, end to end
The complete integration for a typical B2B SaaS. Checkout signup, recurring billing, grace handling, cancellation. Real code that ships.
This is what a B2B SaaS subscription billing integration actually looks like. Not pseudo-code; you can copy-paste this into a Next.js app and it works.
The scenario: you're shipping a SaaS product called Acme. You have a Pro plan at $99/month (well, 99 USDC/month). Customers sign up, pay monthly, and you want to know when they're churning before it becomes a problem.
What we're building
Three routes plus a webhook handler:
/pricing, shows the plan; has a "Subscribe" button./api/checkout/subscribe, creates the subscription plan checkout URL./api/webhooks/strimz, receives the events that matter./thanks?session=…, the post-signup success page.
We'll skip a bunch of standard Next.js boilerplate (Tailwind setup, env config, etc.) and focus on the Strimz parts.
One-time setup
In your dashboard, create the plan:
Save the plan id in your env: STRIMZ_PRO_PLAN_ID=plan_acme_pro_…. You'll use it in the checkout route.
Also create a webhook endpoint, subscribed to the events you care about:
The pricing page
A "Subscribe" button. When clicked, POSTs to the checkout route and redirects to the URL the route returns.
The checkout route
For a basic flow, that's literally it. The plan id maps to a Strimz-hosted page that handles wallet connect, EIP-2612 permit signing, and the first-cycle charge. You don't need to call the SDK for the signup itself.
If you want to pass metadata or pre-fill the payer's email, you'd create a custom subscription session via the API. We're keeping this minimal; for most cases the plan URL is enough.
The webhook handler
This is where the meaningful logic lives. The events you care about are subscription state transitions.
The actual handlers. What your business logic does for each:
The success page
After the subscription enrolment confirms, Strimz redirects to the plan's successUrl. By default the plan doesn't have one configured; you can set it per-plan in the dashboard or override at the subscription create level.
If you set https://acme.com/thanks?session={CHECKOUT_SESSION_ID} as the success URL, the page lands with the session id in the query.
Don't grant the access here. The webhook handler does that. The success page is purely UI; the entitlement is granted asynchronously when subscription.created lands.
If you want the success page to wait for the entitlement (so customers don't see a "trial active" page before your DB knows about them), poll your own DB for a few seconds, then show the welcome state. The webhook usually arrives in under a second, but it can be a beat slower under load.
What's not in this recipe
Cancellation flow. See Self-serve cancel.
The customer-facing dashboard showing subscription state. Standard CRUD; nothing Strimz-specific.
Failed-charge recovery UI. The email above is the minimum; for a smoother UX you'd build a "Top up your wallet" page in your product and link the customer to it.
Plans-by-tier (Pro + Team + Enterprise). Create one plan per tier; the rest of the integration is the same.
What's also not in this recipe
The "what if Strimz is down" failure mode. The honest answer is: if Strimz is down, your checkout breaks. Your existing customers' renewals also won't fire during the outage (they'll fire when we come back). You should subscribe to our status page and treat sustained outages as a customer-comms event.
This is the same trade-off any third-party billing system has. The argument for Strimz is that we're cheaper than Stripe and our customers are paying in dollars they hold in stablecoins anyway. The argument against is the dependency. Make the call that's right for your business.
