How Modan collects and validates provider FX rates
A rate is only as good as the process behind it. This page describes Modan's, plainly: where the numbers come from, how often, what checks they pass, and the things Modan refuses to do to them.
Updated 2 Sep 2026 · 5 min read · by Modan
Sources
Modan tracks named providers — IMTOs, fintechs, commercial banks, central banks, crypto venues and others — and records what each one publishes for a corridor. Every provider carries two labels: provider_type, what kind of institution it is, and rate_type, what kind of price it publishes (official, interbank, retail, p2p or parallel). The two are independent: a commercial bank may publish a retail board rate or an interbank one. The providers index lists every tracked source with both labels.
A provider is catalogued before it is counted. New sources are seeded inactive and only become part of coverage when a rate feed is live, so the corridor and provider counts never include a source Modan is not actually observing.
Cadence
Each provider's published rate is re-checked roughly every 15 minutes. Every observation is stored with the time it was observed, and nothing is overwritten: the history is append-only. The corridor and provider pages show the latest observation per provider and its timestamp; the history endpoints return the series.
Validation
An observation must name a tracked provider and a valid currency pair — the database, not a client, is the authority on both, and a malformed row is rejected rather than repaired. Rates are range-checked against the rest of the corridor at ingestion so a decimal slip does not become a record. What passes is stored as observed; what fails is not silently replaced with an estimate.
The independent mid
Provider quotes are benchmarked against a mid-market reference sourced separately from every provider and refreshed hourly. Pairs are crossed through USD from that feed, and a crossed mid carries the timestamp of its staler leg, never the fresher one. Every response names the feed in mid_source — that field, not this page, is the authority on where a given mid came from. Where the feed does not quote a currency (USDT, USDC) the mid is omitted, not estimated.
What Modan does not do
- No interpolation: a missing value is null or omitted, never filled from neighbours.
- No ranking across kinds: an official or parallel print is never crowned as the best rate, and spread is measured only within a rate type.
- No silent staleness: a provider whose feed breaks simply stops producing observations; its last quote stays visible with its timestamp and a freshness marker, and is never carried forward as if new.
- No unlabelled delay: Free and Individual API keys receive rates as of the top of the current UTC hour and every response says so; Team keys receive every observation in real time.
Retention and audit
Observations are kept indefinitely and are retrievable by corridor, provider and time through the API. Changes to the provider catalogue are logged separately. If you find a number that looks wrong, tell us with the corridor and timestamp; the observation will be checked against the source, and a correction, if one is warranted, is recorded as a new observation rather than an edit.
One thing can remove an observation from the API: a confirmed capture error. A rate recorded at ten or a hundred times its true value is a parsing failure, not a price, and leaving it in would misstate the market on every chart that includes it. Such an observation is withdrawn, not deleted — it moves to a quarantine record that keeps the original value, timestamp, who withdrew it and why, and it can be put back. Withdrawal never rewrites a rate in place, and it is only ever applied to a value the provider did not publish. Where we can establish what the provider actually published, the corrected observation is appended at the same timestamp as the one it replaces and the withdrawn record points to it — so the series reads correctly from then on, and the mistake stays on the record instead of disappearing.
One narrow case is corrected mechanically: a rate recorded a clean factor of ten from what every other provider quoted that day. A value of 1,371,027 where the market is near 1,364 is not a different opinion about the price — it is the same digits with a comma read as a thousands separator. Restoring the point recovers what the provider published rather than estimating it, and the digit sequence is left untouched; if putting the point back would need more precision than we store, the observation is left for a person instead. Anything that is not a clean power of ten is never corrected automatically, and every mechanical correction is recorded with the corridor median and the number of quotes it was judged against, so it can be checked or reversed.
Frequently asked questions
- Can I trust a single observation?
- Treat it as what it is: what one named provider published at one stated time, checked against the corridor at ingestion. Look at its timestamp and freshness, and at the history if the decision matters. Modan does not smooth, average or interpolate observations.
- What happens when a provider's feed breaks?
- New observations stop. The last one stays on the page with its timestamp and a freshness marker (live, recent or stale), and is never carried forward as if it were current. Coverage counts include the provider only while it has a current quote.
- Where does the independent mid come from?
- From a mid-market reference feed sourced separately from every provider and refreshed hourly, crossed through USD. The mid_source field in every response names the feed for that mid; at the time of writing every mid on record has come from open.er-api.