Skip to main content

Fire Grid

Fire Grid aggregates individual fire events (hotspots) onto an H3 hexagonal grid. Instead of returning every hotspot, the grid buckets them into hexagonal cells at a chosen resolution and returns one aggregated record per cell. This keeps responses small and stable across zoom levels while still conveying where, how recently, and how intensely fire is burning.

Two endpoints expose the same aggregation in different shapes:

EndpointResponseUse it when…
GET /v1/fires/h3/json/Plain JSON array of cell records (no geometry)You render the cells yourself from the h3_cell index, or you only need the per-cell metrics (counts, FRP, recency) without geometry.
GET /v1/fires/h3/geojson/GeoJSON FeatureCollection; each feature is a cell polygonYou want ready-to-draw hexagon polygons and prefer not to convert H3 indices to geometry yourself.

Both endpoints accept the same query parameters, require the apikey header, and share the same bounding box (xmin, ymin, xmax, ymax), time (date, minutes), satellite/algorithm, confidence and epsg filters as GET /v1/fires/. The two parameters specific to the grid are:

  • h3_resolution (015, default 8): the size of the cells (see below).
  • shape_mode (point or shape, default point): whether a hotspot is assigned to the single cell containing its centroid (point), or to every cell its footprint overlaps once buffered by half its GSD (shape).

Using the right API

  • Analysis / custom rendering: /fires/h3/json/. The array form is the lightest payload. You get the h3_cell index for every populated cell and can compute the boundary, centroid or neighbours locally with any H3 binding, or feed the metrics straight into a table or chart.
  • Map display: /fires/h3/geojson/. Each feature already carries the cell polygon in the requested epsg, so you can hand the FeatureCollection directly to a GeoJSON layer. The properties of every feature are exactly the fields documented in the JSON schema below.

Both endpoints return the identical set of aggregated properties, so you can switch between them without changing how you interpret a cell.

Choosing the cell resolution from the map zoom

The API does not infer resolution from a map zoom, you pass h3_resolution explicitly. Pick a resolution so that cells stay a comfortable on-screen size: too coarse and the fire footprint is a single blob, too fine and you request thousands of tiny cells.

A good default heuristic for a standard 256 px Web-Mercator tile pyramid is:

h3_resolution = clamp(zoom - 3, 0, 15)

which keeps cells roughly 20–60 px across. Reissue the request with the new resolution whenever the user zooms across a threshold. As a reference, the average H3 cell edge length per resolution:

Map zoomh3_resolutionApprox. cell edgeTypical view
0–30–11300 km → 480 kmWhole globe / continents
41480 kmSub-continental
52180 kmLarge country
6369 kmRegion
7426 kmLarge metro area
8510 kmMetro area
963.7 kmCity
1071.4 kmDistrict
118 (default)530 mNeighbourhood
129200 mBlocks
131076 mIndividual hotspots
14+11–15≤ 29 mSub-hotspot detail

Interpreting a cell

Every cell (a JSON array element, or one GeoJSON feature's properties) has the same fields:

FieldMeaning
h3_cellThe H3 index (base-16 string) at the requested resolution. Convert it to a boundary, centroid or set of neighbours with any H3 library.
latest_acquisition_timeThe most recent satellite acquisition among the hotspots in the cell, i.e. how fresh the activity is.
min_gsdSmallest (best) ground sampling distance, in metres, among the hotspots in the cell. Lower = more spatially precise detection.
scale_factorPre-computed rendering scale in [0.25, 0.95] derived from the GSD (see scaling below).
max_frpHighest fire radiative power, in MW, observed in the cell.
satellitesDistinct satellites that contributed a hotspot to the cell.
leo_hotspot_countHotspots detected by low-earth-orbit satellites (higher spatial resolution, infrequent revisit).
geo_hotspot_countHotspots detected by geostationary satellites (coarser resolution, frequent revisit).
cluster_idsThe distinct fire cluster IDs the cell's hotspots belong to. Use these to cross-reference GET /v1/clusters/{id}.

A cell tells you: something was detected here (h3_cell), how recently (latest_acquisition_time), how strong (max_frp), how trustworthy the position is (min_gsd, scale_factor), and by what (satellites, leo_hotspot_count, geo_hotspot_count).

Colouring a cell

Colour communicates the dimension that matters for your use case. Two common schemes:

  • By recency (default for live monitoring). Compute the cell age from latest_acquisition_time (now - latest_acquisition_time) and map it onto a ramp, e.g. bright red/orange for the last hour, fading toward a muted grey/brown for older activity. This makes the current fire front stand out against cooling areas.
  • By intensity. Map max_frp onto a sequential ramp (e.g. yellow → red → purple). FRP spans orders of magnitude, so apply a logarithmic scale and clamp to a sensible maximum before mapping.

Whatever the hue encodes, you can encode a second dimension in opacity. For example intensity in hue and recency in opacity, or vice-versa. Because the json and geojson endpoints expose identical fields, the same colour logic works for both.

Scaling a cell by GSD (inverted GSD)

Rendering every cell as a full hexagon overstates the certainty of coarse detections. To convey spatial precision, scale each cell polygon about its centroid by scale_factor before drawing it. The scale is inversely related to GSD: precise (small-GSD) detections are drawn close to the full hexagon, while coarse (large-GSD) detections shrink toward the cell centre.

scale_factor is pre-computed server-side so both endpoints agree. It is derived from the cell's effective minimum GSD:

  1. Per hotspot, the effective GSD is its gsd, except hotspots flagged low_accuracy, which are penalised to 2000 m.
  2. The cell takes the minimum effective GSD across its hotspots.
  3. That minimum is mapped to a scale, clamped to [0.25, 0.95]:
MIN_GSD = 150 # m → best resolution we distinguish
MAX_GSD = 2000 # m → coarsest / low-accuracy
MIN_SCALE = 0.25
MAX_SCALE = 0.95

if min_gsd <= MIN_GSD: scale = MAX_SCALE # 0.95, near full hexagon
elif min_gsd >= MAX_GSD: scale = MIN_SCALE # 0.25, small marker
else: scale = MAX_SCALE - (min_gsd - MIN_GSD)
/ (MAX_GSD - MIN_GSD) * (MAX_SCALE - MIN_SCALE)

To apply it when drawing, scale the polygon around its centroid c:

p' = c + scale_factor * (p - c) for each vertex p of the cell

The json endpoint returns scale_factor alongside the metrics; the geojson endpoint returns it as a feature property. If you prefer to derive the scale yourself (for example to re-tune the constants), apply the formula above to the cell's min_gsd, but note that min_gsd is the raw minimum GSD and does not carry the low_accuracy penalty, so it will differ from scale_factor for cells that only contain low-accuracy detections. Prefer the pre-computed scale_factor unless you have a reason not to.