RECORDS ARE PUBLISHED REGULATORY ACTIONS. FIELDS THE ISSUING AUTHORITY DID NOT PUBLISH ARE MARKED AS NOT STATED, NEVER FILLED IN.
Drug Eye AfricaNational Actions, Continental Reach
Data

Using the data

All 797 records are open to read, one by one or a page at a time, with no account and no key. That is not a trial and it will not be withdrawn: a register nobody can cite is not doing its job, and the people this exists for — a pharmacist checking a batch, a regulator confirming what another authority did — should never have to ask anyone’s permission.

Taking a copy of the whole register is a different request, and that one we ask about. It is the work described on the about page: notices read, batch numbers pulled out of PDFs and checked, dates decoded, every source archived.

Free to consult, and we mean any of it. Every record, every field, every filter — up to 50 at a time and as far as the first 200 matches of a query, which is everything we hold for every country except Egypt. Beyond that, or as a single file, write to us. Institutions, researchers and authorities are exactly who it is for.

Endpoints

v1
GET /api/v1/notices?cc=ZM&action=recall&from=2026-01-01
Regulatory actions, filterable on every classification axis. Add format=csv for a spreadsheet.
GET /api/v1/notices/{alert_id}
One record with its batches, version history and context.
GET /api/v1/batches/WL25024
Batch lookup across every authority at once. The highest-intent query on the service.
GET /api/v1/manufacturers/{slug}
Every recorded action naming a manufacturer, continent-wide.
GET /api/v1/events/{slug}
Cross-border clusters with the propagation lag computed.
GET /api/v1/authorities · /api/v1/coverage
Reference data, including the coverage matrix as JSON.

Sending us records

for authorities
POST /api/v1/submissions
For an authority whose own system already holds its recalls. Post them rather than retyping them. Reading needs no key; sending does, because a key names an organisation and can be withdrawn.

A submission is stored, not published. What you send is kept exactly as sent and waits for a person to read it against the notice. Nothing posted here reaches the register until they have. The response says received, and that is the whole of what it claims.

A submission is recorded at tier 2 — confirmed to us directly by the authority — or tier 3, a named credible secondary source. Tier 1 means the authority published the notice on its own channel and we captured it there, which a POST is not. Tier 0 is the rank only a named officer of the issuing authority can create, and it is refused here in as many words.

Every submission in a request is checked before any of it is stored, so your system and this register never disagree about what was accepted. A refusal names each field and says what is wrong with it. Where a submission is later set aside, the row keeps its place and states the reason.

Send the notice with it. Post as multipart/form-data with a submission part holding the JSON and a document part holding the file — PDF, Word, JPEG, PNG, HTML or plain text, up to 4 MB. One document to one submission: a batch export is a list of actions with no single notice behind it, and a form that pretended otherwise would attach the wrong file to the wrong recall. The response quotes the SHA-256 we computed on receipt, so you can check it is the file you meant before it is archived.

A submission with no document is still one we want. It will say on its face that no published notice was found, which is a legitimate thing for a record to say. Silence is not.

Do not send us a link to your own notice. If you have published it, that is a tier 1 record and belongs to us to capture from the channel that published it — so source_url is refused here. Send the address of that channel to notices@drugeyeafrica.org instead and we will capture this notice and every one after it.

Two other doors exist and need no software at all: an email to notices@drugeyeafrica.org, or the export your system already produces, sent as a CSV. Both go through the same reading.

Record shape

openFDA-aligned
{
  "alert_id": "DEA-KE-2026-0015",
  "cc": "KE",  "country": "KE",  "regulator": "PPB",
  "regulator_ref": "REC/2026/015",
  "date_published": "2026-07-20",
  "product_name": "Flazart",
  "inn": null,  "manufacturer": null,
  "batch_numbers": ["WL25024","WL25025","WL25026"],
  "action_type": "recall",
  "classification": null,
  "defect_category": null,
  "verification_tier": 1,
  "source_url": "https://web.pharmacyboardkenya.org/...",
  "no_published_notice_note": null,
  "source_archive_url": null,
  "source_archive_held": false,
  "source_sha256": null,
  "source_retrieved_at": null,
  "status": "active",  "version": 1,
  "publication_tier": "B",  "noindex": true
}

Nulls are returned, not omitted. A consumer can tell the difference between “the authority did not state this” and “we did not capture it”. Every record carries verification_tier, source_url, no_published_notice_note and source_archive_url, whatever their values.

source_archive_url is null unless the archived copy is on storage you can fetch. A copy on a machine you cannot reach is not evidence, and a path naming somebody’s home directory is not an address; the register does not publish one as though it were. Where a copy exists but is not yet reachable, source_archive_held is true and source_sha256 identifies it exactly.

Verification tiers

  • Tier 0 — entered and published by a named officer of the issuing regulator. The portal that would create these is not built, so no record carries this rank yet. It is the top of the scale, not a rank on offer.
  • Tier 1 — published by the regulator and captured by us
  • Tier 2 — confirmed to us by the authority, but not published by them
  • Tier 3 — reported by a named credible secondary source
  • Tier 4 — reported and unconfirmed, published as an open question

Publication tiers and indexing

A record reaches search engines only with a date, a product name, and either a batch number or a stated reason. Everything else is kept out of them until that is filled in — but it is stored, searchable and readable here from the moment it lands. Nothing is held back; it is only kept from being found by somebody who would read a half-finished record as the whole story.

Feeds

Atom, so a search you build here is a subscription you can keep. Every filter the register offers works on the feed: build the view you want on the register, then put the same query string on /feed.xml.

  • /feed.xml — every published action, newest first
  • /feed.xml?cc=EG&action=recall — any register search, saved
  • /country/<slug>/feed.xml — one market
  • /manufacturer/<slug>/feed.xml — one company, across every market we read

A feed carries what the register lists, including records too incomplete to be given a public URL — the entry says which fields the authority did not state. It never carries a superseded record. Each entry’s identifier is its alert ID, which is permanent, so a record corrected or superseded is not re-delivered as something new.

Also here