cimplify
Concepts

Element events

Cimplify Elements communicate with the parent page via `window.postMessage`. Below is the full event union sent _from_ the iframe, defined as `IframeToParentMessage` in `@cimplify/sdk`. The parent-side controller in the SDK already validates and dispatches these for you; this page is for when you want to wire them up directly.

Origin and routing

Iframe messages are signed with a per-element nonce URL param. The parent controller in elements.ts verifies origin (must be cimplify.io or a subdomain over HTTPS, or localhost) and matches nonce or event.source before dispatching. If you handle messages yourself, do the same.

function isAllowedOrigin(origin: string): boolean {
  const url = new URL(origin);
  if (url.hostname === "localhost" || url.hostname === "127.0.0.1") return true;
  if (url.protocol !== "https:") return false;
  return url.hostname === "cimplify.io" || url.hostname.endsWith(".cimplify.io");
}

Lifecycle events

ready

First message after iframe load. Carries the initial content height. The parent should respond with an init message containing businessId, publicKey, and any appearance/order options.

{ type: "ready", height: 412 }

height_change

Emitted whenever the iframe content resizes. Apply the value to the iframe's style.height for seamless embedding.

{ type: "height_change", height: 564 }

Authentication events

requires_otp

The customer entered a contact and an OTP has been dispatched. The masked contact is suitable for a "code sent to ***123" status line.

{ type: "requires_otp", contactMasked: "+233·····001" }

contact_provided

The OTP request failed (or was bypassed) but the customer provided a contact you can carry through to a guest checkout.

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

authenticated

OTP verified. The token is short-lived; the parent controller automatically broadcasts set_token to other Elements (Address, Payment, Account) so they pick up the same session.

{
  type: "authenticated",
  accountId: "acc_…",
  customerId: "cus_…",
  token: "lk_…",
  customer: { name: "Jane", email: "jane@…", phone: "+233…" }
}

token_refreshed

Background re-issue of the Link token. The new value supersedes the old one.

{ type: "token_refreshed", token: "lk_…" }

logout_complete

Customer signed out. The parent controller clears address/payment/customer state and aborts any in-flight checkout.

{ type: "logout_complete" }

Form-state events

address_selected / address_changed

Emitted when the customer picks a saved address (address_selected) or edits a new one (address_changed). saveToLink only appears on address_changed and indicates whether the customer ticked "save to Link".

{
  type: "address_changed",
  address: {
    street_address: "12 Independence Ave",
    city: "Accra",
    region: "Greater Accra",
    country: "GH",
    /* optional: latitude, longitude, apartment, postal_code, phone_for_delivery, delivery_instructions */
  },
  saveToLink: true
}

payment_method_selected

Customer chose a payment method. method.type is "mobile_money", "card", or "cash". saveToLink reflects the "remember me" checkbox state.

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

order_type_changed

Customer toggled between delivery, pickup, or dine-in. Emitted only by CheckoutElement.

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

request_submit

Customer pressed the in-iframe submit button (when renderSubmitButton is enabled). The parent should respond by calling elements.processCheckout(...).

{ type: "request_submit" }

Checkout events

checkout_status

Non-terminal lifecycle transition. See checkout lifecycle for the full state list.

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

checkout_complete

Terminal. Either success: true with an order, or success: false with a recoverable/non-recoverable error.

// Success
{
  type: "checkout_complete",
  success: true,
  order: { id, order_number, status, total, currency },
  enrolled_in_link: true
}

// Failure
{
  type: "checkout_complete",
  success: false,
  error: {
    code: "PAYMENT_DECLINED",
    message: "The provider declined the payment.",
    recoverable: true
  }
}

Error event

Anything that doesn't fit a more specific event: initialization failure, lost connectivity, validation errors before submit. Always carries a code and human-readable message.

{ type: "error", code: "BUSINESS_ID_REQUIRED", message: "…" }

Parent → iframe messages

For completeness, the parent posts these (ParentToIframeMessage):

TypeSent by parent to…
initseed businessId, publicKey, appearance, orderTypes
set_tokenbroadcast a Link token to non-auth Elements
set_cartpush the cart summary into CheckoutElement
get_datarequest current address/payment selection
refresh_tokenforce a Link token refresh
logoutsign the customer out
process_checkoutstart a payment flow
abort_checkoutcancel an in-flight payment

Next

On this page