Skip to main content

Documentation Index

Fetch the complete documentation index at: https://dev.moonpay.com/llms.txt

Use this file to discover all available pages before exploring further.

The Challenge frame handles verification steps required by another flow. Two upstream flows mount it today:
  • The buy frame emits a challenge event with a URL — use that URL to mount the frame and complete the card transaction.
  • The identity flow mounts the frame directly to capture identity data (for example, document capture or liveness checks).
The frame is self-driving: after the handshake, there are no further parent-to-child messages. It sequences through all required verification steps and emits complete when the pipeline finishes. The complete and cancelled payloads are discriminated by flow so you can branch on the originating flow.

URL

For the buy flow, the URL is provided by the buy frame’s challenge event payload. For the identity flow, the URL is provided by the upstream identity verification call. In both cases, do not construct or modify the URL yourself.

Requirements

Size

Render the frame in a modal or full sheet so the customer can complete verification. The frame adapts to any size, but a full-screen or large modal works best for flows like 3D Secure that load bank-hosted pages.

Initialization parameters

PropertyTypeRequiredDescription
clientTokenstringIncluded automatically in the challenge URL for CSP compliance. Do not remove it.
channelIdstringGenerate a fresh channel ID on your side and append it to the challenge URL before setting it as the frame src.
challengeTokenstringOpaque token. Do not modify or parse it.

Events

All events are dispatched using the message pattern described in the frames protocol. Below are the event payloads specific to the Challenge frame.

Outbound events

frame->parent These events are sent from this frame to the parent window.

handshake

The frame requests that you open a message channel.
{
  "version": 2,
  "meta": { "channelId": "ch_challenge_1" },
  "kind": "handshake"
}

ready

The challenge UI is rendered and visible to the customer.
{
  "version": 2,
  "meta": { "channelId": "ch_challenge_1" },
  "kind": "ready"
}

complete

All required verification steps have resolved. Remove the challenge frame and branch on the discriminated payload:
  • flow: "buy" — the transaction pipeline finished. Remove the buy frame too and navigate to the confirmation screen.
  • flow: "identity" — the customer was verified. Use identityId to continue your onboarding flow.
{
  "version": 2,
  "meta": { "channelId": "ch_challenge_1" },
  "kind": "complete",
  "payload": {
    "flow": "buy",
    "transaction": {
      "id": "txn_01",
      "status": "pending"
    }
  }
}

cancelled

The customer dismissed the challenge. Remove the challenge frame and act on the discriminated payload:
  • flow: "buy" — remove the buy frame too, then offer a retry path. The payload carries transactionId and challengeToken (when known) so you can resume without restarting the pipeline.
  • flow: "identity" — offer a retry path or exit. No extra payload is emitted.
{
  "version": 2,
  "meta": { "channelId": "ch_challenge_1" },
  "kind": "cancelled",
  "payload": {
    "flow": "buy",
    "transactionId": "txn_01",
    "challengeToken": "eyJhbGciOi..."
  }
}

error

The challenge failed. Remove the challenge frame (and the buy frame, if the buy flow was driving it), then surface the message to the developer.
{
  "version": 2,
  "meta": { "channelId": "ch_challenge_1" },
  "kind": "error",
  "payload": {
    "code": "invalid_challenge",
    "message": "Could not decode challenge from response."
  }
}
Common codes:
CodeDescription
configurationErrorFrame initialization failed (for example, the challengeToken is missing)
invalid_tokenThe challengeToken could not be decoded
unsupported_flowThe token type is not supported by this frame
invalid_challengeChallenge details could not be decoded from the token
missing_quoteThe buy flow could not decode the quote from the challengeToken

Inbound events

parent->frame These events are sent from the parent window to this frame.

ack

Acknowledge the handshake. This is the only message you send to the challenge frame — it is self-driving after the handshake.
{
  "version": 2,
  "meta": { "channelId": "ch_challenge_1" },
  "kind": "ack"
}