When to use the buy button
MoonPay gives you three ways to run a buy. Pick the one that matches how much of the experience you want to own.| Approach | What you build | Best for |
|---|---|---|
Buy button (setupBuyButton()) | A container. MoonPay renders the button, the payment-method picker, and the confirmation sheet. | A fast, low-effort express checkout where you want a single ready-made payment button. |
Headless buy (setupBuy()) | Your own button, amount entry, and confirmation screen. The frame is headless and emits events. | Full control over the purchase UI while MoonPay runs the pipeline behind the scenes. |
Widget (pay-with-widget) | Nothing — MoonPay renders the entire flow, from amount entry to confirmation. | The quickest path to a complete buy experience when you do not need a custom UI. |
setupBuy() when the customer confirms.
Both run the same buy pipeline and emit the same events.
Prerequisites
- A connected customer (via
client.getConnection()orclient.connect()). See Connect a customer. - A UI surface where you can render the buy button frame.
- A destination wallet address for the purchased crypto.
Flow overview
Get a quote
Request a quote for the amount the customer wants to spend. Pass the destination
wallet and the asset the customer will receive. You do not pass a payment method
here — the customer picks one inside the buy button.Only quotes with Display the quote in your UI: source amount, destination amount, fees, and
exchange rate. Monitor
executable: true can be used to execute a transaction. See the
quotes API reference for the
fields required to receive executable: true.expiresAt and refresh the quote before it expires. If
the button is already rendered, call buyButton.setQuote(newSignature) instead
of re-creating it — see Refresh an expiring quote.Render the buy button
Pass the quote
signature and a container element to
client.setupBuyButton(). The
frame renders a payment button — card, Apple Pay, or Google Pay, depending on
what’s available to the customer — into your container. On tap, the frame opens
the confirmation sheet and runs the buy pipeline.For the frame URL, parameters, and events, see the buy button
frame reference.Render the buy button
Like
setupBuy(), the buy button
emits a ready event once the button is rendered and ready to tap. For Apple
Pay and Google Pay, it fires after the customer’s device is confirmed to
support the wallet.Handle the events
onEvent receives BuyButtonEvent
events as the pipeline progresses. Handle each kind:ready— the button is rendered and ready for the customer to tap. Use it to hide any loading placeholder.complete— the pipeline finished. The payload carries atransaction. Inspect itsstatusfirst: whenstatusis"failed", readfailureReasonand show it to the customer; otherwise passtransaction.idtogetTransaction()to poll for the final status.challenge— verification is required before the transaction can proceed. Render the challenge frame at theurlfrom the payload. Do not construct the URL yourself.error— the flow encountered an error. Logcodeandmessage, then tear down the frame. Themessageis for logs, not for display to customers.
Handle challenges
When the buy button emits a The challenge frame handles all verification types automatically — KYC, Strong
Customer Authentication (SCA), CVC re-entry, wallet ownership,
micro-authorization, and 3D Secure (3DS). You never need to distinguish between
them.
challenge event, the customer must complete one or
more verification steps before the transaction can proceed. Set up the challenge
frame with the URL from the event payload. For the full flow, see Handle
challenges.The challenge frame is self-driving: after initialization, it sequences through
all required verification steps, creates the transaction, and emits complete
when the pipeline finishes.Handle challenges
Track the transaction
When the buy button or challenge frame emits
complete, the payload includes a
transaction with an id and status. The transaction is created and payment
is processing. Poll for the final status with
getTransaction().Track the transaction
Webhook support is coming soon. Until then, use polling to track transaction
status.
Refresh an expiring quote
Quotes expire. If the current quote expires before the customer taps the button, fetch a new one and callsetQuote() with its signature instead of
re-rendering the frame.
Refresh the quote
buyButton.dispose() to unmount the
frame. After you dispose it, no further events reach your onEvent callback.
Transaction statuses
Transactions have the following statuses:- Pending: The transaction has been initiated and the payment accepted. The assets are being transferred.
- Complete: The transaction is finalized. The payment is complete and the assets have been delivered to their destination.
- Failed: The transaction has failed. The payment was not executed and funds were not transferred.
Next steps
setupBuyButton() reference
Full method signature, parameters, events, and errors.
Buy button frame
Frame URL, parameters, and protocol messages.
Connect a customer
Connect a customer’s MoonPay account before you start a buy.
Handle challenges
Render the challenge frame when verification is required.