GET /medication/availability
Returns the market-availability status of a French medication, from the official ANSM shortage reports (data.ANSM): the reported shortages, risks of shortage, tensions, returns to market and discontinuations relayed exactly as published, each with its date, medical domain and the official ansm.sante.fr report URL. The answer is served from a local store built from the open data.ANSM dataset, so a lookup resolves in milliseconds with no network call and no secret at request time.
Use it when an agent needs to check whether a medication is sourceable
before acting - order it, prescribe it, or propose an alternative. It extends
the “pre-action checks” angle on the prescription and ordering side, a natural
pair with /medication/generics (a reference
brand is short → which equivalents exist?). Lookup is by identifier or
substance only - there is no search by symptom, indication or fuzzy name
in v1. See the live /catalog for the authoritative
endpoint listing and price.
Shortage reports are a French (data.ANSM) notion. The scope of this
endpoint is FR: a US ndc key returns an honest coverage note, never an
error, and no US equivalent is promised.
no_known_shortage is not “in stock”
This is the central point of the endpoint. The ANSM only records reported
shortages - it is a register of signalements, not a picture of pharmacy
stock. So the absence of a report means “no shortage known to the ANSM”,
never “available on the shelf”. The synthesis status for a medication with
no report is therefore named no_known_shortage (not available), and
every FR answer carries the veracity note:
ANSM only records reported shortages; the absence of a report does not guarantee pharmacy stock
An agent must read no_known_shortage as “the ANSM has published nothing about
this medication”, not as a positive stock guarantee.
This endpoint returns sourced, dated facts - ANSM statuses, dates and report links exactly as published. It is never a clinical recommendation, a therapeutic alternative or a dosage. That line is the boundary of the service.
x402 golden rule: the agent pays for the answer to its question. A
well-formed key with no shortage report is a successful answer too -> a
200 billed with data.status: "no_known_shortage" (or data.found: false
for a substance key) - the absence of a report is the information. Only
requests the service cannot answer - no key, several keys, a malformed key, an
empty substance - leave the 200 range and are not billed.
Parameters
Exactly one of the three keys, as a query parameter. Zero or several keys,
a malformed key, or an empty substance/dci is a 400 INVALID_INPUT.
| Parameter | Type | Required | Description |
|---|---|---|---|
cis | string | one of the three | French CIS code - exactly 8 digits (BDPM) |
substance | string | one of the three | INN/DCI substance name, resolved through the shared canonical substance key (substance=acetaminophen finds the paracetamol reports) |
dci | string | one of the three | Synonym of substance - same join key, not combinable with it (two keys = 400) |
ndc | string | one of the three | US product NDC labeler-product (e.g. 0071-0155) - out of FR scope, returns a coverage note |
GET /medication/availability?cis=65806466
substance and dci are two names for the same key - pass one, never
both. Substance resolution folds through the shared canonical substance key
plus the known French labels of the DCI↔INN table, so an English INN reaches
the reports of the same molecule.
200 response - UnifiedResponse
{
"data": { ... },
"provenance": {
"source": "ANSM — disponibilité des médicaments (ansm.sante.fr)",
"fetched_at": "2026-07-19T20:37:57Z",
"freshness": { "kind": "snapshot", "as_of": "2026-07-18T00:00:00Z" }
}
}
provenance depends on the key that resolved the answer:
| Key(s) | source | freshness.kind |
|---|---|---|
cis, substance, dci | ANSM — disponibilité des médicaments (ansm.sante.fr) | snapshot - dated data.ANSM image |
ndc | medication-grid availability coverage (data.ANSM scope) | live - pure local scope statement, no store consulted |
Fields of data
The shape depends on the key - the two FR shapes are never mixed.
| Field | Type | Present for | Description |
|---|---|---|---|
status | string | cis | Synthesis status - the status of the most recent report, or no_known_shortage when none exists |
signals | object[] | cis | The ANSM reports for that CIS (see below); [] when none |
found | bool | substance/dci | false with items: [] when no report references the substance - a billed 200 |
items | object[] | substance/dci | The reports whose published substances match (same fields as signals[]) |
note | string | every FR answer | The veracity caveat, quoted above - the absence of a report is not a stock guarantee |
coverage | object | ndc only | { scope: "FR", note }, the honest FR-scope statement (see below) |
A field the source does not carry is omitted from the JSON, never served
null.
A signals[] / items[] entry
Both shapes carry the same report fields:
| Field | Type | Description |
|---|---|---|
cis | string | The reported speciality’s CIS - mapped from the ANSM name by the pipeline, omitted when not mapped, never guessed |
name | string | Speciality name as published by the ANSM |
status | string | Report status - one of rupture / risque_rupture / tension / remise_a_disposition / arret_commercialisation (closed set) |
updated_at | string | Report update date as published by the ANSM - the only tracking date the source exposes, never a shortage start date (the ANSM table does not publish one) |
restock_date | string | Return-to-market date as published: observed for a remise_a_disposition status, forecast otherwise; omitted when none is announced |
domain | string | Medical domain (e.g. Cardiologie) |
source_ref | string | URL of the official ansm.sante.fr report - traceability |
For a cis key, the synthesis status is the status of the most recent
report (highest updated_at) - the service never reorders reports by an invented
severity. Statuses, dates and links are relayed exactly as published -
they are facts, not a recommendation to switch to another medication.
Example - a shortage, resolved by CIS
GET /medication/availability?cis=65806466 (a known shortage), against the
2026-07-18 data.ANSM snapshot:
{
"data": {
"status": "rupture",
"signals": [
{
"cis": "65806466",
"name": "Alprostadil Intsel Chimos 0,5 mg/ml, solution injectable",
"status": "rupture",
"updated_at": "2022-11-23",
"domain": "Cardiologie",
"source_ref": "https://ansm.sante.fr/disponibilites-des-produits-de-sante/medicaments/alprostadil-intsel-chimos-0-5-mg-ml-solution-injectable-alprostadil"
}
],
"note": "ANSM only records reported shortages; the absence of a report does not guarantee pharmacy stock"
},
"provenance": {
"source": "ANSM — disponibilité des médicaments (ansm.sante.fr)",
"fetched_at": "2026-07-19T20:37:57Z",
"freshness": { "kind": "snapshot", "as_of": "2026-07-18T00:00:00Z" }
}
}
The synthesis status is rupture (the most recent report’s status); the
report carries no restock_date (no return announced -> the field is omitted).
A CIS may carry several reports, in which case status reflects the latest.
A well-formed CIS with no report is a paid answer
GET /medication/availability?cis=60424338 (or an unknown but well-formed CIS
such as ?cis=99999999) returns a 200, billed, with:
{
"data": {
"status": "no_known_shortage",
"signals": [],
"note": "ANSM only records reported shortages; the absence of a report does not guarantee pharmacy stock"
}
}
The agent asked “is a shortage reported for this medication?”, and “none
reported” is the answer. Read no_known_shortage as “the ANSM has published
no report”, never as “available in stock” - that is exactly why the note
travels with every FR answer. Contrast this with the 400s below, which are
malformed requests and are not billed.
Resolving by substance
GET /medication/availability?substance=alprostadil (or ?dci=alprostadil)
returns a 200, billed, with data.found and data.items[] instead of
status + signals:
{
"data": {
"found": true,
"items": [
{
"cis": "65806466",
"name": "Alprostadil Intsel Chimos 0,5 mg/ml, solution injectable",
"status": "rupture",
"updated_at": "2022-11-23",
"domain": "Cardiologie",
"source_ref": "https://ansm.sante.fr/disponibilites-des-produits-de-sante/medicaments/alprostadil-intsel-chimos-0-5-mg-ml-solution-injectable-alprostadil"
}
],
"note": "ANSM only records reported shortages; the absence of a report does not guarantee pharmacy stock"
}
}
A substance with no matching report returns data.found: false and
data.items: [] - a billed 200, no shortage known to the ANSM.
A US NDC is honest coverage, not an error
GET /medication/availability?ndc=0071-0155 returns a 200, billed, with:
"coverage": {
"scope": "FR",
"note": "shortage reports come from data.ANSM (French market); NDC keys are out of scope in v1"
}
provenance.source is "medication-grid availability coverage (data.ANSM scope)" and freshness.kind is "live": it is a pure local scope
statement, consulting no store (so an ndc key never returns a 503). There
is no US shortage-report equivalent in v1 - the endpoint says so honestly
rather than guessing.
Freshness
Answers are served from a dated snapshot of the data.ANSM dataset;
freshness.as_of carries the date of the extraction that backed the answer. If
a refresh is missed, the service keeps serving the last good snapshot -
honestly dated by as_of - and never turns staleness into a 5xx. A dataset
not yet ingested at all is a 503 DATA_UNAVAILABLE (there is no last good
snapshot to serve) for the cis/substance/dci keys; an ndc key depends
on no store and never returns 503.
Errors
Only requests the service cannot answer leave the 200 range - none of them are billed.
| Status | code | Case |
|---|---|---|
| 400 | INVALID_INPUT | Zero or several keys; a malformed key (e.g. a cis that is not 8 digits, a package NDC); an empty substance/dci |
| 503 | DATA_UNAVAILABLE | The data.ANSM dataset has not been ingested yet - there is no last good snapshot to serve (cis/substance/dci only) |
| 404 | NOT_FOUND | Unknown route |
| 500 | INTERNAL | Internal error (detail logged, not exposed) |
{ "error": "provide exactly one of: cis, substance, dci, ndc", "code": "INVALID_INPUT" }
Attribution
French shortage data is derived from data.ANSM (disponibilité des médicaments), the open dataset published by the ANSM on ansm.sante.fr (source and date required, carried in every response).
See also
GET /medication/generics- the reference brand and equivalent generics of a medication, to source an alternative when one is short.GET /medication/resolve- the official identity card of a medication (status, substances, price) before checking its availability.- For agents - discovery surfaces, the live
/catalogand how settlement works.