Embedded checkout
When a redirect doesn't fit. Render Strimz checkout inside your own page with the React SDK. Strimz still owns the wallet flow, the relayer, and the on-chain submission.
Hosted is the path most merchants take. Embedded is the answer when a redirect doesn't fit, usually because the checkout is one step inside a multi-step product flow that you don't want to break.
With embedded, the checkout renders inside your page instead of on a separate one. Strimz still owns the wallet flow, the relayer, and the on-chain submission. You own the page around it.
When to actually pick embedded
A few cases where it makes sense:
You have a multi-step checkout and payment is one step in the middle. A redirect would drop the customer out of your flow and back in again.
You have a specific UI requirement. Inline forms, side-panel checkouts, modal-based flows. That doesn't map onto a redirect. (Most "I want a different layout" cases actually want hosted with a slightly different framing; embedded is for when the layout genuinely can't redirect.)
The embedded checkout is the hosted checkout in a frame, so the payer still sees the Strimz checkout UI and connects their wallet inside it.
If none of those apply, stay on hosted. You'll ship faster and have less to maintain.
Install
The two packages: @strimz/sdk gives your server StrimzClient, which takes your secret key and must never run in the browser. @strimz/sdk-react is the browser layer: a provider, hooks, and components that use a publishable key. It has no TanStack Query dependency.
Server-side: create the session
Same as hosted. The session doesn't care where the payer is going to sign.
Client-side: mount the provider
StrimzProvider carries the publishable key. It is the only key the browser ever sees.
Render <Providers> around your app in your root layout. The publishable key is browser-safe. See API keys for what it can and can't authorize.
Client-side: embed the checkout
StrimzCheckoutEmbed renders the Strimz checkout for a session inline, in an iframe on your page. The payer connects a wallet and signs inside the frame, so you don't wire a wallet stack yourself.
The embedded checkout never navigates, and it ignores the session's successUrl and cancelUrl. When the payer finishes, it tells your page: onSuccess gets the transaction hash, onCancel fires when they press Cancel, and onError gets a StrimzCheckoutError whose code is load_failed, merchant_not_ready or payment_reverted. A failure the payer can retry, such as a rejected signature, stays inside the frame. These callbacks need @strimz/sdk-react 0.3.0 or later.
The embedded checkout follows the payer's system light or dark preference and has no theme toggle of its own. To match your page, pass theme="light" or theme="dark":
useStrimzSession reads the session with the publishable key and polls until it reaches a terminal state (confirmed, failed, expired, or cancelled), so the panel switches to its success state on its own.
If you'd rather open the checkout in a popup from your own button, use <StrimzPayButton sessionId={sessionId} /> or the useStrimzCheckout() hook, which returns { open(sessionId), close(), status }.
What you still own
The surrounding UI. Where the checkout sits, what the page says around it, and what you show before and after payment.
The success UI. useStrimzSession gives you the session and its status; what you do with it is up to you. Most merchants show a confirmation screen and link to their next step.
Fulfilment. Grant access or ship the order from your webhook handler, not from the browser. The browser can be closed or tampered with; the signed webhook can't.
What Strimz still owns
The wallet flow. Wallet connect, the typed-data prompts, and the chain switch all happen inside the checkout.
The relayer. We pay the gas. We broadcast.
The indexer. We watch for the on-chain confirmation and project it into the session.
The webhook. Once the indexer confirms, we fire payment.completed to whatever endpoints you've subscribed.
The state machine. The session statuses are driven entirely by Strimz's backend; the React SDK reads them but doesn't write them.
Subscriptions, briefly
For recurring billing, use <StrimzSubscribeButton planId /> or <StrimzSubscriptionEmbed planId />. They open the hosted plan checkout (/sub/<planId>) and report onSuccess({ subscriptionId, txHash }). See Subscription plans in the React SDK.
See @strimz/sdk-react for the full component and hook surface.

