Skip to main content
This guide shows you how to detect and handle challenges that require customer authentication or verification before MoonPay can continue an action.

Prerequisites

  • A connected customer.
  • A UI surface where you can render frames (WebView on mobile, iframe on web).

When challenges appear

Challenges are extra steps a customer must complete before MoonPay can continue an action. Common reasons include:
  • Strong Customer Authentication (SCA), for example 3D Secure
  • Identity verification (KYC)
  • Card-specific checks such as CVC re-entry or micro-authorization
Today, challenges are surfaced by frames — frames emit a challenge event that points to the Challenge frame. Other surfaces may emit challenges in the future (for example, identity APIs).

Where challenges are emitted

A frame emits a challenge event when verification is required. The payload carries a fully-formed URL that you load into the dedicated Challenge frame: The event uses the same envelope across all of these frames:
Example challenge event
{
  "version": 2,
  "meta": { "channelId": "ch_1" },
  "kind": "challenge",
  "payload": {
    "kind": "frame",
    "url": "https://blocks.moonpay.com/platform/v1/challenge?challengeToken=..."
  }
}

How to handle a challenge

  1. Listen for the challenge event on the frame. Treat the action as blocked until the challenge resolves.
  2. Mount the Challenge frame at the URL from the event payload. Pass the URL through as-is — do not construct or modify it. See the Challenge frame reference for the frame URL, parameters, and events.
  3. Handle the Challenge frame events:
    • ready — the challenge UI is rendered and visible.
    • complete — verification resolved. The Challenge frame reports any downstream artifacts (for example, the transaction id and status for the buy flow).
    • cancelled — the customer dismissed the challenge. Offer a retry path.
    • error — the challenge failed. Log the code and message (both are developer-facing and not intended for end-user UI) and show the customer a generic next step, such as retrying or choosing a different payment method.
  4. Tear down the originating frame after complete, cancelled, or error. For the buy frame, call buyResult.value.dispose().

Implementation tips

  • Use a full-screen surface on mobile: challenge flows often involve authentication or verification, so treat them like a separate screen or full sheet.
  • Validate postMessage events: if you integrate frames manually, validate origin and message shape. The frames protocol documents the shared envelope format.
  • Handle cancellation and timeouts: if the customer closes the challenge or it fails, show a clear next step (retry, choose a different payment method, or exit the flow).