curl --request POST \
--url https://api.sand.etherfuse.com/organization/{organizationId}/quote \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"source": {
"type": "stored",
"id": "3f9a2c1e-5b7d-4e8f-9a01-2b3c4d5e6f70"
},
"destination": {
"type": "stored",
"id": "8c1d2e3f-4a5b-4c6d-8e7f-901a2b3c4d5e"
},
"sourceAmount": "1000",
"sourceAsset": "MXN",
"destinationAsset": "USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN"
}
'const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
source: {type: 'stored', id: '3f9a2c1e-5b7d-4e8f-9a01-2b3c4d5e6f70'},
destination: {type: 'stored', id: '8c1d2e3f-4a5b-4c6d-8e7f-901a2b3c4d5e'},
sourceAmount: '1000',
sourceAsset: 'MXN',
destinationAsset: 'USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN'
})
};
fetch('https://api.sand.etherfuse.com/organization/{organizationId}/quote', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.sand.etherfuse.com/organization/{organizationId}/quote"
payload = {
"source": {
"type": "stored",
"id": "3f9a2c1e-5b7d-4e8f-9a01-2b3c4d5e6f70"
},
"destination": {
"type": "stored",
"id": "8c1d2e3f-4a5b-4c6d-8e7f-901a2b3c4d5e"
},
"sourceAmount": "1000",
"sourceAsset": "MXN",
"destinationAsset": "USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"quoteId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"sourceAmount": "<string>",
"destinationAmount": "<string>",
"sourceAsset": "<string>",
"destinationAsset": "<string>",
"sourceRail": "spei",
"destinationRail": "spei",
"rateAfterFees": "<string>",
"rateBeforeFees": "<string>",
"feeBps": 123,
"feeAmount": "<string>",
"fees": [
{
"type": "transactionFee",
"amount": "<string>",
"asset": "<string>",
"bps": 123
}
],
"createdAt": "2023-11-07T05:31:56Z",
"expiresAt": "2023-11-07T05:31:56Z",
"midMarketRate": "<string>"
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}Create quote
Prices a transfer from one of the organization’s payment accounts to another. Both accounts must belong to the organization in the route. Pass the quote’s quoteId to POST /organization/{organizationId}/order with the same organizationId before expiresAt; a quote is valid for 2 minutes.
One side must be a wallet. Supported shapes: fiat to crypto (onramp), crypto to fiat (offramp), a same-chain swap between two wallets, and a cross-chain transfer of the same token between wallets on two supported chains. Fiat to fiat is not supported.
Rails. Each side moves on one rail. Omit sourceRail or destinationRail and we use the account’s default rail for that direction (the rail with isDefault: true in the account’s rails). When two of an account’s rails tie, name the rail. The account’s status for that direction on that rail must be ready, or the quote fails with 409 payment-account-not-ready.
Assets. Send an asset from GET /supported_assets: a currency code such as MXN for a fiat side, a token’s asset for a crypto side. Filter that list by paymentAccountId to see what each account can use.
Approval. The organization must be approved, or the quote fails with 409 organization-not-approved.
curl --request POST \
--url https://api.sand.etherfuse.com/organization/{organizationId}/quote \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"source": {
"type": "stored",
"id": "3f9a2c1e-5b7d-4e8f-9a01-2b3c4d5e6f70"
},
"destination": {
"type": "stored",
"id": "8c1d2e3f-4a5b-4c6d-8e7f-901a2b3c4d5e"
},
"sourceAmount": "1000",
"sourceAsset": "MXN",
"destinationAsset": "USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN"
}
'const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
source: {type: 'stored', id: '3f9a2c1e-5b7d-4e8f-9a01-2b3c4d5e6f70'},
destination: {type: 'stored', id: '8c1d2e3f-4a5b-4c6d-8e7f-901a2b3c4d5e'},
sourceAmount: '1000',
sourceAsset: 'MXN',
destinationAsset: 'USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN'
})
};
fetch('https://api.sand.etherfuse.com/organization/{organizationId}/quote', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.sand.etherfuse.com/organization/{organizationId}/quote"
payload = {
"source": {
"type": "stored",
"id": "3f9a2c1e-5b7d-4e8f-9a01-2b3c4d5e6f70"
},
"destination": {
"type": "stored",
"id": "8c1d2e3f-4a5b-4c6d-8e7f-901a2b3c4d5e"
},
"sourceAmount": "1000",
"sourceAsset": "MXN",
"destinationAsset": "USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"quoteId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"sourceAmount": "<string>",
"destinationAmount": "<string>",
"sourceAsset": "<string>",
"destinationAsset": "<string>",
"sourceRail": "spei",
"destinationRail": "spei",
"rateAfterFees": "<string>",
"rateBeforeFees": "<string>",
"feeBps": 123,
"feeAmount": "<string>",
"fees": [
{
"type": "transactionFee",
"amount": "<string>",
"asset": "<string>",
"bps": 123
}
],
"createdAt": "2023-11-07T05:31:56Z",
"expiresAt": "2023-11-07T05:31:56Z",
"midMarketRate": "<string>"
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}{
"type": "https://docs.etherfuse.com/ramp/v2/errors/quote-expired",
"title": "Quote expired",
"status": 400,
"detail": "quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not exist",
"instance": "tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d",
"errors": [
{
"pointer": "#/accountDetails/clabe",
"detail": "This field is required."
}
],
"required": [
"<string>"
],
"missing": [
"<string>"
]
}Authorizations
API key sent in the Authorization header, with no Bearer prefix.
Path Parameters
The organization this call acts for: your API key's organization or one of its customer organizations. Any other id returns 404 not-found.
Body
A payment account in a quote, tagged by type. Use stored with a registered account's id. inline is not supported yet and returns 400 invalid-request.
- stored
- inline
Show child attributes
Show child attributes
A payment account in a quote, tagged by type. Use stored with a registered account's id. inline is not supported yet and returns 400 invalid-request.
- stored
- inline
Show child attributes
Show child attributes
Amount the source sends, as a positive decimal string.
"1000"
An asset from GET /supported_assets: a currency code such as MXN for a fiat source, or a token's asset for a crypto source.
"MXN"
An asset from GET /supported_assets: a currency code for a fiat destination, or a token's asset for a crypto destination.
"USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN"
The rail the source moves on. Omit to use the source account's default rail.
spei, pix, solana, base, polygon, monad, stellar, avalanche The rail the destination moves on. Omit to use the destination account's default rail.
spei, pix, solana, base, polygon, monad, stellar, avalanche Partner fee for this quote in basis points, in place of your organization's default partner fee. Values above 500 are capped at 500.
x >= 0Response
The quote.
Pass to POST /organization/{organizationId}/order. Becomes the order's id.
Decimal string.
The network that moves the money. For a wallet, the rail is its chain.
spei, pix, solana, base, polygon, monad, stellar, avalanche The network that moves the money. For a wallet, the rail is its chain.
spei, pix, solana, base, polygon, monad, stellar, avalanche The rate the customer gets after fees, as a decimal string.
The rate before our fee, as a decimal string.
Total fee in basis points.
Total fee as a decimal string, in the source asset, rounded down to that asset's decimals. Each line in fees is in its own asset, so the lines do not add up to this total when their assets differ.
The fee lines. The order created from this quote returns the same lines.
Show child attributes
Show child attributes
Create the order before this time. 2 minutes after createdAt.
The mid-market FX rate, as a decimal string. Present only on quotes that convert between currencies.