Skip to main content
Every endpoint in the reference follows the same rules for authentication, errors and lists. They are collected here so the reference pages can stay about what each endpoint actually does.

Authentication

Authentication is session based. You sign in once against /auth/* and the API sets a session cookie that every subsequent request carries.
Sessions are cached for five minutes, so a burst of calls does not hit the database for every request. Sign-in attempts are rate limited to 60 per minute. Besides email and password, the auth layer also supports username sign-in, email one-time codes, and OAuth as a provider. The full set of auth endpoints has its own generated schema:
Because authentication rides on a cookie, a browser client must send requests with credentials included, and its origin must be on the API’s allow list.

Roles and scoping

Users carry one of four roles: admin, merchant, merchant_manager and user. The management endpoints documented here require merchant. A valid session without that role gets 403 FORBIDDEN. Scoping is implicit and worth understanding: the API resolves your organization from your session and filters everything by it. You never pass an organization id, and you cannot read another organization’s stations or sessions by guessing an id. A resource that exists but belongs elsewhere answers as not found.

Errors

Errors always come back in the same shape, with a machine-readable type you can branch on.
Some errors carry an attributes object with extra context. Failed OCPP commands use it to explain what the station said:
Branch on type, never on message. Messages are written for humans and may be reworded; types are part of the contract.

Errors you will meet everywhere

Errors specific to commands

Command endpoints talk to hardware over the network, so they fail in ways a normal CRUD endpoint does not. Handling these three well is most of what makes an integration feel solid.
CHARGING_STATION_OFFLINE. The station has no live OCPP session, so the command cannot be delivered at all. Chargers drop and reconnect routinely, so treat this as a normal condition, not an incident.
CHARGING_STATION_COMMAND_TIMEOUT. The frame was delivered but no reply arrived within the window. The command may still have taken effect on the charger, so prefer reading the resulting state over blindly retrying.
CHARGING_STATION_COMMAND_FAILED. The charger answered with an error. attributes carries its reason, which is usually the fastest way to tell a firmware limitation from a bad request.

Lists, pagination and sorting

Every list endpoint is a POST to /search. It reads as unusual for a read operation, but it keeps rich filters in a JSON body instead of a long and ambiguous query string. Pagination and sorting are the same everywhere:
perPage defaults to 25 and is capped at 150. Filters sit alongside these keys at the top level of the body, not nested under a filters object. The response splits results from metadata, so a table can render its pager without a second call:

Filters by endpoint

Each search accepts its own filters on top of the shared pagination keys: Log search is the richest of them, and excludeEventTypes is the one worth knowing about: stations emit a great deal of Heartbeat and MeterValues traffic, and excluding those is usually the difference between a readable log and a wall of noise.

Dates and units

Timestamps are ISO 8601 strings in UTC, both in and out. The dashboard endpoint accepts utcOffsetMinutes so a client can bucket a time series by local days without shifting the data itself. Energy is expressed in kWh. Stations report meter readings in Wh or kWh depending on the vendor, and the CSMS converts on the way in, so you never have to guess which unit a number is in.

The health endpoint

One endpoint needs no authentication:
It answers as long as the API process is up. It deliberately does not touch the database, so it reports liveness rather than full readiness.