GET /api/regulations
The core endpoint. Returns tracked regulations, filterable and paginated. Sorted by effective publication date, most recent first.
| Parameter | Type | Description |
|---|---|---|
view | string | all (default) · healthtech — the default view is every classified item; healthtech narrows to general-scope, health-tech-relevant ones. The default changed in v6 (it was healthtech) — pass view=healthtech explicitly if you relied on the narrow view |
search | string | Full-text search (indexed) across original and English titles, summaries and descriptions |
topic[] | array | Classifier topic slug (repeatable; values OR together), e.g. samd, ai-act, ehds, reimbursement. Bare topic= also accepted for one value; /api/topics lists the full vocabulary with display labels |
scope | string | general (binds a class of actors) · single_entity (one named product or company) |
kind[] | array | Document type (repeatable): rule_change · guidance · consultation · safety_alert · approval · supply_notice · enforcement · administrative · news. Bare kind= also accepted for one value |
breadth[] | array | How widely a document binds (repeatable): framework · sector · product_class. breadth[]=framework&breadth[]=sector is the “big ideas only” query — framework acts and sector rules without single-product-type classifications. Bare breadth= also accepted |
relevance | string | Health-tech relevance floor: core · adjacent · all (default, no floor). Narrows within view, never widens it |
sort | string | relevance (default, blends health-tech score, obligation level and recency, then demotes news and administrative kinds, single-entity scope and narrow breadth) · newest · impact (obligation level, HIGH first) |
since | date | ISO date; only items published or first seen on/after it — poll this from an integration |
impact[] | array | Obligation level (repeatable): HIGH · MEDIUM · LOW. Shown on the site as “Obligation”; the parameter name is unchanged |
category[] | array | One of the ten categories below (repeatable) |
region[] | array | e.g. EU-wide, Germany, France (repeatable) |
source | string | Source registry key, e.g. ema, uk_mhra — the keys behind /sources. Every item returns its own sourceKey, so a result can be turned straight back into a query. Repeatable as source[] |
dateRange | string | today · week · month · 3months · 6months · year |
hasDeadlines | boolean | true returns only items with extracted deadlines |
page | integer | Page number, default 1 |
limit | integer | Items per page, default 50, max 200 |
collapse | string | instrument groups rows in the returned page that share an instrumentIds value or digest series; the first row in sort order represents the group and lists its siblings in alsoReported. Grouping is per page: a collapsed page may return fewer than limit rows, and pagination.total stays the document count. Default: off — one row per document |
curl "https://www.health-signal.com/api/regulations?topic=samd&since=2026-08-01"
curl "https://www.health-signal.com/api/regulations?impact[]=HIGH&dateRange=month&limit=10"
curl "https://www.health-signal.com/api/regulations?source=ema&kind=guidance"
A value outside its vocabulary is a 400, not a filter that quietly does nothing. The body names every offending parameter in invalid, so one request tells you about all the typos in a filter bundle rather than the first. This matters more than it sounds: until August 2026 an unknown value was dropped, so ?category=Devices (not a real category) answered with the entire corpus and looked like a successful query. /feed.xml is deliberately still lenient — a feed reader cannot show you an error body, so a subscription with one stale parameter keeps working instead of going dark.
Every item carries a classification object — scope, breadth, healthTech.relevant/score, kind, topics, an always-populated English display title (titleEn), and a one-sentence extractive summaryEn (null when the source text states no concrete change). The axes are independent: kind is what sort of document it is, scope is whether it binds a class or one named thing, breadth is how widely it binds, and categories is the subject. impact is derived from all three.
GET /feed.xml
RSS 2.0 of the newest ~50 items, chronological. Accepts the same filter parameters as /api/regulations — topic[], kind[], breadth[], relevance, impact[], scope, category[], region[], source, search, view (built by the same code, so the two cannot drift) — which makes any filtered view of the site a subscribable URL. Pagination, sort, since, dateRange and collapse do not apply: a feed is a rolling newest-window of one item per document by design.
curl "https://www.health-signal.com/feed.xml?kind[]=rule_change&kind[]=consultation&relevance=core"
curl "https://www.health-signal.com/feed.xml?topic[]=ai-act&topic[]=samd"
GET /api/topics
The classifier’s controlled topic vocabulary with display labels — the valid values for topic/topic[]. Static; changes only with releases.
Sample response
{
"status": "success",
"data": {
"regulations": [
{
"_id": "6908d35e99792966b6f85b38",
"title": "AI Act General Application (High-Risk AI)",
"description": "Obligations for high-risk AI systems apply…",
"link": "https://eur-lex.europa.eu/…",
"source": "European Commission",
"sourceKey": "ec_health",
"impact": "HIGH",
"impactScore": 3,
"categories": ["Digital Health & AI"],
"geographicScope": ["EU-wide"],
"originalPubDate": "2026-06-14T00:00:00",
"createdAt": "2026-06-15T05:17:03",
"classification": { "kind": "rule_change", "scope": "general", "breadth": "framework", "healthTech": { "score": 92, "relevant": true }, "topics": ["ai-act"], "titleEn": "AI Act General Application (High-Risk AI)" },
"hasDeadlines": true,
"deadlineStatus": "upcoming",
"nextDeadline": "2026-08-02",
"deadlines": [
{ "date": "2026-08-02", "eventType": "ENTERS_FORCE", "originalText": "General application" }
]
}
],
"pagination": { "page": 1, "limit": 10, "total": 1522, "pages": 153 }
}
}
Response fields
Each item in data.regulations carries the following fields.
| Field | Type | Description |
|---|---|---|
_id | string | Stable document identifier |
title | string | Regulation title |
description | string | Summary text |
link | string | Canonical URL to the official source |
source | string | Issuing body, as a display name (UK MHRA). Prose — it changes if an agency renames itself |
sourceKey | string | Registry key of the issuing body (uk_mhra). This is what ?source= accepts. Sparse: absent on a few early documents stored before the field existed |
impact | string | Obligation level — how widely and how hard the document binds: HIGH (creates or changes binding obligations for a class of actors) · MEDIUM (binds one narrow product type, or proposes something that would bind broadly) · LOW (no new obligation for a class). Derived in v7 from kind, scope and breadth, so it no longer signals how interesting an item is — classification.healthTech.score carries that. Displayed as “Obligation”; field name and values unchanged |
impactScore | integer | Numeric obligation level: 3 / 2 / 1 |
categories | array | One or more of the ten categories |
geographicScope | array | e.g. EU-wide, Germany |
originalPubDate | string | Publication date (ISO 8601, may be null) |
createdAt | string | When the item entered HealthSignal (ISO 8601) |
classification | object | The classifier’s verdict: kind, scope, breadth (framework · sector · product_class — how widely the document binds), healthTech.score (0–100 topical proximity), topics[], titleEn, summaryEn, appliesFrom, status |
hasDeadlines | boolean | Whether any deadlines were extracted |
deadlineStatus | string | e.g. upcoming, none |
nextDeadline | string | Next upcoming deadline date (may be null) |
deadlines | array | { date, eventType, originalText } per deadline |
instrumentIds | array | Normalized legal-instrument IDs extracted from the raw text — eu:2017/745, mdcg:2024-14, mhra:dsi/2026/5, us-fr:2026-14358. Absent when no instrument is cited |
digestKey | string | Present on items in a source’s recurring digest series (e.g. MHRA’s weekly Field Safety Notices round-up) |
alsoReported | array | Only with collapse=instrument: the grouped siblings this row represents — { id, source, dateLabel, kind } |