---
title: Filtering
description: Filter features by attribute with CQL2, by area with bbox, and by time on observed_at — and discover each collection's queryable fields.
---

## Attribute filters — CQL2

Pass a CQL2 expression in `filter` with `filter-lang=cql2-text`. Full CQL2 is supported:
comparison, boolean and arithmetic operators, `IN`, `LIKE`, spatial operators, functions.

```bash
# Live, high-confidence, energetic detections
curl -sG -H "Authorization: Bearer $TOKEN" \
  "https://api.deepfire.co/ogc/features/v1/collections/deepfire:hotspots/items" \
  --data-urlencode "filter-lang=cql2-text" \
  --data-urlencode "filter=active = true AND confidence = 'HIGH' AND fire_radiative_power > 50" \
  --data-urlencode "f=application/geo+json"
```

## Spatial filter — `bbox`

`bbox=min_lon,min_lat,max_lon,max_lat` in WGS84 — **longitude first**, then latitude.
Example: California.

```bash
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://api.deepfire.co/ogc/features/v1/collections/deepfire:hotspots/items?bbox=-125,32,-114,42&limit=1000&f=application/geo%2Bjson"
```

## Time filters — use CQL on `observed_at`

Filter by time with a CQL predicate. `observed_at` is indexed, so this is fast even
against the full history:

```bash
curl -sG -H "Authorization: Bearer $TOKEN" \
  "https://api.deepfire.co/ogc/features/v1/collections/deepfire:hotspots/items" \
  --data-urlencode "filter-lang=cql2-text" \
  --data-urlencode "filter=observed_at > TIMESTAMP('2026-07-01T00:00:00Z')" \
  --data-urlencode "f=application/geo+json"
```

:::caution[`datetime=` needs a closed interval]
The standard `datetime=` parameter works only with a **closed** interval
(`datetime=2026-07-01T00:00:00Z/2026-07-06T00:00:00Z`). Open-ended intervals (`.../..`)
are **not** supported and return an error — prefer the CQL form above.
:::

## Combining filters

`bbox`, `filter`, and `limit` combine freely:

```bash
curl -sG -H "Authorization: Bearer $TOKEN" \
  "https://api.deepfire.co/ogc/features/v1/collections/deepfire:hotspots/items" \
  --data-urlencode "bbox=-10,36,4,44" \
  --data-urlencode "filter-lang=cql2-text" \
  --data-urlencode "filter=active = true AND fire_radiative_power > 20" \
  --data-urlencode "limit=5000" \
  --data-urlencode "f=application/geo+json"
```

Scoped queries (bbox + time window + `active`) are also what keeps you clear of the
30-second query limit — see [Performance & limits](/guides/performance-and-limits).

## Discovering filterable fields

Each collection publishes its filterable attributes at `/queryables` as a JSON Schema
document, e.g. [Queryables for hotspots](/reference/hotspots/queryables-deepfire-hotspots). Note the
media type — it's `application/schema+json`, not plain JSON:

```bash
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://api.deepfire.co/ogc/features/v1/collections/deepfire:hotspots/queryables?f=application/schema+json"
```
