Skip to content

API examples

Worked curl calls for every endpoint, with the reasoning behind each result's shape. The machine-readable contract — every field, type and a response example cut from the live calculation — is on the Endpoints page, rendered from the committed openapi.json. Where the two disagree, the spec wins: it is regenerated from the running app and checked in CI.

All examples assume the API is running locally:

uvicorn backend.app.main:app --reload

The interactive Swagger UI (/docs) and ReDoc (/redoc) are served by the running app.


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

The full response, with an example excerpted from the live calculation, is in the rendered spec.


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: five materials block a defensible total — Earth (decision #26 hard block, no EU substitute), Crude oil, Floor Tiles and Anti-termite (anomalous or uncited factors), and Antirust paint (CORRECTED provisional 4.87 kg CO₂/kg). Those five are listed in incomplete_reason. The other 13 materials still carry their individual A1-A3 GWP.

Four materials — Cement, Steel Rebars, Rock and Sand — resolve their factor from a provenance-gated seed EPD rather than from the reference workbook (AR-63), and surface source_epd_id, provenance_cascade_step and the full five-axis Weidema pedigree alongside the value. The other fourteen are still inline literals and report all three as null; that asymmetry is tracked debt, not a finished state.

Every CORRECTED row — those four plus Antirust paint — also carries reference_value, the reference workbook's factor it supersedes (2_lca_vn.xlsx LCI Final column I, unit kg_CO2_eq_kg), and divergence_pct = (factor − reference) / reference × 100: Rock +190.1 %, Sand −4.0 %, Cement −14.6 %, Steel Rebars −78.2 %, Antirust paint −95.4 %. Both are null on VALIDATED and BLOCKED rows (AR-71).

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

The full response, with an example excerpted from the live calculation, is in the rendered spec.

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 Anti-termite are BLOCKED and Antirust paint is PROVISIONAL, the aggregate is withheld and the blockers are surfaced in incomplete_reason. Per-material impacts remain available for the 13 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 freight — A4!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

The full response, with an example excerpted from the live calculation, is in the rendered spec.

The A4 total is intentionally null

Unlike A1-A3, where 13 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

The full response, with an example excerpted from the live calculation, is in the rendered spec.

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.