Skip to main content
This guide walks through the full checkout flow, from creating a session to receiving settled funds. Maash supports two ways to present the checkout to your customer:

Redirect flow

Redirect the customer to a Maash-hosted checkout page. Simplest to set up.

Iframe flow

Embed the checkout widget directly in your page via postMessage.
Both flows follow the same payment lifecycle described below.

Flow overview

Step-by-step breakdown

1

Create a checkout session

Your server calls the Maash API to create a checkout session with the payment amount and configuration:
curl -X POST https://api.maash.io/checkout/sessions \
  -H "Content-Type: application/json" \
  -H "x-api-key: mk_live_1234567890abcdef1234567890abcdef" \
  -H "x-maash-user-type: checkout" \
  -d '{
    "merchant_id": "mer_01ABC",
    "transaction_id": "order_789",
    "amount_usd": 50.00
  }'
The API returns a checkout_url_with_token and session_id. Store the session_id to track this payment.
2

Present the checkout to the customer

You have two options:
  • Redirect: Send the customer to the checkout_url_with_token in their browser.
  • Iframe: Embed the checkout widget in your page using the iframe URL with query parameters (merchant_id, transaction_id, amount). The iframe communicates payment results back to your page via postMessage. See Iframe Integration for full details.
In both cases, the checkout page displays your merchant name, logo, and the payment amount.
3

Customer selects payment method

On the checkout page, the customer selects their preferred token (USDC or USDT) and blockchain network. The system:
  1. Generates a price quote with fees
  2. Creates an ephemeral wallet address via Maash Bridge
  3. Generates a blockchain-specific payment URI
  4. Creates a QR code and uploads it to S3
The customer sees the wallet address and a QR code they can scan with their wallet app.
4

Customer sends payment

The customer sends stablecoins to the ephemeral wallet address. They can:
  • Scan the QR code with a mobile wallet
  • Click the payment URI to open a desktop wallet (MetaMask, Phantom, etc.)
  • Copy the address and send manually
5

Payment detection and confirmation

When the blockchain confirms the transaction, Maash Bridge detects the deposit and notifies Maash. The system verifies:
  • The correct token was received
  • The amount is within the tolerance range (default: 0.1%)
  • The required number of confirmations have been reached
6

Cross-chain settlement

Maash Bridge bridges the received tokens to USDC on Solana through its smart deposit address infrastructure. This happens automatically regardless of which chain the customer paid on.
7

Merchant notification

Maash sends a webhook to your webhook_url with the payment result. See Webhooks for payload details.If you use the iframe integration, the widget also sends a maash_payment_complete postMessage event for immediate UI updates. Always verify payments via webhooks on your server before fulfilling orders.

Session statuses

A checkout session progresses through these statuses:
StatusDescription
pendingSession created, waiting for customer to select payment method
awaiting_paymentCustomer selected token/chain, waiting for payment
confirmingPayment detected, waiting for blockchain confirmations
completedPayment confirmed and settled
underpaidReceived amount is below the expected amount minus tolerance
overpaidReceived amount exceeds the expected amount plus tolerance
expiredSession expired before payment was received
failedPayment processing failed

Session expiration

Checkout sessions expire after a configurable duration (default: 48 hours). You can set this with the expires_in_seconds parameter when creating a session.
{
  "expires_in_seconds": 3600
}
After expiration, the session status changes to expired and the checkout URL becomes invalid. The API returns a 410 Gone response for expired sessions.

Confirmation times

Each chain requires a different number of block confirmations before a payment is considered final. See Supported Chains for the full list.

Handling edge cases

If the received amount falls below the expected amount minus the tolerance percentage, the payment status is set to underpaid. You receive a payment.underpaid webhook. Decide how to handle this in your application (prompt the customer to send the remaining amount or issue a partial refund).
If the received amount exceeds the expected amount plus the tolerance percentage, the payment status is set to overpaid. You receive a payment.overpaid webhook. The full amount is still settled.
If a customer does not send payment before the session expires, you receive a payment.expired webhook. Create a new checkout session if the customer wants to retry.

Next steps

Webhooks

Set up webhook verification and handle all payment event types.

Supported chains

View confirmation times and contract addresses for each chain.

Error handling

Handle API errors and implement retry strategies.

Testing

Test the full checkout flow in sandbox mode.