Loading documentation...
Side-by-side reference of how the native datasource APIs look for a representative set of HeatWaves requests. Datasets 1–11 cover the matrix for BRIS/BRASK smoke tests (dataset 12 is an extra BRIS case). Each example pairs the HeatWaves intent with the exact upstream request body or form. Together with category-native-to-cat-code.md and filter-axes-native-to-filter-id.md, these eleven examples are designed to be sufficient for any HeatWaves ETL developer to compose a working native request for any (datasource, dimension, filter) combination supported by the platform.
Every numeric id, parameter name, and value below is sourced from one of:
category-native-to-cat-code.md — cat_code ↔ native_api_code mappingfilter-axes-native-to-filter-id.md — filter parameter names and values per sourcelib/data-model/adapters/_brisRequestBody.ts — BRIS request builder (buildBrisRequestBody)lib/data-model/adapters/_brisUpstream.constants.ts — BOLIG_IDS, NON_RESIDENTIAL_MATRIKKEL_LEAF_IDS, BRIS_QUESTION_AGGREGATIONS, TIME_OPTIONSlib/data-model/adapters/brask-passthrough.ts — BRASK form mechanics (shared constants in lib/data-model/adapters/_braskWebForms.constants.ts: BRASK_FILTER_FIELD_MAP, BRASK_AXIS / braskExplorerAxisId, BRASK_UTFORSK_RBL_*)ssb-pxwebapi-tables.md — SSB table 12058 variable referenceUnless otherwise noted, every example is a time series with years on the x-axis, antall (or kr) on the y-axis, and categories within the chosen dimension as series.
Filter vocabulary in HeatWaves intent lines — per filter-axes-native-to-filter-id.md: — = axis omitted / unfiltered upstream slice (NULL *_code FK on facts; no filter-row standard_code). RESIDENTIAL, DEVELOPED, etc. = resolved filters.standard_code. none / n/a = axis not available on that upstream endpoint. Do not use ALL or ALL_BUILDINGS here — those codes belong on categories (cross-tab dimension totals), not the filter axes.
Three upstream endpoints are exercised across the eleven datasets:
| Source | Endpoint | Body type |
|---|---|---|
| BRASK | POST https://brask.finansnorge.no/ | application/x-www-form-urlencoded (ASP.NET form) |
| BRIS — Alle branner og ulykker | POST https://brannstatistikk.no/api/v1/missionreports/aggregate | application/json (full filter body) |
| BRIS — Hvordan bygningsbranner starter | POST https://brannstatistikk.no/api/v1/missionreports/restrictedaggregation | application/json (minimal body) |
| SSB | POST https://data.ssb.no/api/v0/no/table/12058 | application/json (PxWebApi v0 query, returns json-stat2) |
All BRASK requests must first GET https://brask.finansnorge.no/ and include the __VIEWSTATE, __VIEWSTATEGENERATOR, and __EVENTVALIDATION hidden fields from the response. Those three fields are omitted from every example below for readability.
HeatWaves intent
dim_code = 4 (Arnested) — seriesfire_type = DEVELOPED, building_type = RESIDENTIALNative API
POST https://brannstatistikk.no/api/v1/missionreports/aggregate Content-Type: application/json
{ "hitsToReturn": 0, "skipped": 0, "missionTypes": { "ids": [], "isMissingValue": false }, "revisedMissionTypes": { "ids": [10026], "isMissingValue": false }, "monthNumbers": { "ids": [], "isMissingValue": false }, "dayOfWeek": { "ids": [], "isMissingValue": false }, "responseTimeLimitGreaterThan": true, "callOutTimeLimitGreaterThan": true, "effortDurationGreaterThan": true, "counties": { "ids": [], "isMissingValue": false }, "municipalities": { "ids": [], "isMissingValue": false }, "basicStatisticalUnits": { "ids": [], "isMissingValue": false }, "fireDepartments": { "ids": [], "isMissingValue": false }, "hundredAndTenCentrals": { "ids": [], "isMissingValue": false }, "streetAddress": "", "geoShapeFilter": { "polygons": [], "circles": [] }, "fireStations": { "ids": [], "isMissingValue": false }, "dispatchedFireDepartments": { "ids": [], "isMissingValue": false }, "buildingTypes": { "ids": [ "111","112","113","121","122","123","124","131","133","135","136", "141","142","143","144","145","146","151","152","159","161","162", "163","171","172","181","182","183","193","199" ], "isMissingValue": false }, "naceCodes": { "ids": [], "isMissingValue": false }, "includeAssistanceMissions": false, "includeExercises": false, "includeMissionsHandledByHundredAndTen": false, "includePoliceCauseWithNoMission": false, "includeRVRMissionsFromBris": false, "includeApprovedMissions": true, "onlyApprovedMissions": true, "answers": [], "aggregationQuery": { "includeNationalFigures": false, "aggregationDefinition": { "id": "403", "name": "Arnested - politi", "type": "TERMS", "interval": null, "question": true, "groupAnswer": false, "restricted": false, "includeMissing": true, "calculatedSubAggregationDefinitions": [], "nextLevelAggregationDefinition": { "id": "MISSION_CALL_TIME_YEAR", "name": "År", "type": "DATE_HISTOGRAM", "interval": "YEAR", "question": false, "groupAnswer": false, "restricted": false, "includeMissing": true, "calculatedSubAggregationDefinitions": [] } } } }
Notes — aggregationDefinition.id = "403" is Police-only on /aggregate. HeatWaves ingest sends one Matrikkel leaf id per slice (buildingTypeIdsOverride); the 30-id Bolig body below is the upstream shape for a manual rollup request only — see filter-axes-native-to-filter-id.md. Leaf reference list: BOLIG_IDS in _brisUpstream.constants.ts. Result rows are keyed by 403_* answer ids — see category-native-to-cat-code.md §4 (cat_codes 401-421).
HeatWaves intent
dim_code = 4 (Arnested) — seriesfire_type = DEVELOPED, building_type = none (not supported on this endpoint)Native API
POST https://brannstatistikk.no/api/v1/missionreports/restrictedaggregation Content-Type: application/json
{ "revisedMissionTypes": { "ids": [10026], "isMissingValue": false }, "counties": { "ids": [], "isMissingValue": false }, "hundredAndTenCentrals": { "ids": [], "isMissingValue": false }, "includePoliceCauseWithNoMission": false, "aggregationQuery": { "includeNationalFigures": false, "aggregationDefinition": { "id": "227", "name": "Antatt arnested (startsted)", "type": "TERMS", "interval": null, "question": true, "groupAnswer": false, "restricted": false, "includeMissing": true, "calculatedSubAggregationDefinitions": [], "nextLevelAggregationDefinition": { "id": "MISSION_CALL_TIME_YEAR", "name": "År", "type": "DATE_HISTOGRAM", "interval": "YEAR", "question": false, "groupAnswer": false, "restricted": false, "includeMissing": true, "calculatedSubAggregationDefinitions": [] } } } }
Notes — aggregationDefinition.id = "227" is restrictedOnly. The restricted body has no buildingTypes field at all (see filter-axes-native-to-filter-id.md §2 — Building Type is unsupported on /restrictedaggregation). Result rows are keyed by 227_* answer ids — category-native-to-cat-code.md §4 (cat_codes 422-448).
HeatWaves intent
dim_code = 3 (Objekt) — seriesfire_type = DEVELOPED, building_type = RESIDENTIALNative API
POST https://brannstatistikk.no/api/v1/missionreports/aggregate Content-Type: application/json
Same envelope as Dataset 1 with two changes:
{ "...": "[same as Dataset 1, except:]", "buildingTypes": { "ids": ["...30 BOLIG_IDS..."], "isMissingValue": false }, "aggregationQuery": { "includeNationalFigures": false, "aggregationDefinition": { "id": "405", "name": "Brannen startet i - politi", "type": "TERMS", "question": true, "groupAnswer": false, "restricted": false, "includeMissing": true, "calculatedSubAggregationDefinitions": [], "nextLevelAggregationDefinition": { "id": "MISSION_CALL_TIME_YEAR", "name": "År", "type": "DATE_HISTOGRAM", "interval": "YEAR", "question": false, "groupAnswer": false, "restricted": false, "includeMissing": true, "calculatedSubAggregationDefinitions": [] } } } }
Notes — aggregationDefinition.id = "405" is fullOnly. Result rows are keyed by 405_* answer ids — category-native-to-cat-code.md §3 (cat_codes 301-322).
HeatWaves intent
dim_code = 3 (Objekt) — seriesfire_type = DEVELOPED, building_type = — (unfiltered — all buildings)Native API
Identical to Dataset 3 except buildingTypes.ids is empty:
{ "...": "[same as Dataset 3, except:]", "buildingTypes": { "ids": [], "isMissingValue": false } }
Notes — Compare side-by-side with Dataset 3 to see the building-type filter on/off delta cleanly. Empty buildingTypes.ids array means "all building types" per filter-axes-native-to-filter-id.md §2.
HeatWaves intent
dim_code = 2 (Tennkilde) — seriesfire_type = CONFINED, building_type = none (not supported on this endpoint)Native API
POST https://brannstatistikk.no/api/v1/missionreports/restrictedaggregation Content-Type: application/json
{ "revisedMissionTypes": { "ids": [10086, 10212], "isMissingValue": false }, "counties": { "ids": [], "isMissingValue": false }, "hundredAndTenCentrals": { "ids": [], "isMissingValue": false }, "includePoliceCauseWithNoMission": false, "aggregationQuery": { "includeNationalFigures": false, "aggregationDefinition": { "id": "264", "name": "Antatt tennkilde", "type": "TERMS", "question": true, "groupAnswer": false, "restricted": false, "includeMissing": true, "calculatedSubAggregationDefinitions": [], "nextLevelAggregationDefinition": { "id": "MISSION_CALL_TIME_YEAR", "name": "År", "type": "DATE_HISTOGRAM", "interval": "YEAR", "question": false, "groupAnswer": false, "restricted": false, "includeMissing": true, "calculatedSubAggregationDefinitions": [] } } } }
Notes — revisedMissionTypes.ids = [10086, 10212] covers Branntilløp komfyr + Branntilløp i bygg annet. Brann i skorstein (10175) is omitted here — it does not exist in the restricted "Hvordan bygningsbranner starter" dataset (see filter-axes-native-to-filter-id.md §1). Result rows are keyed by 264_* — category-native-to-cat-code.md §2 (cat_codes 208-213).
HeatWaves intent
dim_code = 2 (Tennkilde / Kilde) — seriesfire_type = CONFINED, building_type = RESIDENTIAL, region = Oslo, building_age = 1-5This is the most filter-heavy BRASK example — exercises every BRASK filter mechanic in one request.
Native API
POST https://brask.finansnorge.no/ Content-Type: application/x-www-form-urlencoded
__VIEWSTATE=<from initial GET>
__VIEWSTATEGENERATOR=<from initial GET>
__EVENTVALIDATION=<from initial GET>
ctl00$Innhold$ddlRad=5
ctl00$Innhold$ddlKolonne=7
ctl00$Innhold$rblVerdi=2
ctl00$Innhold$rblBeregning=1
ctl00$Innhold$lbBransje=
ctl00$Innhold$lbAldersgruppe=2
ctl00$Innhold$lbFylke=3
ctl00$Innhold$lbDag=
ctl00$Innhold$lbKilde=
ctl00$Innhold$lbKvartal=
ctl00$Innhold$lbMåned=
ctl00$Innhold$lbNæring=0
ctl00$Innhold$lbType=2
ctl00$Innhold$lbUkedag=
ctl00$Innhold$lbÅr=
ctl00$Innhold$lbÅrsak=
ctl00$Innhold$btnKjør=Lag tabell
Notes — Field-by-field justification:
ddlRad=5 — row dimension = kilde (Utforsk ddlRad index = BRASK_AXIS.kilde (5) in _braskWebForms.constants.ts; not fire_data.categories.dim_code).ddlKolonne=7 — column dimension = ar (BRASK_AXIS.ar = 7).rblVerdi=2 — value type = erstatningsbelop (kr); 1 would be antallSkader.lbAldersgruppe=2 — native value 2 = "1-5" per filter-axes-native-to-filter-id.md §3 (normalizes to HeatWaves bucket 0-5).lbFylke=3 — Oslo per filter-axes-native-to-filter-id.md §4.lbNæring=0 — Beboelse = RESIDENTIAL per filter-axes-native-to-filter-id.md §2.lbType=2 — Kald = CONFINED per filter-axes-native-to-filter-id.md §1.lb* fields sent empty (= Alle / no filter).HeatWaves intent
dim_code = 1 (Årsak) — seriesfire_type = CONFINED — komfyr only, building_type = noneNative API
POST https://brannstatistikk.no/api/v1/missionreports/restrictedaggregation Content-Type: application/json
{ "revisedMissionTypes": { "ids": [10086], "isMissingValue": false }, "counties": { "ids": [], "isMissingValue": false }, "hundredAndTenCentrals": { "ids": [], "isMissingValue": false }, "includePoliceCauseWithNoMission": false, "aggregationQuery": { "includeNationalFigures": false, "aggregationDefinition": { "id": "269", "name": "Brannvesenets vurdering", "type": "TERMS", "question": true, "groupAnswer": false, "restricted": false, "includeMissing": true, "calculatedSubAggregationDefinitions": [], "nextLevelAggregationDefinition": { "id": "MISSION_CALL_TIME_YEAR", "name": "År", "type": "DATE_HISTOGRAM", "interval": "YEAR", "question": false, "groupAnswer": false, "restricted": false, "includeMissing": true, "calculatedSubAggregationDefinitions": [] } } } }
Notes — Single-mission-type slice; the narrowest fire-type filter possible on BRIS. Useful as an ETL ingestion canary because the row count is small and easy to verify by hand. aggregationDefinition.id = "269" is restrictedOnly. Result rows are keyed by 269_* — category-native-to-cat-code.md §1 (cat_codes 117-122).
HeatWaves intent
dim_code = 1 (Årsak) — seriesfire_type = — (unfiltered), building_type = — (unfiltered), region = OsloNative API
POST https://brask.finansnorge.no/ Content-Type: application/x-www-form-urlencoded
__VIEWSTATE=<from initial GET>
__VIEWSTATEGENERATOR=<from initial GET>
__EVENTVALIDATION=<from initial GET>
ctl00$Innhold$ddlRad=6
ctl00$Innhold$ddlKolonne=7
ctl00$Innhold$rblVerdi=2
ctl00$Innhold$rblBeregning=1
ctl00$Innhold$lbBransje=
ctl00$Innhold$lbAldersgruppe=
ctl00$Innhold$lbFylke=3
ctl00$Innhold$lbDag=
ctl00$Innhold$lbKilde=
ctl00$Innhold$lbKvartal=
ctl00$Innhold$lbMåned=
ctl00$Innhold$lbNæring=
ctl00$Innhold$lbType=
ctl00$Innhold$lbUkedag=
ctl00$Innhold$lbÅr=
ctl00$Innhold$lbÅrsak=
ctl00$Innhold$btnKjør=Lag tabell
Notes
ddlRad=6 — row dimension = arsak (BRASK_AXIS.arsak = 6 in _braskWebForms.constants.ts).ddlKolonne=7 — column dimension = ar (year).rblVerdi=2 — kr.lbFylke=3 — Oslo only.lbType= and lbNæring= empty — all fire types / all building types.HeatWaves intent
dim_code = 4 (Arnested) — seriesfire_type = DEVELOPED, building_type = — (unfiltered — all buildings), region = OsloDirect cross-source counterpart to Datasets 6 and 8 — shows how Oslo is filtered on the BRIS side.
Native API
POST https://brannstatistikk.no/api/v1/missionreports/aggregate Content-Type: application/json
{ "...": "[same as Dataset 1 envelope, except:]", "revisedMissionTypes": { "ids": [10026], "isMissingValue": false }, "counties": { "ids": [3], "isMissingValue": false }, "buildingTypes": { "ids": [], "isMissingValue": false }, "aggregationQuery": { "includeNationalFigures": false, "aggregationDefinition": { "id": "403", "name": "Arnested - politi", "type": "TERMS", "question": true, "groupAnswer": false, "restricted": false, "includeMissing": true, "calculatedSubAggregationDefinitions": [], "nextLevelAggregationDefinition": { "id": "MISSION_CALL_TIME_YEAR", "name": "År", "type": "DATE_HISTOGRAM", "interval": "YEAR", "question": false, "groupAnswer": false, "restricted": false, "includeMissing": true, "calculatedSubAggregationDefinitions": [] } } } }
Notes — cross-system caveat
lbFylke = 3 and BRIS counties.ids = [3] both happen to equal Oslo, but the systems align only by coincidence for Oslo. Every other county diverges:
2 = Akershus, 7 = Vestfold, 19 = Troms).30 = Viken for 2020-2023 incidents, 32 = Akershus for post-2024 incidents — see fylke-code appendix below).municipalities.ids = [301] would also work for Oslo in BRIS.HeatWaves intent
building_type = RESIDENTIAL (encoded by selecting the Boligbranner statistical variable, not a parameter), region = OsloCross-source counterpart to Datasets 6, 8, 9 — same Oslo geography across all four sources.
Native API
POST https://data.ssb.no/api/v0/no/table/12058 Content-Type: application/json
{ "query": [ { "code": "KOKkommuneregion0000", "selection": { "filter": "item", "values": ["0301"] } }, { "code": "ContentsCode", "selection": { "filter": "item", "values": ["KOSboligbranner0000"] } }, { "code": "Tid", "selection": { "filter": "top", "values": ["10"] } } ], "response": { "format": "json-stat2" } }
Notes
12058 is the SSB KOSTRA fire and safety table. Variable codes are documented in ssb-pxwebapi-tables.md.building_type_code NULL; Bygningsbranner / KOSbygningsbrann0000) instead of RESIDENTIAL, swap the ContentsCode value accordingly. For kr instead of antall: KOSerstatnbygnin0000.KOKkommuneregion0000: municipality codes (0301 = Oslo) or EAK for national total. PxWeb → region_code: filter-axes-native-to-filter-id.md §4; upstream codes: ssb-pxwebapi-tables.md.Tid is years natively in SSB — no equivalent of BRIS's nextLevelAggregationDefinition is needed. The "top": "10" value means "the most recent 10 years"; replace with { "filter": "item", "values": ["2020","2021","2022","2023","2024"] } for an explicit list.json-stat2: row-major value array — decode contract in pipeline-slices-idempotency-and-triggers.md §4.3; PxWebApi mechanics in ssb-pxwebapi-tables.md.HeatWaves intent
dim_code = 2 (Tennkilde) — seriesfire_type = DEVELOPED, building_type = noneThis is the only example in the doc that does NOT match the "year on x-axis" rule — included expressly to show the simpler payload shape for ETL slices that only need categorical totals.
Native API
POST https://brannstatistikk.no/api/v1/missionreports/restrictedaggregation Content-Type: application/json
{ "revisedMissionTypes": { "ids": [10026], "isMissingValue": false }, "counties": { "ids": [], "isMissingValue": false }, "hundredAndTenCentrals": { "ids": [], "isMissingValue": false }, "includePoliceCauseWithNoMission": false, "aggregationQuery": { "includeNationalFigures": false, "aggregationDefinition": { "id": "264", "name": "Antatt tennkilde", "type": "TERMS", "question": true, "groupAnswer": false, "restricted": false, "includeMissing": true, "calculatedSubAggregationDefinitions": [] } } }
Notes — Identical to Dataset 5 with two changes: revisedMissionTypes.ids = [10026] (DEVELOPED), and nextLevelAggregationDefinition is omitted entirely from the aggregationDefinition object. The response shape is then a flat result[0].buckets[<category>].count map (no time sub-buckets); the BRIS adapter parses that into fact_yearly rows for /explore charts via get_fire_data.
HeatWaves intent
dim_code = 4 (Arnested) — seriesfire_type = DEVELOPED, building_type = none, period = 2024This is the canonical day-grain BRIS request used by the daily ingest adapter
(lib/data-model/adapters/bris.daily.ts).
Tier-2 sends the same body with interval: "MONTH" per drifted year; Tier-3
sends this body with the period narrowed to a single (year, month).
Native API
POST https://brannstatistikk.no/api/v1/missionreports/aggregate Content-Type: application/json
{ "hitsToReturn": 0, "skipped": 0, "missionTypes": { "ids": [], "isMissingValue": false }, "revisedMissionTypes": { "ids": [10026], "isMissingValue": false }, "monthNumbers": { "ids": [], "isMissingValue": false }, "dayOfWeek": { "ids": [], "isMissingValue": false }, "responseTimeLimitGreaterThan": true, "callOutTimeLimitGreaterThan": true, "effortDurationGreaterThan": true, "counties": { "ids": [], "isMissingValue": false }, "municipalities": { "ids": [], "isMissingValue": false }, "basicStatisticalUnits": { "ids": [], "isMissingValue": false }, "fireDepartments": { "ids": [], "isMissingValue": false }, "hundredAndTenCentrals": { "ids": [], "isMissingValue": false }, "streetAddress": "", "geoShapeFilter": { "polygons": [], "circles": [] }, "fireStations": { "ids": [], "isMissingValue": false }, "dispatchedFireDepartments": { "ids": [], "isMissingValue": false }, "buildingTypes": { "ids": [], "isMissingValue": false }, "naceCodes": { "ids": [], "isMissingValue": false }, "includeAssistanceMissions": false, "includeExercises": false, "includeMissionsHandledByHundredAndTen": false, "includePoliceCauseWithNoMission": false, "includeRVRMissionsFromBris": false, "includeApprovedMissions": true, "onlyApprovedMissions": true, "answers": [], "periodStart": "2024-01-01", "periodEnd": "2024-12-31", "aggregationQuery": { "includeNationalFigures": false, "aggregationDefinition": { "id": "403", "name": "Arnested - politi", "type": "TERMS", "interval": null, "question": true, "groupAnswer": false, "restricted": false, "includeMissing": true, "calculatedSubAggregationDefinitions": [], "nextLevelAggregationDefinition": { "id": "MISSION_CALL_TIME_DAY", "name": "Dag", "type": "DATE_HISTOGRAM", "interval": "DAY", "question": false, "groupAnswer": false, "restricted": false, "includeMissing": true, "calculatedSubAggregationDefinitions": [] } } } }
Response shape — verified live
The full raw response is committed at
.live_responses/dataset_12_police_arnested_DAY_2024.json.
Key invariants the daily adapter relies on:
result[0].buckets[<answer_id>].subAggregationBuckets keys are Unix-ms
timestamps that decode via new Date(Number(ts)).toISOString().slice(0, 10)
to ISO dates (UTC midnight, no timezone offset).result[0].total === Σ inner.count across every category × day bucket
(3244 / 3244 in the sample).count: 0.
transformBrisDailyResponse skips zero cells the same way
transformBraskDailyTable does.-1 bucket ("Ikke besvart") resolves through
resolveCatCodeFromBrisBucket (native_name = 'Ikke besvart' in the catalog).Notes — Same body as Dataset 1 with buildingTypes.ids = [],
nextLevelAggregationDefinition.interval = "DAY", and explicit
periodStart / periodEnd. Switching interval to "MONTH" is the
Tier-2 monthly-probe variant of the same body.
Authoritative codes for BRIS counties.ids come from SSB klass 104 (Standard for fylkesinndeling). Post-2024 incidents (from 2024-01-01): BRIS uses the same numeric ids as the HeatWaves canonical county spine — one table only, in regions-and-cresta.md (section “Canonical region set (2024, county level)”). Do not copy that table here; update the canonical doc when the spine changes.
Pre-2024 (incidents 2020-01-01 to 2023-12-31) — BRIS klass 104 historical fylke ids for request bodies only (differs from the 2024 canonical list):
| Code | Fylke |
|---|---|
| 03 | Oslo |
| 11 | Rogaland |
| 15 | Møre og Romsdal |
| 18 | Nordland |
| 30 | Viken |
| 34 | Innlandet |
| 38 | Vestfold og Telemark |
| 42 | Agder |
| 46 | Vestland |
| 50 | Trøndelag |
| 54 | Troms og Finnmark |
| 99 | Uoppgitt |
ETL caveat — BRIS returns historical incidents under the codes that were valid at the time of the incident. A query that filters counties.ids = [30] (Viken) only matches incidents from 2020-2023; post-2024 incidents in the same geography are split across [31, 32, 33]. HeatWaves should normalize across both code sets when building cross-year region series. Source: https://data.ssb.no/api/klass/v1/classifications/104/codes.
| # | Datasource | Dimension | Fire type | Building type | Region | Endpoint | Body type |
|---|---|---|---|---|---|---|---|
| 1 | Police (Sub-A) | Arnested | DEVELOPED | RESIDENTIAL | — | /aggregate | full JSON |
| 2 | DSB | Arnested | DEVELOPED | n/a | — | /restrictedaggregation | minimal JSON |
| 3 | Police (Sub-A) | Objekt | DEVELOPED | RESIDENTIAL | — | /aggregate | full JSON |
| 4 | Police (Sub-A) | Objekt | DEVELOPED | — | — | /aggregate | full JSON, empty buildingTypes.ids |
| 5 | DSB | Tennkilde | CONFINED (no skorstein) | n/a | — | /restrictedaggregation | minimal JSON |
| 6 | BRASK | Tennkilde | CONFINED | RESIDENTIAL | Oslo | form POST | URL-encoded form, value=kr, age 1-5 |
| 7 | Brigade | Årsak | CONFINED komfyr-only | n/a | — | /restrictedaggregation | minimal JSON, single mission |
| 8 | BRASK | Årsak | — | — | Oslo | form POST | URL-encoded form, value=kr |
| 9 | Police (Sub-A) | Arnested | DEVELOPED | — | Oslo | /aggregate | full JSON, counties.ids=[3] |
| 10 | SSB | (totals) | n/a | RESIDENTIAL via dataset | Oslo (0301) | PxWebApi v0 | JSON-stat2 query |
| 11 | DSB | Tennkilde | DEVELOPED | n/a | — | /restrictedaggregation | minimal JSON, no time sub-agg |
| 12 | Police (Sub-A) | Arnested | DEVELOPED | — | — | /aggregate | full JSON, interval: DAY, periodStart/periodEnd |
Every native request above was executed by scripts/smoke_api_comparison.mjs. Full raw responses are saved under .live_responses/ (one file per dataset — .json for BRIS/SSB, .html for BRASK). That directory is tracked in git so documentation links to pinned samples stay valid in fresh clones; re-run the smoke script when upstream responses or slice templates change, then commit refreshed files. The summary below lets you cross-check key totals against the source websites without opening the raw files.
Smoke-test environment
node scripts/smoke_api_comparison.mjs-1 in BRIS results is the "missing answer" bucket returned because aggregationDefinition.includeMissing = true. Subtract it from grandTotal to get the answered-only count.These three identities hold across the responses and confirm the slice logic in filter-axes-native-to-filter-id.md is internally consistent:
grandTotal = 32,320 = Dataset 4 (Police Objekt DEVELOPED, all buildings) grandTotal = Dataset 11 (DSB Tennkilde DEVELOPED, no sub-agg) grandTotal. All three slice the same population (DEVELOPED Brann i bygning nationwide, 2016–2026).grandTotal = 15,879 = Dataset 3 (Police Objekt DEVELOPED, RESIDENTIAL) grandTotal. Same building-type filter, same mission slice.grandTotal = 3,930 — strictly less than Dataset 1's 15,879. Oslo's share is roughly 25% of national, which matches the public Oslo brannvesen statistics for the period.| # | Endpoint | Question id | Mission types | Cats | Grand total | Year range | Top 3 (cat → count) |
|---|---|---|---|---|---|---|---|
| 1 | /aggregate | 403 (Arnested - politi) | [10026] | 21 | 15,879 | 2016–2026 | -1 → 10,092 · Kjøkken → 1,055 · Stue → 930 |
| 2 | /restrictedaggregation | 227 (Antatt arnested) | [10026] | 28 | 32,320 | 2016–2026 | Kjøkken → 4,708 · Stue → 3,996 · Utvendig → 3,897 |
| 3 | /aggregate | 405 (Brannen startet i - politi) | [10026] | 23 | 15,879 | 2016–2026 | -1 → 10,151 · Ukjent → 1,444 · Løst elektrisk utstyr → 842 |
| 4 | /aggregate | 405 | [10026] | 23 | 32,320 | 2016–2026 | -1 → 21,074 · Ukjent → 2,735 · Løst elektrisk utstyr → 1,515 |
| 5 | /restrictedaggregation | 264 (Antatt tennkilde) | [10086, 10212] | 7 | 31,392 | 2016–2026 | -1 → 31,313 · Elektrisitet → 48 · Annen → 14 |
| 7 | /restrictedaggregation | 269 (Brannvesenets vurdering) | [10086] | 4 | 17,801 | 2016–2026 | -1 → 17,751 · Feil bruk → 46 · Ukjent → 3 |
| 9 | /aggregate | 403 | [10026] + counties=[3] | 22 | 3,930 | 2016–2026 | -1 → 2,176 · Kjøkken → 360 · Stue → 229 |
| 11 | /restrictedaggregation | 264, no time sub-agg | [10026] | 7 | 32,320 | n/a (categories-only) | Ukjent → 10,940 · Elektrisitet → 7,539 · Åpen ild → 6,530 |
| 12 | /aggregate | 403, interval: DAY, period 2024 | [10026] | 22 | 3,244 | 2024-01-01..2024-12-31 (366 day buckets) | -1 → 1,683 · Ukjent → 211 · Stue → 210 |
Dataset 5 has very few non-
-1answers (79 of 31,392) because Tennkilde (264) is rarely filled in for confined incidents. Dataset 7 likewise has only 50 non--1answers because Brigade-vurdering (269) is rarely populated forBranntilløp komfyrevents.
BRASK numbers are reported in tusen kr (thousands of NOK) when rblVerdi=2. The "Grand total" column below is the SUM × SUM cell of the returned table (sum across all categories AND all years).
| # | Row dim | Filters | Cats | Year range | Grand total (tusen kr) | Sample row totals |
|---|---|---|---|---|---|---|
| 6 | kilde (5) | Kald + Bolig + Oslo + 1–5 år + kr | 7 | 1985–2025 | 2,042 | Ildsted → 18 · Varme arbeider → 0 · Åpen ild → 0 · Elektroniske apparater → 60 · Husholdning → 166 |
| 8 | arsak (6) | Oslo + kr (no fire-type / building-type filter) | 7 | 1985–2025 | 14,554,292 | Antatt påsatt → 706,655 · Menneskelig feil → 1,725,625 · Teknisk svikt → 1,257,457 · Selvantennelse → 351,404 · Lynnedslag → 231,198 |
Dataset 6's filters are narrow enough (Oslo + 1–5 år + Kald + Bolig) that the entire 41-year dataset only sums to ~2 million NOK in claims — verify on the BRASK UI by setting Aldersgruppe = 1–5, Fylke = Oslo, Type = Kald, Næring = Beboelse, Verdi = Erstatningsbeløp. The mostly-zero year columns are accurate. Dataset 8 returns 7 Årsak rows = the seven canonical BRASK cause categories from
category-native-to-cat-code.md§1 (cat_codes 101–107).
SSB Boligbranner for Oslo (region 0301), 2016–2025, raw value array from json-stat2:
| Year | Antall boligbranner |
|---|---|
| 2016 | 265 |
| 2017 | 214 |
| 2018 | 247 |
| 2019 | 228 |
| 2020 | 238 |
| 2021 | 272 |
| 2022 | 204 |
| 2023 | 219 |
| 2024 | 250 |
| 2025 | 289 |
| Total 2016–2025 | 2,426 |
SSB numbers are independent of BRIS/BRASK (different methodology — SSB sources from KOSTRA municipal reporting). For 2016–2025 SSB reports 2,426 boligbranner in Oslo. Compare to BRIS Dataset 9 (Police Arnested, Oslo, DEVELOPED, all buildings, 2016–2026) which reports 3,930 incidents — the BRIS number is larger because it includes non-RESIDENTIAL buildings, the
-1missing bucket, and one extra year.
| Source | Manual check |
|---|---|
| BRIS | Open https://brannstatistikk.no/search, build the same query in the UI (mission type → group by → time), and compare the displayed counts. |
| BRASK | Open https://brask.finansnorge.no/, set the same Rad/Kolonne dropdowns and filter checkboxes (Type, Næring, Aldersgruppe, Fylke), and compare the table. |
| SSB | Open https://www.ssb.no/statbank/table/12058/, select region = Oslo, statistikkvariabel = Antall boligbranner, år = last 10, and compare the values. |
Re-run with node scripts/smoke_api_comparison.mjs. Raw responses overwrite the files in .live_responses/ so you can diff before/after on subsequent runs.