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.

ParameterTypeRequiredDescription
cisstringone of the threeFrench CIS code - exactly 8 digits (BDPM)
substancestringone of the threeINN/DCI substance name, resolved through the shared canonical substance key (substance=acetaminophen finds the paracetamol reports)
dcistringone of the threeSynonym of substance - same join key, not combinable with it (two keys = 400)
ndcstringone of the threeUS 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)sourcefreshness.kind
cis, substance, dciANSM — disponibilité des médicaments (ansm.sante.fr)snapshot - dated data.ANSM image
ndcmedication-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.

FieldTypePresent forDescription
statusstringcisSynthesis status - the status of the most recent report, or no_known_shortage when none exists
signalsobject[]cisThe ANSM reports for that CIS (see below); [] when none
foundboolsubstance/dcifalse with items: [] when no report references the substance - a billed 200
itemsobject[]substance/dciThe reports whose published substances match (same fields as signals[])
notestringevery FR answerThe veracity caveat, quoted above - the absence of a report is not a stock guarantee
coverageobjectndc 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:

FieldTypeDescription
cisstringThe reported speciality’s CIS - mapped from the ANSM name by the pipeline, omitted when not mapped, never guessed
namestringSpeciality name as published by the ANSM
statusstringReport status - one of rupture / risque_rupture / tension / remise_a_disposition / arret_commercialisation (closed set)
updated_atstringReport 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_datestringReturn-to-market date as published: observed for a remise_a_disposition status, forecast otherwise; omitted when none is announced
domainstringMedical domain (e.g. Cardiologie)
source_refstringURL 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.

StatuscodeCase
400INVALID_INPUTZero or several keys; a malformed key (e.g. a cis that is not 8 digits, a package NDC); an empty substance/dci
503DATA_UNAVAILABLEThe data.ANSM dataset has not been ingested yet - there is no last good snapshot to serve (cis/substance/dci only)
404NOT_FOUNDUnknown route
500INTERNALInternal 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 /catalog and how settlement works.