Use this file to discover all available pages before exploring further.
Render the Challenge frame into your UI to resolve verification steps required
by another flow (for example, a buy transaction or an identity capture). The
challenge frame is self-driving — after initialization, it sequences through
all required verification steps and emits complete when the pipeline
finishes.Unlike other setup methods, setupChallenge() takes a url provided by the
upstream flow’s challenge event. Pass it through as-is — the URL already
carries the channelId the SDK needs to wire up the frame. Do not modify the
URL yourself.For more context, see the Handle
challenges guide.
Setup challenge
import { createClient, type BuyEvent, type ChallengeEvent,} from "@moonpay/platform-sdk-web";const client = createClient({ sessionToken: "c3N0XzAwMQ==" });const buyResult = await client.setupBuy({ quote: quoteResult.value.data.signature, container: document.querySelector("#buyContainer"), onEvent: async (event: BuyEvent) => { if (event.kind !== "challenge") return; // The url comes from the challenge event — pass it through as-is. const challengeResult = await client.setupChallenge({ url: event.payload.url, container: document.querySelector("#challengeContainer"), onEvent: (event: ChallengeEvent) => { switch (event.kind) { case "ready": // Challenge UI is rendered and visible to the customer break; case "complete": if (event.payload.flow === "buy") { console.log(event.payload.transaction); } else if (event.payload.flow === "identity") { console.log(event.payload.identityId); } buyResult.value.dispose(); break; case "cancelled": // Customer dismissed the challenge — offer a retry path buyResult.value.dispose(); break; case "error": console.error(event.payload.message); buyResult.value.dispose(); break; } }, }); if (!challengeResult.ok) { // Handle error console.error(challengeResult.error.kind, challengeResult.error.message); return; } },});
The URL from the upstream flow’s challenge event payload. Pass it through unchanged. The URL must include the channelId query parameter (the upstream flow always sets it).
container
HTMLElement
✅
A DOM element to render the Challenge frame into.
onEvent
(event: ChallengeEvent) => void
Callback invoked for Challenge flow events. See ChallengeEvent.
This method does not require a separate auth token. The client uses stored
credentials from an active connection.
onEvent receives events as the challenge flow progresses. Use event.kind to
decide how to handle each event. The complete and cancelled payloads are
discriminated by payload.flow so you can branch on the originating flow.
kind
Payload
When you receive it
"ready"
—
The Challenge UI is rendered and visible to the customer.
The challenge frame is self-driving. After acknowledging the initial
handshake, the SDK does not send further messages to the frame. The frame
internally handles all verification types automatically — including CVC
confirmation, 3D Secure, identity verification (KYC), Strong Customer
Authentication (SCA), micro-deposit authorization, and wallet ownership proof.
You never need to distinguish between them.
Unmounts the frame. After you call this, no further events are dispatched to your onEvent callback.
Unlike setupBuy(), setupApplePay(), and setupGooglePay(), the
ChallengeFrame does not expose a setQuote() method. The challenge frame
runs to completion on its own.