---
title: "How to publish a daily FX rate sheet from live quotes without promising a price you can't honor"
seoTitle: "How to publish a daily FX rate sheet from live quotes"
description: "Build a daily indicative rate sheet for customers or sales from live quote data: which endpoint to pull, timestamps, disclaimer wording, refresh cadence."
date: "2026-10-13"
updated: "2026-10-13"
category: "payments"
author: "BlindPay Team"
howto:
  name: "How to publish a daily indicative FX rate sheet from live quotes"
  steps:
    - name: "Pick the corridors and a reference amount"
      text: "List the currency pairs your customers ask about and choose one reference amount per pair, so every row is priced at a comparable size."
    - name: "Pull indicative rates at a fixed time"
      text: "Call the indicative endpoint for payin rows and take payout rows from a reference payout quote, all inside the same few minutes."
    - name: "Add your own markup"
      text: "Apply any partner fee to the indicative numbers yourself, because the preview's fee fields cover BlindPay's fee only."
    - name: "Stamp and label every row"
      text: "Print the snapshot time with time zone, the word indicative, and the disclaimer on the sheet itself, not in a footnote elsewhere."
    - name: "Publish and refresh on a schedule"
      text: "Send the sheet at the same time every day, refresh intraday on volatile corridors, and archive each version."
    - name: "Execute only on binding quotes"
      text: "When a customer wants to transact, create a binding quote and show its numbers, whatever the sheet said."
faq:
  - q: "What is an FX rate sheet?"
    a: "A rate sheet is a list of exchange rates a company shares with customers or its sales team, usually once a day, so people can estimate costs without calling an API. It is indicative by design. Each row shows a currency pair, a rate, a reference amount, and the time the snapshot was taken. Actual conversions always run on a binding quote created at the moment of the transaction."
  - q: "Can a customer hold me to a rate on my rate sheet?"
    a: "Only if your terms say so, which is why the sheet should say clearly that it is indicative. The FX Global Code asks market participants to make clear whether the prices they provide are firm or merely indicative. Put the word indicative on every row, add the snapshot time, and state that the transaction executes at the rate in the binding quote."
  - q: "Which BlindPay endpoint should feed a rate sheet?"
    a: "For payin rows, POST /payin-quotes/fx returns an indicative rate and amount without creating a quote or reserving pricing. It covers fiat to stablecoin pairs, such as BRL to USDC. For payout rows, take the rate from a payout quote created against a reference bank account at snapshot time. It expires unused after 5 minutes, and no money moves until a payout executes."
  - q: "How often should a rate sheet refresh?"
    a: "Daily is the floor, at a fixed time customers can learn. Corridors that move fast, such as ARS or COP, may need an intraday refresh or a shorter validity note. Align the snapshot with a time your audience already watches, for example after Banxico publishes the FIX at 12:00 Mexico City time, and archive every version."
  - q: "Why does the binding quote differ from my rate sheet?"
    a: "Time, size, fees, and markup. The market moved since the snapshot, the customer's amount differs from the reference amount, the fee direction may differ, and the indicative endpoint's fee fields cover BlindPay's fee only, before any partner fee you add. A sheet that states its reference amount and snapshot time makes the difference easy to explain, which keeps sales conversations short."
---

A daily FX rate sheet is an indicative price list built from live quote data: one row per currency pair, priced at a stated reference amount, stamped with the snapshot time, and labeled as an estimate. Customers use it to plan. Every real conversion still runs on a binding quote created at the moment of the transaction.

Sales teams want a number to send. Customers want to budget before they log in. A rate sheet serves both, as long as nobody mistakes it for a price. The API-level difference between previews and quotes is in [indicative rate vs binding quote](/resources/more/indicative-rate-vs-binding-quote-api). This page is the publishing workflow on top of it.

**Key takeaways**

- A rate sheet is information, never a commitment. Say "indicative" on every row.
- Price every row at a stated reference amount and snapshot time, so differences have an explanation.
- At BlindPay, `POST /payin-quotes/fx` previews payin rates without creating or reserving anything.
- The preview excludes your own partner fee. Add your markup to the sheet yourself.
- Publish at a fixed time, refresh volatile corridors intraday, and archive every version.

## What belongs on a rate sheet?

Five columns per row and one paragraph of terms. Anything less invites the "but your sheet said" email.

| Column | Example | Why it's there |
| --- | --- | --- |
| Pair and direction | BRL to USDC (payin) | Buy and sell rates differ, so direction is part of the price |
| Indicative rate | 5.46 BRL per USDC | The number people came for, in the quoting convention they expect |
| Reference amount | R$ 10,000 | Rates can vary by size, so state the size you priced |
| Snapshot time | 2026-10-13 12:05 America/Mexico_City | Tells the reader how stale the number is |
| Status | Indicative | Repeated per row, because rows get copied out of context |

Rates read as units of local currency per one stablecoin, the way BlindPay quotes return them. [How to read an FX quote](/resources/more/how-to-read-an-fx-quote) explains the convention, and getting it wrong on a sheet sent to 200 customers is a bad morning.

## Which data should feed the sheet?

Live quote data from the provider you actually execute with, pulled at one moment. Screen rates from a search engine or a market data feed tell you where the market is, not what your customers will get.

**Payin rows.** BlindPay's `POST /payin-quotes/fx` endpoint "returns an indicative rate and amount without creating a payin quote," per the [payin quotes docs](/docs/payin-quotes). It previews a payin direction only: `from` is a fiat currency and `to` is a stablecoin. The response carries `commercial_quotation` (the market rate), `blindpay_quotation` (the rate including BlindPay's fee), `result_amount`, `instance_flat_fee`, and `instance_percentage_fee`. The minimum `request_amount` is 500 minor units.

**Payout rows.** Take them from a payout quote created at snapshot time against a reference bank account for each currency. The [payout quote](/docs/payout-quotes) returns the same two rate fields, holds for 5 minutes, and expires unused. Nothing moves until a payout executes against it.

**Your markup.** The `/fx` preview takes no `partner_fee_id`, so its fee fields never include your own margin. If you add a partner fee, apply it to the sheet's numbers yourself. [Partner fees on live quotes](/resources/more/partner-fees-markup-on-live-quotes) shows the math.

Pull every row inside the same few minutes. A sheet whose BRL row is from 09:00 and MXN row from 11:00 can't be compared line by line.

## How should the disclaimer read?

Short, specific, and on the sheet itself. The [FX Global Code](https://www.globalfxc.org/uploads/fx_global.pdf), Principle 9, says market participants should "make clear whether the prices they are providing are firm or merely indicative." Central banks follow the same habit for their own reference rates: the ECB says its [euro reference rates](https://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html) are "published for information purposes only" and that "using the rates for transaction purposes is strongly discouraged."

A template that covers the four questions people ask:

> Indicative rates as of 12:05 America/Mexico_City on October 13, 2026, priced at the reference amount shown per row. These rates are for information only and are not an offer. Every conversion executes at the rate and fees in the binding quote shown before you confirm. Quotes are valid for a limited time, usually 5 minutes.

Have legal review it once. Then never edit it per email.

## How often should the sheet refresh?

Daily at a fixed time, with intraday updates where the corridor moves faster than your readers can tolerate. Pick the time your audience already watches.

| Audience | Good snapshot time | Reason |
| --- | --- | --- |
| Mexico-facing sales | After 12:00 Mexico City | Banxico releases the FIX "a partir de las 12:00 horas" on banking business days ([Banxico](https://www.banxico.org.mx/tipcamb/tipCamMIAction.do?idioma=sp)) |
| Euro-facing customers | After 16:00 CET | The ECB updates reference rates "at around 16:00 CET every working day" |
| Brazil-facing customers | Late morning São Paulo | Your readers are at work and can act on it the same day |
| Volatile corridors (ARS, COP) | Twice a day, or a 2-hour validity note | Rates can move more inside a day |

Mind your request budget when you automate it. A sheet with 6 corridors in 2 directions is 12 calls per refresh, which is nothing. A sheet that refreshes every minute on a development instance runs into the roughly 100 requests per minute cap, which returns a `429` with a `Retry-After` header ([sandbox vs production](/docs/learn/sandbox-vs-production)).

## How do you stop the sheet from becoming a promise?

By making the binding quote the only path to a transaction. Three rules:

1. **Sales never quotes from the sheet in writing as a price.** They quote it as an estimate and send the customer to the confirm screen.
2. **The product never prefills a payment with a sheet rate.** The confirm screen always shows the binding quote's `blindpay_quotation`, fees, and received amount, plus a countdown from `expires_at`.
3. **Support answers differences with the sheet's own metadata.** Snapshot time and reference amount explain most gaps in one sentence.

**Illustrative example.** The sheet at 12:05 shows BRL to USDC at 5.46 for R$ 10,000, so about 10,000 / 5.46 = 1,831.50 USDC. A customer opens the app at 15:40 and converts R$ 10,000. The binding quote comes back at 5.49: 10,000 / 5.49 = 1,821.49 USDC. The gap is 10.01 USDC, or 10.01 / 1,831.50 x 10,000 = about 55 bps, from three and a half hours of market movement. The sheet did its job: the customer budgeted within 0.6% and paid the quoted price, not a stale one.

If the customer wants certainty on a future date, a sheet is the wrong tool. [Live quote vs forward contract vs fixed rate](/resources/more/live-quote-vs-forward-contract-vs-fixed-rate) covers the instruments that lock longer, and [how on/off-ramp providers make money](/resources/more/how-onramp-offramp-providers-make-money) explains why holding a price for hours costs someone money.

## What should you archive?

Every version, with the raw responses. Store the request time, the request body, and the full response for each row, plus the published file. When a customer disputes a conversion months later, you can show what the sheet said, when, and that the transaction ran on a separate binding quote with its own ID. Keep the archive next to your quote records so finance has one place to look.

## What to do next

Script the sheet on a development instance first: call `/payin-quotes/fx` for each payin pair, add your markup, stamp the rows, and render the disclaimer. The [payin quotes reference](/docs/payin-quotes) documents every field the script reads.
