GET REST responses are cached. A cache hit skips the Monid call entirely, so it costs nothing and returns faster than a fresh call would: measured on 2026-09-06, a cold ask took a median 5,256ms against 69ms once cached. Every response carries an X-Cache header telling you which one happened.
curl
X-Cache: hit, with no Monid call behind it.
What makes two requests “the same”
A cache entry is keyed on the request path plus the query parameters, sorted. Parameter order does not matter:?ticker=AAPL&limit=1 and ?limit=1&ticker=AAPL hit the same entry.
The cache is shared across callers by default. If someone asked for Apple’s balance sheet a minute before you, your call is a hit and bills nothing. This is safe because a response never contains anything specific to the caller; cost and provenance only appear on a traced request, and traced requests never touch the cache. An operator who does not want callers to benefit from each other’s spend can set CACHE_PER_CALLER=1, which adds the API key to the entry key.
How long entries live
A request names a closed period when it carries an
accession_number, a year before the current one, or an upper date bound (end_date, report_period, report_period_lte, report_period_lt, filing_date, filing_date_lte, filing_date_lt) before today. A lower bound alone (start_date, report_period_gte) does not count, because the newest period in the answer is still open. period=ttm never counts: a trailing-twelve-month row is priced at the latest close, so it always carries a live figure.
A day rather than forever, because a company can restate a closed period in a later filing.
What never gets cached
Non-GET requests, POST /financials/search/screener is the only one, are never cached. Requests with the X-Monid-Trace header bypass the cache, since the point of tracing is to see the route taken. Error responses, anything with a status of 400 or higher, are never cached either. The MCP transport at /mcp and /api is never cached, regardless of method.
Where entries live
By default the cache is in the server process: bounded to 4,096 entries, oldest evicted first, and gone on restart. SetCACHE_URL (and CACHE_TOKEN for Upstash, or a redis:// / rediss:// URL for Redis) and entries move to that store, where every machine shares them and a deploy does not throw them away. The hosted deployment at api.financialdatasets.rip runs this way. A store that cannot be reached counts as a miss, never an error; the cache is a latency and cost optimization, not a guarantee.