Skip to main content
Mount the headless Buy frame into your UI and execute a transaction from a quote signature. The frame renders no visible UI — it drives the buy pipeline in the background and emits events you handle from your own purchase screen.
The Buy frame is headless. When it emits a challenge event, render a separate challenge frame with client.setupChallenge() at the URL from the event payload. See the Handle challenges guide for the full flow.
Setup buy

Parameters

This method does not require a separate auth token. The client uses stored credentials from an active connection.

BuyEvent

onEvent receives events as the buy pipeline progresses. Use event.kind to decide how to handle each event.

FrameTransaction

This is the transaction object returned when the buy pipeline completes. FrameTransaction is a discriminated union — the failure variant carries failureReason, the non-failure variant always carries id. Pass id to client.getTransaction() to poll for the final status.

BuyChallengePayload

BuyEventError

Result

client.setupBuy() returns a Result<BuyFrame, SetupBuyError>.

Result envelope

Result<BuyFrame, SetupBuyError>

BuyFrame

SetupBuyError

Full example

The following example walks through the full card-payment flow: get a quote for a stored card, mount the headless Buy frame, hand off to a challenge frame when verification is required, and dispose of the frame when the transaction completes.
Buy with a stored card
For the end-to-end card payment walkthrough — listing payment methods, adding a card, and tracking the transaction to a terminal status — see the Pay with card guide. For details on the challenge flow, see Handle challenges.

Bank transfer

Bank-transfer payments (SEPA for EUR) use the same headless flow as cards. You fetch a bank-transfer quote, mount the Buy frame with its signature, and read the transaction id from the complete event. The difference is what happens after the transaction is created: instead of charging a card, the customer sends funds to a MoonPay bank account, so you render the deposit details yourself. Bank transfers are a floating payment method, so the amounts are estimates until the transfer settles. The quote returns exchangeRateType: "floating"; render the estimated crypto amount with a tilde (for example, ~0.2345 BTC) and tell the customer the final amount is set when their funds settle. See Exchange rate type. For the full walkthrough, including confirming availability, rendering the deposit details, handling requotes and cancellations, and tracking the transaction to a terminal status, see the Pay with bank transfer guide.
Buy with a bank transfer
The customer must include the payment reference with their bank transfer. Transfers sent without it are rejected. Surface this prominently in your own UI, for example, “Always include your payment reference or your transfer will be rejected.” See Bank-transfer deposit details.
types.ts