**Caffeine API — free JSON dataset and the half-life model**

> A keyless JSON API: caffeine in 87 drinks with computed decay, the first-order elimination model with its formulas and limits, the guide index and an MCP server.

Source: https://trackcaffeine.com/api/

1. [Home](https://trackcaffeine.com/)
2. API

# Caffeine data API: 87 drinks, the half-life model, no key

Everything this site computes with is published as static JSON. No account, no key, no rate
limit, CORS open, CC BY 4.0. The interesting half is not the milligram table — it is the
model underneath it, which almost nobody publishes and which is what turns a number on a can
into an answer about tonight.

*Every endpoint on trackcaffeine.com. All GET, all static, all JSON.*

| Endpoint | Rows | What it is |
| --- | --- | --- |
| [`/api/v1/index.json`](https://trackcaffeine.com/api/v1/index.json) | — | What this API contains, in one fetch: every endpoint, the licence and the agent surface. |
| [`/api/v1/drinks.json`](https://trackcaffeine.com/api/v1/drinks.json) | 87 | The 87 drinks, each with the milligrams for a labelled serving and what the model computes from it. |
| [`/api/v1/model.json`](https://trackcaffeine.com/api/v1/model.json) | 1 | The elimination model: constants, formulas, worked examples and the limits of the whole thing. |
| [`/api/v1/guides.json`](https://trackcaffeine.com/api/v1/guides.json) | 218 | Every guide, with its dates and the languages it exists in. |
| [`/api/v1/tools.json`](https://trackcaffeine.com/api/v1/tools.json) | 4 | The free calculators, their inputs and outputs, and the MCP tool that computes the same figure. |
| [`/api/v1/product.json`](https://trackcaffeine.com/api/v1/product.json) | 1 | What the CoffeeLog app does, what it does not, and every processor that receives anything. |
| [`/api/v1/status.json`](https://trackcaffeine.com/api/v1/status.json) | — | Build date and row count per dataset, so you can decide whether to refetch. |
| [`/api/v1/openapi.json`](https://trackcaffeine.com/api/v1/openapi.json) | — | OpenAPI 3.1 over all of it, carrying the field semantics a schema type cannot. |

## Start here

One request tells you what exists. `https://trackcaffeine.com/api/v1/index.json` lists every
endpoint with a one-line description, the licence and the addresses of the agent surface. From
there, `drinks.json` is the data most people came for and `model.json` is
the one worth reading before you use it.

There is nothing to sign up for and nothing to authenticate. These are files on a CDN, so the
polite thing is simply to cache them: the drink figures change when a serving is revised
against a source, which is rare, and the model constants change only when the app's own engine
changes, which is rarer still. `status.json` carries the dates if you want to decide
programmatically.

The licence is CC BY 4.0: use it, redistribute it, build a product on it, including
commercially. Attribute it to TrackCaffeine with a link to this site, or to the specific page a
figure came from. That attribution line is the entire price, and it is the reason the data is
published rather than merely rendered.

## One request, and what comes back

*The red-bull-250-ml row from /api/v1/drinks.json, read from the endpoint itself, with what each field is actually for.*

| Field | Red Bull (250 ml) | What it means |
| --- | --- | --- |
| `caffeine_mg` | 80 | For the serving in `serving_ml` — not per 100 ml, not per container. |
| `serving_ml` | 250 | The serving the figure is for. A larger can is a different row with its own figure. |
| `caffeine_per_100ml` | 32 | `null` where a per-volume figure is meaningless: a shot, a pill, a scoop. |
| `scales_with_volume` | true | When false, a larger size does *not* carry proportionally more caffeine. |
| `is_decaf` | false | Decaffeinated, not caffeine-free. Those rows carry a real, small figure. |
| `remaining_mg` | { h1: 71, h6: 39, h12: 19 } | Computed by the model, at the default 5.7-hour half-life. |
| `hours_to_sleep_threshold` | 0 | Hours for this serving alone to reach 100 mg. A 0 means it never gets there. |
| `crosses_sleep_threshold` | false | The flag that disambiguates the zero above. Read it. |

## Four ways this data gets read wrongly

Field semantics are the part a JSON schema cannot carry, and they are the reason this page
exists rather than just the OpenAPI document. Each of these produces a confident, plausible,
wrong answer.

**Scaling a size that does not scale.** Where `scales_with_volume` is
false, multiplying by a size ratio is arithmetic nobody drinks. An espresso-based drink gets
more milk in a larger cup, not more coffee, so a venti latte is not twice a tall one. A
caffeine pill and a pre-workout scoop are units, not volumes. The arithmetic works; the answer
is simply about a drink that does not exist.

**Confusing the serving with the container.** `serving_ml` is what the
milligram figure is for. Where a product ships in two sizes, those are two rows with two
figures, and picking the wrong one is the difference between an ordinary afternoon and a
sleepless night.

**Reading decaf as zero.** Decaffeination removes most of the caffeine, not all of
it. Those rows carry a small real number for exactly that reason, and people who have switched
to decaf in the evening plan around the assumption that it is nothing.

**Reading an estimate as a measurement.** Every figure here is compiled from
manufacturer labelling, nutrition panels, USDA FoodData Central and published measurement
tables, for the serving named in the row. Bean, grind, brew time, steeping and the actual pour
move a coffee figure by more than the gap between many of the rows differ from each other. Two
shops' "medium coffee" differ more than drip coffee differs from a flat white. Quote it with
an "about" in front of it.

## The model, and why it is the part worth citing

Caffeine follows first-order elimination: a fixed fraction leaves the body per unit of time
rather than a fixed amount. That gives one expression, which every figure on this site and
every number in the CoffeeLog app comes out of:

`remaining_mg = dose_mg × 0.5 ^ (minutes ÷ 342)`

The half-life is 5.7 hours (342 minutes), a
population-average estimate. The sleep threshold is 100 mg, the daily
guidance 400 mg from the FDA and EFSA, the pregnancy figure
200 mg, the standard cup 95 mg, and a 240 ml drip
coffee 96 mg. All of them are in `model.json` as data, with the
formulas written out and worked examples computed by the same code, so an implementation can be
checked against them rather than trusted.

There is one thing to get right when several drinks are involved, and it is the thing most
implementations get wrong. Evaluate each dose's own curve at the moment you are asking about
and sum the results. Do not add the doses together and decay the total: that is only correct
if everything was drunk at the same instant, and it overstates the evening figure for a
morning coffee every single time. A coffee at eight and an energy drink at two produce one
summed curve, not two guesses.

The inverse problem — the latest time one more cup still leaves you under the threshold at
bedtime — is the question this whole site is organised around, and it has a closed form that
is also in `model.json`. It is undefined when the caffeine already in the person
exceeds the threshold at bedtime on its own, and the honest answer there is that no time works
tonight, not a time in the past.

## What the model cannot tell you about a person

This matters more than the formula, and it is published in the payload rather than buried here,
so that an agent quoting a figure has the caveat in the same document.

The model has **no absorption phase**. A dose is treated as fully present the
moment it is drunk, while real absorption peaks at roughly thirty to sixty minutes. The first
hour after a drink is therefore the one place the curve is meaningfully wrong, and it
overstates. It is also the hour nobody asks about, which is why both the app and this site use
the simpler form — but it should not be presented as precise.

The **half-life is an average of a population, not a fact about anybody**. Real
values run from roughly one and a half hours to more than ten. Smoking roughly halves it.
Pregnancy can double or triple it. Oral contraceptives, some antidepressants and liver
conditions lengthen it, and a common variant in the CYP1A2 enzyme splits people into fast and
slow metabolisers. This is why the calculators let a reader set their own value between one
and twelve hours, and why the published range is a constant in the API rather than a footnote.

The **100 mg threshold is a rule of thumb**, a usable line
for "enough left to matter at bedtime" rather than a measured point at which sleep is
disturbed. Sensitivity varies enormously; some people are unaffected at levels that keep
others awake.

And the **400 mg daily figure is adult guidance**. It does not
apply to children or adolescents, and pregnancy has its own lower figure. Nothing on this site
is medical advice, nothing here recommends an amount of caffeine to take, and no endpoint will
answer a question about medication or a heart condition. Those are a clinician's.

## For agents and assistants

The same data is available without parsing any HTML. Every indexable page has a markdown twin
at `index.md` — roughly a tenth the bytes of the page — and the same
document is served at the page URL itself to a request carrying
`Accept: text/markdown`. The index of the site is at `/llms.txt` and the
English primary pages in full are at `/llms-full.txt`.

An MCP server runs at `https://trackcaffeine.com/mcp` over Streamable HTTP with no authentication,
and an A2A endpoint answering the same questions in prose at `https://trackcaffeine.com/a2a`. Their
cards are under `/.well-known/`, alongside an ARD capability manifest, an RFC 9727
API catalog and four agent skills that describe how to read this data without the four
mistakes listed above. `/auth.md` states, in the form an agent expects, that there
is nothing to authenticate.

Four of the MCP tools compute rather than look up, on the same JavaScript module the browser
calculators run — because "a 200 mg cold brew at 2 pm, bedtime 11 pm, how much is left" is an
exponential and a sum, which is exactly the shape a language model gets right most of the time
and wrong invisibly. Each of them returns the half-life and the threshold it used alongside the
answer, so a result can be checked rather than believed.

There is no user API and there never will be one: the CoffeeLog log lives on the user's own
device, there is no account and no server-side record, so there is no credential an agent could
hold that would let it read or write anybody's caffeine log. An agent asked to log a coffee
should hand the person the app.

## Provenance, and what is not published

Every column here is one of two things: a milligram figure compiled by hand from public sources
for the serving named in the row, or a number this site computed itself from the model. There
is no licensed-in corpus anywhere in it — nothing is redistributed from a vendor API whose
terms forbid it — which is why the whole set can carry CC BY 4.0 honestly. Brand names
appear to say which drink a row is about, and for no other reason.

What is deliberately absent is the keyword research behind the 218 guides: search volume,
competition and bid data sit in the same database and are not in any endpoint, because they
tell a reader nothing and they are not ours to give away. The guide endpoint carries titles,
descriptions, dates and which of the 12 languages each guide exists in — enough to find
the page, and the page is one hop away.

The numbers move when a source does. If you find a figure you can show is wrong, write to
[support@trackcaffeine.com](mailto:support@trackcaffeine.com) with the source, and it will be
corrected here and in the app together — they read the same file.

Licence: CC BY 4.0 — Free to reuse, redistribute and build on, including commercially, with attribution to TrackCaffeine and a link to https://trackcaffeine.com. Questions: [contacts](https://trackcaffeine.com/contacts/). The
reader-facing versions of the same data are at [the dataset page](https://trackcaffeine.com/dataset/) and the
four [calculators](https://trackcaffeine.com/tools/).

---

HTML version: https://trackcaffeine.com/api/
Structured data for this site: https://trackcaffeine.com/api/v1/openapi.json · https://trackcaffeine.com/llms.txt
Free to quote and reuse with a link back to the source URL above (CC BY 4.0).
