Galen open data, and how to read it without getting it wrong
Everything this journal is built on is published as JSON: the corpus, the source registry behind every number in it, the reference tables its articles compare, and the one formula it prints. No key, no account, no rate limit, CC BY 4.0. This page is the part a schema cannot carry — what each field means, and which of them are patterns rather than figures.
Start here: what is not in this data
A veterinary reference published as machine-readable data travels further, is quoted
more often and lasts longer than the same sentence on a page, and it arrives stripped
of the context a reader would have had. So the limits come first rather than last,
and they are carried as a scope_limits block inside every single payload
rather than only here.
There are no doses anywhere in this data — no milligrams per kilogram, no volumes, no intervals, no course lengths, for any species and any product. That is an editorial decision rather than an omission, and it is the one this site would not trade for any amount of traffic. A dose depends on the individual animal, the product in front of you and the reason for using it; the figure that applies is printed on the approved label and interpreted by a veterinarian who has examined the animal. A dose quoted from a general reference is one of the ordinary ways an overdose happens.
Nothing here diagnoses. A sign is not a disease and a list of signs is not a differential. What is published is what a measurement or a label phrase means, so that a conversation with a veterinarian starts from the right place instead of from a web search. No product is named and none is recommended, because which product is appropriate is a clinical decision and, in most jurisdictions, a prescribing one. And an absent row is never a statement of safety: these tables list what they list, and the space around them is unexamined rather than cleared.
Two further absences are worth naming because their presence is what a consumer will look for first. There are no numeric withdrawal periods and no maximum residue limits in this data. They are product-, species- and route-specific, they change, and publishing a snapshot of them would produce a set of figures that are authoritative-looking, endlessly quotable and wrong within a year — which is precisely the failure mode a reference site exists to avoid. What is published instead is the structure: what determines the length of a withdrawal period, what it is counted from in each presentation, and the five recurring ways a correctly intended wait still ends in a residue finding. For the figures, Codex Alimentarius and the national register are keyed in the source registry.
The datasets
Eight documents, all under /api/v1/, all regenerated from the same modules
the pages render from on every build. There is no export step and no second copy to go
stale.
| Endpoint | Size | What it is |
|---|---|---|
| articles.json | 32 articles | Every published article with its title, its answer-first takeaways, its FAQ, the entities it is about and the keys of the sources it cites. |
| sources.json | 38 entries | The citation registry — every standards body, regulator, guideline set and reference work the journal cites, with the list of articles that cite each one. |
| vital-signs.json | 8 species | Rectal temperature, heart rate and respiratory rate for healthy adult animals at rest, with the caveats that decide whether a range can be used at all. |
| labelling.json | 5 tables | Strength units, storage vocabulary, in-use shelf life by pharmaceutical form, what governs the length of a withdrawal period, and the five recurring ways a correct wait still fails. |
| hazards.json | 2 tables | The medicine groups behind most companion-animal exposures, and the six plants sold under the word “lily”. Orientation, never triage. |
| heat-stress.json | formula + 28-cell grid | The index variant this site publishes, the grid it produces, and what fails first in each production system under heat load. |
| galen.json | 1 document | The editorial policy as data, with a list of what is deliberately out of scope that is as long as the list of what is in it. |
| status.json | 1 document | When each dataset was last rebuilt, and the state of the publication queue. |
The entry point is index.json, which lists all of them
with their row counts; openapi.json is the OpenAPI
3.1 description of the same surface. Both are advertised in the response
Link headers of every page, so a client that has fetched any URL on this
site already knows where they are.
Four fields that are routinely read backwards
This is the section the schema cannot carry, and it is the reason this page exists in addition to the OpenAPI document.
typical_in_use_period is an order of magnitude, not a period.
It describes how a pharmaceutical form behaves once it is opened — a reconstituted
lyophilised vaccine is stable in hours because its stability was in the dryness, a
tablet jar in months because the change is moisture exchange with the air. It is not a
figure to apply to a container. The period that applies is on that container, it runs
from first broaching rather than from manufacture, and it can be shorter than the
remaining shelf life by months.
A storage phrase is not always a temperature range. “Do not freeze” and “protect from light” are independent instructions, not stricter versions of one. A product held faultlessly at 2–8 °C has still failed “do not freeze” if the container sat against a freezing surface at the back of the refrigerator, and almost every inactivated and adjuvanted vaccine carries that instruction. Likewise “store in a freezer” is a specific requirement rather than a colder form of refrigeration, and it applies to a small number of products rather than to biologicals generally.
An international unit has no conversion to milligrams. It measures biological activity against a reference preparation, so the factor differs from substance to substance and there is no arithmetic that crosses between them. The same section of the data carries the related trap: concentration is not quantity. A 100 mL bottle at 200 mg/mL holds more active substance than a 250 mL bottle at 50 mg/mL, and the mistake is common enough that the article this table comes from is built around it.
A reference range describes a population and has soft edges. The vital
signs dataset gives eight species as [low, high] pairs, and the useful
comparison is not against those pairs but against what a particular animal reads on an
ordinary day when it is well. An animal a tenth of a degree outside a band is not
thereby unwell; one comfortably inside it can be seriously ill. Young stock sit at or
above the top of every band on all three measures, so an adult range applied to a calf,
a lamb, a puppy or a kitten manufactures false alarms. And the chicken row is three to
four degrees above every mammal in the table, which is normal for a bird and is the
single most common misreading of it.
The one formula, published as arithmetic
This site contains exactly one thing that computes, and it is now in one place. The temperature-humidity index —
THI = 1.8T + 32 − (0.55 − 0.0055 × RH) × (1.8T − 26)
— is implemented in a single ES module that the JSON endpoint, the MCP tool and the build gate all import. Before that module existed the index was written out in the article's prose, evaluated by hand into the twenty-eight numbers of that page's grid, and quoted again in two FAQ answers, with nothing comparing the copies. The grid in heat-stress.json is now computed on every build, and a gate asserts that every cell of the figure the article draws still agrees with it to a tenth of a point.
The caveats travel with the number rather than beside it. Several THI variants are in
circulation and they do not agree, so variant is attached to every computed
result — a THI value without its variant is not a value. No threshold is published at
all, because a threshold is specific to the species, the index version and the
production level: a higher-yielding animal reaches it sooner because its own metabolism
is part of the load. And the index ignores air speed and radiant heat entirely, which
means two buildings at an identical index are not equivalent if one has air moving over
the animals and shade over the yard.
Where the numbers come from, and how a correction propagates
Citations on this site are keys into a registry of 38 primary sources rather than raw URLs in prose. That is a small piece of housekeeping with a disproportionate effect, and it is why the registry is published: when an agency reorganises its website, one entry is corrected and every article that cites it is corrected with it, rather than a dead link surviving in eight pages because nobody re-read them. sources.json carries each entry with the list of articles citing it, computed from the corpus rather than maintained by hand, so a source with no citations shows an empty list instead of implying coverage it does not have.
The reference tables work the same way in the other direction. All 9 of them, 55 rows in total, live in one data module, and a build gate asserts that every cell still appears in the table of the article it belongs to. A number cannot differ between the page and the API, because the build fails if it does. This matters more than it sounds: two copies of a figure, each individually correct, are the classic way a reference site drifts, and nothing about the drift is visible in a review.
Corrections are the most useful message this site receives. If a figure is wrong, a source has moved or a rule has changed, write to [email protected] with the URL and the source that contradicts it. A correction lands in the registry or the reference module and reaches the page, the markdown twin, the JSON and the MCP tool on the next build, because there is only one copy of it.
Reading the site as markdown
Every indexable page has a markdown twin at a stable address, and it is a fraction of the bytes of the HTML — which on a long article is the difference between an agent reading the whole page and truncating it halfway through the section it needed. Two ways, and both work:
- append
index.mdto any page URL, as in/journal/withdrawal-periods-meat-milk-eggs/index.md; - or send
Accept: text/markdownto the ordinary page URL.
llms.txt indexes every page with a one-line summary, and
llms-full.txt carries the full text of the reference
articles in a single file. The twins are allowed to AI crawlers and disallowed to
search crawlers in robots.txt, which is a crawl-budget decision rather than
a policy one: the search engines already have this text in HTML, and doubling the
crawlable URL space buys nothing.
MCP and A2A
POST /mcp speaks JSON-RPC 2.0 and exposes the same data as named tools,
plus one that computes: the temperature-humidity index, from the module described
above, for whatever temperature and humidity the caller supplies. There is a matching
A2A endpoint at POST /a2a which answers a free-text question by routing it
to one of the same tools. Both are read-only, both are anonymous, and both refuse
before they look anything up — a question about what to give an animal is declined
rather than answered with the nearest plausible table, because arriving with data at
all would imply the question had been answered.
Neither writes anything, spends anything or reads any user data, which is why there is nothing to authenticate. auth.md says so in the form an agent expects, and the protected-resource metadata declares an empty list of authorization servers rather than omitting the document — an empty list is a fact a client can read, where an absent document is ambiguous.
Licence, attribution and what belongs to whom
The compilation is CC BY 4.0: the article index, the reference tables as structured here, the source registry and every derived field. Use it commercially, modify it, redistribute it; the only condition is that you credit Galen with a link. That link is the entire commercial argument for publishing any of this, and it is a better deal for both sides than a licence nobody is confident enough to rely on.
What is not covered is equally clear. The standards, guidelines, codes and reference works this journal cites belong to the bodies that publish them — the European Medicines Agency, the Food and Drug Administration, the Veterinary Medicines Directorate, the World Organisation for Animal Health, Codex Alimentarius, the WHO, the Merck Veterinary Manual and the companion-animal bodies listed in the registry — and their own terms apply to their contents. What this site publishes is the compilation, the structuring and the plain-English rendering, which are its own work. The distinction matters: a dataset assembled out of someone else's licensed content and redistributed under a permissive licence is not generous, it is a licensing error with a friendly face.
A last note on what the data is for. It is not an attempt to replace the pages. Every row carries the URL of the article that argues it, because the argument is the part that stops a figure being misapplied, and a number lifted out of its caveat is how a reference becomes a hazard. Quote the row, keep the caveat, and link the page.