Skip to content

Endpoints

GET /health

Liveness probe.

curl http://localhost:8000/health
# {"status":"ok","version":"0.0.1"}

GET /quantities/keur-songho

Returns corrected material quantities for the Keur Songho School Complex reference project.

CORRECTED formulas (C1–C4) are applied. BLOCKED parameters appear in blocked_parameters.

curl http://localhost:8000/quantities/keur-songho

Response (excerpt):

{
  "project_name": "Keur Songho School Complex",
  "materials": [
    {"category": "raw_earth", "quantity": {"value": 751.9, "unit": "m3"}},
    {"category": "water",     "quantity": {"value": 293.4, "unit": "m3"}},
    {"category": "cement",    "quantity": {"value": 23301.0, "unit": "kg"}}
  ],
  "blocked_parameters": [
    "BLOCKED: row 51 rebar/mesh density for 300 kg/m³ slab not attributed. ..."
  ]
}

POST /quantities/explode

Explode a user-supplied BoQ into material quantities.

Phase 1 supports only "Keur Songho School Complex". Returns 501 for other projects.

curl -X POST http://localhost:8000/quantities/explode \
  -H "Content-Type: application/json" \
  -d '{
    "project_name": "Keur Songho School Complex",
    "line_items": [
      {"code": "A.III.4", "unit": "m3", "quantity": 4.608}
    ]
  }'

Phase 1 limitation

Generic BoQ explosion (arbitrary line items mapped to domain formulas) is planned for Phase 2 once the Assembly recipe model is defined. The POST /quantities/explode endpoint currently delegates to the same Keur Songho dispatcher as the GET endpoint.


GET /lca/a1-a3/keur-songho

Returns the A1-A3 (product stage) GWP for the Keur Songho School Complex reference project.

Applies E = weight × factor per material (VALIDATED formula, decision #23). Each per-material result carries its factor, source citation, verdict, geographic-provenance tag (decision #26), pending_african_data flag, and Weidema axis-4 note.

The aggregate total is null: four materials block a defensible total — Earth (decision #26 hard block, no EU substitute), Crude oil and Floor Tiles (anomalous factors, likely unit errors), and Antirust paint (CORRECTED provisional 4.87 kg CO₂/kg). Those four are listed in incomplete_reason. The other 14 materials still carry their individual A1-A3 GWP.

curl http://localhost:8000/lca/a1-a3/keur-songho

Response (excerpt):

{
  "project_name": "Keur Songho School Complex",
  "stage": "A1-A3",
  "materials": [
    {
      "material": "Cement",
      "category": "cement",
      "weight": {"value": 23301.047, "unit": "kg"},
      "factor": 0.779,
      "impact": {"value": 18151.52, "unit": "kg_CO2_eq"},
      "status": "computed",
      "formula_verdict": "VALIDATED",
      "provenance_verdict": "BLOCKED",
      "geographic_provenance": "okobaudat_interim",
      "pending_african_data": true
    },
    {
      "material": "Earth",
      "category": "earth",
      "weight": {"value": 1494888.525, "unit": "kg"},
      "factor": null,
      "impact": null,
      "status": "blocked",
      "formula_verdict": "BLOCKED",
      "geographic_provenance": "local_data_required",
      "pending_african_data": true,
      "blocked_reason": "Earth A1-A3 BLOCKED (decision #26 hard block; attribution item 12) ..."
    }
  ],
  "total": null,
  "incomplete_reason": [
    "Earth: ...",
    "Crude oil: ...",
    "Floor Tiles: ...",
    "Antirust paint: ..."
  ]
}

The A1-A3 total is intentionally null

The tool never emits a partial total as if complete (result policy, decision #23). Because Earth, Crude oil, Floor Tiles and Antirust paint are BLOCKED/PROVISIONAL, the aggregate is withheld and the blockers are surfaced in incomplete_reason. Per-material impacts remain available for the 14 computable materials.


GET /lca/a4/keur-songho

Returns the A4 (transport to site) GWP for the Keur Songho School Complex reference project.

Applies A4_i = Σ_legs (mass_i [t] × distance [km] × factor [kg CO₂-eq/t·km]) (VALIDATED formula, decision #23). Mass comes from the LCI mass path — A4 never re-derives quantities. Each material carries one result per transport leg, with distance, transport work (t·km), route note, distance source, provenance verdict and Weidema axis-4 score.

The aggregate total is null: both transport emission factors are BLOCKED (decision #23 Axis 2).

  • Road truck — the workbook's 0.26 kg CO₂-eq/kWh (A4!I5:I22) has no cited dataset; the Pedrazzi thesis describes the same model with different numbers (0.27 kg CO₂-eq/kWh, 386 kW) and names no programme operator either.
  • Sea freightA4!L11 = 182.4/(F11*N11) back-solves a rate from an unexplained 182.4 kg CO₂-eq constant, then broadcasts it to every sea-freighted material via $L$11.

Decision #26 admits only an IPCC EFDB or ÖKOBAUDAT transport-EPD factor per t·km for A4. Fifteen materials are therefore BLOCKED and listed in incomplete_reason. Water, Crude oil and Waste Oil are on-site (zero distance per A4!B25) and compute to exactly 0 — a zero-length leg contributes nothing whatever the factor turns out to be.

curl http://localhost:8000/lca/a4/keur-songho

Response (excerpt):

{
  "project_name": "Keur Songho School Complex",
  "stage": "A4",
  "materials": [
    {
      "material": "Steel Rebars",
      "category": "steel_rebar",
      "mass": {"value": 1330.6, "unit": "kg"},
      "legs": [
        {
          "mode": "road_truck",
          "distance": {"value": 88.0, "unit": "km"},
          "transport_work": {"value": 117.09, "unit": "tkm"},
          "factor": null,
          "impact": null,
          "route_note": "Shanghai Port (China) → Dakar Port",
          "provenance_verdict": "BLOCKED",
          "geographic_provenance": "blocked",
          "weidema_axis4_score": 5
        },
        {
          "mode": "sea_freight",
          "distance": {"value": 21279.0, "unit": "km"},
          "transport_work": {"value": 28314.25, "unit": "tkm"},
          "factor": null,
          "impact": null,
          "route_note": "Shanghai Port (China) → Dakar Port",
          "provenance_verdict": "BLOCKED"
        }
      ],
      "impact": null,
      "status": "blocked",
      "formula_verdict": "VALIDATED",
      "blocked_reason": "road_truck: A4 road-freight factor BLOCKED ... ; sea_freight: ..."
    },
    {
      "material": "Water",
      "category": "water",
      "mass": {"value": 299583.55, "unit": "kg"},
      "legs": [
        {
          "mode": "road_truck",
          "distance": {"value": 0.0, "unit": "km"},
          "transport_work": {"value": 0.0, "unit": "tkm"},
          "factor": null,
          "impact": {"value": 0.0, "unit": "kg_CO2_eq"},
          "route_note": "On-site (no transport)",
          "geographic_provenance": "not_applicable"
        }
      ],
      "impact": {"value": 0.0, "unit": "kg_CO2_eq"},
      "status": "computed",
      "formula_verdict": "VALIDATED"
    }
  ],
  "total": null,
  "incomplete_reason": ["Rock: ...", "Gravel: ...", "..."]
}

The A4 total is intentionally null

Unlike A1-A3, where 14 of 18 materials remain computable, A4 has no usable emission factor at all. Sourcing a road-freight and a sea-freight factor per t·km from IPCC EFDB or an ÖKOBAUDAT transport EPD (sourcing tasks A4-1 and A4-2) is the gate for reporting any A4 result. See docs/methodology/lca-a4-transport-spec.md §8.


GET /lca/a5/keur-songho

Returns the A5 (on-site construction and installation) GWP for the Keur Songho School Complex reference project.

Applies A5_e = rated_power [kW] × usage [h] × factor [kg CO₂-eq/kWh] and share_e = A5_e / Σ A5 (both VALIDATED formulas, decision #23). The A5 sheet is already written in the EN 15804+A2 energy-carrier form, so — unlike A4 — no algebraic reduction was needed to reach it.

A5 is the first stage that is not material-keyed. A1-A3, A4, B4, C2, C3, C4 and D all carry one row per material and join on the 18-row LCI inventory. A5 carries one row per item of site plant, and the workbook's own INTERPRETATION sheet places its three A5 rows below the 18 material rows with every material-stage cell empty. Results are therefore keyed on SiteEquipment (generator, cutting_machine, welding_machine), not MaterialCategory.

The aggregate total is null: the single site-energy emission factor is BLOCKED (decision #23 Axis 2). Four independent reasons, any one sufficient —

  • No citation. A5!F5:F7 = 0.26 kg CO₂-eq/kWh is a bare literal in three cells. The sheet has no source column, no cell comments and no legend.
  • Decision #26 governs it. A5 construction energy is named explicitly as an energy-linked stage on which EU grid factors are BLOCKED outright; an African national grid factor from IEA World Energy Statistics or IPCC EFDB is required, and 0.26 sits in the EU-average band.
  • The workbook contradicts itself. The same file carries a Senegal grid factor at B1!D5 = 1.1 kg CO₂/kWh — 4.2× larger, unreconciled, and itself unverified (AR-09).
  • It is applied to a diesel genset. A generator consumes no grid electricity; its per-kWh factor is a fuel-combustion quantity (published gensets run ≈ 0.7–0.8 kg CO₂-eq/kWh), so a grid-shaped number is a category error here whatever grid it came from.

total_energy_demand is reported — 1 080 kWh — because energy demand is power × hours and needs no emission factor. This is the shape every blocked module should aim for: report the half that is defensible, withhold the half that is not.

curl http://localhost:8000/lca/a5/keur-songho

Response (excerpt):

{
  "project_name": "Keur Songho School Complex",
  "stage": "A5",
  "equipment": [
    {
      "equipment": "generator",
      "label": "Generator",
      "rated_power": {"value": 27.6, "unit": "kW"},
      "usage": {"value": 20.0, "unit": "h"},
      "energy_demand": {"value": 552.0, "unit": "kWh"},
      "carrier": "site_electricity",
      "factor": null,
      "impact": null,
      "share": null,
      "status": "blocked",
      "formula_verdict": "VALIDATED",
      "power_source": "2_lca_vn.xlsx A5!C5 = 27.6 kw (literal, no source note; ...). Attribution pending (AR-55).",
      "usage_source": "2_lca_vn.xlsx A5!E5 = 10*2 -> 20.0 h. Multiplicands undocumented; ...",
      "provenance_verdict": "BLOCKED",
      "geographic_provenance": "blocked",
      "pending_african_data": true,
      "weidema_axis4_score": 5,
      "blocked_reason": "A5 site energy factor BLOCKED (spec §4.1, sourcing task A5-1 / register row AR-54): ..."
    }
  ],
  "total": null,
  "total_energy_demand": {"value": 1080.0, "unit": "kWh"},
  "incomplete_reason": ["Generator: ...", "Cutting Machine: ...", "Welding Machine: ..."],
  "scope_note": "A5 scope covers on-site construction plant energy ONLY, as the reference calculation does. ..."
}

This is a deliberately partial A5, and every response says so

EN 15804+A2 §6.3.4.4 places six further sub-scopes in A5 — material installation losses, on-site water, packaging waste treatment, temporary works, transport of plant and workers, and site earthworks. None of them exists in 2_lca_vn.xlsx, and none is invented here: filling them would put numbers into an ISO 14071 review that trace to nothing. scope_note carries that statement on every response so the figure can never read as a complete A5. Choosing which sub-scopes v1 declares, and documenting a cut-off justification for the rest, is register row AR-58.

The A5 GWP total is intentionally null

Sourcing a Senegalese grid factor from IEA World Energy Statistics or IPCC EFDB (register row AR-54, which turns on AR-09) is the gate. It cannot be sourced blind: whether A5 needs a grid factor at all depends on resolving whether the cutting and welding machines ran off the generator, in which case the sheet double-counts their energy and needs a fuel-combustion factor instead (AR-56). See docs/methodology/lca-a5-construction-spec.md §4.