Prerequisite: You need a KYC-approved wallet on your organization. See Registering Wallets & Bank Accounts. Swaps do not require a bank account.
For onboarding your customers, see Onboarding Customers.
Swaps are currently available on Stellar and Solana. EVM chains (Base, Polygon, Monad) support direct on/off-ramps but do not yet support crypto-to-crypto swaps.
Swap Flow
Discover Assets
Show Details
Show Details
Either of these endpoints will give you the asset identifiers needed for quotes:
- GET /ramp/assets — Requires auth. Returns only assets available for your specific blockchain, currency, and wallet. Best for building integrations where you already know the customer’s wallet.
- GET /lookup/stablebonds — Public, no auth. Returns all stablebonds across all chains with pricing and supply data. Best for exploring what’s available before onboarding a customer.
identifier from either response as the asset value in your quote.Swap constraint: The target asset must be a stablebond. The source asset can be any token (typically USDC).Asset identifier format differs by chain:
- Solana — Base58 mint address (e.g.
AvvetPGuuB5FD5m86fpw3LtDKyQoUFT1mG9WarNQLW4q) - Stellar —
CODE:ISSUERformat (e.g.CETES:GC3CW7...)
SYMBOL:0x... (Stellar format) on other chains will return UnsupportedBlockchain.USDC addresses for swap sources:
- Stellar sandbox:
USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5 - Stellar production:
USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN - Solana sandbox:
4D4r1KuS9WxbPCzzAJnWtYUJSSzDEZzrF1CbwajWGVjg - Solana production:
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
Create a Swap Quote — POST /ramp/quote
Show Details
Show Details
Quotes expire after 2 minutes. For swaps, set
type: "swap" with the source token identifier as sourceAsset and the stablebond identifier as targetAsset. The response includes requiresSwap: true and the exchangeRate between the two assets. See POST /ramp/quote for the full schema.Copy
Ask AI
curl -X POST https://api.sand.etherfuse.com/ramp/quote \
-H "Authorization: <api_key>" \
-H "Content-Type: application/json" \
-d '{
"quoteId": "<uuid>", # You generate this UUID
"customerId": "<org_uuid>", # From onboarding
"blockchain": "stellar",
"quoteAssets": {
"type": "swap",
"sourceAsset": "USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5",
"targetAsset": "CETES:GC3CW7EDYRTWQ635VDIGY6S4ZUF5L6TQ7AA4MWS7LEQDBLUSZXV7UPS4"
},
"sourceAmount": "10"
}'
Create the Swap — POST /ramp/swap
Show Details
Show Details
Unlike orders, the swap endpoint requires
blockchain and publicKey in the request body (these are not derived from the quote). The endpoint returns an empty 200 — all swap progress is delivered via webhooks. See POST /ramp/swap for the full schema.Copy
Ask AI
curl -X POST https://api.sand.etherfuse.com/ramp/swap \
-H "Authorization: <api_key>" \
-H "Content-Type: application/json" \
-d '{
"orderId": "<uuid>", # You generate this UUID
"quoteId": "<quote_uuid_from_step_2>", # From Step 2
"publicKey": "<wallet_public_key>", # From onboarding
"blockchain": "stellar"
}'
The
orderId here is a swap identifier you generate — it tracks this swap through webhooks. The optional targetWallet field lets you send the swapped tokens to a different wallet than publicKey.Sign the Transaction
Show Details
Show Details
After creating the swap, you’ll receive a Sign the
swap_updated webhook with the sendTransaction — a pre-built, encoded transaction ready to sign.Copy
Ask AI
{
"swap_updated": {
"orderId": "<swap_uuid>",
"customerId": "<org_uuid>",
"sendTransaction": "AQAAAA...encoded_transaction",
"status": "created"
}
}
sendTransaction using a wallet adapter and submit it to the testnet blockchain. Once confirmed, you’ll receive another swap_updated webhook with status: "completed".Do not build your own transaction. Always use the
sendTransaction provided in the webhook. This transaction is pre-built by Etherfuse with the correct swap parameters.Verify Completion
Show Details
Show Details
Monitor swap progress via
swap_updated webhooks. Status progression: swap_created → swap_funded → swap_completed (or swap_failed). Register a webhook for the swap_updated event type via POST /ramp/webhook.Unlike on/off-ramps, there is no polling endpoint for swap status — webhooks are the only way to track progress.
Interactive Tutorial
Use the interactive tutorial below to test the swap flow with your sandbox API key. Each step builds on the previous one, and you can edit the request bodies before sending.Show Chain-specific swap examples
Show Chain-specific swap examples
Stellar — USDC to CETES:Solana — USDC to CETES:
Copy
Ask AI
{
"blockchain": "stellar",
"quoteAssets": {
"type": "swap",
"sourceAsset": "USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5",
"targetAsset": "CETES:GC3CW7EDYRTWQ635VDIGY6S4ZUF5L6TQ7AA4MWS7LEQDBLUSZXV7UPS4"
}
}
Copy
Ask AI
{
"blockchain": "solana",
"quoteAssets": {
"type": "swap",
"sourceAsset": "4D4r1KuS9WxbPCzzAJnWtYUJSSzDEZzrF1CbwajWGVjg",
"targetAsset": "AvvetPGuuB5FD5m86fpw3LtDKyQoUFT1mG9WarNQLW4q"
}
}
Show Common errors
Show Common errors
| Error | Cause | Fix |
|---|---|---|
InvalidSwapTarget | Target asset is not a stablebond | Swap target must be a registered stablebond — use identifiers from /lookup/stablebonds |
UnsupportedBlockchain | Swaps not yet available on this chain, or using wrong identifier format | Swaps are currently available on Stellar and Solana. Check your asset identifier format. |
Quote not found or expired | Quote TTL is 2 minutes | Create a fresh quote |
Terms and conditions have not been completed | Wallet not KYC-approved | Complete the onboarding flow |
Unexpected | Swap provider (Jupiter/SDEX) returned an error | Check that the source asset has testnet liquidity against the target |