Scopes & modules
The 17 API scopes, what each grants, its module gate, and which are control scopes.
Every API key carries a set of scopes. A scope is only usable when two things are true:
- The token carries the scope, and
- The account has the module that gates it still active.
If the scope is missing you get 403 forbidden_scope; if the module is inactive you get 403 forbidden_module (the message names the missing scope or module — see Errors).
The key-creation screen in the owner platform only offers the scopes your plan includes. A client without the bess module never sees bess:read / bess:write as options; one without earnings never sees earnings:read. So in practice a key can only be minted with scopes your account is entitled to.
Read scopes
| Scope | Grants (endpoint areas) | Module |
|---|---|---|
plant:read | overview, plant/*, locations, loggers, inverters, strings, sensors, gaps — core live telemetry | basic_scada |
weather:read | weather (on-site EMI stations, latest + history) | basic_scada |
diagnostics:read | efficiency/* rankings, string compare, iv/* (panel library, CEC search, expected-vs-measured I-V) | basic_scada |
energy:read | energy/hourly, per-logger hourly-energy | basic_scada |
curtailment:read | curtailment (active + scheduled rows), curtailment/suggest, commands/relay-history | basic_scada |
markets:read | markets, per-market day-ahead prices, markets/compare | basic_scada |
alerts:read | alerts list | basic_scada |
reports:read | reports/* (overview, catalog, runs, subscriptions) | basic_scada |
earnings:read | earnings/* (summary, hourly, market assignments, cross-border prices) | earnings |
predictions:read | predictions/* (production forecast, forecast-vs-actual, price forecast, model status) | ai_predictions |
bess:read | all bess/* telemetry, clusters, PCS, envelope, protection, alarms, dispatch/control logs, schedules | bess |
om:read | work-orders, defects, om/categories, om/notifications | om |
Write scopes
| Scope | Grants | Module | Control? |
|---|---|---|---|
alerts:write | Acknowledge / resolve alerts | basic_scada | — |
reports:write | Create / update / delete / run report subscriptions | basic_scada | — |
om:write | Create/update/approve work orders, checklist items, defects, notification reads | om | — |
curtailment:write | Schedule a curtailment window, curtail immediately, release a group | basic_scada | Yes — commands the plant |
bess:write | Optimize dispatch, approve / reject / approve-all / edit-hour on proposed schedules | bess | Yes — commands the plant |
Control scopes
curtailment:write and bess:write are control scopes — they command physical plant behaviour, not just records. Treat keys that carry them like passwords:
- Grant them only to integrations that genuinely need to act on the plant.
- Prefer a dedicated key per control integration so you can revoke it in isolation.
- Rotate or revoke immediately if a control key is exposed.
Even so, the API is bounded by hard safety rails. Curtailment can only ever reduce output — no call can raise a plant above its grid-connection permit (see Curtailment). BESS writes are dispatch-proposal actions only; raw hardware control (power on/off, breaker, grid-mode, fault-reset, protection/setup) is not exposed by the API (see BESS).
Modules
Each scope maps to a module entitlement on your account. The module must be active for the scope to work, regardless of what the token carries:
| Module | Scopes it gates |
|---|---|
basic_scada | plant:read, weather:read, diagnostics:read, energy:read, curtailment:read, curtailment:write, markets:read, alerts:read, alerts:write, reports:read, reports:write |
earnings | earnings:read |
ai_predictions | predictions:read |
bess | bess:read, bess:write |
om | om:read, om:write |
Grant each integration only the scopes it needs — a monitoring dashboard wants plant:read, energy:read and maybe weather:read, not curtailment:write.

