Headless / server-side
Your own backend, your own UI, your own auth. The SDK gives you BillingClient and apiKey + identity from @monetize.software/sdk/core (Node / Bun / Deno / Edge / Workers); for any other backend language, the same endpoints are documented as plain HTTPS in the REST API reference.
import { BillingClient } from '@monetize.software/sdk/core';
const billing = new BillingClient({
paywallId: '3',
apiOrigin: 'https://YOUR_DOMAIN',
apiKey: process.env.MONETIZE_API_KEY!
});
// Per request: bind the user from your own auth system
billing.setIdentity({ email: user.email, userId: user.id });
const { url } = await billing.createCheckout({
priceId: 'monthly',
idempotencyKey: crypto.randomUUID()
});
// Redirect user to urlWhen to pick this
- You already have your own auth system (Auth0 / Supabase / Clerk / hand-rolled) — and you don’t want users to sign in twice.
- You sell from a backend that isn’t a JS runtime — Python, Go, PHP, Ruby, .NET, Rust.
- You want server-rendered access checks in Next.js Server Components / Remix loaders / SvelteKit.
- You sync subscription state to your own DB via webhooks, not via in-browser state subscriptions.
What you don’t need
- Custom domain — not strictly required for pure server-to-server. Set explicit
successUrl/errorUrlpercreateCheckoutand you’re set (more). - A frontend in JS — your backend talks to us via REST; your frontend talks to your own backend.
- Our auth —
apiKey+identityis the canonical pattern; no user has to register in monetize.software’s auth system.
What’s in this path
Cross-cutting features in this scenario
Need a frontend too? You don’t have to commit to one path. Plenty of integrations are split — backend handles billing via apiKey + webhooks, and a small PaywallUI modal or React usePaywallAccess() hook lives in the browser for UX. See Browser — drop-in or Browser — custom UI.