Create sessions on your server
Your secret key stays on your server. Create the payment session there, send the session id to the browser, and open checkout from the browser with a publishable key.
A payment session sets what the payer is charged: the amount, the currency, and the metadata you read back in your webhook. Only your server should decide that, so only your server creates sessions, with your secret key (sk_test_… or sk_live_…).
The browser never sees the secret key. It asks your server for a session, gets back the session id, and opens checkout for that id with your publishable key (pk_test_… or pk_live_…).
Why the secret key stays on the server
Anything in a browser bundle can be read by anyone who loads your page. A secret key there lets anyone create sessions, issue refunds, and read your customers under your account.
To stop that early, StrimzClient from @strimz/sdk refuses to start in a browser. Constructing it in a page, a web worker, an Electron renderer, or a React Native app throws StrimzAuthenticationError with code secret_key_in_browser. See @strimz/sdk for how the runtime is detected.
The Strimz API backs this up: routes that take a secret key only answer browsers on the Strimz dashboard's own origin. A browser call from your site to POST /v1/payment-sessions fails its CORS check before it reaches Strimz.
The flow
- The payer clicks Pay on your page.
- Your page calls your own server, for example
POST /api/checkout. - Your server calls
strimz.paymentSessions.create(...)with your secret key and returns{ id }. - Your page opens checkout for that id with
useStrimzCheckout().open(id). - Strimz sends
payment.completedto your webhook when the payment confirms. Fulfil the order there.
Server: Next.js route handler
Route handlers run on the server, so StrimzClient works here, on the Node.js and Edge runtimes alike. Keep the key in a variable without the NEXT_PUBLIC_ prefix so Next.js never inlines it into the browser bundle.
Set the amount on the server from your own catalogue. Do not take it from the request body, which the payer controls.
Server: Express
Browser: open checkout
Wrap your app in StrimzProvider with your publishable key, as shown in @strimz/sdk-react. Then:
To show the payment inline instead of in a popup, pass the id to <StrimzCheckoutEmbed sessionId={id} />. See Embedded checkout.
Seeing a CORS error?
If your browser console shows a CORS error from api.strimz.finance on a call such as POST /v1/payment-sessions, the API is working as intended. That route takes a secret key, and Strimz refuses it from any website other than the Strimz dashboard so that secret keys cannot be used from browser code.
Move the call into a server route like the ones above and have the browser call your route instead. The routes a browser may call from any origin are listed in Calling Strimz from a browser.

