Prerequisites
- A MoonPay account with card payments enabled. Contact your MoonPay account team to enable it.
- A connected customer (via
client.getConnection()orclient.connect()). - A UI surface where you can render MoonPay frames (iframe on web, or WebView on mobile).
- A destination wallet address for the purchased crypto.
Flow overview
List payment methods
Fetch the customer’s available payment method types and stored cards.The result contains two collections:
paymentMethodConfigs— available payment method types. Check fortype: "card"to confirm card payments are available for this customer.paymentMethods— the customer’s stored cards. Each entry includesbrand,last4,expirationMonth,expirationYear,cardType, andavailability.
availability.active: false), show the reasons value and prompt the user to
add a new card.Add a card
When the customer needs to add a new card, set up the Add Card frame. The frame
collects card details and billing address inside a PCI-compliant MoonPay-hosted
UI — card data never touches your domain. For the frame URL, size, and events,
see the Add Card frame reference.The
Add a card
complete event returns the new card’s full details including its id. Use
this id to get a quote. You do not need to fetch payment
methods again.Get a quote
With a stored card selected, request a quote. Pass the card’s On the same confirmation view, show the contextual quote summary and fee
breakdown before the customer submits the card payment. You remain responsible for this
presentation. See Going Live
for the canonical requirements and fee
behavior for how fees relate to
the source amount. Monitor
id in
paymentMethod so MoonPay can evaluate card-specific requirements.expiresAt and refresh the quote before it expires.
If the quote expires after the buy button is loaded, the frame sends an error
with code quoteExpired. Call buyResult.value.setQuote(newSignature) with a
new quote instead of re-creating the frame.Execute the transaction
Headless buy button
Callclient.setupBuyButton() with headless: true when the customer confirms
the purchase in your UI. In headless mode the frame renders no visible UI: it
starts the purchase as soon as it loads and emits events for you to handle, so
you keep full control over your purchase UI. For the frame URL, parameters, and
events, see headless mode in the
Buy Button frame reference.setupBuyButton
Handle challenges
When the buy button emits a The 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 — do not construct the URL yourself.
For the frame URL, parameters, and events, see the Challenge
frame reference.The 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
{ transaction: { id, status } }. Unless status is failed, the transaction
is created and payment is processing. A failed transaction carries
failureCode and failureReason, and has no id when the transaction was
never created. See the Buy Button
frame reference for the failure
codes.Track the transaction
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.
You can also track transaction status with the existing
transaction-updated
webhook.