Blog

Why a cache hit still costs a credit, and what the cache contract actually gives you

A cache hit on an enrichment API costs the same credit as a fresh fetch. Here is why, what the 24 hour freshness window covers, and how to store on top.

The Triguna team 16 August 2026

A cache hit costs one credit. So does a fresh lookup, and so does a 404. If you are reading the cache as a way to spend less, that is the wrong model, and it will surprise you on the invoice.

What use_cache actually does

use_cache is a boolean and it defaults to true. When a stored copy of the entity is under 24 hours old, the API serves that copy instantly instead of retrieving it again. Set the flag to false and you force a fresh retrieval. That is the entire knob.

GET /v1/people/profile?profile_id=williamhgates&use_cache=false

There is no separate cache endpoint and no way to peek without paying. A read is a read.

Why the cache hit still bills

Billing is one credit per answered lookup, at $0.005 per credit. The cache changes how fast the answer arrives, not whether you got one. A stored copy under a day old is the same data delivered faster, and it is charged the same single credit. You are paying for the retrieval, not for whether a fresh network round trip happened behind it.

This is the same logic that makes a 404 cost a credit: looking up an identifier that resolves to no record is a real retrieval, and it costs the same work as finding one. The pricing page has the per-status table, including which codes are free.

Read the age out of the headers, not the body

Provenance lives in the response headers and never in the JSON, so a cached response is not distinguishable from a fresh one by its body. It is distinguishable by its headers:

X-Data-Source: ...
X-Fetched-At: 2026-08-15T12:35:54Z
X-Data-Age-Seconds: 74210
X-Credits-Charged: 1
X-RateLimit-Remaining: 9

X-Data-Age-Seconds is how you tell a cache hit from a fresh fetch: a fresh fetch reads 0, and 74210 is a copy from about twenty hours ago, comfortably inside the window. X-Fetched-At is when the data was actually retrieved, not when you asked for it. Record both alongside the row so you know the true age of every field you stored. There is no source field inside the JSON to parse. The full header list is in the caching reference.

stale_fallback: where the cache does something a fetch cannot

The freshness window is not the only time a stored copy comes back. During an outage, the API can return a stored copy marked stale_fallback instead of erroring. That is the case where the cache earns its credit: it hands you last known good data when the live retrieval is unavailable. Handle it as a successful response with a caveat attached, not as a failure. A copy that is a week old usually beats a 503 in the middle of a signup.

We wrote about the version of this with no fallback at all, where the data simply stopped, in when your enrichment provider goes dark.

The cache is freshness, your database is cost control

Because a cache hit bills, the API cache is not where you save money. Your own storage is. The pattern is boring and it holds:

  1. Call once, store the whole response, not just the fields you parse today.
  2. Read from your database for anything inside your own freshness window.
  3. Call again only when your stored copy is older than the freshness you actually need.

The 24 hour window is a safety net against re-fetching data that barely changed. It is not a substitute for a stored copy you control, because it charges a credit every time it saves you a round trip. That is the argument in full in store the raw payload.

For a nightly job the arithmetic is stark. There is no bulk path, so N entities is N calls, at up to 10 requests per second, one credit each, cache hit or not. Decide your refresh cadence against your own stored X-Fetched-At, and pace the run so it does not overspend, which the nightly backfill guide walks through end to end.

When to force a fresh copy

Set use_cache=false when you specifically need data newer than the window, for example re-checking a company the hour a funding round is announced. It costs the same credit as a cached read, so freshness is the only reason to spend it, never cost. For everything else, leaving the flag true and letting a recent copy answer is faster and identical in price.

Next

  • Company API: the fields GET /v1/companies/details returns, and the slug that has to be exact.
  • Pricing: one credit per answered lookup, and which status codes cost nothing.
  • Store the raw payload: the storage layer the cache is not a substitute for.
  • Enrich on signup: where a cached read and a stale_fallback both keep a new user moving.
  • Nightly backfill: pacing N calls when every one bills, cache hit or not.

cachingcostbilling

Start with one request

Free credits on signup, no card required. Usage-based pricing after that.