Try a virtual charger

Start a charger in your sandbox in one call, then play the driver and the car: plug in, charge, pause, fault the outlet or cut the connection.

4 min readEdit this page
On this page

A virtual charger is a charger that Flowion runs for you inside your project's sandbox. It connects, reports its outlets, answers commands and records sessions exactly like a physical charger, and it appears in the API and the console as an ordinary charger. Whatever you build against it works against real hardware.

You also get the other side of the cable: you can play the driver and the car, and stage the situations that are hard to produce on demand, such as a faulted outlet or a charger that loses its connection mid-session.

Before you start

Virtual chargers live in sandbox mode. Use the console switched to sandbox, or an API key created in sandbox mode (it starts with flw_ak_test_). Using them needs the virtual_charger.charger.manage permission, which the User policy includes in sandbox mode, so nobody needs the Admin policy.

The examples use $PROJECT for your project id and $VC for a virtual charger's id. The Quickstart shows where both come from.

Pick a charger and a car

Both come from a fixed catalogue:

GET/v1/projects/$PROJECT/virtual-chargers/catalogbash
curl "$API/projects/$PROJECT/virtual-chargers/catalog" \
  -H "Authorization: Bearer $TOKEN"
ChargerchargerModelId
AC 7.4 kW, single-phaseac-7-4-1p
AC 22 kW, three-phaseac-22-3p
DC 50 kWdc-50
DC 150 kWdc-150
DC 350 kW, two outletsdc-350-dual
CarvehicleModelId
Compact 40 kWhcompact-ac-40
Long Range 77 kWhlong-range-77
Big Pack 100 kWhbig-pack-100
Cargo Van 90 kWhvan-90

The cars behave like cars. Each has a battery size, a limit on how much AC power it takes on board and a charging curve, so a car can take less than the charger offers, and it slows down as its battery fills.

Start a 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": "dc-350-dual", "name": "Bay 4"}'
200Response
{
  "id": "4f0c2a9e-7b1d-4e8a-9c3f-2d6b8a1e5c70",
  "chargingStationId": "b2c4a8e0-1f3d-4c5b-9e7a-8d6f0b2c4a8e",
  "chargerModelId": "dc-350-dual",
  "name": "Bay 4",
  "state": "running",
  "connectors": [
    {"connectorId": 1, "status": "Available"},
    {"connectorId": 2, "status": "Available"}
  ],
  "idleExpiresAt": "2026-10-01T10:00:00Z"
}

name is optional; leave it out and the charger is named after its model. id is the virtual charger, used for everything you do at it on this page. chargingStationId is the charger record every other part of the API uses: sessions, commands, settings, webhooks and live updates all work with it unchanged.

A project can have up to ten virtual chargers switched on at once. A charger with no session and nobody using it switches itself off after an hour; idleExpiresAt says when. List them with GET /projects/$PROJECT/virtual-chargers.

Plug in a car

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": "big-pack-100",
       "startSocPercent": 15, "targetSocPercent": 80}'

startSocPercent is the battery level the car arrives with. targetSocPercent is optional: the car stops drawing power when it gets there, and the outlet reports SuspendedEV while the session stays open. Without it, the car charges to 100%.

Start a session

There are two ways, the same two a real charger has.

From your app. Send a remote start to the charger, as in the Quickstart. If no car is plugged in yet, the outlet waits for one: plug in within the wait and the session starts.

At the charger, with a card. Present a card's value directly, or the id of a card enrolled in the project:

POST/v1/virtual-chargers/$VC/connectors/1/start-transactionbash
curl -X POST \
  "$API/virtual-chargers/$VC/connectors/1/start-transaction" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"idToken": "04A2B3C4D5E6F7"}'

Send exactly one of idToken and idTokenId. The card is checked like a card at any real charger, so it has to be allowed to charge there: see Let drivers charge with RFID cards. A card the platform refuses answers 502.

Drive the car

ToCall
End the session at the chargerPOST /virtual-chargers/$VC/connectors/1/stop-transaction
Pause the car mid-sessionPOST /virtual-chargers/$VC/connectors/1/pause
Let it draw power againPOST /virtual-chargers/$VC/connectors/1/resume
Unplug the carPOST /virtual-chargers/$VC/connectors/1/unplug

Unplugging needs the session to be over first; end it, then unplug.

Stage a problem

Fault an outlet. Name the error the outlet reports, and clear it when you are done:

POST/v1/virtual-chargers/$VC/connectors/1/faultbash
curl -X POST "$API/virtual-chargers/$VC/connectors/1/fault" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"errorCode": "GroundFailure"}'

POST /virtual-chargers/$VC/connectors/1/clear-fault clears it.

Cut the connection. The charger keeps working while it is offline, the way real hardware does: sessions it starts or ends and the meter readings it takes are queued, then delivered in order when it reconnects.

POST/v1/virtual-chargers/$VC/drop-connectionbash
curl -X POST "$API/virtual-chargers/$VC/drop-connection" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"comeback": {"afterSeconds": 120}}'

comeback is "now", "onCommand" (it stays offline until you call POST /virtual-chargers/$VC/reconnect) or {"afterSeconds": n}, from 1 to 3600 seconds.

Reboot it. POST /virtual-chargers/$VC/reboot closes the connection, ends any open session with the reason Reboot, and brings the charger back as if it had just been powered up.

Ignore power limits. Some chargers accept a power limit and then keep drawing more. Recreate one to see how your setup copes:

PUT/v1/virtual-chargers/$VC/ignore-limitsbash
curl -X PUT "$API/virtual-chargers/$VC/ignore-limits" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ignore": true}'

See what is happening at the charger

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

This is the charger's own view: whether it is connected, how many messages it has queued while offline, and for each outlet the car plugged in, its battery level, the power it is taking right now, and any fault or pause. While an outlet waits for a car after a remote start, waitingForCarUntil says until when.

Everything you do at a virtual charger is also listed in the charger's activity in the console, with who did it and when.

Switch it off, on, or delete it

ToCall
Switch it offPOST /virtual-chargers/$VC/stop
Switch it back onPOST /virtual-chargers/$VC/start
Delete itDELETE /virtual-chargers/$VC

Switching off works like a power cut: the car stays plugged in, and when the charger comes back on it reports the open session as ended by a power loss. The charger keeps its history, and while it is off it does not count toward the ten that can be switched on at once. Deleting switches it off and retires the charger. Its sessions stay readable afterwards.

Next