Query Features
How to filter, paginate, and sort features from any ADAM collection. This guide is a series of focused recipes — pick the one that matches your need.
The endpoint everything here builds on:
GET /collections/{collectionId}/items
Response is always a GeoJSON FeatureCollection with numberMatched, numberReturned and pagination links.
Discover what you can filter on
Before you filter, ask the collection what is filterable:
GET /collections/{collectionId}/queryables
The response is a JSON Schema. Every property that appears at properties.{name} is a valid operand for the filter= query parameter.
import httpx
BASE = "https://api.adam.geospatial.wfp.org/api"
qs = httpx.get(f"{BASE}/collections/adam.adam_eq_events/queryables").json()
print(list(qs["properties"].keys()))
Recipe — bounding box
Spatial filter, minLon,minLat,maxLon,maxLat, WGS84:
GET /collections/adam.adam_eq_events/items?bbox=26,36,45,42
For extents that cross the antimeridian (180°), pass a single bbox where minLon > maxLon:
?bbox=170,-20,-170,20
Recipe — temporal window
Single instant:
?datetime=2026-04-15T12:00:00Z
Closed interval:
?datetime=2026-04-01T00:00:00Z/2026-04-30T23:59:59Z
Open-ended (useful for "everything since ..."):
?datetime=2026-04-01T00:00:00Z/..
Recipe — attribute filter (CQL2)
Use the filter= parameter with OGC CQL2 syntax. Operands must appear in /queryables.
?filter=mag >= 6.0
Combine conditions with AND / OR:
?filter=mag >= 6.0 AND depth < 30
Remember to URL-encode the filter value when constructing URLs by hand — httpx does it for you.
Recipe — combine spatial, temporal and attribute filters
All three parameters stack, intersected:
resp = httpx.get(
f"{BASE}/collections/adam.adam_eq_events/items",
params={
"bbox": "26,36,45,42",
"datetime": "2026-01-01T00:00:00Z/..",
"filter": "mag >= 6.0",
"sortby": "-datetime",
"limit": 50,
},
)
fc = resp.json()
Recipe — paginate through all results
items returns at most limit features. For anything unbounded, paginate with offset and the numberMatched the response returns:
def iter_all(url, params, page_size=500):
offset = 0
while True:
page = httpx.get(url, params={**params, "limit": page_size, "offset": offset}).json()
for f in page["features"]:
yield f
offset += page["numberReturned"]
if offset >= page["numberMatched"] or page["numberReturned"] == 0:
return
for feature in iter_all(
f"{BASE}/collections/adam.adam_eq_events/items",
{"datetime": "2026-01-01T00:00:00Z/.."},
):
...
Recipe — sort
Prefix a queryable name with - for descending order:
?sortby=-datetime # most recent first
?sortby=mag # ascending
Recipe — select output format
Most endpoints do content negotiation via the f parameter:
?f=json # machine-readable JSON (often the default)
?f=geojson # explicit GeoJSON
?f=html # the live HTML browser (see the Quickstart)
When things go wrong
400 Bad Request— usually an invalidfilterexpression or a malformedbbox/datetime. Check names against/queryables.- Empty results — the filters intersect to nothing. Open the collection's HTML browser to confirm there is data for your window.
- Slow paginated runs — reduce
limitor add tighterbbox/datetime. Avoid full-catalogue scans during peak hours.
Next steps
- Display on a Map — render your filtered features visually
- Fetch Event Outputs — drill into a single feature's derived products
- API — Features Reference — full endpoint contract
Live references
- Items endpoint on Swagger →
items_collections__collectionId__items_get - Queryables on Swagger →
queryables_collections__collectionId__queryables_get - Browse earthquake items live → /api/collections/adam.adam_eq_events/items