cimplify
Cimplify Link

CheckoutElement

The full unified checkout iframe. Auth, address, payment method, and submit all live in one frame. This is the iframe behind `<CimplifyCheckout>` and the hosted Pay page, sharing the same code at `packages/link/src/pages/elements/checkout/`.

Iframe URL

https://link.cimplify.io/elements/checkout?businessId=biz_…&nonce=<random>

# Alias (same component, same behavior):
https://link.cimplify.io/elements/payment?businessId=biz_…&nonce=<random>

What it renders

A vertically stacked form whose sections appear conditionally based on auth state and order type:

  • Auth section: contact + OTP, hidden once a token is present.
  • Order type: pickup / delivery / dine-in toggle (only when orderTypes contains more than one).
  • Address section: shown for delivery orders. Picks from saved addresses if signed in; otherwise a form with optional "use my location".
  • Payment section: saved methods if signed in; otherwise the merchant's configured options (mobile-money providers, card, cash).
  • Save info: "remember me for 1-click checkout" toggle when the customer is signed in to Link.
  • Submit button: rendered only when renderSubmitButton: true.
  • Cart summary: when set_cart has been called, switches the layout to two columns and shows itemized totals.

Init message

After ready, send the standard init. Fields specific to CheckoutElement:

FieldNotes
orderTypesSubset of delivery | pickup | dine_in. Defaults to ["pickup", "delivery"].
defaultOrderTypePre-selected order type. Falls back to first entry of orderTypes.
renderSubmitButtonWhen true the iframe renders its own Pay button and emits request_submit. When false, you trigger process_checkout from the parent.
submitLabelOverride the Pay button copy.
prefillEmailSeed the auth contact field.
appearanceSee Appearance API.
demoModeSkip API; useful for screenshots.

Mounting

React (high-level)

import { CimplifyCheckout } from "@cimplify/sdk/react";

<CimplifyCheckout
  client={client}
  cartId={cart.id}
  orderTypes={["delivery", "pickup"]}
  defaultOrderType="delivery"
  submitLabel="Pay GH₵29.99"
  appearance={appearance}        // memoize!
  onComplete={handleComplete}
  onStatusChange={handleStatus}
/>

Vanilla

const checkout = elements.create(ELEMENT_TYPES.CHECKOUT, {
  orderTypes: ["delivery", "pickup"],
  defaultOrderType: "delivery",
  submitLabel: "Pay GH₵29.99",
});

checkout.on(EVENT_TYPES.REQUEST_SUBMIT, async () => {
  const result = await elements.processCheckout({
    cart_id: cart.id,
    order_type: "delivery",
  });
  // …
});

checkout.mount("#checkout");

Pre-filling the cart

set_cart renders the line-item summary alongside the form. The element switches to a 2-column layout when a cart is provided. CheckoutCartData:

interface CheckoutCartData {
  items: CheckoutCartItem[];
  subtotal: string;
  tax_amount: string;
  total_discounts: string;
  service_charge: string;
  total: string;
  currency: string;          // ISO 4217
}

interface CheckoutCartItem {
  name: string;
  quantity: number;
  unit_price: string;        // Money string
  total_price: string;
  image_url?: string;
  line_type: "simple" | "service" | "bundle" | "composite" | "digital";
  variant_name?: string;
  scheduled_start?: string;  // ISO 8601 (services)
  scheduled_end?: string;
  selections?: { name: string; quantity: number; variant_name?: string }[];
  add_ons?: { name: string; price: string }[];
  special_instructions?: string;
}

Lifecycle

See checkout lifecycle for the full state machine. The element emits checkout_status for every transition and checkout_complete on terminal success or failure.

Authorization challenges

When the payment provider needs an OTP, PIN, birthday, phone, or address to authorize, the element switches to its built-in AuthorizationView and emits checkout_status: "awaiting_authorization" with context.authorization_type. The customer enters the challenge inside the iframe; you don't need to render anything yourself.

Recovery

If the customer reloads while a payment is in flight, the element rehydrates from local storage on next mount and resumes from the last known state. The first lifecycle event you receive will be checkout_status: "recovering".

Next

On this page