Skip to main content
Render the Buy Button frame into your UI. The frame renders a single payment button that matches the payment method in the quote (Apple Pay, Google Pay, or a saved card) and runs the buy pipeline on tap. Use it when you want MoonPay to render the payment button. Pass headless: true to run the same purchase with no button. Use headless mode for saved-card and bank transfer (SEPA) quotes when you draw your own purchase button.
The button covers Apple Pay, Google Pay, and saved-card quotes. For bank transfers (SEPA), render your own button and call setupBuyButton() with headless: true. See Bank transfer.
The buy button can emit a challenge event mid-pipeline. Render a separate challenge frame using client.setupChallenge() at the URL from the event payload.
Setup buy button

Parameters

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

Button settings

Pass applePayButtonSettings and googlePayButtonSettings as plain objects. The SDK serializes each one and passes it to the frame, which applies the one that matches the button it renders. You can pass both. Every property is optional, and the frame ignores a property with an invalid value while still applying the rest. For the allowed values and validation rules, see the frame reference: Apple Pay button settings and Google Pay button settings.
Style the wallet buttons
The default button is 44px high. If you set a custom height, size the container to match it. Both types are exported from @moonpay/platform-sdk-web. The settings have no effect when you call setupBuyButton with headless: true, since the frame renders no button.

BuyButtonEvent

onEvent receives events as the buy pipeline progresses.

FrameTransaction

FrameTransaction is a discriminated union — the failure variant carries failureCode and failureReason, the non-failure variant always carries id. Pass id to client.getTransaction() to poll for the final status.

BuyButtonEventError

Result

client.setupBuyButton() returns a Result<BuyButtonFrame, SetupBuyButtonError>.

Result envelope

Result<BuyButtonFrame, SetupBuyButtonError>

BuyButtonFrame

SetupBuyButtonError

Headless mode

Pass headless: true when you draw your own purchase button. The frame renders nothing inside container and starts the purchase as soon as it loads. Call setupBuyButton() when the customer confirms the purchase in your UI, not before, because setting up the frame is what starts the purchase. Headless mode sends the same BuyButtonEvent events, with these differences:
  • It accepts saved-card and bank transfer (sepa) quotes for a connected customer only. An Apple Pay or Google Pay quote gets an "error" with code unsupportedPaymentMethod, and a guest checkout quote gets invalidQuote.
  • It never sends "buttonPressed" or "cancelled".
  • After "ready", it sends exactly one of "complete", "challenge", or "error".
  • It reads setQuote() only after an "error" with code quoteExpired. At any other time the frame ignores it, so it never starts a second purchase.
  • On "challenge", open the challenge frame without resume. The challenge frame finishes the purchase and sends its own "complete".
For the frame-level behavior, see Headless mode on the Buy Button frame.
Headless mode with a saved card
For the end-to-end card payment walkthrough, 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, call setupBuyButton() with headless: true, and read the transaction id from the "complete" event. The difference is what happens after the transaction is created: the customer sends the funds from their bank. Fetch the transaction with the id and show the customer the bank details from bankTransferDepositInfo, including the payment reference, and the amount to send from source.amount. 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