Skip to main content
This guide takes you from zero to a working cross-chain payment: get a deposit address from a quote, let a user deposit, and get notified when funds are delivered.

Prerequisites

  • An API key (UUID) from the Mayan team β€” see Getting access.
  • The base URL: https://mps-api.mayan.finance.
All authenticated requests send your key in the x-api-key header.

1. Get a deposit address from a quote

Request a Mayan quote with mpsDeposit: true and a destinationAddress (where the funds settle), then read mpsDepositAddress from an eligible quote. It’s a deterministic address on the quote’s source chain β€” in the example below the payer funds on Arbitrum and the merchant receives USDC on Base. The address is minted under your API key, so MPS must be enabled for it.
Response (abridged β€” one quote shown):
Read mpsDepositAddress from any eligible quote (SWIFT, MONO_CHAIN, or a direct FAST_MCTP) β€” they all share the same address. Quotes that aren’t eligible return mpsDepositAddress: null.
The address is deterministic and permanent for a given recipient + mpsUserId β€” requesting another quote returns the same address, so it’s safe to call on every checkout. It’s null unless MPS is enabled for your key, destinationAddress is set, and the amount clears the token’s minimum.

2. Let the user deposit

Show mpsDepositAddress to your user and have them send the input token on the source chain (Arbitrum, in the example above). MPS detects the deposit and settles it to your destination token automatically β€” no signature, no transaction to build.
  • A quote from an EVM source chain returns an EVM address (valid on that chain).
  • A quote from Solana returns a Solana vault for SPL / Token-2022 deposits (USDC, USDT, WETH).
Whitelisted tokens β€” the native coin and USDC on EVM, and USDC / USDT / WETH on Solana β€” are detected automatically. For any other token, trigger indexing yourself with POST /request-index. See Supported tokens.

3. Receive the settlement

You have two ways to track a payment β€” use whichever fits your stack:
The stream is served over Socket.IO (bun add socket.io-client). Connect and receive deposit_detected and status_changed events as they happen.
See Events for the full payloads and reconnection/replay guidance.
A payment is done when a swap reaches status: "completed" (terminal: true, category: "success"). Most transfers settle in seconds. See Swap Statuses for the full lifecycle.

Full example: e-commerce checkout

Map your order ID to a stable mpsUserId so the same order always maps to the same deposit address, then watch for the terminal event.
Show the deposit address to the customer. They send ~2 USDC on Arbitrum; the merchant receives USDC on Base, and you get a status_changed β†’ completed event to fulfil the order.
Deposits below the per-chain minimum USD value are detected but not settled. You still receive a deposit_detected event with queued: false and ignoredReason: "below_min", so it’s never a silent gap.

Watch a payment end-to-end

Get an address from a quote (step 1), then subscribe to the event stream (Socket.IO) and wait until the settlement is terminal. This is the snippet most integrations start from β€” it prints each event and resolves on completed (success) or dead (gave up).
Full runnable examples (deposit ~2 USDC on Base or Solana β†’ receive USDC on Arbitrum) are on the Examples page.