Introduction
API guide
  • AuthenticationSoon
  • Your first API callSoon
  • Interactive API referenceSoon
  • Roles and permissionsSoon
  • Errors, pagination and versioningSoon
  • Live updatesSoon
  • Sending commands to a chargerSoon
  • Rate limitsSoon
Troubleshooting
  • My charger will not connectSoon
  • It connects, then dropsSoon
  • A command timed out or returned 409Soon
  • A card is not being authorizedSoon
  • My transaction looks wrongSoon
  • Meter values are missing or sparseSoon
  • Reading the OCPP message logSoon
  • Known limitationsSoon
Reference
  • GlossarySoon
  • Endpoint indexSoon
  • OCPP message supportSoon
  • Status and error codesSoon
  • ChangelogSoon
Flowion Docs

Keep a site within its electrical limits

A site has one grid connection with a fixed rating. Ten 22 kW chargers behind a 63 A supply cannot all run flat out — the physics does not care how many drivers turned up. Something has to decide, continuously, how to divide what is available.

This is the part of a CSMS with no OCPP equivalent. The protocol gives you a way to tell a station what it may draw; deciding what to tell it is entirely the CSMS's problem, and it needs a model of the wiring that OCPP never supplies.

Model the wiring first#

A site is a physical location. Within it, circuits form a tree that mirrors the actual electrical installation:

Site "Depot A"
 └─ Circuit "Main"        3-phase, 250 A     ← the grid connection
     ├─ Circuit "Row 1"   3-phase, 125 A
     └─ Circuit "Row 2"   3-phase, 125 A

A circuit with no parent is a Main circuit — the connection to the grid. Main is only legal at the top of a site's tree.

curl -X POST https://api.flowion.io/v1/sites/$SITE/circuits \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Row 1", "phase_count": 3, "rated_current_amps": 125,
       "parent_circuit_id": "'"$MAIN"'"}'

Each circuit records a phase count (1 or 3) and a rated current in amps. Voltage is a fixed 230 V per phase. A single-phase circuit must also name which line it is wired to — L1, L2 or L3.

That last requirement is not bureaucracy. Three single-phase chargers all on L1 overload that line while the site's total draw looks comfortable. An aggregate watt figure hides exactly this failure, so single-phase circuits are checked per line.

The tree cannot lie#

Two invariants are enforced when you write, not when you read:

  1. A child's lines must be a subset of its parent's. A single-phase parent can only host single-phase children on the same line.
  2. Children's rated current, summed per line, must not exceed the parent's rating on that line.

A write that would break either is rejected. The consequence is useful: a circuit tree that oversubscribes its own wiring cannot be persisted. If the API refuses your tree, the installation you described is not buildable.

Attach EVSEs, not chargers#

Circuit membership is per-EVSE. A charger with two EVSEs can have them on different circuits, because they draw independently.

This is also why getting the EVSE/connector distinction right at commissioning matters. A station that reports two EVSEs where it physically has one shared power module will be modelled as able to draw twice what it can. See The vocabulary.

Static limits#

A charging limit is a ceiling installed against a scope:

curl -X POST https://api.flowion.io/v1/chargers/$CHARGER/charging-limits \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"scope": {"type": "station_limit"},
       "priority": 10,
       "recurrence": "daily",
       "schedule": {"unit": "amps",
                    "periods": [{"start_offset_seconds": 0, "limit": 16}]}}'

Scopes:

  • station_limit — a hard ceiling on the whole charger's total draw across every connector.
  • default_policy — the policy applied to new sessions, for one connector or all of them.

A schedule is a series of periods, each with a start offset and a limit, in amps or watts. recurrence is once, daily, weekly or per_session; priority decides which limit wins when several apply to the same scope at once, and starts_at/ends_at bound when a limit is eligible at all.

List and remove them:

curl https://api.flowion.io/v1/chargers/$CHARGER/charging-limits \
  -H "Authorization: Bearer $TOKEN"
curl -X DELETE https://api.flowion.io/v1/chargers/$CHARGER/charging-limits/$ID \
  -H "Authorization: Bearer $TOKEN"

To ask a station what it believes is currently in force — as opposed to what you installed — use the live command:

curl -X POST https://api.flowion.io/v1/chargers/$CHARGER/commands/get-effective-limit \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'

Worth doing when behaviour disagrees with configuration: the station's own view is the one that governs what it actually draws.

Capping a single session#

Two different ceilings, easily confused:

  • A charging limit caps the rate — how much current or power.
  • A transaction limit caps the total — energy, time, or state of charge.

Both can be set when starting a session remotely, and a transaction limit can be changed mid-session. See Start and stop sessions remotely.

Dynamic balancing#

Static limits divide capacity in advance. They are safe, and they are wasteful: a 63 A supply split four ways gives every charger 16 A whether three of them are idle or not.

Dynamic balancing re-divides continuously against real demand — inferring what each session actually wants, sharing available capacity between active sessions, and reclaiming it as cars finish. The optimizer that does this runs continuously and actuates through the same charging-profile mechanism as static limits.

Two properties worth designing around:

Scale-up and scale-down are not symmetric. Reducing a charger's allowance must take effect before the capacity is given away elsewhere; increasing it can be optimistic. A balancer that treats both the same will briefly oversubscribe the circuit.

A limit is a ceiling, not a setpoint. Telling a session it may draw 16 A does not make it draw 16 A. Cars taper as their batteries fill, and a car drawing 6 A of its 16 A allowance is leaving 10 A that a naive allocator will never notice is free.

Price-optimized allocation — shifting load toward cheap hours using day-ahead prices — is designed but not built. See OCPP feature coverage.

What to check when a site trips#

  1. Does the circuit tree match the installation? A tree that models something other than the real wiring will balance against fiction.
  2. Are single-phase chargers spread across lines? Three on L1 is a line overload the totals will not show.
  3. Are all EVSEs attached to a circuit? An unattached EVSE is invisible to any allocator.
  4. Does the station agree? Compare get-effective-limit against what you installed.

Endpoints#

Sites & Circuits · Charging Limits · Commands