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. Email support@mayan.finance to get one. No key yet? Try the public demo key 03b9969f-7c6a-4bd1-9ad4-c0e0e9f3dcb7 (shared, for evaluation only). You need a key for the MPS panel and for the tracking endpoints below; getting a deposit address from a quote works without it.
  • 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. No API key is required for this call; the solanaProgram and forwarderAddress parameters route the quote through MPS.
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 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). Mayan 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 native SOL and SPL / Token-2022 deposits (SOL, USDC, USDT, WETH, WSOL).
Whitelisted tokens (the native coin and USDC on EVM, and SOL / USDC / USDT / WETH / WSOL 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 ~5 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 ~5 USDC on Base or Solana β†’ receive USDC on Arbitrum) are on the Examples page.

Next steps

Swap Statuses

Every status a deposit passes through, and which ones are terminal.

API Reference

Every endpoint, request and response shape, and the error model.