Sites & Circuits
Physical locations (Sites) within an environment and the circuit wiring tree (Circuits) connecting their charging stations — see docs/architecture/tenancy.md.
10 endpoints
Fetches a single circuit by id.
get/v1/circuits/{circuit_id}Requires a bearer token
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| circuit_id* | path | string<uuid> | Circuit id |
Responses
| Status | Body | Description |
|---|---|---|
| 200 | CircuitSummary | The circuit |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 404 | ErrorBody | No circuit with this id exists, or the caller cannot access it |
Re-parents a circuit. Requires the caller to be an Owner or Admin.
patch/v1/circuits/{circuit_id}Requires a bearer token
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| circuit_id* | path | string<uuid> | Circuit id |
Request bodySetCircuitParentRequest
| Field | Type | Description |
|---|---|---|
| parent_circuit_id | string | null<uuid> | — |
Responses
| Status | Body | Description |
|---|---|---|
| 200 | CircuitSummary | The updated circuit |
| 400 | ErrorBody | parent_circuit_id equal to the circuit's own id |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 403 | ErrorBody | The caller is a member but not an Owner or Admin |
| 404 | ErrorBody | No circuit with this id exists, the caller cannot access it, or parent_circuit_id does not exist on this site |
| 409 | ErrorBody | This circuit's rated current would exceed its new parent's remaining capacity, or the new parent is a descendant of this circuit |
| 422 | ErrorBody | This circuit's line is not a subset of its new parent's |
Deletes a circuit. Requires the caller to be an Owner or Admin.
delete/v1/circuits/{circuit_id}Requires a bearer token
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| circuit_id* | path | string<uuid> | Circuit id |
Responses
| Status | Body | Description |
|---|---|---|
| 204 | — | The circuit was deleted |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 403 | ErrorBody | The caller is a member but not an Owner or Admin |
| 404 | ErrorBody | No circuit with this id exists, or the caller cannot access it |
| 409 | ErrorBody | This is the only circuit remaining on its site |
Fetches a circuit's live per-line voltage/amperage and per-connector demand.
get/v1/circuits/{circuit_id}/statsRequires a bearer token
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| circuit_id* | path | string<uuid> | Circuit id |
Responses
| Status | Body | Description |
|---|---|---|
| 200 | CircuitStatsResponse | The circuit's live stats |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 404 | ErrorBody | No circuit with this id exists, or the caller cannot access it |
Lists an environment's sites, paginated. Pass `q` to restrict the page (and `total`) to sites whose `name` case-insensitively contains it.
get/v1/environments/{environment_id}/sitesRequires a bearer token
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| environment_id* | path | string<uuid> | Environment id |
| page | query | integer<int32> | 1-indexed page number. Defaults to 1. |
| per_page | query | integer<int32> | Sites per page, capped at 100. Defaults to 20. |
| q | query | string | Free-text filter over name, matched case-insensitively as a
substring — q=north matches a site named North Depot. Composes
with pagination (page/per_page/total describe the filtered
set). Omitted, empty, or whitespace-only behaves as no filter at
all, same as before this parameter existed. |
Responses
| Status | Body | Description |
|---|---|---|
| 200 | ListSitesResponse | A page of the environment's sites |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 404 | ErrorBody | No environment with this id exists, or the caller cannot access it |
Creates a site in the environment. Requires the caller to be an Owner or Admin.
post/v1/environments/{environment_id}/sitesRequires a bearer token
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| environment_id* | path | string<uuid> | Environment id |
Request bodyCreateSiteRequest
| Field | Type | Description |
|---|---|---|
| main_circuit_rated_current_amps* | integer<int32> | The rating of the Site's Main circuit, created atomically alongside it — every Site has a capacity tree from the moment it exists (see docs/architecture/tenancy.md), and there is currently no way to re-rate a circuit after creation, so this is the only chance to set it. |
| name* | string | — |
Responses
| Status | Body | Description |
|---|---|---|
| 201 | SiteSummary | The newly created site |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 403 | ErrorBody | The caller is a member but not an Owner or Admin |
| 404 | ErrorBody | No environment with this id exists, or the caller cannot access it |
Fetches a single site by id.
get/v1/sites/{site_id}Requires a bearer token
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| site_id* | path | string<uuid> | Site id |
Responses
| Status | Body | Description |
|---|---|---|
| 200 | SiteSummary | The site |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 404 | ErrorBody | No site with this id exists, or the caller cannot access it |
Updates a site's settings — `name`, `price_zone` and/or `time_zone`.
patch/v1/sites/{site_id}Requires a bearer token
Requires the caller to be an Owner or Admin of the site's organization,
the same "settings action" bucket as
environments::update::update_environment.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| site_id* | path | string<uuid> | Site id |
Request bodyUpdateSiteRequest
| Field | Type | Description |
|---|---|---|
| name | string | null | New name for the site. Omit the field entirely to leave it
unchanged; an explicit null is rejected rather than silently
ignored — a site name may not be cleared (there is no "unset"
state, unlike price_zone/time_zone). |
| price_zone | string | null | Which ENTSO-E bidding zone (EIC code) this site's charging_stations should
be priced against. Send null to clear it; omit the field
entirely to leave it unchanged. Validated against
energy::KNOWN_BIDDING_ZONES (see ADR-0021) — an EIC code
this platform doesn't collect prices for is rejected rather than
stored and silently yielding an empty forecast forever. |
| time_zone | string | null | The IANA time zone (e.g. Europe/Stockholm) an operator reads this
site's timestamps in. Send null to clear it; omit the field
entirely to leave it unchanged. Validated against the IANA
database — a bad value here would reach apps/web's date
formatting and throw, so it is rejected here instead. |
Responses
| Status | Body | Description |
|---|---|---|
| 200 | SiteSummary | The updated site |
| 400 | ErrorBody | The name is empty, too long, or explicitly null, the time zone is not an IANA name, or the price zone is not one of energy_core::KNOWN_BIDDING_ZONES (unknown_bidding_zone) |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 403 | ErrorBody | The caller is a member but not an Owner or Admin |
| 404 | ErrorBody | No site with this id exists, or the caller cannot access it |
Lists a site's circuits, unpaginated.
get/v1/sites/{site_id}/circuitsRequires a bearer token
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| site_id* | path | string<uuid> | Site id |
Responses
| Status | Body | Description |
|---|---|---|
| 200 | ListCircuitsResponse | The site's circuits |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 404 | ErrorBody | No site with this id exists, or the caller cannot access it |
Creates a circuit on the site. Requires the caller to be an Owner or Admin.
post/v1/sites/{site_id}/circuitsRequires a bearer token
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| site_id* | path | string<uuid> | Site id |
Request bodyCreateCircuitRequest
| Field | Type | Description |
|---|---|---|
| line | string | null | Required (Some) iff phase_count is 1; must be None for 3. |
| name* | string | — |
| parent_circuit_id | string | null<uuid> | — |
| phase_count* | integer<int32> | 1 or 3. |
| rated_current_amps* | integer<int32> | — |
Responses
| Status | Body | Description |
|---|---|---|
| 201 | CircuitSummary | The newly created circuit |
| 400 | ErrorBody | Invalid phase_count/line combination, or parent_circuit_id equal to the circuit's own id |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 403 | ErrorBody | The caller is a member but not an Owner or Admin |
| 404 | ErrorBody | No site with this id exists, the caller cannot access it, or parent_circuit_id does not exist on this site |
| 409 | ErrorBody | This circuit's rated current would exceed its parent's remaining capacity |
| 422 | ErrorBody | This circuit's line is not a subset of its parent's |