Blood pressure classification tables as open JSON

Both reference tables, the derived formulas and the home-monitoring protocol, as keyless JSON under CC BY 4.0. No account, no key, no rate limit, CORS open to everything. The same module the calculators on this site run on.

Every blood pressure app, chart and calculator on the web encodes the same two tables, and a surprising share of them encode at least one of the two wrongly. There is no canonical machine-readable copy to work from: the guidelines are published as PDFs of clinical prose, the tables inside them are laid out for a reader rather than a parser, and the thresholds get transcribed by hand into one codebase after another. This page is our attempt to stop doing that. The tables the calculators on this site classify against are published here as data, with the document each band came from attached to it, and you are free to use them.

There is nothing to sign up for. Every endpoint is a static JSON file served from the same origin as the pages, with Access-Control-Allow-Origin: *, so a browser application can fetch it directly. The licence is Creative Commons Attribution 4.0: use it commercially, modify it, redistribute it, and credit Tonelva with a link. That attribution line is the entire business model of this page, and we would rather you took the data and linked back than retyped the thresholds and got one of them wrong.

What is here

DatasetRowsWhat it carries
reference-tables.json 13 bands Both classification tables, the MAP and pulse-pressure formulas, the averaging protocol, and what Europe changed in 2024.
tools.json 5 The free calculators: what each takes, what it returns, and which are callable over MCP.
guides.json 20 The reference corpus, each article with the question it answers and a link to its markdown twin.
tonelva.json 1 What the app does, and a list the same length of what it does not.
status.json 1 When each dataset was last rebuilt, and the date of each guideline it encodes.

The entry point is /api/v1/index.json and the machine description is OpenAPI 3.1. Every payload repeats its own provenance, licence and limits, because a retrieved JSON document travels alone just as a retrieved paragraph does, and a licence that only exists on this page is a licence nobody reading the file will ever see.

The four fields implementers get backwards

The rest of this page is field semantics. It is the part a schema cannot carry, and it is where the mistakes live.

combine is the whole classification rule. Every band carries either "or" or "and". Almost all of them are "or", and that is not a detail: it means a reading falls into a band if either number reaches it. A reading of 118/92 is stage 2 hypertension under the American table and grade 1 under the European one, on the diastolic value alone, and no amount of normal systolic pulls it back down. The single exception in either table is the American Elevated band, which is joined by "and": systolic 120–129 and diastolic under 80. A reading of 125/84 is therefore not elevated, it is stage 1, and an implementation that treats every band as an or will report it as the milder category.

rank is severity, and the arrays are ordered by it. Take the bands in the order given and stop at the first one whose condition is met. The arrays run from most severe to least, which is the order the guidelines themselves describe classification in. Evaluate them in the opposite direction and every high reading lands in the lowest band it also happens to satisfy. The rank is shared between the two tables, so you can line them up row against row — which is what makes it possible to say that a reading is two bands more severe under one framework than the other.

published_band tells you whether a band came from the guideline. One band in each table — the one called Low — is ours, not theirs. Neither the American nor the European office classification publishes a hypotension band at all: both tables simply stop at optimal or normal. We add a low band because a home diary that silently accepts 86/54 without comment is not being useful, but it carries published_band: false so that nobody cites it to a document that does not contain it. Everything else in both tables is true and traceable to the source on the same object.

frameworks_disagree is the field to surface, not to hide. It is returned by every classification, and when it is true the honest presentation shows both labels. The temptation is to pick the local one and move on. The reason not to is that the reader will meet the other one soon afterwards — on a monitor, in a leaflet, from a relative in another country — and will have no way to reconcile two reputable sources that contradicted each other, which is exactly the confusion this whole site exists to remove.

Why the two tables disagree at all

The American guideline is the 2017 ACC/AHA document, which moved the hypertension threshold down to 130/80 and split the range above it into stage 1 and stage 2. The European table here is the 2018 ESC/ESH office classification, which kept the diagnostic threshold at 140/90 and inserted a band called high-normal between 130–139 and 85–89 that the American table has no equivalent for. Both committees read a largely overlapping evidence base. Blood pressure risk is continuous, so where the word hypertension begins is a judgement about labelling and the consequences of labelling, not a discovery about biology. There is a full explanation at why the American and European thresholds differ.

Europe changed again in 2024, and the payload says so. The 2024 ESC guideline replaced the ladder below 140/90 with a single category called elevated blood pressure, covering 120–139 systolic or 70–89 diastolic. It did not move the hypertension threshold, which is still 140/90. We classify against the older table because that is what home monitors print, what patient leaflets use, what the 2023 ESH guideline retained, and what lines up band for band against the American categories a reader is trying to reconcile. But a reader arriving with the newer wording deserves to be told rather than silently contradicted, so the change is carried in the data as europe_changed_in_2024, with the old values beside it. If you are building something for a European clinical audience rather than a general one, that block is the thing to read first.

One copy of the arithmetic

The calculators in your browser, these JSON endpoints and the MCP server all import a single ES module, published at /js/engine.js. It is plain JavaScript with no build step, so you can read it, and it is the reason the answer you get from the API is the answer the page shows: there is no second implementation to drift. A vector suite runs on every build and is pinned to the worked examples printed on the tool pages themselves, so an arithmetic change that would alter a published sentence fails the build rather than shipping quietly.

Four of the five tools are callable as MCP tools over JSON-RPC 2.0 at POST https://tonelva.com/mcp, and the same lookups are available to agent-to-agent clients at POST https://tonelva.com/a2a. The server card is at /.well-known/mcp/server-card.json. They compute rather than look up, which matters here: classifying a reading, weighting diastole twice for a mean arterial pressure, and discarding the first day of a monitoring week are all exactly the shape of operation a language model performs correctly most of the time and incorrectly without any signal that it has.

Every page is also available as markdown

Append index.md to any URL on this site, or send Accept: text/markdown, and you get the page as markdown instead of HTML. It is a fraction of the bytes, because the stylesheet on this site is inlined into every document and none of it is text you want. /llms.txt indexes every page; /llms-full.txt carries the full text of the calculators and the publisher pages in one file.

What is deliberately not here

The competitor snapshot. This site has comparison pages, and the obvious dataset to publish alongside them would be the table behind them — ratings, prices, release dates, store descriptions for each rival app. It is not here and will not be. That metadata comes from the Apple App Store and is Apple's to license rather than ours, and the descriptions are each publisher's own marketing. Publishing them keyless and CC BY would relicense content we do not own and distribute our competitors' copy at our own expense, travelling further through agents than any page would. The comparisons stay where they are, signed, with the interested party named.

Anyone's readings. There is nothing to publish. The calculators run entirely in your browser and transmit nothing; the app keeps its diary on the device with no account and no sync. No reading reaches a server that could publish it.

Population statistics. No prevalence figures, no distribution by age, no outcome rates. Tonelva measures nothing and holds no cohort, and putting our name on numbers lifted from a dataset we did not build would be exactly the kind of confident sourcing this page is arguing against.

The limits that travel with anything you take

A category is a label for one measurement. Hypertension is diagnosed from repeated readings, usually taken away from a clinic, and interpreted by a doctor who knows the rest of the person's health. Nothing in this data recommends, starts, stops or adjusts treatment, and no figure in it is a personal target — targets are set by the clinician managing that person's care, and the ranges quoted here are population reference bands.

Tonelva records readings from a cuff. It does not measure blood pressure, and neither does any phone: not from a camera, not from a fingertip on a screen, not from a watch without a cuff. If you are building something on this data, that sentence is worth carrying through to your own interface, because the belief that a phone can take a reading is common and actively harmful. And a reading above 180 systolic or 120 diastolic together with chest pain, breathlessness, weakness, vision change or confusion is emergency care rather than a diary entry, which is a thing to say before any classification rather than after it.

Using it

Fetch what you need and cache it; the files are rebuilt with the site and status.json carries the build time along with the date of each guideline encoded. There is no versioning scheme beyond the /v1/ in the path: if a band changes because a guideline changes, it changes in place and the source object on it changes with it, because a stale threshold served under an old version number is worse than a corrected one. If something here is wrong, or a field is ambiguous enough that you had to guess, write to [email protected] — a reimplementation that got it wrong because our documentation was unclear is a defect on this side.

Why you can check us

Log a reading in three taps. Free, no account. Get the app

Get Tonelva on your phone

Free on iPhone and Android. No account, no cloud.

Point your camera at the code, or use the links below.

Download on theApp Store Get it onGoogle Play