Webhook payload
What lands on your endpoint
Every event is a JSON POST with attestation headers. EC Publications and the Regulatory Watch subsystem (SCCS, Safety Gate, EUR-Lex — shown below) share the same X-BDAPI-* header namespace; they are told apart by the X-BDAPI-Event value (e.g. `ec.publication.detected` vs `watch.safety_gate.alert.analyzed`). The body is the canonical event document, including AI-enriched analysis when available. Failures on your end (5xx, timeout) trigger the retry policy automatically.
Sample payload — Safety Gate alert (Watch subsystem)
{
"event": "watch.safety_gate.alert.analyzed",
"event_id": "01HQZK9YBV-7M8K-3R2N-0P4S-5T6U7V8W9X0Y",
"source_engine": "safety_gate",
"source_id": 12345,
"tier": "premium",
"timestamp": "2026-05-15T08:32:11.000Z",
"item": {
"alert_number": "A12/01234/26",
"report_id": "12345",
"product_name": "Cosmetic moisturiser, brand X",
"brand": "Brand X",
"risk_type": "Chemical",
"risk_level": "serious",
"notifying_country": "DE",
"country_of_origin": "CN",
"source_url": "https://ec.europa.eu/safety-gate-alerts/screen/webReport/alertDetail/12345",
"published_at": "2026-05-15T00:00:00Z",
"detected_at": "2026-05-15T08:00:00Z"
},
"analysis": {
"criticality": "CRITICAL",
"summary_es": "Notificación A12/01234/26: producto leave-on excede el límite Annex V de MIT (0.0015 %). Estado miembro notificante: Alemania. Sin período de transición — retirada recomendada para SKUs afectados.",
"risk_assessment": "Concentración de MIT detectada por encima del límite regulatorio en formulación de aplicación prolongada.",
"regulatory_implications": "Annex V entry 57 — MIT prohibido en leave-on desde el Reglamento (UE) 2017/1224.",
"cross_market_relevance": "Relevante para los 27 EM. Producto en e-commerce paneuropeo.",
"recommended_action_for_brand_owners": "Auditar fórmulas, retirar lotes afectados, notificar PCPC nacional.",
"needs_human_review": false,
"confidence": 0.92,
"model": "claude-sonnet-4-5"
}
}
Sample payload — EUR-Lex act (Watch subsystem)
{
"event": "watch.eurlex.act.analyzed",
"event_id": "01HQZM4P7R-2K9D-4N8T-1B6S-7C0V9W2X3Y4Z",
"source_engine": "eurlex",
"source_id": 4821,
"tier": "premium",
"timestamp": "2026-05-20T06:15:42.000Z",
"item": {
"id": 4821,
"celex_number": "32026R0712",
"title": "Commission Regulation (EU) 2026/712 amending Annex V to Regulation (EC) No 1223/2009 as regards the maximum concentration of a preservative",
"act_type": "regulation",
"date_document": "2026-05-18",
"eli_uri": null,
"source_url": "https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32026R0712",
"detected_at": "2026-05-20T06:00:00Z"
},
"analysis": {
"criticality": "HIGH",
"summary_es": "Reglamento (UE) 2026/712: modifica el Anexo V para reducir la concentración máxima de benzoato de sodio en productos leave-on. Período de transición hasta el 01/12/2026. Revisar fórmulas con conservantes del Anexo V.",
"substances": [
{
"name": "Sodium benzoate",
"cas": "532-32-1",
"max_concentration": "2.5% (leave-on)",
"proposed_action": "restricted"
}
],
"key_dates": [
{ "type": "entry_into_force", "date": "2026-06-07" },
{ "type": "application_deadline", "date": "2026-12-01" }
],
"needs_human_review": false,
"confidence": 0.90,
"model": "claude-sonnet-4-5"
}
}
Illustrative sample. CELEX is the stable identifier used for deduplication and source linking; eli_uri is reserved and currently null. Beyond date_document, the affected substances, CAS numbers and critical dates (entry into force, application deadline) are extracted from the act text and surfaced in the analysis block — key_dates and substances.
Full HTTP request (headers + body excerpt)
POST /webhooks/bdapi HTTP/1.1
Host: your-app.example
Content-Type: application/json
X-BDAPI-Event: watch.safety_gate.alert.analyzed
X-BDAPI-Timestamp: 1747297931
X-BDAPI-Signature: sha256=9f2c4d1e8a7b3f6c2e8d1a5b4c7e9f0a2b3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f
X-BDAPI-Delivery: 00000000-0000-0000-0000-000000000000
User-Agent: BDAPI-Watch/1.0 (+https://bdapi.app)
{ "event": "watch.safety_gate.alert.analyzed", "source_engine": "safety_gate", ... }
Attestation headers — unified X-BDAPI-* namespace
- X-BDAPI-Event
- Full event name and the field you route on. Format: `watch.{engine}.{noun}.{type}` for Watch (e.g. `watch.safety_gate.alert.analyzed`) or `ec.publication.detected` for EC Publications. The receiver should ignore unknown event types and return 200.
- X-BDAPI-Timestamp
- Unix epoch in SECONDS (not milliseconds, not ISO 8601). Used to construct the signature. Reject requests older than 5 minutes to defend against replay.
- X-BDAPI-Signature
- HMAC-SHA256 hex digest of `timestamp + "." + raw_body`, keyed with your webhook secret. Format: `sha256=<hex>`. NOTE: the signed string is the concatenation, not the body alone.
- X-BDAPI-Delivery
- UUID v4 unique per delivery attempt, sent on Watch dispatches (not EC Publications). Use it as a unique constraint on your inbound table so retries become no-ops. Mirrored in `payload.event_id`.
Footgun
Note: BD-API signs `timestamp + "." + raw_body`, NOT the body alone. And it signs the raw bytes of the body — if your framework JSON-parses before exposing the body, capture the raw payload before parsing. Re-serialising and then hashing will not match the signature. EC Publications and Watch use the identical X-BDAPI-Event / X-BDAPI-Timestamp / X-BDAPI-Signature headers and the same algorithm — only Watch dispatches add X-BDAPI-Delivery, and you branch on the X-BDAPI-Event value.