hntavirus.com API

Public, read-only HTTP API for hantavirus surveillance data. Cases, news, WHO Disease Outbreak News, AI-written daily briefings and raw datasets. Free for research and journalism — please credit the site and upstream sources.

Base URL
https://hntavirus.com
Auth
none (public)
Format
JSON · GeoJSON · CSV · XML
CORS
open on /api/dataset/*, /api/cases

Public endpoints

MethodEndpoint 
GET/api/statsExample
GET/api/casesExample
GET/api/cases/by-country/{iso}
GET/api/country/{iso}Example
GET/api/newsExample
GET/api/who-don
GET/api/sourcesExample
GET/api/timeseriesExample
GET/api/briefingExample
GET/api/dataset/cases.geojson
GET/api/dataset/cases.csv
GET/api/dataset/news.json
GET/feed.xml
GET/sitemap.xml
GET/sitemap-news.xml
GET/api/stats
+

High-level dashboard counts.

cURL
curl https://hntavirus.com/api/stats
Response
{
  "total": 107,
  "confirmed": 24,
  "suspected": 21,
  "deaths": 9,
  "locations": 30,
  "lastOnset": 1778025600000
}
GET/api/cases
+

All case features as GeoJSON, paginated server-side and merged.

cURL
curl https://hntavirus.com/api/cases
Response
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "id": 1,
      "geometry": {
        "type": "Point",
        "coordinates": [8.6054, 47.4847]
      },
      "properties": {
        "OBJECTID": 1,
        "STATUS": "CONFIRMED",
        "ONSET": 1778025600000,
        "DEATH": null,
        "LASTLOCATION": "ZURICH",
        "SOURCE": "https://www.bag.admin.ch/...",
        "Exposure_Group": "MV Hondius, Disembarked April 24th",
        "DETAILS": "Departed ship, Swiss national, confirmed case"
      }
    }
  ]
}
GET/api/country/{iso}
+

Stats, recent cases, recent news, WHO DON entries, aggregate timeline.

cURL
curl https://hntavirus.com/api/country/{iso}
Response
{
  "stats": {
    "iso": "CH",
    "total": 2,
    "confirmed": 1,
    "suspected": 1,
    "deaths": 0,
    "newsCount": 0,
    "donCount": 0
  },
  "recentCases": [
    {
      "objectId": 1,
      "status": "CONFIRMED",
      "location": "ZURICH",
      "onset": 1778025600000,
      "death": null,
      "age": null,
      "sex": 1,
      "lon": 8.605,
      "lat": 47.484
    }
  ],
  "recentNews": [],
  "recentWho": [],
  "aggregate": [
    { "day": "2026-05-12", "cases": 2, "confirmed": 1, "suspected": 1, "deaths": 0, "newsCount": 0 }
  ]
}
GET/api/news
+

Latest news ordered by pub_date DESC.

cURL
curl 'https://hntavirus.com/api/news?lang=es&limit=5'
Response
{
  "source": "d1",
  "items": [
    {
      "id": "978acd2b",
      "title": "French and Spanish hantavirus evacuees test positive...",
      "url": "https://www.sbs.com.au/news/article/...",
      "source": "sbs.com.au",
      "domain": "sbs.com.au",
      "country": "AU",
      "lang": "en",
      "image": "https://...",
      "pubDate": "2026-05-11T23:45:00.000Z",
      "origin": "gdelt"
    }
  ]
}
GET/api/sources
+

Live status of each upstream data source.

cURL
curl https://hntavirus.com/api/sources
Response
{
  "sources": [
    { "source": "who_don", "ok": true, "lastRunAt": "2026-05-12T00:16:15.000Z", "count": 8, "ms": 1222 },
    { "source": "gdelt",   "ok": true, "lastRunAt": "2026-05-12T00:16:15.000Z", "count": 35, "ms": 22142 },
    { "source": "promed",  "ok": true, "lastRunAt": "2026-05-12T00:16:15.000Z", "count": 0, "ms": 17147 },
    { "source": "arcgis",  "ok": true, "lastRunAt": "2026-05-12T00:16:15.000Z", "count": 107, "ms": 16878 }
  ]
}
GET/api/timeseries
+

Daily series for charts.

cURL
curl https://hntavirus.com/api/timeseries
Response
{
  "kind": "cases",
  "iso": null,
  "days": 7,
  "series": [
    { "day": "2026-05-06", "value": 3 },
    { "day": "2026-05-07", "value": 1 }
  ]
}
GET/api/briefing
+

AI-written daily briefing in the requested locale.

cURL
curl 'https://hntavirus.com/api/briefing?locale=es'
Response
{
  "ok": true,
  "source": "cached",
  "briefing": {
    "locale": "es",
    "day": "2026-05-12",
    "body": "Hasta hoy se han notificado...",
    "generatedAt": "2026-05-12T01:15:00Z"
  }
}

Quick examples

cURL

# Stats
curl https://hntavirus.com/api/stats

# News (Spanish)
curl 'https://hntavirus.com/api/news?lang=es&limit=5'

# Country dashboard
curl https://hntavirus.com/api/country/CH

# Briefing (German)
curl 'https://hntavirus.com/api/briefing?locale=de'

# Dataset download
curl -o cases.geojson \
  https://hntavirus.com/api/dataset/cases.geojson

JavaScript

const r = await fetch(
  "https://hntavirus.com/api/country/CH"
);
const data = await r.json();
console.log(data.stats.confirmed);

Python

import requests
cases = requests.get(
  "https://hntavirus.com/api/dataset/cases.geojson"
).json()
print(len(cases["features"]))

Errors

All error responses follow a consistent JSON shape: { "error": "human description" }

StatusMeaning
200Success
201Created
400Bad request body
404Not found
429Too many requests (Cloudflare default protection)
500Server error
502Upstream source failure

Versioning, rate limits & attribution

  • Current version: v1 (implicit). Breaking changes will move to /api/v2/* with a deprecation period. Schema additions are non-breaking.
  • Rate limits are soft, enforced by Cloudflare. Expect 429 only under abuse.
  • Cache headers: most endpoints emit Cache-Control: public, s-maxage=300, stale-while-revalidate=600. Bypass with ?fresh=1 where supported.
  • If you use the data publicly, please link back to hntavirus.com and credit upstream sources (ArcGIS / WHO DON / GDELT / ProMED / r/ContagionCuriosity).

Contact & issues

Issues, data corrections → open a GitHub issue or contact via the press page. Maintained by hntavirus.com.