API Guide
EDOPS — the Environmental Dimensions of Place Service — generates structured environmental signatures for a coordinate, a buffer/basin-ring scope, or a historical polity's territory. Signatures are derived from global datasets aggregated at the hydrological sub-basin level in BasinATLAS, with optional historical enrichment from LMR v2.1 (paleoclimate), eVolv2k v4 (volcanic events), and HYDE 3.4 (land use).
Base URL: https://edops.computingplace.org/api
Interactive schema: edops.computingplace.org/api/schema
A full worked example payload: edops_schema.json
Research prototype. The API is publicly accessible but not under a stability guarantee — parameters and response fields may change between versions.
This page documents the endpoints below, and only those — every other route this app serves exists to support the Sandbox/Explorer/Workbench pages directly and isn't public API surface (hidden from the interactive schema accordingly).
Local vs. upstream
Many Band A–D fields appear as pairs: a local value (the sub-basin only) and an
upstream value (its entire contributing watershed, to the headwaters). Upstream keys
carry an _upstream suffix, e.g. aridity / aridity_upstream.
Aggregation depends on the variable: intensive quantities — aridity, precipitation, temperature, soils, slope — are area-weighted averages over the catchment; extensive quantities like river area and reservoir volume are sums. See each variable's Codebook entry for its rule. A few variables, like discharge, have no upstream counterpart at all — their local value is already the integrated result of everything above.
The divergence between local and upstream is usually the meaningful reading, not the upstream value alone: a desert city fed by a distant mountain river occupies a qualitatively different position than one where the two converge. Because the upstream figure spans the whole catchment, it can blend very different terrain into one number — read it against its local counterpart. The API returns both raw values; it does not compute or return the divergence itself.
Full variable-by-variable reference: see the Codebook.
Endpoints
GET /api/signature
Return environmental signature for a coordinate.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
lat |
float (-90 to 90) | yes | — | Latitude, decimal degrees, in [-90, 90]. |
lon |
float (-180 to 180) | yes | — | Longitude, decimal degrees, in [-180, 180]. |
bands |
str | no | ABCDE |
Which profile groups to include, e.g. "ABCDE" or "ABCDET". |
level |
int | no | 8 |
Basin hierarchy level: 8 or 6. |
from_year |
int | no | — | Start year CE for Band T temporal enrichment (0–1998). |
to_year |
int | no | — | End year CE for Band T temporal enrichment (0–1998). |
flat |
bool | no | false |
If true, return flat field values instead of nested profile_groups; Band T temporal data appears at key "temporal" rather than in profile_groups. |
Response
Default (flat=False): basin identity/geometry fields (id, hybas_id, geom_geojson, ...) plus
"profile_groups": {"<band letter>": {"label": str, "items": [{"key", "label", "value"}, ...]}}
for each requested band. Band T (if requested) nests under profile_groups["T"] instead, with
its own "_status" ("ok" | "not_requested" | "error").
flat=True: the same identity/geometry fields plus every variable as a top-level key (no
profile_groups nesting); Band T appears at top-level key "temporal" instead.
Full variable inventory (what each band/key means): see the Codebook (/docs/codebook/).
GET /api/area
Return an areal environmental signature for a named Cliopatria polity.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
polity |
str | yes | — | Cliopatria polity name, exact match (e.g. "Northern Song"). |
year |
int | yes | — | Resolver year CE — selects the polity boundary active at this year. |
level |
int | no | 6 |
Basin hierarchy level: 6 or 8. |
bands |
str | no | ABCDET |
Band letters to compute, e.g. "ABCDET". Add T to include Band T (requires from_year and to_year). |
from_year |
int | no | — | Band T span start, year CE. Required when T is in bands. |
to_year |
int | no | — | Band T span end, year CE. Required when T is in bands. |
detail |
bool | no | false |
If true, include per-variable histogram objects in the response. |
Response
Same profile_groups envelope as GET /api/signature, but each value is a distribution across
the polity's member basins, not an average (see engine.py). Adds:
"resolver": {"type": "polity", "polity", "polity_id", "fromyear", "toyear", "year"}
"member_ids": [hybas_id, ...]
"band_t_span": {"from_year", "to_year"} -- present only when Band T requested
detail=true adds a per-variable "distribution" histogram object.
Full variable inventory: see the Codebook (/docs/codebook/).
GET /api/areas
Areal signature dispatcher — resolves to a set of member basins by scope, then aggregates their signature as a distribution (not an average). scope is confusingly named "area" alongside GET /api/area, but the four scope kinds are not all areas in the geometric sense: single_basin and polity are bounded regions, buffer is an arbitrary radius, and basin_ring is a topological set of basins, not a shape.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
scope |
str | yes | — | Spatial scope of the query: 'buffer', 'single_basin', 'polity', or 'basin_ring'. Determines which of lat/lon/radius_km/polity/year are required (see each param's own description) and the shape of the scope block in the response. |
lat |
float (-90 to 90) | no | — | WGS-84 latitude, decimal degrees. Required for scope=buffer, single_basin, basin_ring. |
lon |
float (-180 to 180) | no | — | WGS-84 longitude, decimal degrees. Required for scope=buffer, single_basin, basin_ring. |
radius_km |
float | no | — | Buffer radius in km. Required for scope=buffer. |
polity |
str | no | — | Cliopatria polity name, exact match (e.g. "Northern Song"). Required for scope=polity. |
year |
int | no | — | Resolver year CE — selects the polity boundary active at this year. Required for scope=polity. |
level |
int | no | 6 |
Basin hierarchy level: 6 or 8. |
bands |
str | no | ABCDE |
Band letters to compute, e.g. "ABCDE" or "ABCDET". Add T to include Band T (requires from_year and to_year). |
from_year |
int | no | — | Band T span start, year CE. Required when T is in bands. |
to_year |
int | no | — | Band T span end, year CE. Required when T is in bands. |
detail |
bool | no | false |
If true, include per-variable histogram objects in the response. |
Response
Same areal-signature envelope as GET /api/area (profile_groups as distributions across member
basins, not averages), plus a `scope` block whose shape depends on `scope`. detail=true adds
per-variable histogram objects. Full variable inventory: see the Codebook (/docs/codebook/).
GET /api/health
Confirm the service is running.
Response
{"status": "ok"}
Example requests
Bands A and B only — Athens
curl "https://edops.computingplace.org/api/signature?lat=37.97&lon=23.73&bands=AB"
Full baseline signature — Samarkand
curl "https://edops.computingplace.org/api/signature?lat=39.65&lon=66.98&bands=ABCDE"
With historical climate — Rome, early imperial period
curl "https://edops.computingplace.org/api/signature?lat=41.9&lon=12.5&bands=ABCT&from_year=1&to_year=400"
Flat mode — all fields as top-level keys
curl "https://edops.computingplace.org/api/signature?lat=16.8167&lon=-2.9833&bands=ABCDE&flat=true"
Areal signature for a polity — Northern Song at 1080 CE
curl "https://edops.computingplace.org/api/area?polity=Northern%20Song&year=1080&bands=ABCDE"
Buffer scope via the scope dispatcher
curl "https://edops.computingplace.org/api/areas?scope=buffer&lat=16.8167&lon=-2.9833&radius_km=100&bands=ABCDE"
Notes for application developers
/areavs/areas: not a clean singular/plural pair./areais polity-only./areasdispatches onscope, and its four resolver types aren't all "areas" in the geometric sense —single_basinandpolityare bounded regions,bufferis an arbitrary radius, andbasin_ringis a topological set of neighboring basins, not a shape at all. "Area" in EDOPS currently covers several distinct things; not yet normalized to one term.- CORS: Cross-origin requests are allowed — call the API directly from browser JavaScript.
- No basin found: If the coordinate falls outside all known sub-basins (open ocean, ice sheet), the API returns HTTP 404.
- Response modes: By default, environmental variables are grouped under
profile_groups. Pass&flat=trueon/signatureto receive all variable values as flat top-level keys instead. - Band T availability:
_statusreflects whether the Band T mechanism ran, not whether every source had data — LMR, eVolv2k, and HYDE each have independent coverage windows, and a single query can mix available and unavailable sources. Check the per-source fields (lmr_status, the*_notefields) rather than_statusalone. See edops_schema.json for a full worked example. leveldefault varies by endpoint, deliberately left as-is —/signaturedefaults to8;/areaand/areasdefault to6./signaturealways returns a single basin's data regardless of level, so this only affects resolution, not payload shape or size. Pass it explicitly if your use case depends on which sub-basin resolution you get.- Rate limits: None enforced currently.
EDOPS is part of the Computing Place research initiative. Contact: karl.geog@gmail.com