Your first API call
This walks one credential down the resource hierarchy — organization,
environment, charger, EVSE, connector — with nothing but curl. If you
would rather have a charger to point at first, do
Set up your workspace and come back.
export API=https://api.flowion.io/v1
0. Two credentials, two jobs#
The first few steps below — discovering which organization and environment you are working in — need a signed-in human's JWT, because listing organizations and environments are organization-wide questions an API key cannot answer (see Authentication). Get one the way Set up your workspace describes and put it here:
export TOKEN="..."
Once you know which environment you are working in, you will mint an API key scoped to it — the credential your own backend should actually hold going forward, rather than a browser session's token.
1. Who am I, and what can I see?#
curl -s "$API/organizations" \
-H "Authorization: Bearer $TOKEN" | jq
{
"data": [
{
"id": "b3f5...",
"name": "Acme Charging",
"slug": "acme",
"viewer_role": "owner",
"created_at": "2026-01-14T09:00:00Z",
"updated_at": "2026-01-14T09:00:00Z"
}
],
"page": 1,
"per_page": 20,
"total": 1
}
This is a page of the organizations you belong to, not every organization
on the platform. viewer_role is your own role in each one, resolved from
real membership — never something you can pass in. Note the envelope:
data, page, per_page, total. Every list endpoint in this API
returns exactly this shape; see
Errors, pagination and versioning.
2. Pick an environment#
export ORG=b3f5...
curl -s "$API/organizations/$ORG/environments" \
-H "Authorization: Bearer $TOKEN" | jq
Every organization has at least prod, created for you when the
organization was. Grab its id:
export ENV=...
3. Mint a key for it#
Everything from here on is environment-scoped, which is exactly what an API key is for. Minting one requires Owner or Admin — the token you have been using so far, if you set the workspace up yourself:
curl -X POST "$API/environments/$ENV/api-keys" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "first api call", "role": "user"}' | jq
The response carries key, once — save it, then switch to it for
everything below:
export TOKEN=flw_live_...
role: "user" is deliberate here: this key only needs to read chargers,
not manage the organization, so it gets the narrowest role that can do
that. See Authentication for the full shape
of this response and why key cannot be fetched again.
4. List the chargers in it#
curl -s "$API/environments/$ENV/charging-stations" \
-H "Authorization: Bearer $TOKEN" | jq
charge_point_id is the identity you gave the station when you
provisioned it — the same string it authenticates with on the OCPP
connection. Grab one station's id (a UUID, distinct from
charge_point_id):
export CHARGER=...
5. Its EVSEs#
curl -s "$API/charging-stations/$CHARGER/evses" \
-H "Authorization: Bearer $TOKEN" | jq
An EVSE is one socket a vehicle can plug into. A single-connector station has exactly one.
6. Down to a connector#
export EVSE=...
curl -s "$API/evses/$EVSE/connectors" \
-H "Authorization: Bearer $TOKEN" | jq
That is the whole hierarchy this API is scoped by — one human token to discover where you are, one API key, scoped to what you found, for everything after. Core concepts covers why the hierarchy is shaped this way; Roles and permissions covers what happens the moment one of these calls is made by a credential that does not have access to something in the chain.
Every response is JSON, every request should be too#
Content-Type: application/json on any request carrying a body, and every
error is JSON too — there is no endpoint that answers a bare 500 or an
HTML error page. See Errors, pagination and versioning
for the shape.
Next: Roles and permissions, or jump straight to Sending commands to a charger if you have a station connected and want to act on it.