An indicative rate previews a price. A binding quote locks it. How to show a live price while the user types, then lock it before they pay.
An indicative rate is a price preview: the provider shows what a conversion would cost right now but does not commit to it. A binding quote is a price the provider will execute at, for a stated window, under a quote ID. Good payment UX uses both: the preview while the user types, the quote when they commit.
Most teams get this backwards. Some create a binding quote on every keystroke, which burns quotes and requests for nothing. Others show a cached rate and settle at a different one, which is slippage with extra steps. This guide covers the two-call pattern, what each BlindPay response contains, and the four reasons a preview and a quote disagree.
Key takeaways
POST /payin-quotes/fx returns an indicative rate and creates nothing. POST /payin-quotes returns a quote that holds for 5 minutes.An indicative rate tells you where the price is. A binding quote tells you what you will get. The glossary for this cluster defines both the same way: a firm (binding) quote is a price the provider commits to execute at, and an indicative rate is shown for information only.
FX markets treat the line between the two as a conduct issue. The FX Global Code (updated December 2024), Principle 9, says market participants handling orders should "make clear whether the prices they are providing are firm or merely indicative." Payment APIs should be just as clear.
| Indicative rate | Binding quote | |
|---|---|---|
| Provider commits to it? | No | Yes, for the stated window |
| Has an ID you can execute against? | No | Yes |
| Has an expiry? | No | Yes (expires_at) |
| Stored by the provider? | No | Yes |
| Who carries a market move? | You, at execution | The provider, inside the window |
| Right place in the UI | Amount field, calculators, corridor pages | Confirm screen, approval lists |
| BlindPay payin endpoint | POST /payin-quotes/fx | POST /payin-quotes |
Because a binding quote is a commitment, and commitments are not free. Each one asks the provider to stand behind a price for minutes, and almost all of them will expire unused if you create one per keystroke.
Three practical problems follow:
429 with a Retry-After header (sandbox vs production). A busy amount field gets there fast.Preview while the amount changes, lock when the user commits. Five steps:
expires_at.The on/off-ramp liquidity guide explains why the window length shapes which of these screens you can afford.
POST /instances/{instance_id}/payin-quotes/fx returns an indicative rate and amount without creating a payin quote. Per the payin quotes docs, it doesn't persist anything and doesn't reserve pricing.
| Field | Direction | What it means |
|---|---|---|
from | Request | The fiat currency the payer sends, for example BRL |
to | Request | The stablecoin the destination receives: USDC, USDT, or USDB on development |
request_amount | Request | Minor units, minimum 500 ($5.00). MXN, COP, and ARS sender amounts must be whole units |
currency_type | Request | sender or receiver, same meaning as on a payin quote |
commercial_quotation | Response | The raw market rate |
blindpay_quotation | Response | The rate including BlindPay's fee |
result_amount | Response | The other side of the conversion |
instance_flat_fee | Response | The flat-fee component |
instance_percentage_fee | Response | The percentage fee, in basis points |
The preview covers the payin direction: from is a fiat currency and to is a stablecoin. On the payout side, the payout quote itself is what you show on the confirm screen.
An ID, an expiry, and every fee line. A payin quote response carries id, expires_at (epoch milliseconds), sender_amount, receiver_amount, commercial_quotation, blindpay_quotation, flat_fee, partner_fee_amount, billing_fee_amount, and is_otc.
It holds for 5 minutes by default. OTC payin quotes, BRL only and priced through BlindPay's OTC desk, hold for 10 seconds. Payout quotes also default to 5 minutes, and SEPA payout quotes can be shorter because the rail's own deadline can be tighter (cut-off times). An expired quote is rejected when you try to use it, and nothing moves. The field-by-field tour lives in stablecoin API quotes explained.
Four reasons, and only the first one is the market.
/fx endpoint takes no partner_fee_id, so instance_percentage_fee never includes your own markup. If your platform adds a partner fee, the preview looks better than the quote. Add your markup to the preview yourself.cover_fees, which decides whether the payer pays the fee on top or the recipient absorbs it. Make sure your preview math assumes the same direction you'll send on the quote.Illustrative example. A payer types R$10,000 at 09:00:00. The preview shows a blindpay_quotation of 5.45 BRL per USDC:
That 18 bps is not slippage. The payer never agreed to 1,834.86. They agree to 1,831.50, and that is what lands. Label the preview as an estimate and nobody feels cheated.
Locking a price means someone carries the market risk for the length of the lock, so longer locks cost more. Stripe's FX Quotes API makes the trade-off visible: a lock_duration of none returns an informational rate at no charge, while 5-minute, 1-hour, and 24-hour locks add a duration premium. For BRL, MXN, and COP, which sit in Stripe's second currency group, that premium is 0.12% for 5 minutes, 0.15% for 1 hour, and 0.30% for 24 hours.
Illustrative example. On a R$50,000 conversion, a 0.12% lock costs R$60 and a 0.30% lock costs R$150. The 24-hour lock costs 2.5 times the 5-minute lock for the same money. Short windows are cheap because the provider carries little risk, which is why binding quotes across the industry last minutes, not days. If you want the treasury view of longer locks, see live quote vs forward contract vs fixed rate.
Whenever nobody confirms a number they expect to pay or receive. That covers:
Decision rule: if a person confirms an amount, require a binding quote. If a person is only browsing, an indicative rate is fine, as long as it is labeled as an estimate. Why buy and sell prices differ in the first place is covered in why on-ramp and off-ramp rates differ, and the on-ramp integration guide shows where the payin quote sits in the full flow.
Wire the two calls into your amount screen on a free development instance: debounce /payin-quotes/fx for the typing phase, then create the binding quote on Continue. The payin quotes reference has both requests and every field.
Seven places blockchain payments beat bank rails: contractor payroll, remittances, B2B suppliers, marketplaces, 24/7 treasury, bill pay, and PSP payouts.
AP2, ACP, and x402 each verify that an AI agent had permission to spend. Here is what every protocol covers, who backs it, and the reconciliation gap none of them close.
The three roles behind every card program, stablecoin cards included: what each one does, who carries liability, and what to ask a provider.