Skip to content
GridCapacityAPI.com

Using the API

Errors

The error envelope and every error code, with its status and what to do about it.

One shape, everywhere

Every error — including a 404 for a path that does not exist — is JSON in the same envelope, with a status code that means what it says.

{
  "error": {
    "code": "plan_required",
    "message": "'history' requires the pro plan or above.",
    "request_id": "req_…",
    "details": {
      "capability": "history",
      "required_plan": "pro"
    }
  }
}
  • Branch on code. Codes never change; messages may be reworded.
  • Plan refusals name details.required_plan, the cheapest plan that would have answered, and details.capability, so a client can show the right upgrade prompt without a second request.
  • Codes with more to say carry details: the comparability classes found, the newest data available.
  • Quote request_id when you write to us: it finds the request in our logs.

No route fetches from an operator at request time: every answer is served from stored data, so a request here cannot fail because an operator’s website is down. When a source fails to import, its last published data keeps serving and its health says so; source_not_available is only for a source that has never published or has been switched off.

Request

Request errors
CodeStatusWhenWhat to do
invalid_parameter400A parameter is malformed, out of range, not accepted by the route, a sort key not on its allow-list, or a limit above your plan's page size.The message names the parameter and what was expected. Fix the request; retrying it unchanged fails the same way.
invalid_cursor400The cursor is not one the API issued, or was issued for a different query.Start again without a cursor. The API refuses rather than silently restarting at page one.
route_not_found404No endpoint exists at this path. The answer is still JSON in the error envelope.Check the path against /v1/openapi.json.

Key and plan

Key and plan errors
CodeStatusWhenWhat to do
unauthorized401The key is missing, malformed or revoked, on a route that needs one.Send Authorization: Bearer with a live or test key from the dashboard.
plan_required403The route or parameter needs something your plan does not include: history, the change feed, as_of, exports, webhooks, or a value above the plan's limit such as a nearby radius.details.capability names what was missing and details.required_plan the cheapest plan that would answer. Upgrade, or drop the parameter.

Data

Data errors
CodeStatusWhenWhat to do
country_not_supported404The country code is valid but the API has nothing registered for it.GET /v1/coverage lists what is covered.
operator_not_supported404The operator is known, but none of its publications is registered.See its page for what it publishes; GET /v1/operators?covered=true lists covered operators.
operator_not_found404No operator has this id or slug.GET /v1/operators lists them.
asset_not_found404No asset has this id. A merged asset's id keeps resolving, so this means it never existed.Search with GET /v1/substations.
source_not_found404No source has this id.GET /v1/sources lists them.
capacity_not_available404The asset (or postcode) exists, but no capacity record is published for it.Nothing to retry: the operator publishes no figure there. /v1/substations?has_capacity=true lists assets that have one.
source_not_available409The source you named is disabled, registry-only, or has never published.GET /v1/sources/{id}/status says which. Last published data, where there is any, keeps serving.
source_data_stale409Nothing satisfies fresh_after. details.newest is the newest data available.Loosen fresh_after, or treat it as the answer you asked for: no data rather than old data.
capacity_semantics_not_comparable422comparability=strict and the matching records span more than one comparability class. details.classes lists them.Narrow the query to one class (by source, country or methodology), or use best_effort and read meta.warnings.
source_rights_restricted451The request names only sources whose rights do not permit serving values.Their records are still listed in queries that include other sources, with the value withheld and a link to the operator.

Limits

Limits errors
CodeStatusWhenWhat to do
rate_limit_exceeded429Too many requests per second for your plan.Wait Retry-After seconds. Page with cursors one page at a time rather than in parallel.
quota_exceeded429This month's request quota is used up.Retry-After points at the start of the next UTC month. RateLimit-Remaining shows it coming.

Exports and webhooks

Exports and webhooks errors
CodeStatusWhenWhat to do
export_limit_exceeded429The account already has three exports queued or running.Wait for one to finish (GET /v1/exports/{id}), then create the next. details.limit is the ceiling.
download_limit_exceeded429Every export download slot on the service is in use.Retry after the seconds in Retry-After. The file is still there.
export_not_ready409The export is queued, running or failed, so there is no file to download.Poll GET /v1/exports/{id} until status is succeeded. details.status says where it is.
export_expired410The export's file has expired and was deleted: seven days after it was built, or earlier when the rights of a source changed after it was created.Create the export again.
export_not_found404No export of yours has this id.GET /v1/exports lists yours.
webhook_not_found404No webhook endpoint of yours has this id.GET /v1/webhooks lists yours.

Server

Server errors
CodeStatusWhenWhat to do
internal_error500Something failed on our side. The detail is logged, not sent.Retry with backoff. If it persists, send us the request_id.