SENTINARA API

Quickstart

#1. Make a request (no key needed)

bash
curl https://api.sentinara.org/v1/countries/IDN

Every response has the same envelope:

json
{
  "data": { "iso3": "IDN", "name": "Indonesia", "...": "..." },
  "meta": {
    "request_id": "8d3f…",
    "tier": "anonymous",
    "data_updated_at": "2026-10-31T06:03:50.174Z",
    "attribution": "SENTINARA (sentinara.org) analysis of WHO …",
    "license": "CC BY 4.0",
    "docs": "https://docs.sentinara.org/reference#country"
  }
}

#2. List, filter and paginate

bash
curl "https://api.sentinara.org/v1/countries?region=SEAR&sort=-cases&limit=10"

List responses add meta.total and links.next. Follow links.next until it is null. See Pagination & filtering.

#3. Get a key for higher limits

Without a key you can make 30 requests per minute. Create a key in a minute, then send it in a header:

bash
curl https://api.sentinara.org/v1/warnings \
  -H "Authorization: Bearer $SENTINARA_KEY"

Never put the key in the URL; the API rejects that with api_key_in_query.

#4. Use it from your language

javascript
// Node.js 18+ (server side: use a secret key)
const res = await fetch('https://api.sentinara.org/v1/indonesia/forecast', {
  headers: { Authorization: `Bearer ${process.env.SENTINARA_KEY}` },
});
if (!res.ok) throw new Error((await res.json()).detail);
const { data } = await res.json();
console.log(data.months[0]);
python
import os, requests

r = requests.get(
    "https://api.sentinara.org/v1/countries/BRA/series",
    params={"from": "2025-01"},
    headers={"Authorization": f"Bearer {os.environ['SENTINARA_KEY']}"},
    timeout=30,
)
r.raise_for_status()
for row in r.json()["data"]:
    print(row["month"], row["cases"])
r
library(httr2)
resp <- request("https://api.sentinara.org/v1/indonesia/annual") |>
  req_url_query(format = "csv") |>
  req_perform()
annual <- read.csv(text = resp_body_string(resp))

#5. Download CSV

Every list endpoint returns CSV with ?format=csv or Accept: text/csv:

bash
curl -o indonesia-series.csv "https://api.sentinara.org/v1/indonesia/series?format=csv"

In Google Sheets: =IMPORTDATA("https://api.sentinara.org/v1/indonesia/annual?format=csv").

#6. Cache politely

The data changes once a week. Send the ETag back as If-None-Match and you get 304 Not Modified with no body. Conditional requests still count towards limits, but they are fast and light.

SENTINARA, a nonprofit organisation of Digivana Group · Data CC BY 4.0 · Terms · Security · OpenAPI