The data
Freshness and history
Every value carries two clocks: when the operator says it applies, and when we saw it. They answer different questions, and neither is substituted for the other.
The two clocks
| Field | Whose clock | What it answers |
|---|---|---|
| source_effective_at | The operator's | When the operator says the data applies: a dataset's processing date, a file's modified date, a “situation at end of August” line. null when the operator does not say. |
| retrieved_at | Ours | When we fetched the publication this value came from. |
| last_confirmed_at | Ours | The last time we checked and found it unchanged. A monthly file confirmed yesterday is current as of yesterday. |
We can prove our own clock; we can only report the operator’s. So time-travel queries run on ours, and the operator’s date is always returned beside them.
Source health
API availability and source freshness are separate promises. Each record carries its source’s health in freshness.source_health, and GET /v1/sources/{id}/status has the detail: last attempt, last success, last change, freshness_seconds, the staleness threshold and the last run.
| Health | Meaning |
|---|---|
| healthy | The latest run published or confirmed the data, and it is within its freshness window. |
| stale | The operator has not changed the data for longer than the source's cadence allows, however many successful fetches that took. |
| degraded | The latest run was held by a quality check. The last good data keeps serving. |
| failing | Three or more consecutive runs failed. The last good data keeps serving. |
| disabled | Switched off by an operator of this service, or its rights are blocked. |
| unknown | Never run. |
A failing source keeps serving
Preferring no answer to an old one
fresh_after=2026-09-01T00:00:00Z keeps only records whose data is at least that recent. If nothing qualifies, the answer is 409 source_data_stale with the newest date available in details.newest — so an automated decision never runs on data older than it should.
History (Pro and above)
Every series keeps its past values as intervals of our observation time: [observed_from, observed_to), with observed_to: null for the current one. A value that did not change over three imports is one interval, not three rows.
curl "https://api.gridcapacityapi.com/v1/substations/sub_…/capacity/history?from=2026-01-01&direction=injection" \ -H "Authorization: Bearer gc_live_..."{
"data": [
{
"series_id": "cs_01k5…",
"direction": "injection",
"technology": "generic_generation",
"availability_type": "available",
"firmness": "firm",
"unit": "MW",
"horizon": {
"type": "snapshot",
"year": null,
"label": null
},
"scenario": null,
"season": null,
"variant": null,
"methodology_id": "example_ghc_2026",
"access": {
"status": "granted",
"attribution": "Source: Example DSO"
},
"observations": [
{
"id": "cap_01k3…",
"value": 18,
"value_mw": 18,
"qualifier": null,
"status": null,
"status_label": null,
"observed_from": "2026-03-02T04:10:00Z",
"observed_to": "2026-06-01T04:12:00Z",
"source_effective_at": "2026-02-28T00:00:00Z"
},
{
"id": "cap_01k5…",
"value": 11.5,
"value_mw": 11.5,
"qualifier": null,
"status": null,
"status_label": null,
"observed_from": "2026-06-01T04:12:00Z",
"observed_to": null,
"source_effective_at": "2026-05-31T00:00:00Z"
}
]
}
],
"meta": {
"request_id": "req_…"
}
}Placeholder values; the shape is the contract. A withheld series is listed with its intervals and every value null: you can see that the operator published and when, not what.
as_of (Pro and above)
as_of=2026-06-15T00:00:00Z on the capacity routes answers “what did the latest published data say at that moment”, on our observation clock: the value whose interval contains it. It is how an analysis made in June can be reproduced in December.
The change feed (Pro and above)
GET /v1/changes lists every added, changed, removed and restored series, oldest first. Each change’s id is the cursor: store the last one you processed and ask for since= it next time. Filter by country, operator, source or change_type.
removedmeans the series is absent from the operator’s latest publication; its history stays.- Changes carry the same
accessas records. Where it iswithheld, the values are null: you learn that something moved, not what it moved to.