Features
Postcode lookup
Some operators publish capacity per supply area and define the areas by postcode rather than by geometry. The lookup answers the question a project starts with: which areas serve this address, and what do their operators report?
The lookup
curl "https://api.gridcapacityapi.com/v1/postcodes/NL/1234AB" \ -H "Authorization: Bearer gc_live_..."The answer lists every area an operator’s publication says serves the postcode, each with the source that says so and the area’s current capacity records, in the same shape as everywhere else. A postcode can be served by more than one area — a transmission operator’s area and a regional operator’s, for example — and each comes back with its own records.
{
"data": {
"country": "NL",
"postcode": "1234AB",
"areas": [
{
"asset": {
"id": "zone_01k5…",
"type": "congestion_zone",
"name": "Example supply area",
"slug": "example-supply-area",
"country": "NL",
"operator": {
"id": "op_…",
"slug": "example-dso",
"name": "Example DSO",
"type": "DSO"
},
"network_level": "mv",
"voltage_kv": null,
"location": null
},
"source_id": "nl_example_postcodes",
"capacity": [
{
"id": "cap_01k5wxyz…",
"series_id": "cs_01k5…",
"asset": {
"id": "zone_01k5…",
"type": "congestion_zone",
"name": "Example supply area",
"slug": "example-supply-area",
"country": "NL",
"operator": {
"id": "op_…",
"slug": "example-dso",
"name": "Example DSO",
"type": "DSO"
},
"network_level": "mv",
"voltage_kv": null,
"location": null
},
"direction": "offtake",
"technology": "generic_load",
"capacity": {
"type": "available",
"value": null,
"unit": "status",
"value_mw": null,
"qualifier": null,
"status": "waitlist",
"status_label": "Example operator label"
},
"firmness": "unknown",
"curtailment": null,
"horizon": {
"type": "snapshot",
"year": null,
"label": null
},
"scenario": null,
"season": null,
"variant": null,
"details": {},
"methodology": {
"id": "example_ghc_2026",
"title": "Example hosting-capacity method, 2026 edition",
"capacity_basis": "operator_calculated",
"network_state": "n_minus_1",
"binding": false,
"non_additive": true,
"includes_reserved": true,
"includes_allocated": null,
"includes_pre_reserved": true,
"includes_pending_requests": null,
"comparability_class": "example_ghc"
},
"freshness": {
"source_effective_at": "2026-09-01T00:00:00Z",
"retrieved_at": "2026-09-25T04:12:51Z",
"last_confirmed_at": "2026-09-25T04:12:51Z",
"source_health": "healthy"
},
"provenance": {
"source_id": "xx_example_hosting_capacity",
"source_record_id": "12345",
"source_url": "https://operator.example/hosting-capacity",
"payload_sha256": "9f86d081884c7d65…",
"license": "CC BY 4.0",
"rights_mode": "commercial_use_with_attribution"
},
"access": {
"status": "granted",
"attribution": "Source: Example TSO"
},
"decision_context": {
"binding": false,
"formal_connection_study_required": true,
"source_indicative": true,
"statement": "The operator's latest published dataset reports … under methodology …."
}
}
]
}
]
},
"meta": {
"request_id": "req_…"
}
}Placeholder values; the shape is the contract.
Postcodes
- The country is the ISO code in the path. The Netherlands is the country whose operators publish this mapping today; coverage says what the API holds.
- Dutch areas are defined per six-character postcode (PC6), such as
1234AB. Spaces and case do not matter; a four-digit PC4 is not an area key, so pass the full postcode. - A postcode no published area serves answers
404 capacity_not_available. A country with nothing registered answers404 country_not_supported.
Reading the answer
| Field | Meaning |
|---|---|
| areas[].asset | The area, as an asset: usually type congestion_zone or area, with location null when the operator publishes none. |
| areas[].source_id | The publication that maps this postcode to this area. |
| areas[].capacity | The area's current capacity records, with their methodology, freshness, provenance and access, exactly as the search returns them. |
Which area serves a postcode is part of what an operator publishes, under the same licence as its figures. So a mapping is answered only from a source whose rights permit it; a mapping from any other source is left out and counted in meta.warnings (withheld_mappings), and a postcode that only such sources map answers 451 source_rights_restricted, naming them.
Colours are statuses, not numbers
status: capacity.status is normalised and status_label carries the operator’s own words. The Dutch operators say the colour, not arithmetic on the transport-capacity figures beside it, decides whether capacity can be allocated, so the API never subtracts one figure from another to produce a headroom they did not publish.Many postcodes
One request per postcode, within your plan’s rate limit. For a portfolio, walk the list sequentially and cache the answers: the underlying mapping changes when the operators republish, usually monthly.
import os, time, requests
KEY = os.environ["GRID_API_KEY"]
for pc in ["1234AB", "5678CD"]:
r = requests.get(f"https://api.gridcapacityapi.com/v1/postcodes/NL/{pc}",
headers={"Authorization": f"Bearer {KEY}"}, timeout=15)
if r.status_code == 404:
print(pc, r.json()["error"]["code"]); continue
r.raise_for_status()
for area in r.json()["data"]["areas"]:
for rec in area["capacity"]:
print(pc, area["asset"]["name"], rec["direction"], rec["capacity"]["type"],
rec["capacity"]["value"], rec["capacity"]["unit"], rec["capacity"]["status_label"])
time.sleep(1) # the Free plan allows one request a second; raise it with yours