- A channel that turns incoming USDC on Solana into EURC on Base
- A channel that turns incoming USDT on Ethereum into USDC on Arbitrum
How it works
1
The user gets a deposit address on Solana owned by MoonPay Enterprise
2
An
autoramp ties that address to the destination:i. it turns all incoming USDC into EURC on Baseii. and delivers it to the user’s connected wallet3
The user sends 1000 USDC to the deposit address
4
As soon as funds arrive, MoonPay Enterprise converts them to EURC on Base and delivers them to the destination wallet
Two ways to run a channel
Most swap channels use a standing autoramp, because the user decides how much to send. Both are shown below.
Prerequisites
Every step must complete before moving to the next. Sandbox-only steps are marked. Set these in your shell first. Every command on this page reuses them.1
Customer is Active
Your customer must have
Active status. This means they have signed the terms and conditions, completed identification (KYC/KYB), and signed any remaining required documents. See Onramp for a full onboarding walkthrough.2
Register the recipient wallet address
Register the destination wallet via Crypto Addresses for Travel Rule compliance. Self-hosted wallets require a signed proof-of-ownership message; hosted wallets require the custodian’s DID.The wallet you pass in
recipient_account must match an address you have already registered for this customer.3
Create the channel
Either create a standing autoramp, or request an exact-out quote and create a quote-source autoramp. Both are shown below.
4
Sandbox: approve the autoramp
An autoramp is created in In production, an autoramp reaches
Authorized status. In Sandbox you advance it yourself, which also provisions the mock deposit account that a simulated deposit needs:Approved on its own once its deposit account is provisioned and verified.Automation route: standing autoramp
Create an autoramp that converts USDC on Solana to EURC on Base at the current mid-market rate.Request
$AUTORAMP_ID lets you paste the remaining commands on this page straight into the same shell.
POST /api/autoramps requires an Idempotency-Key header. Use a unique UUID per request to prevent duplicate autoramps.The request uses
chain in recipient_account, but the response returns the same value as blockchain in recipient. Both are correct: map between them when comparing the request and response.Response
Error response
Validation failures return the error as a plain string body, not a structured object. Arecipient_account that does not match a wallet address you’ve already registered via Crypto Addresses returns 400:
422 covers the cases where the request is well formed but the customer cannot complete the action yet, for example "Customer is unable to complete the action. Consult the customer abilities API", which points you at GET /api/customers/{id}/abilities (see Onboarding).
deposit_rails is empty at Authorized. Poll GET /api/autoramps/{id} or subscribe to webhooks until status = Approved before sharing deposit details with end users. See Autoramp Status.Approved, the response includes the deposit wallet address under deposit_rails. Share it with the user along with the supported assets for that wallet (e.g. EURC, USDC). Non-supported assets sent to the wallet are returned to sender.
Shared EVM deposit address. An autoramp gets one deposit address per source chain, and every EVM chain on the same autoramp shares one address, so the EVM entries in
deposit_rails repeat the same string. Only the token and chain combinations listed in source_currencies are converted: a deposit arriving on an EVM chain you did not declare is not swept, even though the address matches. Declare every chain you want to accept when you create the autoramp. Non-EVM chains such as Solana get their own distinct address.Locked rate: exact-out quote
Use this when you need a precise amount of the destination token. Stablecoin to stablecoin pairs lock for up to 10 minutes.1
Request the quote
GET /api/autoramps/quoteSet amount_out for the exact destination amount, or amount_in to price a known source amount. Never set both. recipient_account_id is the UUID of the registered crypto address.amount_in (what the user must send), amount_out, an itemised fee breakdown, rate, rate_lock_valid_until, and a signature.2
Create the autoramp from the quote
POST /api/autorampsSubmit the signed quote payload verbatim.3
Share the deposit address and amount
Show your customer the
deposit_rails address and the exact amount_in figure. A deposit only matches a quote when its amount_in value and source currency match. Deposits that match no active quote, or only an expired one, are returned to sender.Quote-source autoramps can keep accepting new quotes over time via
POST /api/autoramps/{autoramp_id}/quotes. Standalone autoramps created without an initial quote cannot, and always execute at the current rate. See Quotes.Test the full flow in Sandbox
Creating the is half the integration. Simulate a deposit to confirm your webhook handler and reconciliation logic work before you take real money.1
Simulate an incoming deposit
POST /api/sandbox/transaction builds a transaction directly from the route, reusing its currencies, customer, and recipient. amount_in, amount_out, currency_in, currency_out, and state. See Sandbox for the optional fee, fx_rate, and initial_state fields.2
Drive the transaction to Completed
The simulated transaction starts in
Pending. Advance it to trigger the rest of the status webhooks.3
Check the webhooks you received
Your endpoint should have received a
transaction event when the deposit landed, followed by transaction_status events as it moved through FundsReviewInProgress, ConversionInProgress, PayoutInProgress, and Completed.Read transaction_status, not the deprecated status field, for the current state. Payload shapes and the full status table are in Monitoring payments; signature verification is in Webhooks.Once the destination token is delivered,
transaction_hash contains the on-chain hash.Simulate it in the Dashboard
You can run this same flow without writing a single API call. The Partner Dashboard covers every step, from creating the route to settling a simulated deposit.1
Create the route
Switch the sidebar to the App view and pick your customer in the customer selector at the top. Open Operations → Routes, then click on the card and choose .
2
Authorize the route
Go to Developer → Sandbox and open the Autoramps tab. Your new route appears under Unverified Autoramps. Set its status to Authorized using the dropdown on the right.
The dropdown offers Created, Authorized, and Rejected. Pick Authorized: that provisions the mock deposit account, which is what the simulated deposit needs. Sending
"Approved" to PUT /api/sandbox/autoramp/{id} provisions the same account and also moves the route to Approved, so use the API call if you want to see the Approved status your integration waits for.3
Create the simulated deposit
Still under Developer → Sandbox, click New Transaction in the top right. On the Create New Sandbox Transaction screen:
- Customer: search by name, email, or ID and select the customer who owns the route.
- Ramp: pick it from the dropdown. This field still uses the older wording for a route. Entries are labelled by currency pair, for example .
- Amount: enter the deposit amount in the route’s input currency.
4
Settle the transaction
Back on the Sandbox page, open the Transactions tab. Your transaction is listed under Pending Transactions with Accept and Reject buttons. Choose Accept to complete it, or use the Change state dropdown to move it to a specific state and test how your integration reacts.
5
Check the result
Open the transaction from Operations → Transactions to see amounts, fees, and . Webhooks fire exactly as they do on the API path, so this is a good way to exercise your endpoint before you write any integration code.
Move to production
Remove every
/api/sandbox/* call from your integration. Those endpoints do not exist in production.
What to read next
Stablecoins and Blockchains
Which tokens and chains are supported as sources and destinations
Quotes
Full quote reference: expiry policies, multi-currency input, attaching quotes over time
Crypto Addresses
Register self-hosted or hosted wallets for Travel Rule compliance
Autoramp Status
Every status an autoramp moves through, and what unblocks each one
Webhooks
Signature verification, payload schemas, and retry behaviour
Transaction Status
Status mapping, settlement times, and the polling API