cimplify

Choosing a checkout integration

Cimplify ships five layered ways to take a payment. Pick the highest tier you can; each step down the list trades a few minutes of integration time for more control. All five eventually reach the same backend endpoint and emit the same [Element events](/docs/concepts/element-events).

The five tiers

TierHosted byRoughlyYou give up
Drop-in (hosted Pay)pay.cimplify.io5 LOC + a redirectCustomer leaves your site
Embedded iframelink.cimplify.io~20 LOCYou wire postMessage yourself
Controlled Elements (React)Iframe inside your React tree1 component, ~30 LOCYou stay on the React side of the iframe
Vanilla ElementsIframe inside your DOM~50 LOCYou manage mount/unmount manually
Headless (CheckoutPage or your own)YouOpen-endedNo iframe; you build every screen

Decision tree

Do you ship a frontend at all?
  No  → Drop-in (Pay session). Done.
  Yes → Do you need to keep the customer on your domain?
        No  → Drop-in.
        Yes → Are you on React?
              No  → Vanilla Elements.
              Yes → Do you want Cimplify-rendered UI for auth/address/payment?
                    Yes → Controlled Elements (`<CimplifyCheckout>` or piecewise).
                    No  → Headless (`<CheckoutPage>` or your own UI driving `client.checkout.process`).

What stays the same across all tiers

  • The checkout lifecycle (preparing → processing → … → success | failed) is identical.
  • The cart shape (built via client.cart.addItem({ item_id, quantity, ... })) is the same. Drop-in / Pay sessions accept a cart_id; Elements expect the cart to already exist on the customer's session cookie.
  • Server-side, every tier funnels into POST /v1/checkout via the same CheckoutFormData body.
  • Appearance API works the same way for every iframe-based tier.

What differs

ConcernDrop-inEmbedded / Elements / VanillaHeadless
Where the iframe livespay.cimplify.ioYour page
Cimplify-rendered fieldsAll of themAll of themNone
Compliance scope (PCI, OTP)CimplifyCimplify (data never leaves the iframe)You
Cart pre-fill UXServer-built sessionUse set_cart / cartId propYou
Custom layout/copyLimited (Appearance API)Limited (Appearance API)Unlimited

Two-line drop-in example

For most teams this is the right starting point. You can always graduate to embedded later.

server
// Server: create a session with your secret key
const session = await fetch("https://api.cimplify.io/v1/checkout/sessions", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.CIMPLIFY_SECRET_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ cart_id: cart.id, success_url, cancel_url }),
}).then(r => r.json());

return Response.redirect(session.url);

Next

On this page