Public API
Endpoint JSON read-only del tracker outbreak hantavirus MV Hondius. Free, no auth, no rate limit (oltre il fair use Cloudflare). Aggiornati ogni 6h dalla pipeline AI.
Endpoints
Tutti gli eventi geolocalizzati: tappe nave, comunicati ufficiali, casi confermati/sospetti, decessi. Ogni evento ha sources, history, verification status.
~80 eventi, ~200 KB, aggiornato ogni 6h.
Snapshot ufficiali da fonti primarie (WHO, ECDC, autorità nazionali). Conteggi totali nel tempo. Mai derivati da media.
4+ snapshot, ~2 KB.
Registro casi anonimi con movimenti tra luoghi. Nessun PII (solo paese di residenza). Usato per anti double-counting.
~6 casi, ~4 KB.
Serie temporale derivata dagli snapshot autoritativi (scope global/cruise_ship). Per chart trend.
Tono degli articoli (alarm score 0-100) aggregato per giorno e per categoria di fonte. Include il Panic Gap a 30gg (differenza fra tono medio media non-tabloid e bollettini ufficiali) e citazioni rappresentative. Score generato da LLM su titolo + sommario, calibrato con anchor 0/25/55/85.
Schema: by_day[], by_authority_30d{}, panic_gap_30d (null se mancano bollettini ufficiali nel periodo), top_alarming_30d[], top_calm_30d[].
Case tracking v2 — endpoints (sperimentali)
v2 sperimentale: tracciamento individuale dei casi con timeline persona-per-persona, costruito via LLM (Mistral profile_builder + Sonnet case_linker). Schema in fase di stabilizzazione. Contagiati ed esposti restano tenuti separati nei conteggi: gli esposti sono passeggeri evacuati/trasferiti di cui non è noto lo stato clinico, non casi sospetti.
Conteggi totali. Contagiati e esposti separati: contagiati_seguiti_media (sospetti+confermati+critici+decessi) e esposti_monitorati_separati (passeggeri evacuati). Mai sommare.
Schema: contagiati_seguiti_media (int), esposti_monitorati_separati (int), contagiati_breakdown{cases_alive_clinici, deaths, cases_exposed_singoli}, contagiati_tracciati_individualmente (int, casi singoli con timeline), contagiati_untracked_aggregati, n_aggregates_total, by_country{ISO2: {cases, exposed}}, computed_at (ISO).
Casi singoli tracciati individualmente con timeline ricostruita cross-source. Ogni caso ha un case_id stabile (cs-NNN), features (età, gender, residence, profession, narrative_anchors, custom fields), status_history[] (cambi di stato con data + location), linked_event_ids[] (articoli sorgente).
Schema features: age, gender (M|F|null), residence_iso2, residence_admin1, nationality_iso2, profession, hospital_or_facility, narrative_anchors[], _custom{open dict, LLM-discovered}.
Privacy: nessun PII (no nomi/cognomi, no DOB completa, no indirizzi specifici, no codici fiscali). Solo features non identificative singolarmente.
~50 casi, ~80 KB, aggiornato ogni 6h.
Aggregati di contagiati (articoli che citano un numero senza identificazione individuale). Ogni aggregato ha case_ids_likely_inside[] (case_id singoli che probabilmente sono già dentro l'aggregato → cap intelligente: contributo counter = max(0, total − len(inside))). Solo aggregati di contagiati, esposti su endpoint separato.
Schema: agg_id, country_iso2, category (confirmed_case|suspect_case|death), date, total_count, destination, context, case_ids_likely_inside[], case_ids_confirmed_inside[], aggregate_kind (cases|needs_review).
Aggregati di esposti monitorati (passeggeri evacuati/trasferiti/contatti del volo). Stesso schema di aggregates_cases.json ma aggregate_kind=exposed_contacts. Tenuti DISTINTI dai contagiati nel conteggio cronaca.
Esempi d'uso
curl / shell
curl -s https://outbreak-monitor.com/api/v1/events.json | jq '.[0]' # Filtra solo eventi verified curl -s https://outbreak-monitor.com/api/v1/events.json | \ jq '.[] | select(.verification_status == "verified")'
Python
import requests
events = requests.get("https://outbreak-monitor.com/api/v1/events.json").json()
deaths = [e for e in events if e["category"] == "death"]
print(f"{len(deaths)} death events tracked")
JavaScript (fetch)
fetch("https://outbreak-monitor.com/api/v1/snapshots.json")
.then(r => r.json())
.then(snapshots => {
const latest = snapshots
.filter(s => s.scope === "cruise_ship")
.sort((a, b) => b.date.localeCompare(a.date))[0];
console.log("Latest WHO total:", latest.totals);
});
Node.js / Python data science
import pandas as pd
df = pd.read_json("https://outbreak-monitor.com/api/v1/events.json")
df.groupby("source_authority").size()
Schema events.json
| Campo | Tipo | Descrizione |
|---|---|---|
id | string | ID stabile (slug + hash). Idempotente tra deploy. |
lat / lon | float | Coordinate geocoded via Nominatim/OSM. |
location | string | Nome luogo (city, country) canonicalizzato. |
country_iso2 | string | ISO 3166-1 alpha-2. |
event | string | Descrizione evento in italiano (max 120 char). |
event_en | string | Stessa in inglese. |
category | enum | exposure | ship_stop | confirmed_case | suspect_case | death | official_statement |
status | enum | confirmed | suspect | hypothesis |
verification_status | enum | verified | corroborated | unverified | disputed |
source_authority | enum | who | ecdc | national_health | scientific | media_intl | media_it | media_tabloid |
case_ref | string|null | Riferimento a case_registry per dedup persone. |
corroborating_sources | array | Tutte le fonti che hanno riportato l'evento. |
history | array | Timeline degli aggiornamenti (status changes, source upgrades, retractions). |
added / updated | ISO 8601 | Timestamp creation/modifica. |
Caching & freshness
- Cache HTTP
max-age=300(5 min). Cloudflare CDN davanti. - Pipeline aggiorna i JSON ogni 6 ore.
- Per polling efficiente, leggi il header
last-modifiede usaIf-Modified-Since.
Limiti
- Solo metodi
GETeOPTIONS(preflight CORS). - Nessun parametro query: il dataset completo è restituito ad ogni richiesta — filtra lato client. Per dataset più grandi (futuri outbreak) considereremo paginazione.
- Fair use: non DDoS-are. Cloudflare blocca bot aggressivi automaticamente.
- CORS: configurato lato origin con
Access-Control-Allow-Origin: *. Se il header non arriva (dipende dalle policy CDN attive), può essere necessario un proxy lato server.
Stabilità & versioning
URL /api/v1/ garantito stabile. In caso di breaking change schema, sarà rilasciato /api/v2/ mantenendo v1 per ≥6 mesi. Aggiornamenti additivi (nuovi campi opzionali) sono retrocompatibili e non incrementano la versione.
Widget embeddable
Per integrare il box "ufficiali vs media tracked" in un blog/articolo, basta un <iframe>:
<iframe src="https://outbreak-monitor.com/embed.html" width="480" height="280" frameborder="0" loading="lazy" title="Outbreak Tracker — Hantavirus MV Hondius"> </iframe>
Parametri:
| Parametro | Valori | Descrizione |
|---|---|---|
lang | it (default) | en | Lingua dell'interfaccia. |
theme | light | dark | Forza tema. Default: auto via prefers-color-scheme. |
compact | 1 | Versione compatta (~480×130) senza breakdown. |
Esempi:
<!-- Inglese, tema scuro --> <iframe src="https://outbreak-monitor.com/embed.html?lang=en&theme=dark" width="480" height="280" frameborder="0" loading="lazy"></iframe> <!-- Compatto per sidebar --> <iframe src="https://outbreak-monitor.com/embed.html?compact=1" width="480" height="130" frameborder="0" loading="lazy"></iframe>
Self-contained, nessuna dipendenza esterna, mobile responsive (collassa verticale <360px). Fetcha i JSON dell'API ogni caricamento. Cache HTTP max-age=300.
Contatto
Per uso commerciale licensing custom o richieste tecniche: [email protected]