CimplifyCheckout (React)
Mount the Cimplify checkout iframe from React. This is the recommended embedded checkout path for agent-built storefronts and custom merchant sites.
<CimplifyCheckout> gives the merchant a complete checkout on their own page:
contact capture, Cimplify Link verification, saved details, address, payment,
provider authorization, submit, recovery, and status updates. The SDK creates
the checkout iframe and handles the message bridge, OAuth hand-off, checkout
processing, aborts, and completion events.
Under the iframe, checkout mints a durable purchase intent, renders one
immutable terms revision, and confirms that exact revision. A material or
money change emits reviewing_terms; ctx.replacement_terms and
ctx.terms_deltas let the host mirror the review state without guessing from
cart totals.
For most storefronts, this is the embedded checkout integration to use.
Required Auth Setup
Checkout uses the storefront's OAuth client when a shopper chooses to use Cimplify saved details. Add the route handlers from Sign in with Cimplify, then expose these browser env vars:
NEXT_PUBLIC_CIMPLIFY_CLIENT_ID=cim_client_…
NEXT_PUBLIC_CIMPLIFY_REDIRECT_URI=https://your-store.com/auth/callbackThese values let checkout verify the shopper through auth.cimplify.io and
return to the merchant page.
Example
import { CimplifyClient } from "@cimplify/sdk";
import { CimplifyCheckout } from "@cimplify/sdk/react";
const client = new CimplifyClient({
publicKey: process.env.NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY!,
credentials: "include",
});
export function CheckoutScreen({ cartId }: { cartId: string }) {
return (
<CimplifyCheckout
client={client}
cartId={cartId}
orderTypes={["delivery", "pickup"]}
defaultOrderType="delivery"
submitLabel="Pay now"
appearance={{
theme: "light",
variables: { primaryColor: "#059669", borderRadius: "0.85rem" },
}}
onStatusChange={(status, ctx) => {
console.log(status, ctx.display_text);
}}
onComplete={(result) => {
if (result.success) {
window.location.assign(`/orders/${result.order!.id}`);
}
}}
onError={(err) => console.error(err.code, err.message)}
/>
);
}Props
| Prop | Type | Required | Notes |
|---|---|---|---|
client | CimplifyClient | yes | Same client you use elsewhere; the checkout iframe inherits the public key. |
businessId | string | no | Auto-resolved from the public key when omitted. |
cartId | string | no | Auto-resolved via client.cart.get() when omitted. |
intentId | string | no | Confirm an existing hosted-session/paylink intent. The iframe must not mint a replacement. |
initialTerms | CheckoutTermsView | no | Initial display hint for intentId; server authority is re-read before confirmation. |
locationId | string | no | Pin the order to a specific store location. |
orderTypes | ("delivery" | "pickup" | "dine_in")[] | no | Defaults to ["pickup", "delivery"]. |
defaultOrderType | same as above | no | Pre-selected order type. |
submitLabel | string | no | Override the Pay button copy. |
enrollInLink | boolean | no | Default true. Saves details when the shopper opts in. |
appearance | ElementAppearance | no | Memoize this; reference changes after mount are warned about and ignored. |
linkUrl | string | no | Override the Link host for development. |
onComplete | (result: ProcessCheckoutResult) => void | yes | Fires once on terminal success/failure. |
onStatusChange | (status, ctx) => void | no | See checkout lifecycle. reviewing_terms carries replacement terms/deltas or unavailable lines. |
onError | (err: { code, message }) => void | no | Non-terminal initialization or runtime errors. |
For a hosted session or paylink, bind the element to the authority the server already minted. Do not pass the shopper's current cart as a substitute:
<CimplifyCheckout
client={client}
intentId={session.intent_id}
initialTerms={session.terms}
onComplete={handleComplete}
/>initialTerms is sent in the initial iframe handshake so the screen can render
before Pay is clicked. The iframe still fetches the intent again and confirms
the current server-issued terms; the hint is never payment authority.
Checkout Sign-In UX
Checkout collects email or phone inline. Once the contact is valid, the SDK
starts Cimplify OAuth with that contact as login_hint and checkout-oriented
copy.
If the shopper already has a matching Cimplify session, checkout loads saved details without showing verification UI. If the shopper needs to verify, hosted auth opens directly to OTP/passkey for that contact. The checkout iframe only receives the access token after verification succeeds.
The UI does not reveal account existence before verification. It can show a generic "Use saved details with Cimplify" action after a valid contact, then Cimplify decides whether silent sign-in, OTP, passkey, consent, or account switching is needed.
Account Switching
When the shopper is signed in during checkout, checkout shows the verified
contact and a Change action. Choosing Change starts Cimplify OAuth with an
account-switch prompt so the shopper can use a different Cimplify account before
selecting saved details or entering new payment information.
Agent Checklist
- Use
<CimplifyCheckout>for embedded checkout. - Set
NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY,NEXT_PUBLIC_CIMPLIFY_CLIENT_ID, andNEXT_PUBLIC_CIMPLIFY_REDIRECT_URI. - Add
/auth/callbackwith both GET and POST handlers. - Use
cpk_test_/cpk_live_for Cimplify public keys. - Leave shopper verification to
auth.cimplify.io. - Load saved Link details only after verification completes.
Next
- Appearance API: Theme checkout
- Vanilla checkout: Same checkout controller without React
- Raw checkout iframe: Manual postMessage integration
Embedded checkout iframe
Mount the same checkout UI as Cimplify Pay on your own domain. Raw iframe embedding is possible, but saved-details sign-in requires an OAuth bridge; most storefronts should use the SDK controller.
Vanilla checkout
The framework-agnostic checkout surface. Use this from Vue, Svelte, plain HTML, or anywhere React wrappers are not the right fit. The same CimplifyElements controller backs `<CimplifyCheckout>`.