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.
x-api-key header.
1. Get a deposit address from a quote
Request a Mayan quote withmpsDeposit: 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.
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
ShowmpsDepositAddress 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:- WebSocket (real-time)
- Polling
The stream is served over Socket.IO (See Events for the full payloads and reconnection/replay guidance.
bun add socket.io-client). Connect and receive deposit_detected and status_changed events as they happen.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 stablempsUserId so the same order always maps to the same deposit address, then watch for the terminal event.
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 oncompleted (success) or dead (gave up).
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.