Quotes & Pricing

How currency pairs are priced, and when you need a quote.

POST /v1/customers/{customerId}/quotes

This endpoint has one job, which is to price an FX pair. That price becomes the LP_EXECUTION leg of whatever consumes it.

What a quote becomes

A quote has no transaction type of its own. What you do with it decides that.

Consumed byBecomes
POST /v1/customers/{customerId}/conversionsA CONVERSION. Both sides are the customer's own balances.
POST /v1/customers/{customerId}/payouts/fiatA PAY_OUT, with the FX running as a leg inside it. Value leaves the customer.
NothingA pay-in never consumes a quote. The deposit intent's indicativeRate is its price.

There is no buy side or sell side. A quote is a directed pair with the amount fixed on one end.

Setting the amount

Set fromAmount to fix what's debited, or toAmount to fix what lands. Sending both is an error rather than a way to constrain both ends.

Use toAmount when the recipient has to receive an exact figure, such as settling an invoice. Use fromAmount when the debit is the fixed side, such as sweeping a balance.

The two conditional fields

chain and rail mirror each other. Each one is governed by one half of the pair.

Pair shapechainrail
stablecoin to fiat, or fiat to stablecoinrequiredrequired
fiat to fiatomitrequired
stablecoin to stablecoinrequiredomit

Supplying a field the pair shape forbids fails the request with pair_shape_violation rather than being ignored.

Why the rail is part of the price

(rail, currency) names the route being priced.

Rails into the same corridor don't cost the same. A quote that didn't know the rail could only return an average, and the difference would land in Alfred's margin instead of the customer's rate. (ACH, BOB) and (ACH, CLP) price separately. (CHATS, USD) means US dollars delivered in Hong Kong, which prices differently from US dollars delivered in the US.

So a quote is priced for one rail and can't be moved to another. A SPEI quote can't fund a PIX payout, and trying gets you rail_mismatch.

When you don't need one

Two cases come up regularly.

The first is a same-currency movement. When the funding balance and the destination share a currency there is no FX leg. A USD Corporate Account paying out to a USD account over ACH is a plain transfer, and so is an MXNa balance paying out to MXN over SPEI.

The second is par redemption. USDC or USDT going to USD is priced from the fee table at par. You may pass a quote to lock fees, but it is never required.

Alfred never introduces an artificial conversion to make a transaction fit a shape.

The route registry tells you which case applies. GET /v1/countries/{country} carries a quote object per route, broken down by pair shape.

Fees

Provider fees, network fees and Alfred's fee come back as separate itemized entries. They are never folded into the rate.

Rounding residuals post to the reconciliation account. They are never absorbed into a customer's conversion.

Your rates and fees are commercial terms that you agree with us separately. Read what a given movement costs from the quote instead of from a stored rate card. The quote is priced for the specific pair and rail you asked for.

Checking the numbers yourself

The quote response carries everything you need to verify the arithmetic rather than take it on trust.

FieldWhat it is
fromAmountWhat gets debited
toAmountWhat lands
rateThe FX rate applied
fees[]Each fee as its own entry, with a type, an amount and a currency
rateLockedAtWhen the rate was fixed
expiresAtExecute before this. Typically around two minutes

The type on each fee is one of provider, network, alfred, conversion or payout. Nothing is aggregated, so you can attribute every charge.

The currency on a fee tells you which side it lands on. A fee denominated in fromCurrency comes off the source. A fee denominated in toCurrency comes off what arrives. Group the fees by currency and you can reconstruct both ends.

Store the whole quote rather than only the rate. When you reconcile against a statement later, rateLockedAt and the itemized fees are what let you explain a figure that someone is querying.

Confirm against a real sandbox quote whether a source-side fee is deducted before the rate is applied or after. The response gives you fromAmount, toAmount, rate and every fee, so one live quote settles it for your own reconciliation.

Executing

GET /v1/quotes/{quoteId}

This re-reads the rate, the fees and the expiry. Use it to recover if you lost the create response.

Execution has to land inside expiresAt. An expired quote gets quote_expired, and the fix is to request a new quote. A quote that has already been used gets quote_consumed.

One more check happens before anything is locked. A pair whose route isn't LIVE fails with route_unsupported.


Did this page help you?