Skip to content
DeepfireDeepfire Docs
Esc
↑↓navigate↵open⌘Jpreview
On this page

Fire spread

Run a fire spread simulation from any cluster or point.

/v1/fire-spread - choose between different models and ignition settings.

Attributes

Field Required Default Notes
clusterId no id of a feature in deepfire:clusters
latitude, longitude no A single-point ignition instead of a cluster
durationHours yes 1–24
model no elmfire elmfire or forefire
ensembleMembers no 1 1–50
sources no see below source codes from Data sources
lookbackHours no 24 1–168; only hotspots within this timeframe seed the simulation
domainBufferKm no 25 5–50; km around the ignition the model may spread into, see Model parameters
elmfire no ELMFIRE overrides, only with model: elmfire, see Model parameters

One of clusterId or latitude/longitude is required.

Examples

You can initate a fire spread either from a satellite cluster or a point.

For the cluster, you can pass in the cluster id:

curl -s -i -X POST "https://api.deepfire.co/v1/fire-spread/simulations" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"clusterId": "65d45ca4-a7b5-4d7e-85f3-516163c2a31d", "durationHours": 12}'

Alternatively, you can pass in a lat lon value:

curl -s -X POST "https://api.deepfire.co/v1/fire-spread/simulations" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"latitude": 39.0, "longitude": -105.5, "durationHours": 6}'

Choosing the ignition from a cluster

The fire is seeded from the cluster’s hotspots. sources is an include-list of exact source codes, the same values you filter hotspots by; to leave a satellite out, don’t list it. Omitted, it means our default set of high confidence satellite sources.

Only VIIRS and Landsat from the last six hours, ten ensemble members:

curl -s -X POST "https://api.deepfire.co/v1/fire-spread/simulations" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "clusterId": "65d45ca4-a7b5-4d7e-85f3-516163c2a31d",
    "durationHours": 12,
    "ensembleMembers": 10,
    "sources": ["VIIRS_SNPP_NRT", "VIIRS_NOAA20_NRT", "VIIRS_NOAA21_NRT", "LANDSAT_NRT"],
    "lookbackHours": 6
  }'

Model parameters

Every parameter is optional. Omitted ones take the defaults below, which are Deepfire’s calibrated values for the 30 m fuel grid we run on and in places differ from ELMFIRE’s own built-in defaults. ELMFIRE overrides go in an elmfire block using ELMFIRE’s own parameter names, so you can read them up in the upstream reference; the block is rejected with model: forefire. ForeFire runs take domainBufferKm only — its remaining script settings are solver numerics and stay fixed.

The response echoes domainBufferKm and elmfire: while the run is QUEUED they hold what you sent, and once the run has reported back they hold the full resolved set, every parameter with the value the run used, so a stored result stays interpretable after these defaults change. The one exception is seed, which is only echoed when you pinned it.

domainBufferKm applies to both models. It is the buffer around the ignition that defines the modelled area; a fire that reaches its edge stops there and the result carries summary.edgeReached: true. Larger domains cost proportionally more compute.

ELMFIRE

Names are ELMFIRE’s namelist keys, lower-cased; each is described in the ELMFIRE input parameter reference under &SIMULATOR, &INPUTS, &MONTE_CARLO and &SPOTTING.

Parameter Default Notes
crown_fire_model 2 1 Finney (2004), 2 Scott & Reinhardt (2001)
foliar_moisture_content 110 Percent, 30–200. Lower values make crown fire initiation easier
max_low 8 1–50. Caps the fire ellipse’s length-to-width ratio
crown_fire_spread_rate_limit 250 ft/min, greater than 0 and at most 5000. Caps crown fire rate of spread
critical_canopy_cover 0.39 0–1. Canopy cover fraction below which crown fire cannot start
wind_speed_fluctuation_intensity 0.3 Above 0, at most 1; ensembles only (0 for single-member runs). Each member scales wind speed by 1 ± intensity/2
wind_direction_fluctuation_intensity 0.06 Above 0, at most 1; ensembles only (0 for single-member runs). Each member rotates wind direction by ± intensity/2 of a full circle
seed random 0–2147483647. Set it to make a run reproducible; omitted, every run draws a fresh seed

Spotting (ember transport) sits in a nested spotting object. The engine samples each _min/_max and _lo/_hi pair afresh on every weather band, so to pin a value set both ends of its range to it. Give both ends when you change one: the API only checks ordering when both are present, and an end that conflicts with the other’s default fails at run time with status: FAILED.

Parameter Default Notes
enable_spotting true Master switch for ember spotting
enable_surface_fire_spotting true Allow surface fires to spot, not only crown fires
spotting_distribution_type LOGNORMAL LOGNORMAL or UNIFORM: the distribution ember travel distances are drawn from
critical_spotting_fireline_intensity 1000 kW/m. Surface fires below this intensity do not spot
mean_spotting_dist_min / _max 5 / 15 Metres. Range of the mean ember travel distance
normalized_spotting_dist_variance_min / _max 250 / 600 Range of the normalised variance of the spotting distance distribution
spot_ws_exp_lo / _hi 0.4 / 0.7 0–2. Wind speed exponent of the spotting distance; the dominant control on ember reach
spot_flin_exp_lo / _hi 0.2 / 0.4 0–2. Fireline intensity exponent of the spotting distance
nembers_min 1 Embers per spotting event, lower bound
nembers_max_lo / _hi 1 / 1 Range of the upper bound on embers per event
global_surface_fire_spotting_percent_min / _max 0 / 0.13 Percent of burning surface-fire pixels that launch embers
crown_fire_spotting_percent_min / _max 0.1 / 1.2 Percent of burning crown-fire pixels that launch embers
pign_min / _max 100 / 100 Percent chance a landed ember ignites a spot fire

A reproducible ten-member ensemble with gustier wind and shorter ember throws:

curl -s -X POST "https://api.deepfire.co/v1/fire-spread/simulations" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "clusterId": "65d45ca4-a7b5-4d7e-85f3-516163c2a31d",
    "durationHours": 12,
    "ensembleMembers": 10,
    "domainBufferKm": 30,
    "elmfire": {
      "seed": 42,
      "wind_speed_fluctuation_intensity": 0.5,
      "spotting": {
        "spot_ws_exp_lo": 0.4,
        "spot_ws_exp_hi": 0.5,
        "mean_spotting_dist_min": 5,
        "mean_spotting_dist_max": 10
      }
    }
  }'

Poll until it finishes

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://api.deepfire.co/v1/fire-spread/simulations/2f8a…"

status moves from QUEUED to one of:

Status Meaning
COMPLETED result holds the spread polygons
NO_SPREAD The model ran but the fire did not grow meaningfully; no result
FAILED See errorMessage — e.g. the cluster is outside the modelled regions

While QUEUED, the response carries Retry-After; polling every 10 seconds is plenty. A run that is still QUEUED after 60 minutes is marked FAILED (“Simulation timed out”).

A completed simulation (truncated):

{
  "id": "2f8a…",
  "status": "COMPLETED",
  "clusterId": "65d45ca4-a7b5-4d7e-85f3-516163c2a31d",
  "model": "elmfire",
  "durationHours": 12,
  "ensembleMembers": 1,
  "sources": ["LANDSAT_NRT", "MODIS_NRT", "SENTINEL_3A", "SENTINEL_3B", "VIIRS_NOAA20_NRT", "VIIRS_NOAA21_NRT", "VIIRS_SNPP_NRT"],
  "lookbackHours": 24,
  "locationName": "Makedonski Brod, North Macedonia",
  "ignitionPointCount": 52,
  "ignition": { "type": "FeatureCollection", "features": [ … ] },
  "domainBufferKm": 25,
  "elmfire": {
    "crown_fire_model": 2,
    "foliar_moisture_content": 110.0,
    "spotting": { "enable_spotting": true, "spot_ws_exp_lo": 0.4, "spot_ws_exp_hi": 0.7, "…": "every spotting parameter" }
  },
  "summary": {
    "burnedAreaM2": 11835900,
    "initialBurnedAreaM2": 4210200,
    "edgeReached": false,
    "windSpeedAvgMs": 1.5,
    "windDirectionAvg": 178.7
  },
  "result": {
    "type": "FeatureCollection",
    "features": [
      {
        "type": "Feature",
        "geometry": { "type": "MultiPolygon", "coordinates": [ … ] },
        "properties": { "hour": 0, "elapsed_seconds": 0, "initial_burned": true }
      },
      {
        "type": "Feature",
        "geometry": { "type": "MultiPolygon", "coordinates": [ … ] },
        "properties": { "hour": 1, "elapsed_seconds": 3600 }
      },
      { "…": "one feature per hour" }
    ]
  },
  "links": { "self": "https://api.deepfire.co/v1/fire-spread/simulations/2f8a…" }
}

Already-burned interior

When the cluster has a perimeter — the linked incident’s official (NIFC) perimeter, or otherwise Deepfire’s satellite-derived perimeter — its interior is treated as already burned before the run, so the fire only spreads outward from the perimeter’s edge rather than re-burning the inside. In that case:

  • result starts with one extra feature at hour: 0 flagged "initial_burned": true. It is the pre-burned interior, not spread; the hourly features exclude it.
  • summary.initialBurnedAreaM2 is that interior’s area. summary.burnedAreaM2 counts only the new spread, and a run that never grows past the perimeter finishes as NO_SPREAD.

Hotspots outside the perimeter still seed the run as usual. A cluster with no perimeter behaves exactly as before: no hour-0 feature, no initialBurnedAreaM2.

Limits and errors

Limit Value
Runs in flight 2 per API client; a third request gets 429 too-many-simulations
Duration 1–24 hours
Ensemble members 1–50 (ignored for forefire, which always runs one member)
Domain 5–50 km buffer around the ignition

A 422 invalid-request names the field in its message: malformed JSON, an unknown field (Unknown field 'elmfire.spotting.spot_ws_exp_hihi', with the accepted names), a wrong type (integers must be JSON numbers, booleans must be true/false), a value outside the ranges above, an unknown sources code or model, an elmfire block with model: forefire, a wind fluctuation intensity without an ensemble, or an inverted _min/_max pair. A 404 cluster-not-found means the cluster id is unknown.

Rules the engine checks itself, such as a single range end that conflicts with the default other end, or an ignition outside the modelled regions, surface asynchronously as status: FAILED with an errorMessage.

List previous simulations

Everything your organization has run, from the API or the web app, plus the simulations Deepfire runs automatically on fires in your jurisdiction (auto: true). Newest first, keyset-paginated; list items omit result.

curl -sG -H "Authorization: Bearer $TOKEN" \
  "https://api.deepfire.co/v1/fire-spread/simulations" \
  --data-urlencode "since=2026-09-01" \
  --data-urlencode "limit=50"

Was this page helpful?