Quickstart

Run a whole charging session from the API with no hardware: start a virtual charger, plug in a car, start charging and read the energy back.

On this page

Run a complete charging session from your terminal, with no hardware and no site visit. You will start a virtual charger in your project's sandbox, plug a car into it, start charging with one API call and read the session back as it fills up.

Before you start

You need two things from the console:

  1. An organization. Sign in and create one. It comes with a project called prod, and you become its Owner.

  2. A sandbox API key. Switch the console to sandbox and create an API key that holds the Admin policy. Sandbox keys start with flw_ak_test_. Copy the secret now: it is shown once.

Then set up your shell:

bash
export API=https://api.flowion.io/v1
export TOKEN=flw_ak_test_...

Everything in sandbox mode stays there. Nothing you do on this page reaches a live charger or a real invoice.

1. Find your project

Look up your organization by the slug you gave it, then list its projects:

GET/v1/organizations/by-slug/acmebash
curl "$API/organizations/by-slug/acme" \
  -H "Authorization: Bearer $TOKEN"

Save the id as $ORG, then:

GET/v1/organizations/$ORG/projectsbash
curl "$API/organizations/$ORG/projects" \
  -H "Authorization: Bearer $TOKEN"

Save the id of the project with "isDefault": true as $PROJECT.

2. Start a virtual charger

Virtual chargers come from a catalogue of charger and car models:

GET/v1/projects/$PROJECT/virtual-chargers/catalogbash
curl "$API/projects/$PROJECT/virtual-chargers/catalog" \
  -H "Authorization: Bearer $TOKEN"

Start a 22 kW three-phase AC charger:

POST/v1/projects/$PROJECT/virtual-chargersbash
curl -X POST "$API/projects/$PROJECT/virtual-chargers" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"chargerModelId": "ac-22-3p"}'
200Response
{
  "id": "4f0c2a9e-7b1d-4e8a-9c3f-2d6b8a1e5c70",
  "chargingStationId": "b2c4a8e0-1f3d-4c5b-9e7a-8d6f0b2c4a8e",
  "chargerModelId": "ac-22-3p",
  "name": "Virtual AC 22 kW",
  "state": "running",
  "connectors": [{"connectorId": 1, "status": "Available"}],
  "idleExpiresAt": "2026-10-01T10:00:00Z"
}

Save id as $VC: it is how you act at the charger, as a driver would. Save chargingStationId as $CHARGER: it is the charger itself, the same record a physical charger has, and what the rest of the API works with.

3. Plug in a car

Park a 77 kWh car at outlet 1, with its battery at 20%:

POST/v1/virtual-chargers/$VC/connectors/1/plug-inbash
curl -X POST \
  "$API/virtual-chargers/$VC/connectors/1/plug-in" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"vehicleModelId": "long-range-77",
       "startSocPercent": 20}'

4. Start charging from the API

This is the same call you would make to a real charger from your own app:

POST/v1/charging-stations/$CHARGER/commandsbash
curl -X POST "$API/charging-stations/$CHARGER/commands" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"type": "remoteStartTransaction", "connectorId": 1}'
200Response
{
  "id": "7d3e9b20-5a1c-4f6e-8b2d-0c9a4e7f1b36",
  "commandType": "remoteStartTransaction",
  "chargingStationId": "b2c4a8e0-1f3d-4c5b-9e7a-8d6f0b2c4a8e",
  "status": "sent",
  "createdAt": "2026-10-01T09:01:00Z"
}

The command is on its way. Read it back with GET /charging-stations/$CHARGER/commands/{id} until status is accepted, which means the charger agreed to start.

5. Watch the session

GET/v1/charging-stations/$CHARGER/transactions?status=openbash
curl "$API/charging-stations/$CHARGER/transactions?status=open" \
  -H "Authorization: Bearer $TOKEN"
200Response
{
  "data": [
    {
      "id": "c81f4d2a-3b6e-4a9c-8e1d-5f7b2a0c9e43",
      "evseId": 1,
      "connectorNumber": 1,
      "chargingState": "Charging",
      "startedAt": "2026-10-01T09:01:04Z",
      "endedAt": null,
      "energyWh": 1250
    }
  ],
  "nextCursor": null
}

energyWh appears once the charger has sent at least two meter readings, so give it a minute and ask again. To see the car's side of things, the battery level and the power it is drawing right now:

GET/v1/virtual-chargers/$VC/endbash
curl "$API/virtual-chargers/$VC/end" \
  -H "Authorization: Bearer $TOKEN"

6. Stop charging

End the session at the charger, as a driver would:

POST/v1/virtual-chargers/$VC/connectors/1/stop-transactionbash
curl -X POST \
  "$API/virtual-chargers/$VC/connectors/1/stop-transaction" \
  -H "Authorization: Bearer $TOKEN"

List the charger's transactions again without ?status=open: the session now has an endedAt and a stoppedReason.

That is the whole loop: a charger comes online, a car plugs in, your app starts the charge, and the energy is recorded.

If a step fails

  • 409 notSandboxMode. Your key is a live key. Virtual chargers live in sandbox, so use a key that starts with flw_ak_test_.

  • 409 chargerNotRunning. The virtual charger has switched itself off after an hour without activity. Switch it back on with POST /virtual-chargers/$VC/start.

  • 409 when starting a virtual charger. The project already has ten switched on, or the organization is at its sandbox limit. Switch one off or delete one.

  • 404 on something you just created. Check the id, and that the key belongs to the same organization.

Next