Viable logo

API access

Run emissions pathway projections from your own tools. This walkthrough covers authentication, a minimal request payload, standard vs extended responses, and scenario analysis — with copyable and downloadable examples.

API keys are issued to approved customers and partners. This site never embeds a key — use placeholders like YOUR_API_KEY until yours is issued.

1. Authenticate

Protected endpoints expect an API key (or a Cognito JWT for app sessions). Prefer an environment variable — never commit keys to source control or notebooks shared publicly.

Header options

  • Authorization: ApiKey YOUR_API_KEY
  • X-API-Key: YOUR_API_KEY
  • or Authorization: Bearer <JWT> / JWT <token>

Base URL: https://app.viablepathway.net

Request an API key to get access

2. Build the payload

Send a complete organisation payload as JSON. The mini example below uses one org unit, three activities (v2 flat format), and two internal actions — enough to exercise BAU, EXT, and INT pathways without a full inventory dump.

Payload structure

Organisation settings sit at the top level. Inventory, geography, and actions live under orgunits.

Activity data (v2)

Each key is a unique instance id (often catalogActivity@@region). Use catalogactivityid for trend matching and activityname for display. Set activitydataversion: 2 at the top level.

Internal actions

The object key (e.g. useraction_efficiency_2027) becomes actionid in outputs. actionname is a label only. multiplier is a fractional change (e.g. -0.15 = −15%). Optional balancingactivity shifts quantity to another activity (e.g. petrol → EV).

Market-based Scope 2 (optional)

Set electricityapproach: "market" and add per-org-unit recPurchase with a ramp schedule (entries + pricePerKwh). Not required for the mini example below.

BAU → EXT → INT

BAU grows inventory with desiredgrowth. EXT applies external market trends (e.g. grid decarbonisation). INT layers your internalactions on top of EXT.

minimal-payload.json JSON
{
  "organisationid": "DEMO_CO",
  "name": "Demo Company",
  "desiredgrowth": 2,
  "projectionstartyear": 2025,
  "projectionendyear": 2050,
  "currency": "aud",
  "electricityapproach": "location",
  "neartermsbtitarget": "1.5",
  "neartermsbtitargetyear": 2030,
  "activitydataversion": 2,
  "orgunits": {
    "orgunit_sydney": {
      "name": "Sydney Office",
      "orgunitid": "orgunit_sydney",
      "country": "australia",
      "region": "au-nsw",
      "currency": "aud",
      "employees": 120,
      "activitydata": {
        "utilities_electricity_grid@@au-nsw": {
          "activityname": "Grid electricity — NSW",
          "catalogactivityid": "utilities_electricity_grid",
          "region": "au-nsw",
          "activitydatavalue": 500000,
          "activityuom": "kWh",
          "ghgpscope": 2,
          "ghgpscopecategory": "2",
          "emissionfactortrendid": "utilities_electricity_grid",
          "emissionfactorvalue": 0.68,
          "emissionfactorunit": "kgCO2e"
        },
        "companyvehicle_car_petrol@@au-nsw": {
          "activityname": "Fleet — petrol cars",
          "catalogactivityid": "companyvehicle_car_petrol",
          "region": "au-nsw",
          "activitydatavalue": 250000,
          "activityuom": "km",
          "ghgpscope": 1,
          "ghgpscopecategory": "1-2",
          "emissionfactortrendid": "companyvehicle_car_petrol",
          "emissionfactorvalue": 0.192,
          "emissionfactorunit": "kgCO2e"
        },
        "companyvehicle_car_bev@@au-nsw": {
          "activityname": "Fleet — battery electric cars",
          "catalogactivityid": "companyvehicle_car_bev",
          "region": "au-nsw",
          "activitydatavalue": 10000,
          "activityuom": "km",
          "ghgpscope": 2,
          "ghgpscopecategory": "2",
          "emissionfactortrendid": "companyvehicle_car_bev",
          "emissionfactorvalue": 0.05,
          "emissionfactorunit": "kgCO2e"
        }
      },
      "internalactions": {
        "useraction_efficiency_2027": {
          "actionname": "Office energy efficiency",
          "actiontype": "Energy Efficiency",
          "activity": "utilities_electricity_grid@@au-nsw",
          "startyear": 2027,
          "multiplier": -0.15,
          "absolutechange": 0,
          "balancingactivity": "",
          "balancingmultiplier": 0,
          "capitalcost": 80000,
          "capitalcostcalculationmethod": "absolute",
          "description": "Lighting and HVAC upgrades reducing grid electricity use by 15% from 2027."
        },
        "useraction_fleet_ev_2028": {
          "actionname": "Switch petrol fleet to EV",
          "actiontype": "Company Vehicles",
          "activity": "companyvehicle_car_petrol@@au-nsw",
          "startyear": 2028,
          "multiplier": -0.5,
          "absolutechange": 0,
          "balancingactivity": "companyvehicle_car_bev@@au-nsw",
          "balancingmultiplier": 1,
          "capitalcost": 150000,
          "capitalcostcalculationmethod": "absolute",
          "description": "Replace half of petrol car kilometres with battery electric from 2028."
        }
      },
      "historicemissionsyears": [
        2023,
        2024
      ],
      "historicemissions": {
        "1": [
          48.2,
          46.1
        ],
        "2": [
          340,
          325.5
        ],
        "3": [
          12,
          11.5
        ]
      }
    }
  }
}

3. Call calculate

POST /api/calculate runs the calculation engine. Use savePayload=false while experimenting so calls stay compute-only and do not persist organisation input.

Endpoint: https://app.viablepathway.net/api/calculate?savePayload=false

curl — calculate (standard) bash
#!/usr/bin/env bash
# Replace YOUR_API_KEY with the key issued after approval.
# savePayload=false keeps experimental calls from persisting input.

curl -sS -X POST \
  "https://app.viablepathway.net/api/calculate?savePayload=false" \
  -H "Content-Type: application/json" \
  -H "Authorization: ApiKey YOUR_API_KEY" \
  -d @minimal-payload.json
Python — calculate (standard) python
"""Minimal Viable Pathway calculate example.

Set VIABLE_API_KEY in your environment — never commit the key.
"""

import json
import os
import urllib.request

API_KEY = os.environ["VIABLE_API_KEY"]
BASE = "https://app.viablepathway.net"
URL = f"{BASE}/api/calculate?savePayload=false"

with open("minimal-payload.json", encoding="utf-8") as f:
    payload = json.load(f)

req = urllib.request.Request(
    URL,
    data=json.dumps(payload).encode("utf-8"),
    headers={
        "Content-Type": "application/json",
        "Authorization": f"ApiKey {API_KEY}",
    },
    method="POST",
)

with urllib.request.urlopen(req) as resp:
    result = json.load(resp)

print("projectionyears:", result.get("projectionyears"))
print("BAU pathway (tCO2e):", result.get("ghgBAUsumperyear"))
print("EXT pathway (tCO2e):", result.get("ghgEXTsumperyear"))
print("INT pathway (tCO2e):", result.get("ghgINTsumperyear"))

4. Read the response

The standard response is the shape most integrators need first: organisation-level pathway totals, target pathways, waterfall, contributions, and trimmed orgunitResults.

Standard response map

Default POST /api/calculate returns a compact calculatedData-style object: pathway totals, targets, waterfall, and trimmed per-unit results (no full activity arrays).

projectionyears X-axis for pathway charts
ghgBAUsumperyear BAU total tCO₂e per year
ghgEXTsumperyear (+ Min/Max) External-trend pathway (± band)
ghgINTsumperyear (+ Min/Max) Internal-actions pathway (± band)
sbtiPathwayValues / targetyears Science-based target line
waterfallMultiYear Bridge from BAU → EXT → INT
internalActionsContributions Abatement by actionid
orgunitResults[] Per-unit GHG sums (trimmed)
transitionPlan / methodology Narrative / methodology blocks
Pathway totals chart — which arrays drive the lines

All GHG sum arrays are aligned to projectionyears. SBTi / custom target arrays align to targetyears. Illustrative values only — not a live calculation.

response-standard.json (illustrative) JSON
{
  "organisationid": "DEMO_CO",
  "name": "Demo Company",
  "neartermsbtitarget": "1.5",
  "neartermsbtitargetyear": 2030,
  "historicemissionsyears": [
    2023,
    2024
  ],
  "historicemissions": {
    "1": [
      48.2,
      46.1
    ],
    "2": [
      340,
      325.5
    ],
    "3": [
      12,
      11.5
    ]
  },
  "projectionyears": [
    2025,
    2026,
    2027,
    2028,
    2029,
    2030
  ],
  "targetyears": [
    2025,
    2026,
    2027,
    2028,
    2029,
    2030
  ],
  "orgUnits": [
    {
      "id": "orgunit_sydney",
      "name": "Sydney Office"
    }
  ],
  "ghgBAUsumperyear": [
    390,
    397.8,
    405.8,
    413.9,
    422.2,
    430.6
  ],
  "ghgEXTsumperyear": [
    390,
    385,
    372,
    358,
    345,
    332
  ],
  "ghgEXTsumperyearMin": [
    390,
    380,
    365,
    348,
    332,
    318
  ],
  "ghgEXTsumperyearMax": [
    390,
    390,
    380,
    368,
    358,
    346
  ],
  "ghgINTsumperyear": [
    390,
    385,
    340,
    280,
    265,
    250
  ],
  "ghgINTsumperyearMin": [
    390,
    380,
    330,
    268,
    250,
    235
  ],
  "ghgINTsumperyearMax": [
    390,
    390,
    350,
    292,
    280,
    265
  ],
  "sbtiPathwayValues": [
    390,
    365,
    340,
    315,
    290,
    265
  ],
  "userDefinedPathwayValues": null,
  "waterfallMultiYear": {
    "note": "Illustrative stub — real responses include yearly waterfall breakdowns"
  },
  "internalActionsContributions": [
    {
      "actionid": "useraction_efficiency_2027",
      "actionname": "Office energy efficiency",
      "abatementByYear": {
        "2027": 18.5,
        "2030": 22
      }
    },
    {
      "actionid": "useraction_fleet_ev_2028",
      "actionname": "Switch petrol fleet to EV",
      "abatementByYear": {
        "2028": 22,
        "2030": 28
      }
    }
  ],
  "methodology": {
    "note": "Illustrative stub — real responses include methodology statement text"
  },
  "transitionPlan": {
    "note": "Illustrative stub — real responses include structured transition-plan sections"
  },
  "orgunitResults": [
    {
      "id": "orgunit_sydney",
      "orgunitid": "orgunit_sydney",
      "ghgBAUsumperyear": [
        390,
        397.8,
        405.8,
        413.9,
        422.2,
        430.6
      ],
      "ghgEXTsumperyear": [
        390,
        385,
        372,
        358,
        345,
        332
      ],
      "ghgINTsumperyear": [
        390,
        385,
        340,
        280,
        265,
        250
      ],
      "internalActionsContributions": []
    }
  ]
}

Numbers above are shortened for documentation. Real responses use full projectionyears ranges (often through 2050).

5. Extended vs standard

Add extended=true for per-activity time series, scope breakdowns, and MAC curve points used by pathway and activity charts.

curl — calculate (extended) bash
#!/usr/bin/env bash
# Extended response includes per-activity AD/GHG arrays, scope emissions, and MAC curve points.

curl -sS -X POST \
  "https://app.viablepathway.net/api/calculate?extended=true&savePayload=false" \
  -H "Content-Type: application/json" \
  -H "Authorization: ApiKey YOUR_API_KEY" \
  -d @minimal-payload.json

What ?extended=true adds

The web client uses the extended payload. API integrators often start with the standard response, then request extended when they need activity detail, scope stacks, or MAC curves.

Scope stacked pathways

bauScopeEmissions, extScopeEmissions, intScopeEmissions (plus Min/Max for EXT/INT) — each { "1": number[], "2": number[], "3": number[] } aligned to projectionyears.

Activity quantity pathways

projectedEXTAD2 and projectedINTAD2 — arrays of { activity, values[] } for activity-detail charts. Join on activity (instance id).

Per-activity emissions

projectedBAUGHG, projectedEXTGHG, projectedINTGHG — same shape as AD arrays, in tCO₂e per activity.

Scope-split targets & MAC

sbtiPathwayByScope / userDefinedPathwayByScope for scope charts; maccByEndpoint (2030 / 2040 / 2050) for marginal abatement cost curves.

response-extended-excerpt.json (illustrative) JSON
{
  "_comment": "Excerpt of fields added (or expanded) when calling POST /api/calculate?extended=true&savePayload=false. Arrays are shortened for readability.",
  "projectionyears": [
    2025,
    2026,
    2027,
    2028,
    2029,
    2030
  ],
  "bauScopeEmissions": {
    "1": [
      48,
      49,
      50,
      51,
      52,
      53
    ],
    "2": [
      330,
      336,
      342,
      348,
      355,
      362
    ],
    "3": [
      12,
      12.8,
      13.8,
      14.9,
      15.2,
      15.6
    ]
  },
  "extScopeEmissions": {
    "1": [
      48,
      47,
      45,
      43,
      41,
      39
    ],
    "2": [
      330,
      326,
      315,
      303,
      292,
      281
    ],
    "3": [
      12,
      12,
      12,
      12,
      12,
      12
    ]
  },
  "intScopeEmissions": {
    "1": [
      48,
      47,
      45,
      28,
      26,
      24
    ],
    "2": [
      330,
      326,
      283,
      240,
      227,
      214
    ],
    "3": [
      12,
      12,
      12,
      12,
      12,
      12
    ]
  },
  "extScopeEmissionsMin": {
    "1": [],
    "2": [],
    "3": []
  },
  "extScopeEmissionsMax": {
    "1": [],
    "2": [],
    "3": []
  },
  "intScopeEmissionsMin": {
    "1": [],
    "2": [],
    "3": []
  },
  "intScopeEmissionsMax": {
    "1": [],
    "2": [],
    "3": []
  },
  "sbtiPathwayByScope": {
    "1": [
      48,
      45,
      42,
      39,
      36,
      33
    ],
    "2": [
      330,
      308,
      286,
      264,
      242,
      220
    ],
    "3": [
      12,
      12,
      12,
      12,
      12,
      12
    ]
  },
  "userDefinedPathwayByScope": null,
  "projectedEXTAD2": [
    {
      "activity": "utilities_electricity_grid@@au-nsw",
      "values": [
        500000,
        510000,
        520200,
        530604,
        541216,
        552040
      ]
    },
    {
      "activity": "companyvehicle_car_petrol@@au-nsw",
      "values": [
        250000,
        255000,
        260100,
        265302,
        270608,
        276020
      ]
    }
  ],
  "projectedINTAD2": [
    {
      "activity": "utilities_electricity_grid@@au-nsw",
      "values": [
        500000,
        510000,
        442170,
        451013,
        460034,
        469234
      ]
    },
    {
      "activity": "companyvehicle_car_petrol@@au-nsw",
      "values": [
        250000,
        255000,
        260100,
        132651,
        135304,
        138010
      ]
    },
    {
      "activity": "companyvehicle_car_bev@@au-nsw",
      "values": [
        10000,
        10200,
        10404,
        143055,
        145866,
        148732
      ]
    }
  ],
  "projectedBAUGHG": [
    {
      "activity": "utilities_electricity_grid@@au-nsw",
      "values": [
        340,
        346.8,
        353.7,
        360.8,
        368,
        375.4
      ]
    }
  ],
  "projectedEXTGHG": [
    {
      "activity": "utilities_electricity_grid@@au-nsw",
      "values": [
        340,
        336,
        325,
        313,
        302,
        291
      ]
    }
  ],
  "projectedINTGHG": [
    {
      "activity": "utilities_electricity_grid@@au-nsw",
      "values": [
        340,
        336,
        276,
        245,
        232,
        219
      ]
    }
  ],
  "maccByEndpoint": {
    "2030": [
      {
        "actionid": "useraction_efficiency_2027",
        "actionname": "Office energy efficiency",
        "abatement": 22,
        "marginalCost": 45
      },
      {
        "actionid": "useraction_fleet_ev_2028",
        "actionname": "Switch petrol fleet to EV",
        "abatement": 28,
        "marginalCost": 120
      }
    ],
    "2040": [],
    "2050": []
  }
}

6. Scenario analysis

POST /api/scenarioanalysis reuses the organisation payload and overlays climate-scenario emission-factor narratives (for example NGFS, AASB, Arup, TCFD-inspired sets).

scenarioSet Narrative source slug (e.g. ngfs_climate_scenarios)
selectedOrgUnit Required when the org spans multiple countries
baselineEmissions Baseline pathway context in the response
narrativeSummaries[] Per-narrative GHG pathway sums + years
sections Narrative report text blocks
scenario-request.json JSON
{
  "organisationid": "DEMO_CO",
  "name": "Demo Company",
  "desiredgrowth": 2,
  "projectionstartyear": 2025,
  "projectionendyear": 2050,
  "currency": "aud",
  "electricityapproach": "location",
  "scenarioSet": "ngfs_climate_scenarios",
  "selectedOrgUnit": "orgunit_sydney",
  "activitydataversion": 2,
  "orgunits": {
    "orgunit_sydney": {
      "name": "Sydney Office",
      "orgunitid": "orgunit_sydney",
      "country": "australia",
      "region": "au-nsw",
      "currency": "aud",
      "employees": 120,
      "activitydata": {
        "utilities_electricity_grid@@au-nsw": {
          "activityname": "Grid electricity — NSW",
          "catalogactivityid": "utilities_electricity_grid",
          "region": "au-nsw",
          "activitydatavalue": 500000,
          "activityuom": "kWh",
          "ghgpscope": 2,
          "ghgpscopecategory": "2",
          "emissionfactortrendid": "utilities_electricity_grid",
          "emissionfactorvalue": 0.68,
          "emissionfactorunit": "kgCO2e"
        },
        "companyvehicle_car_petrol@@au-nsw": {
          "activityname": "Fleet — petrol cars",
          "catalogactivityid": "companyvehicle_car_petrol",
          "region": "au-nsw",
          "activitydatavalue": 250000,
          "activityuom": "km",
          "ghgpscope": 1,
          "ghgpscopecategory": "1-2",
          "emissionfactortrendid": "companyvehicle_car_petrol",
          "emissionfactorvalue": 0.192,
          "emissionfactorunit": "kgCO2e"
        }
      },
      "internalactions": {},
      "historicemissionsyears": [
        2023,
        2024
      ],
      "historicemissions": {
        "1": [
          48.2,
          46.1
        ],
        "2": [
          340,
          325.5
        ],
        "3": [
          12,
          11.5
        ]
      }
    }
  }
}
curl — scenario analysis bash
#!/usr/bin/env bash
# Scenario analysis reuses the organisation payload and adds scenarioSet.
# Multi-country orgs should also set selectedOrgUnit to an org-unit key.

curl -sS -X POST \
  "https://app.viablepathway.net/api/scenarioanalysis" \
  -H "Content-Type: application/json" \
  -H "Authorization: ApiKey YOUR_API_KEY" \
  -d @scenario-request.json

7. Try it yourself

Download the samples, set your key in the environment, and call the API from your machine or notebook. We share a Jupyter (Colab-ready) notebook after your key is issued — it is not published here so keys never appear on this site.

Ready to call the live API?

Request an API key and we will send access details plus the Jupyter notebook walkthrough.

Request an API key