Research API /api/v1
Read access to the situation platform for theses, research and agency scripts: active-fire detections (NASA FIRMS/GWIS), burnt areas (EFFIS), fire danger (FWI) and the ground sensor network as raw series.
Access and keys
Keys are issued by the operator (samoLabs): request one with your name, institution and purpose via info@samolabs.de. Research keys are free of charge and time-limited; each key is for one person or one system.
Every data request carries the key as a bearer token in the Authorization header:
Authorization: Bearer ffw_YOUR_KEY
401 means: no or unknown key. Obtain access. 403 means: key known but revoked or expired. Contact the operator. An empty result with HTTP 200, by contrast, means: looked, nothing there.
The limit is 120 requests per minute per key. On 429, honour the Retry-After header.
Endpoints
Five data endpoints, all key-protected, all in GeoJSON and CSV:
- GET /api/v1/hotspots
- Active-fire detections with the full raw source columns (brightness temperatures, pixel size, FRP, product id). Detections are pixels, not fire counts.
- GET /api/v1/burnt-areas
- Burnt-area perimeters from EFFIS with all attributes. Geometry in the GeoJSON variant; the CSV variant is the attribute table.
- GET /api/v1/fire-danger
- Fire danger as a time series with all sub-indices of the Canadian FWI system (FFMC, DMC, DC, ISI, BUI). Exactly one model per response; never mix the reference levels country and adminArea.
- GET /api/v1/sensor-stations
- Station registry of the ground sensor network: the master data for the measurement series, including the simulated flag.
- GET /api/v1/sensor-readings
- Sensor network series as untouchable raw values in a 10-minute cycle; ?series=corrected returns the (later versioned) correction layer.
The complete machine-readable contract is available as an OpenAPI 3.0 document at GET /api/v1/docs and loads directly into Swagger UI or Postman.
Formats and time windows
Every endpoint returns GeoJSON (RFC 7946, with an additional meta block) and, with ?format=csv, a CSV variant: comma-separated, one header row, UTF-8. Both pandas.read_csv and readr::read_csv read it without extra options.
The time window comes from ?from and ?to (ISO 8601; a bare date counts as UTC midnight). For reproducible extracts always pass both bounds. The window actually used is echoed in meta.window. If meta.truncated reports a cut, narrow the window; there is deliberately no offset parameter.
Every JSON response carries meta.observation: whether the feeding data chain ran at all and how old its last success is. An empty collection means observed, nothing found; HTTP 503 means did not look. Never equate the two.
Reproducibility: the v1 commitments
The /v1 path segment is a stability commitment to ongoing theses: within v1, fields, parameters, enum values and error codes are never removed, renamed or reinterpreted. Extensions are strictly additive. A break would mean /v2, with a documented transition period for v1.
All timestamps are ISO 8601 in UTC. Research data never switches to a display time zone. The local time of the UI is presentation only.
The sensor network contains simulated demo stations. Every station and every reading therefore carries the simulated field; analyses filter it as the first step. Simulated series appear in no citable dataset.
?series=raw returns the untouchable raw series. ?series=corrected is the correction layer: it currently returns the same raw values, but with correctionModel: null, no correction applied, as a citable statement. Once server-side versioned correction models (humidity bias, co-location factors) are retrofitted, correctionModel carries the model id without any change to the response shape.
Examples
The examples are deliberately untranslated; replace HOST with the address of the installation.
Fetch with curl
curl -H "Authorization: Bearer ffw_YOUR_KEY" \ "https://HOST/api/v1/hotspots?from=2026-07-01&to=2026-08-01&country=BA&format=csv" \ -o hotspots_ba_2026-07.csv
Python (pandas)
import io
import requests
import pandas as pd
resp = requests.get(
"https://HOST/api/v1/sensor-readings",
params={"from": "2026-06-01", "to": "2026-07-01",
"series": "raw", "format": "csv"},
headers={"Authorization": "Bearer ffw_YOUR_KEY"},
timeout=60,
)
resp.raise_for_status()
df = pd.read_csv(io.StringIO(resp.text), parse_dates=["measuredAtUtc"])
df = df[~df["simulated"]] # always drop simulated demo stationsR (httr2 + readr)
library(httr2)
library(readr)
resp <- request("https://HOST/api/v1/fire-danger") |>
req_url_query(model = "effis", from = "2026-06-01",
to = "2026-08-01", format = "csv") |>
req_auth_bearer_token("ffw_YOUR_KEY") |>
req_perform()
danger <- read_csv(resp_body_string(resp))
danger <- subset(danger, level == "adminArea") # never mix reference levels