INFERNIS API Reference

March 18, 2026 · View on GitHub

BC Forest Fire Prediction ML Engine -- Developer API Documentation


Base URL

https://api.infernis.ca/v1

All endpoints are served over HTTPS. HTTP requests will be rejected. The API follows RESTful conventions and returns JSON responses unless otherwise specified.


Authentication

Every request must include a valid API key in the X-API-Key header.

X-API-Key: your_api_key_here

Obtaining an API Key

API keys are provisioned automatically through the INFERNIS dashboard at https://api.infernis.ca/static/index.html. Sign up with email/password or Google, and an API key is generated immediately. The plaintext key is shown once at signup — copy it and store it securely. You can view a masked preview and regenerate your key from the dashboard at any time.

Rate Limits

All API keys have access to every endpoint. Each key has a configurable daily request limit. The default limit is set by the INFERNIS_DAILY_RATE_LIMIT environment variable and can be customized per key in the database.

Contact hello@argonbi.com for custom rate limits, dedicated endpoints, or webhook integrations.


Endpoints

GET /v1/risk/{lat}/{lon}

Point risk query. Returns the fire risk score and all supporting data for the nearest grid cell to the specified coordinates. This is the primary endpoint for single-location risk assessment.

Path Parameters

ParameterTypeRequiredDescription
latfloatYesLatitude in decimal degrees. Range: -90 to 90. Must fall within British Columbia boundaries (approximately 48.0 to 60.0).
lonfloatYesLongitude in decimal degrees. Range: -180 to 180. Must fall within British Columbia boundaries (approximately -140.0 to -114.0).

Query Parameters

None.

Response 200 -- Success

Returns the complete risk assessment for the nearest grid cell.

{
  "location": {
    "lat": 49.25,
    "lon": -121.77
  },
  "grid_cell_id": "BC-5K-004921",
  "timestamp": "2026-07-15T21:00:00+00:00",
  "risk": {
    "score": 0.72,
    "level": "VERY_HIGH",
    "color": "#EF4444"
  },
  "confidence_interval": {
    "lower": 0.61,
    "upper": 0.83,
    "level": 0.90
  },
  "fwi": {
    "ffmc": 91.2,
    "dmc": 68.4,
    "dc": 412.0,
    "isi": 12.8,
    "bui": 89.1,
    "fwi": 34.6
  },
  "conditions": {
    "temperature_c": 32.1,
    "rh_pct": 18.0,
    "wind_kmh": 24.5,
    "precip_24h_mm": 0.0,
    "soil_moisture": 0.12,
    "ndvi": 0.45,
    "snow_cover": false,
    "c_haines": 10.2
  },
  "fire_behaviour": {
    "rate_of_spread_mpm": 5.2,
    "head_fire_intensity_kwm": 3200.0,
    "fire_type": "surface",
    "crown_fraction_burned": 0.0,
    "flame_length_m": 2.1
  },
  "context": {
    "bec_zone": "IDF",
    "fuel_type": "C7",
    "elevation_m": 845
  },
  "forecast_horizon": "24h",
  "next_update": "2026-07-16T21:00:00+00:00"
}

Error Responses

StatusDescription
400Malformed request. Latitude or longitude is not a valid number.
404The specified coordinates do not fall within the BC coverage area.
422Coordinates are valid numbers but outside the acceptable range for BC.
429Rate limit exceeded. See Rate Limiting for details.
503Service temporarily unavailable. The prediction pipeline may be updating.

GET /v1/risk/grid

Area risk query. Returns a GeoJSON FeatureCollection containing risk scores for all grid cells within the specified bounding box. Each Feature includes the same risk data as the point query endpoint.

Query Parameters

ParameterTypeRequiredDefaultDescription
bboxstringYes--Bounding box as south,west,north,east in decimal degrees. All four values must fall within BC boundaries.
levelstringNo--Filter by danger level (e.g., VERY_HIGH, EXTREME).

Response 200 -- Success

Returns a GeoJSON FeatureCollection. Each Feature represents a single grid cell.

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [-121.80, 49.23],
            [-121.75, 49.23],
            [-121.75, 49.27],
            [-121.80, 49.27],
            [-121.80, 49.23]
          ]
        ]
      },
      "properties": {
        "cell_id": "BC-5K-004921",
        "score": 0.72,
        "level": "VERY_HIGH",
        "bec_zone": "IDF",
        "fuel_type": "C7",
        "fwi": 34.6,
        "temperature_c": 32.1
      }
    }
  ],
  "metadata": {
    "bbox": [49.0, -123.5, 50.0, -122.0],
    "cell_count": 42,
    "timestamp": "2026-07-15T21:00:00+00:00"
  }
}

Error Responses

StatusDescription
400Malformed bounding box. Must be four comma-separated decimal values.
422Bounding box is outside BC boundaries or exceeds maximum area.
429Rate limit exceeded.
503Service temporarily unavailable.

GET /v1/risk/heatmap

Visual risk heatmap. Returns a rendered PNG image of fire risk for the specified bounding box. Useful for embedding risk maps in dashboards or GIS applications.

Query Parameters

ParameterTypeRequiredDefaultDescription
bboxstringYes--Bounding box as south,west,north,east in decimal degrees. Must fall within BC boundaries.
widthintNo256Image width in pixels. Range: 64 to 2048.
heightintNo256Image height in pixels. Range: 64 to 2048.
colormapstringNoriskColor map. risk uses the danger level palette; grayscale uses linear grayscale.

Response 200 -- Success

Returns image/png with a color-mapped risk overlay. The color scale follows the standard danger level palette (see Danger Levels).

Response headers include:

Content-Type: image/png
X-Bbox: 49.0,-123.5,50.0,-122.0
X-Timestamp: 2026-07-15T21:00:00+00:00

Error Responses

StatusDescription
400Malformed bounding box or invalid format parameter.
403Forbidden. API key is not authorized for this request.
422Bounding box is outside BC boundaries.
429Rate limit exceeded.
503Service temporarily unavailable.

GET /v1/risk/zones

Zone-level risk summary. Returns aggregate fire risk information for all BC biogeoclimatic (BEC) zones. Each zone includes its average and maximum risk score, danger level, cell count, and number of high-risk cells.

Query Parameters

None.

Response 200 -- Success

{
  "zones": [
    {
      "bec_zone": "IDF",
      "avg_risk_score": 0.542,
      "max_risk_score": 0.891,
      "level": "HIGH",
      "cell_count": 487,
      "high_risk_cells": 15
    },
    {
      "bec_zone": "BWBS",
      "avg_risk_score": 0.234,
      "max_risk_score": 0.612,
      "level": "MODERATE",
      "cell_count": 1203,
      "high_risk_cells": 3
    }
  ],
  "timestamp": "2026-07-15T21:00:00+00:00"
}

GET /v1/fwi/{lat}/{lon}

Raw FWI components. Returns the Canadian Forest Fire Weather Index System components for the specified location without the INFERNIS risk model overlay. Useful when you need the underlying fire weather data independent of the ML predictions.

Path Parameters

ParameterTypeRequiredDescription
latfloatYesLatitude in decimal degrees. Must be within BC.
lonfloatYesLongitude in decimal degrees. Must be within BC.

Response 200 -- Success

{
  "location": {
    "lat": 49.25,
    "lon": -121.77
  },
  "grid_cell_id": "BC-5K-004921",
  "timestamp": "2026-07-15T21:00:00+00:00",
  "fwi": {
    "ffmc": 91.2,
    "dmc": 68.4,
    "dc": 412.0,
    "isi": 12.8,
    "bui": 89.1,
    "fwi": 34.6
  }
}

GET /v1/conditions/{lat}/{lon}

Current conditions. Returns the latest weather observations and environmental data for the specified location. This includes the inputs used by the INFERNIS prediction models.

Path Parameters

ParameterTypeRequiredDescription
latfloatYesLatitude in decimal degrees. Must be within BC.
lonfloatYesLongitude in decimal degrees. Must be within BC.

Response 200 -- Success

{
  "location": {
    "lat": 49.25,
    "lon": -121.77
  },
  "grid_cell_id": "BC-5K-004921",
  "timestamp": "2026-07-15T21:00:00+00:00",
  "conditions": {
    "temperature_c": 32.1,
    "rh_pct": 18.0,
    "wind_kmh": 24.5,
    "precip_24h_mm": 0.0,
    "soil_moisture": 0.12,
    "ndvi": 0.45,
    "snow_cover": false
  }
}

GET /v1/forecast/{lat}/{lon}

Multi-day fire risk forecast. Returns up to 10 days of forecast fire risk trajectories for the nearest grid cell. Days 1--2 use high-resolution HRDPS weather forecasts (2.5km); days 3--10 use GDPS global forecasts (15km). FWI moisture codes are rolled forward day-by-day using forecast weather. A confidence decay factor (0.95 per lead day) attenuates predictions at longer lead times to reflect increasing forecast uncertainty.

Path Parameters

ParameterTypeRequiredDescription
latfloatYesLatitude in decimal degrees. Must be within BC.
lonfloatYesLongitude in decimal degrees. Must be within BC.

Query Parameters

ParameterTypeRequiredDefaultDescription
daysintNo10Number of forecast days to return. Range: 1 to 10.

Response 200 -- Success

{
  "latitude": 49.25,
  "longitude": -121.77,
  "cell_id": "BC-5K-004921",
  "base_date": "2026-07-15",
  "forecast": [
    {
      "valid_date": "2026-07-16",
      "lead_day": 1,
      "risk_score": 0.68,
      "danger_level": 4,
      "danger_label": "VERY_HIGH",
      "confidence": 0.95,
      "fwi": {
        "ffmc": 90.5,
        "dmc": 70.2,
        "dc": 418.0,
        "isi": 11.9,
        "bui": 91.3,
        "fwi": 33.1
      },
      "data_source": "HRDPS"
    },
    {
      "valid_date": "2026-07-17",
      "lead_day": 2,
      "risk_score": 0.71,
      "danger_level": 4,
      "danger_label": "VERY_HIGH",
      "confidence": 0.90,
      "fwi": { "ffmc": 91.0, "dmc": 72.1, "dc": 422.0, "isi": 12.3, "bui": 93.0, "fwi": 34.2 },
      "data_source": "HRDPS"
    },
    {
      "valid_date": "2026-07-18",
      "lead_day": 3,
      "risk_score": 0.62,
      "danger_level": 4,
      "danger_label": "VERY_HIGH",
      "confidence": 0.86,
      "fwi": { "ffmc": 89.8, "dmc": 73.5, "dc": 426.0, "isi": 11.2, "bui": 94.1, "fwi": 32.0 },
      "data_source": "GDPS"
    }
  ],
  "generated_at": "2026-07-15T21:00:00+00:00"
}

GET /v1/history/{lat}/{lon}

Historical fire events. Returns a list of past fire events near the specified location, drawn from the BC Wildfire Service historical database and satellite-detected hotspot archives.

Path Parameters

ParameterTypeRequiredDescription
latfloatYesLatitude in decimal degrees. Must be within BC.
lonfloatYesLongitude in decimal degrees. Must be within BC.

Query Parameters

ParameterTypeRequiredDefaultDescription
yearsintNo5Number of years to look back from the current date. Range: 1 to 50.
radius_kmfloatNo25Search radius in kilometers from the specified point. Range: 1 to 100.

Response 200 -- Success

{
  "location": {
    "lat": 49.25,
    "lon": -121.77
  },
  "search_radius_km": 25.0,
  "years_back": 5,
  "fires": [
    {
      "fire_id": "K50837",
      "fire_name": "Lytton Creek",
      "year": 2021,
      "start_date": "2021-06-30",
      "end_date": "2021-10-15",
      "cause": "LIGHTNING",
      "size_ha": 83816.0,
      "distance_km": 12.4,
      "lat": 50.23,
      "lon": -121.58,
      "source": "CNFDB"
    }
  ],
  "total_fires": 7
}

GET /v1/risk/profile/{lat}/{lon}

Location fire risk profile. Returns a comprehensive fire risk assessment combining historical fire exposure (10yr/30yr/all-time within 10km), structural susceptibility (empirical fire rate with hierarchical fallback), fire regime characteristics, and a composite risk rating blending static pre-computed data with current daily conditions.

Path Parameters

ParameterTypeRequiredDescription
latfloatYesLatitude in decimal degrees. Must be within BC.
lonfloatYesLongitude in decimal degrees. Must be within BC.

Response 200 -- Success

{
  "cell_id": "BC-1K-0093841",
  "location": {"lat": 50.67, "lon": -120.33},
  "context": {
    "bec_zone": "IDF",
    "bec_zone_name": "Interior Douglas-fir",
    "fuel_type": "C3",
    "elevation_m": 482,
    "slope_deg": 12,
    "aspect_deg": 180
  },

  "current": {
    "score": 0.42,
    "level": "HIGH",
    "forecast_7day_max": 0.51,
    "c_haines": 8.2
  },

  "historical_exposure": {
    "fires_10yr": {
      "count": 3,
      "nearest_km": 2.1,
      "largest_ha": 450,
      "causes": {"lightning": 2, "human": 1}
    },
    "fires_30yr": {
      "count": 7,
      "nearest_km": 0.8,
      "largest_ha": 1200,
      "causes": {"lightning": 5, "human": 2}
    },
    "fires_all": {
      "count": 12,
      "nearest_km": 0.3,
      "largest_ha": 3400,
      "causes": {"lightning": 8, "human": 3, "unknown": 1},
      "record_start": 1962
    },
    "radius_km": 10
  },

  "susceptibility": {
    "score": 0.034,
    "percentile": 78,
    "label": "ABOVE_AVERAGE",
    "method": "empirical_10yr",
    "basis": "cell",
    "fire_regime": {
      "mean_return_years": 42,
      "typical_severity": "moderate",
      "dominant_cause": "lightning"
    }
  },

  "composite_risk_rating": {
    "score": 0.72,
    "label": "HIGH",
    "components": {
      "susceptibility_weight": 0.3,
      "historical_exposure_weight": 0.3,
      "current_conditions_weight": 0.4
    }
  }
}

Response Fields

FieldTypeDescription
historical_exposure.fires_{tier}.countintFire events within 10km in the time window
historical_exposure.fires_{tier}.nearest_kmfloatDistance to the nearest fire in that window
historical_exposure.fires_{tier}.largest_hafloatLargest fire by area in that window
historical_exposure.fires_{tier}.causesobjectBreakdown by cause: lightning, human, unknown
historical_exposure.fires_all.record_startintEarliest fire year within 10km (null if none)
susceptibility.scorefloatEmpirical daily fire occurrence rate
susceptibility.percentileintRank relative to all BC cells (0--100)
susceptibility.labelstringWELL_BELOW_AVERAGE, BELOW_AVERAGE, AVERAGE, ABOVE_AVERAGE, WELL_ABOVE_AVERAGE
susceptibility.basisstringData resolution: cell, bec_fuel, or bec
susceptibility.fire_regimeobjectBEC zone-level fire regime (return interval, severity, dominant cause)
composite_risk_rating.scorefloatWeighted blend: 0.3susceptibility + 0.3exposure + 0.4*current
composite_risk_rating.labelstringDanger level from composite score

Error Responses

StatusDescription
404Coordinates outside the BC coverage area.
429Rate limit exceeded.
503Predictions not yet available (daily pipeline hasn't run).
503Fire statistics not yet computed (offline job hasn't run).

GET /v1/status

System health. Returns the current operational status of the INFERNIS API and its underlying data pipelines. Use this endpoint for monitoring and integration health checks. No rate limit is applied to this endpoint.

Query Parameters

None.

Response 200 -- Success

{
  "status": "operational",
  "version": "0.3.0",
  "last_pipeline_run": "2026-07-15T21:00:00+00:00",
  "model_version": "fire_core_v1",
  "grid_cells": 84535,
  "pipeline_healthy": true
}

GET /v1/coverage

Coverage metadata. Returns the BC boundary polygon and grid metadata, including total cell count, resolution, and coordinate reference system information. Useful for initializing map views or validating coordinate inputs before making risk queries.

Query Parameters

None.

Response 200 -- Success

{
  "province": "British Columbia",
  "crs": "EPSG:4326",
  "grid": {
    "resolution_km": 5.0,
    "total_cells": 84535,
    "lat_range": [48.22, 60.00],
    "lon_range": [-139.06, -114.03]
  },
  "bec_zones_count": 14,
  "fuel_types_count": 16
}

GET /v1/explain/{lat}/{lon}

Point risk explanation. Returns SHAP-based feature contributions explaining why risk is at its current level for the nearest grid cell to the specified coordinates. The response includes the top drivers ranked by absolute contribution, with human-readable descriptions, direction of influence (increasing or decreasing risk), raw feature values, and a composed natural-language summary.

Path Parameters

ParameterTypeRequiredDescription
latfloatYesLatitude in decimal degrees. Must be within BC.
lonfloatYesLongitude in decimal degrees. Must be within BC.

Query Parameters

ParameterTypeRequiredDefaultDescription
top_nintNo5Number of top drivers to return, ranked by absolute SHAP contribution. Range: 1 to 28.

Response 200 -- Success

{
  "cell_id": "BC-1K-0093841",
  "score": 0.42,
  "level": "HIGH",
  "drivers": [
    {
      "feature": "dmc",
      "contribution": 0.135,
      "direction": "increasing",
      "value": 87.3,
      "description": "Duff Moisture Code increasing — deep organic fuel drying"
    },
    {
      "feature": "ndvi",
      "contribution": 0.098,
      "direction": "decreasing",
      "value": 0.31,
      "description": "Vegetation greenness decreasing (NDVI 0.31)"
    }
  ],
  "summary": "Risk is HIGH primarily due to Duff Moisture Code increasing — deep organic fuel drying combined with Vegetation greenness decreasing (NDVI 0.31)."
}

Error Responses

StatusDescription
400Malformed request. Latitude or longitude is not a valid number.
404The specified coordinates do not fall within the BC coverage area.
422Coordinates are valid numbers but outside the acceptable range for BC.
429Rate limit exceeded.
503Service temporarily unavailable.

GET /v1/explain/zones

Zone-level risk explanation. Returns per-BEC-zone aggregated risk drivers. For each zone, the response lists features ranked by mean absolute SHAP value across all cells in that zone, showing which factors are driving risk at the regional level.

Query Parameters

ParameterTypeRequiredDefaultDescription
top_nintNo5Number of top drivers to return per zone. Range: 1 to 28.

Response 200 -- Success

{
  "zones": [
    {
      "bec_zone": "IDF",
      "cell_count": 487,
      "drivers": [
        {
          "feature": "dmc",
          "mean_abs_shap": 0.112,
          "direction": "increasing",
          "description": "Duff Moisture Code — deep organic fuel drying"
        },
        {
          "feature": "temperature_c",
          "mean_abs_shap": 0.089,
          "direction": "increasing",
          "description": "Air temperature driving fuel desiccation"
        }
      ]
    }
  ],
  "timestamp": "2026-07-15T21:00:00+00:00"
}

Error Responses

StatusDescription
429Rate limit exceeded.
503Service temporarily unavailable.

Field Descriptions

Risk Response Fields

FieldTypeDescription
location.latfloatLatitude of the query point in decimal degrees.
location.lonfloatLongitude of the query point in decimal degrees.
grid_cell_idstringUnique identifier for the 5km grid cell. Format: BC-{resolution}-{cell_number}, e.g., BC-5K-004921.
timestampstringISO 8601 timestamp indicating when this prediction was generated. Includes Pacific Time offset.
risk.scorefloatComposite fire risk score from 0.0 (no risk) to 1.0 (maximum risk). This is the weighted output of both ML models.
risk.levelstringDanger level derived from the risk score. One of: VERY_LOW, LOW, MODERATE, HIGH, VERY_HIGH, EXTREME.
risk.colorstringHex color code associated with the danger level, suitable for map rendering.
confidence_interval.lowerfloatLower bound of the prediction interval.
confidence_interval.upperfloatUpper bound of the prediction interval.
confidence_interval.levelfloatConfidence level of the interval (e.g., 0.90 for 90%). Present when quantile regression models are trained.
fwi.ffmcfloatFine Fuel Moisture Code. See FWI Components.
fwi.dmcfloatDuff Moisture Code. See FWI Components.
fwi.dcfloatDrought Code. See FWI Components.
fwi.isifloatInitial Spread Index. See FWI Components.
fwi.buifloatBuildup Index. See FWI Components.
fwi.fwifloatFire Weather Index (composite). See FWI Components.
conditions.temperature_cfloatAir temperature in degrees Celsius at the nearest weather station or interpolated grid point.
conditions.rh_pctfloatRelative humidity as a percentage (0--100).
conditions.wind_kmhfloatWind speed in kilometers per hour at 10-meter height.
conditions.precip_24h_mmfloatAccumulated precipitation over the past 24 hours in millimeters.
conditions.soil_moisturefloatVolumetric soil moisture content (0.0--1.0). Derived from remote sensing and station interpolation.
conditions.ndvifloatNormalized Difference Vegetation Index (-1.0 to 1.0). Indicates vegetation greenness and fuel moisture. Values below 0.3 in forested areas suggest dry, fire-prone vegetation.
conditions.snow_coverbooleanWhether snow cover is present at the location. When true, fire risk is typically negligible.
conditions.c_hainesfloatContinuous Haines Index (0--13). Measures lower-atmospheric stability and dryness; higher values indicate greater potential for large, erratic fire growth. Values above 10 are considered critical.
fire_behaviour.rate_of_spread_mpmfloatPredicted head fire rate of spread in meters per minute, computed from the FBP System using current weather and fuel type.
fire_behaviour.head_fire_intensity_kwmfloatByram's head fire intensity in kilowatts per meter of fire front. Values above 4000 kW/m are generally beyond suppression capability.
fire_behaviour.fire_typestringPredicted fire type: surface, intermittent_crown, or active_crown.
fire_behaviour.crown_fraction_burnedfloatFraction of the canopy consumed (0.0--1.0). Non-zero values indicate crown fire activity.
fire_behaviour.flame_length_mfloatEstimated flame length in meters, derived from fire intensity.
context.bec_zonestringBiogeoclimatic Ecosystem Classification zone code. See BEC Zone Codes.
context.fuel_typestringCanadian Forest Fire Behaviour Prediction System fuel type code. See Fuel Type Codes.
context.elevation_mintElevation above sea level in meters.
forecast_horizonstringThe time window the prediction covers. Currently 24h (next 24 hours from the timestamp).
next_updatestringISO 8601 timestamp of the next scheduled prediction update.

FWI Components

The Canadian Forest Fire Weather Index (FWI) System is a set of six components that rate fire danger based on weather observations. INFERNIS computes FWI values from ERA5 reanalysis weather data, interpolated to the prediction grid.

Moisture Codes (Fuel Moisture Tracking)

CodeNameRangeDescription
FFMCFine Fuel Moisture Code0--101Tracks moisture content of surface litter and fine fuels (leaves, needles, grass). Responds quickly to weather changes. Values above 85 indicate dry fine fuels; values above 90 indicate very dry conditions where ignition is likely.
DMCDuff Moisture Code0--300+Tracks moisture in loosely compacted organic material (duff layers 5--10 cm deep). Responds more slowly than FFMC; a rain event may lower FFMC immediately but take days to affect DMC. Values above 40 are considered high.
DCDrought Code0--800+Tracks deep, compact organic layer moisture and seasonal drought. Very slow to respond to rainfall. Values above 300 indicate significant drought; values above 500 indicate severe drought with deep-seated fire potential.

Behaviour Indices (Fire Behaviour Rating)

IndexNameRangeDescription
ISIInitial Spread Index0--70+Combines FFMC and wind speed to rate the expected rate of fire spread. Higher values indicate faster-spreading fires. Values above 10 are considered high.
BUIBuildup Index0--300+Combines DMC and DC to represent the total fuel available for combustion. Higher values mean more fuel can burn, producing more intense fires. Values above 60 are considered high.
FWIFire Weather Index0--100+Combines ISI and BUI into a single fire intensity rating. This is the most commonly referenced single value from the FWI System. Values above 20 are high; above 30 are very high; above 40 are extreme.

Danger Levels

Risk scores from the INFERNIS models are mapped to six danger levels.

LevelScore RangeColor CodeHexDescription
VERY_LOW0.00 -- 0.05Green#22C55ENegligible risk. Wet or snow-covered conditions.
LOW0.05 -- 0.15Blue#3B82F6Minor risk. Fires unlikely under current conditions.
MODERATE0.15 -- 0.35Yellow#EAB308Elevated. Fires possible with an ignition source.
HIGH0.35 -- 0.60Orange#F97316Significant. Fires likely to spread if ignited.
VERY_HIGH0.60 -- 0.80Red#EF4444Severe. Aggressive fire behavior expected.
EXTREME0.80 -- 1.00Dark Red#1A0000Critical. Explosive fire growth potential.

BEC Zone Codes

British Columbia uses the Biogeoclimatic Ecosystem Classification (BEC) system to classify ecological zones. The bec_zone field in the API response uses the following standard abbreviations.

CodeFull NameTypical Elevation (m)Fire Relevance
ATAlpine Tundra>1800Low fire risk due to sparse vegetation and cool temperatures.
BGBunchgrass350--900Grass fires can spread quickly in dry conditions.
BWBSBoreal White and Black Spruce400--1200Significant fire zone; spruce is highly flammable.
CDFCoastal Douglas-fir0--450Moderate risk; drought conditions in summer increase danger.
CWHCoastal Western Hemlock0--1050Generally wet, but extreme drought years create high risk.
ESSFEngelmann Spruce -- Subalpine Fir1200--2000Subalpine forests prone to stand-replacing fires.
ICHInterior Cedar -- Hemlock400--1500Mixed fire regime; moderate to high risk in dry summers.
IDFInterior Douglas-fir300--1450Frequent fire zone; historically fire-maintained ecosystems.
MHMountain Hemlock900--1800Moderate risk; snow limits fire season duration.
MSMontane Spruce1100--1700Moderate risk; dry years produce significant fire activity.
PPPonderosa Pine300--900High fire frequency zone; adapted to frequent low-intensity fire.
SBPSSub-Boreal Pine -- Spruce900--1400Significant fire zone; large fires common in dry years.
SBSSub-Boreal Spruce500--1300High fire activity; large fires common in the BC interior.
SWBSpruce -- Willow -- Birch400--1300Northern boreal zone; fire is the dominant disturbance agent.

Fuel Type Codes

Fuel types follow the Canadian Forest Fire Behaviour Prediction (FBP) System classification. The fuel_type field indicates the dominant fuel type in the grid cell.

Coniferous (C) Types

CodeNameDescription
C1Spruce -- Lichen WoodlandOpen spruce stands with lichen ground cover. Very high spread rates and crowning potential.
C2Boreal SpruceDense boreal spruce with feather moss and lichen. High crowning potential and intense fire behaviour.
C3Mature Jack/Lodgepole PineFully stocked pine stands with closed canopy. Moderate to high fire intensity.
C4Immature Jack/Lodgepole PineDense immature pine with high crown closure. Very high fire intensity and crown fire potential.
C5Red/White PineMature red or white pine stands. Moderate fire intensity; less prone to crowning than C3/C4.
C6Conifer PlantationPlanted conifer stands, typically young and dense. High fire intensity if spacing is tight.
C7Ponderosa Pine / Douglas-firOpen stands of ponderosa pine or Douglas-fir. Surface fire dominant; low to moderate crowning.

Deciduous (D) Types

CodeNameDescription
D1Leafless AspenAspen stands without foliage (spring/fall). Higher fire risk than leafed-out stands.
D2Green Aspen (with BUI >= 80)Aspen stands with full foliage. Fire only occurs under extreme drought (high BUI).

Mixedwood (M) Types

CodeNameDescription
M1Boreal Mixedwood -- LeaflessMixed boreal conifer and deciduous, no foliage. Fire behaviour intermediate.
M2Boreal Mixedwood -- GreenMixed boreal conifer and deciduous, with foliage. Reduced spread compared to M1.
M3Dead Balsam Fir Mixedwood -- LeaflessStands with dead balsam fir component. Highly flammable due to standing dead trees.
M4Dead Balsam Fir Mixedwood -- GreenSame as M3 but with green deciduous foliage. Somewhat reduced fire behaviour.

Open (O) Types

CodeNameDescription
O1aMatted GrassContinuous matted grass fuel. Very high spread rate under wind; low intensity.
O1bStanding GrassStanding dead grass. Extremely high spread rate; the fastest-spreading fuel type in the FBP System.

Slash (S) Types

CodeNameDescription
S1Jack/Lodgepole Pine SlashLogging slash from pine harvest. High fire intensity with heavy fuel loads.
S2White Spruce / Balsam SlashLogging slash from spruce/balsam harvest. Very high intensity and difficult suppression.
S3Coastal Cedar / Hemlock / Douglas-fir SlashCoastal logging slash. Extremely high fuel loads and intense fire behaviour.

Rate Limiting

All API requests (except /v1/status) are subject to a daily rate limit. The limit is configurable per key; the default is set by the INFERNIS_DAILY_RATE_LIMIT environment variable.

Rate Limit Headers

Every response includes the following headers to help you manage request pacing.

HeaderTypeDescription
X-RateLimit-LimitintMaximum number of requests allowed per day for your API key.
X-RateLimit-RemainingintNumber of requests remaining in the current daily window.
X-RateLimit-ResetstringReset time indicator (currently returns "midnight PST").

429 Too Many Requests

When the rate limit is exceeded, the API returns a 429 status code with the following body:

{
  "detail": "Rate limit exceeded. Daily request limit reached. Resets at 2026-07-16T00:00:00-07:00.",
  "retry_after_seconds": 3600
}

The response also includes a Retry-After header with the number of seconds until additional capacity is available.

Best practices:

  • Cache responses locally when the data has not changed (check next_update field).
  • Use the /v1/status endpoint for health checks, as it is not rate-limited.
  • For bulk operations, prefer /v1/risk/grid over multiple point queries, as a single grid request counts as one API call.

Error Responses

All errors follow a consistent JSON format.

Standard Error Body

{
  "detail": "Error message here"
}

Error Codes

StatusMeaningCommon Causes
400Bad RequestMalformed parameters, missing required fields, non-numeric coordinate values.
401UnauthorizedMissing or invalid X-API-Key header.
403ForbiddenValid key but not authorized for this request (e.g., key has been deactivated or flagged).
404Not FoundCoordinates outside BC coverage area, or endpoint does not exist.
422Unprocessable EntityParameters are syntactically valid but semantically incorrect (e.g., latitude of 75.0, which is outside BC).
429Too Many RequestsRate limit exceeded. See Rate Limiting.
500Internal Server ErrorUnexpected server failure. Contact support if persistent.
503Service UnavailablePrediction pipeline is updating or undergoing maintenance. Typically resolves within minutes.

Error Examples

Invalid coordinates (400):

{
  "detail": "Invalid latitude value: 'abc' is not a valid number."
}

Outside BC boundaries (422):

{
  "detail": "Coordinates (45.00, -121.00) are outside the British Columbia coverage area. Latitude must be between 48.0 and 60.0; longitude must be between -140.0 and -114.0."
}

Unauthorized (401):

{
  "detail": "Invalid or missing API key. Provide a valid key in the X-API-Key header."
}

Code Examples

Python (requests)

import requests

API_KEY = "your_api_key_here"
BASE_URL = "https://api.infernis.ca/v1"

headers = {
    "X-API-Key": API_KEY,
}

# Point risk query
response = requests.get(
    f"{BASE_URL}/risk/49.25/-121.77",
    headers=headers,
)
response.raise_for_status()
data = response.json()

print(f"Risk Score: {data['risk']['score']}")
print(f"Risk Level: {data['risk']['level']}")
print(f"FWI: {data['fwi']['fwi']}")
print(f"Temperature: {data['conditions']['temperature_c']}C")
print(f"Fuel Type: {data['context']['fuel_type']}")

# Check rate limit status
remaining = response.headers.get("X-RateLimit-Remaining")
print(f"Requests remaining today: {remaining}")

Python -- Grid Query

import requests

API_KEY = "your_api_key_here"
BASE_URL = "https://api.infernis.ca/v1"

headers = {
    "X-API-Key": API_KEY,
}

# Area risk query with bounding box (south,west,north,east)
params = {
    "bbox": "49.0,-122.5,50.0,-121.0",
}

response = requests.get(
    f"{BASE_URL}/risk/grid",
    headers=headers,
    params=params,
)
response.raise_for_status()
geojson = response.json()

print(f"Cells returned: {geojson['metadata']['cell_count']}")

for feature in geojson["features"]:
    props = feature["properties"]
    if props["level"] in ("VERY_HIGH", "EXTREME"):
        print(f"  {props['cell_id']}: {props['score']:.2f} ({props['level']})")

curl

# Point risk query
curl -H "X-API-Key: your_api_key_here" \
  "https://api.infernis.ca/v1/risk/49.25/-121.77"

# FWI components
curl -H "X-API-Key: your_api_key_here" \
  "https://api.infernis.ca/v1/fwi/49.25/-121.77"

# Current conditions
curl -H "X-API-Key: your_api_key_here" \
  "https://api.infernis.ca/v1/conditions/49.25/-121.77"

# Grid query — bbox is south,west,north,east
curl -H "X-API-Key: your_api_key_here" \
  "https://api.infernis.ca/v1/risk/grid?bbox=49.0,-122.5,50.0,-121.0"

# Historical fires within 50km over the past 10 years
curl -H "X-API-Key: your_api_key_here" \
  "https://api.infernis.ca/v1/history/49.25/-121.77?years=10&radius_km=50"

# System status (no API key required for basic check)
curl "https://api.infernis.ca/v1/status"

# Download heatmap as PNG
curl -H "X-API-Key: your_api_key_here" \
  -o heatmap.png \
  "https://api.infernis.ca/v1/risk/heatmap?bbox=49.0,-122.5,50.0,-121.0"

JavaScript (fetch)

const API_KEY = "your_api_key_here";
const BASE_URL = "https://api.infernis.ca/v1";

async function getFireRisk(lat, lon) {
  const response = await fetch(`${BASE_URL}/risk/${lat}/${lon}`, {
    headers: {
      "X-API-Key": API_KEY,
    },
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`API error ${response.status}: ${error.detail}`);
  }

  const data = await response.json();

  console.log(`Risk Score: ${data.risk.score}`);
  console.log(`Risk Level: ${data.risk.level}`);
  console.log(`FWI: ${data.fwi.fwi}`);
  console.log(`BEC Zone: ${data.context.bec_zone}`);
  console.log(`Fuel Type: ${data.context.fuel_type}`);

  // Check rate limit
  const remaining = response.headers.get("X-RateLimit-Remaining");
  console.log(`Requests remaining: ${remaining}`);

  return data;
}

async function getGridRisk(bbox) {
  const params = new URLSearchParams({
    bbox: bbox,
  });

  const response = await fetch(`${BASE_URL}/risk/grid?${params}`, {
    headers: {
      "X-API-Key": API_KEY,
    },
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`API error ${response.status}: ${error.detail}`);
  }

  return response.json();
}

// Usage
getFireRisk(49.25, -121.77)
  .then((data) => {
    if (data.risk.score >= 0.6) {
      console.warn(`WARNING: ${data.risk.level} fire risk at this location.`);
    }
  })
  .catch(console.error);

Data Update Schedule

INFERNIS integrates multiple data sources, each with its own update cadence. The following table summarizes when data becomes available.

Data SourceUpdate FrequencyTypical AvailabilityNotes
Risk predictionsDaily~14:00 PTComposite ML model output. Depends on all upstream data being current.
Weather observationsHourly~15 minutes past the hourFrom BC Wildfire Service weather stations and Environment Canada.
FWI calculationsDaily~13:50 PTComputed after the noon weather observation, per CWFIS standard.
NDVI (vegetation index)Every 16 days2--3 days after satellite passMODIS 16-day composite cycle. Updated as new composites are processed.
Soil moistureDaily~06:00 PTDerived from remote sensing products and station interpolation.
Topography / DEMAnnuallyJanuaryCanadian Digital Elevation Model. Updated if significant revisions occur.
Fuel type classificationAnnuallyMarchBC Wildfire Service fuel type maps. Updated to reflect logging, growth, and disturbance.
BEC zone boundariesAs neededVariesBC Ministry of Forests classification. Rarely changes.
Historical fire databaseAnnuallyAfter fire season (November)BC Wildfire Service historical records. Updated after each season closes.

Pipeline Dependency Chain

The daily prediction cycle follows this order:

  1. Weather ingest (~12:30 PT) -- Station observations are collected and quality-checked.
  2. FWI calculation (~13:00 PT) -- FWI components are computed from noon weather data.
  3. Condition assembly (~13:30 PT) -- All condition layers (weather, soil, NDVI) are assembled into the grid.
  4. Prediction run (~13:45 PT) -- Both ML models (FireCore and HeatmapEngine) generate scores.
  5. API update (~14:00 PT) -- New predictions are published and the API begins serving updated data.

If any upstream pipeline fails, the API will continue to serve the most recent successful prediction and the /v1/status endpoint will reflect the degraded pipeline status.


Dashboard API

The dashboard endpoints manage user accounts and API key provisioning. They use Firebase Authentication (not API keys). Include a valid Firebase ID token in the Authorization header:

Authorization: Bearer <firebase-id-token>

POST /api/dashboard/register

Idempotent registration. On first call, creates a user account, generates an API key, and returns the plaintext key. On subsequent calls, returns the user profile without the key.

First-time response (200):

{
  "email": "user@example.com",
  "display_name": "Jane Doe",
  "api_key": "a3f8c9e1d2b4...64 hex characters"
}

Returning user response (200):

{
  "email": "user@example.com",
  "display_name": "Jane Doe",
  "key_preview": "a3f8****...****d2e1",
  "daily_limit": 100,
  "billing_cycle_start": "2026-02-15"
}

GET /api/dashboard/profile

Returns the authenticated user's profile with a masked key preview.

Response (200):

{
  "email": "user@example.com",
  "display_name": "Jane Doe",
  "key_preview": "a3f8****...****d2e1",
  "daily_limit": 100,
  "billing_cycle_start": "2026-02-15"
}

Errors: 404 if the user has not registered.

GET /api/dashboard/usage

Returns current billing cycle usage.

Response (200):

{
  "requests_today": 42,
  "daily_limit": 100,
  "billing_cycle_start": "2026-02-15",
  "billing_cycle_end": "2026-03-17",
  "days_remaining": 30
}

POST /api/dashboard/key/regenerate

Deactivates the current API key and generates a new one. The new plaintext key is returned once.

Response (200):

{
  "api_key": "b7d1e4f2a8c6...64 hex characters",
  "message": "New key generated. Your old key has been deactivated."
}

Errors: 404 if the user has not registered.


Versioning

The API is versioned via the URL path (/v1/). Breaking changes will only be introduced in new major versions (e.g., /v2/). Non-breaking additions (new fields in responses, new optional query parameters) may be added to the current version without notice.

When a new major version is released, the previous version will remain available for at least 12 months with a deprecation notice in the response headers:

X-API-Deprecated: true
X-API-Sunset: 2028-01-01

Support

ChannelAvailability
Dashboard: api.infernis.ca/static/index.htmlAlways
GitHub IssuesCommunity support
Email: hello@argonbi.com48-hour SLA

For bug reports, feature requests, or custom rate limits, email hello@argonbi.com.