cimplify
Concepts

Element events

The checkout iframe communicates with the parent page via window.postMessage. This is the raw protocol; SDK users usually consume higher-level controller events instead.

This page documents the raw postMessage contract between link.cimplify.io/elements/checkout and the parent page. The source of truth is IframeToParentMessage and ParentToIframeMessage in @cimplify/sdk.

For agents: if you use <CimplifyCheckout> or createElements, the SDK handles these messages for you. Only implement this page directly when embedding the raw checkout iframe.

Origin and Routing

Iframe messages include a per-element nonce URL parameter. The parent should:

  1. Verify event.origin is the expected Link origin.
  2. Verify event.source matches the iframe's contentWindow.
  3. Verify event.data.nonce matches the iframe URL nonce.

The SDK accepts https://cimplify.io, https://*.cimplify.io, and localhost for development. A raw production integration should normally pin to https://link.cimplify.io.

const LINK_ORIGIN = "https://link.cimplify.io";

window.addEventListener("message", (event) => {
  if (event.origin !== LINK_ORIGIN) return;
  if (event.source !== iframe.contentWindow) return;
  if (event.data?.nonce !== nonce) return;
  // handle trusted message
});

Iframe to Parent

ready

First message after iframe load. Reply with init.

{ type: "ready", height: 412, nonce: "ab12cd34" }

height_change

Content resized. Apply it to the iframe height.

{ type: "height_change", height: 564, nonce: "ab12cd34" }

auth_requested

Checkout needs the parent to authenticate the shopper through Cimplify OAuth.

Checkout after a valid contact:

{
  type: "auth_requested",
  loginHint: "jane@example.com",
  contactType: "email",
  mode: "checkout",
  nonce: "ab12cd34"
}

Checkout account change:

{
  type: "auth_requested",
  mode: "checkout",
  prompt: "login",
  nonce: "ab12cd34"
}

SDK behavior:

  • mode: "checkout" enables silent-first OAuth.
  • loginHint becomes OAuth login_hint.
  • prompt: "login" skips silent auth so the shopper can change accounts.

Raw iframe behavior: start OAuth yourself and send set_token when your callback returns an access token.

contact_provided

The shopper supplied a guest contact. The SDK stores it as checkout customer data, but it is not authenticated identity.

{
  type: "contact_provided",
  contact: "jane@example.com",
  contactType: "email"
}

address_changed / address_selected

{
  type: "address_changed",
  address: {
    street_address: "12 Independence Ave",
    city: "Accra",
    region: "Greater Accra",
    country: "GH"
  },
  saveToLink: true
}

address_selected carries the same address shape and is emitted when a saved address is chosen.

payment_method_selected

{
  type: "payment_method_selected",
  method: {
    type: "mobile_money",
    provider: "mtn",
    phone_number: "+233200000001"
  },
  saveToLink: true
}

order_type_changed

{ type: "order_type_changed", orderType: "delivery" }

request_submit

The iframe Pay button was pressed. Respond with process_checkout or call elements.processCheckout(...).

{ type: "request_submit" }

checkout_status

Non-terminal checkout transition.

{
  type: "checkout_status",
  status: "awaiting_authorization",
  context: {
    display_text: "Approve the prompt on your phone",
    authorization_type: "otp",
    provider: "mtn"
  }
}

checkout_complete

Terminal checkout result.

{
  type: "checkout_complete",
  success: true,
  order: {
    id: "ord_…",
    order_number: "10042",
    status: "confirmed",
    total: "29.99",
    currency: "GHS"
  },
  enrolled_in_link: true
}
{
  type: "checkout_complete",
  success: false,
  error: {
    code: "PAYMENT_DECLINED",
    message: "The provider declined the payment.",
    recoverable: true
  }
}

error

{ type: "error", code: "AUTH_CONFIG_REQUIRED", message: "OAuth clientId and redirectUri are required." }

logout_complete

The iframe completed logout or cleared local auth state.

{ type: "logout_complete" }

Parent to Iframe

init

Sent after ready.

{
  type: "init",
  businessId: "biz_…",
  publicKey: "cpk_live_…",
  prefillEmail: "jane@example.com",
  appearance: { theme: "light" },
  orderTypes: ["delivery", "pickup"],
  defaultOrderType: "delivery",
  renderSubmitButton: true,
  submitLabel: "Pay now",
  token: "eyJ…"
}

set_token

Authenticates the iframe with the access token returned by the merchant OAuth callback. This is how the parent completes an auth_requested flow.

{ type: "set_token", token: "eyJ…" }

set_cart

{
  type: "set_cart",
  cart: {
    items: [{ name: "Jollof bowl", quantity: 1, unit_price: "29.99", total_price: "29.99", line_type: "simple" }],
    subtotal: "29.99",
    tax_amount: "0.00",
    total_discounts: "0.00",
    service_charge: "0.00",
    total: "29.99",
    currency: "GHS"
  }
}

process_checkout

{
  type: "process_checkout",
  cart_id: "cart_…",
  order_type: "delivery",
  location_id: "loc_…",
  enroll_in_link: true,
  customer: { name: "Jane", email: "jane@example.com", phone: null },
  address: { street_address: "12 Independence Ave", city: "Accra", region: "Greater Accra" }
}

Other Commands

MessagePurpose
get_dataAsk the iframe to emit its current selected data where supported.
logoutClear iframe auth state.
abort_checkoutAbort an in-flight checkout.

SDK Events vs Raw Messages

The SDK re-emits a smaller event set from CimplifyElement:

SDK eventSource raw message
readyready
authenticatedEmitted by SDK after OAuth succeeds and set_token is broadcast.
changeaddress_changed, address_selected, payment_method_selected
order_type_changedorder_type_changed
request_submitrequest_submit
errorerror or SDK auth startup/callback errors

On this page