Skip to main content

Overview

There are two ways to charge a car cheaply, and an EV charger surface gives you both. You decide when. Push charge with a start and an end. You own the tariff data, you pick the window, the charger does as it is told. Precise, and only as good as your price feed. The charger decides when. Push one of the three auto.* strategies. The charger’s own optimiser picks the hours, using whatever it knows that you do not: the tariff the home owner configured in the manufacturer’s app, or a live reading of what the solar array is producing right now. Neither is better. Reach for a window when the timing is yours to own, and a strategy when the charger knows something you cannot see.
Coming soon. Live control for EV chargers. Sandbox serves the full command surface end to end, so the walkthrough below works against a sandbox device today. A live EV charger push returns 503 NOT_YET_AVAILABLE until the live path opens.

The three strategies

The two surplus modes answer different questions, and picking the wrong one is the most common mistake here. auto.charge_surplus_only accepts that the car may not fill. auto.charge_surplus_first accepts an electricity bill. Ask which the driver actually wants before you choose. A strategy takes no parameters and no time window. It runs until another command replaces it. See why below.

Step 1: Check what the charger declares

Read the device before you push. A charger that does not declare a strategy will refuse it, and the read tells you which ones it has.
A car is plugged in and nothing is flowing. notChargingReason: "vehicle" says the car itself declined, so this is not a fault to surface. A command that is not in commands is refused with 422 UNSUPPORTED_MODE, and the refusal lists the ones that are. Note this charger declares no target parameter. Stopping at a state of charge means reading it off the car, and most chargers cannot see inside one; they declare energy and count on their own meter instead.

Step 2a: Charge inside a window you choose

Send start and end as plant-local wall-clock times: YYYY-MM-DDTHH:MM:SS, no offset, no Z. The platform reads them in the charger’s own timezone, so 22:00 means ten at night where the car is parked.
A push carrying start waits in scheduled until the window opens. The response echoes both instants normalised to absolute UTC, which is the dispatch-ready form of the wall-clock you sent, not a reinterpretation of it.
The plant is on British Summer Time, so 22:00 local resolves to 21:00Z. At end the platform takes the command back and the charger returns to whatever it was doing before. power and current cap the same rate in different units, so send one, never both. Both together returns 422 UNSUPPORTED_PARAMETER_COMBINATION.

Step 2b: Hand timing to the charger

Same envelope, no parameters, no window.
An immediate push starts in acknowledged rather than passing through scheduled. The strategy is now armed. Nothing may happen for hours, and that is the mode working, not a failure. To defer the handover instead, add a start: the charger takes over at 18:00 and not before.
To stop a strategy, push another command with onConflict: "cancel_and_replace". idle pauses charging; charge takes direct control back; another auto.* swaps the regime. Without onConflict the push returns 409, because the strategy is still the charger’s standing action. Strategies never stack: one intent governs a charger at a time.

Step 3: Read back which regime is running

This is the step that makes a smart-charging interface honest. isCharging says whether energy is moving. activeControlMode says what put it that way.
Plugged in, nothing flowing, activeControlMode: "auto.charge_tariff". The charger is waiting for a cheap hour: status reads scheduled and notChargingReason reads schedule, because the charger’s own price program is what is vetoing right now. Show the driver “waiting for off-peak”, not “not charging”. The same reading with activeControlMode: "idle" means somebody stopped it, which is worth telling the driver about. Same stillness, opposite meaning. Branch on activeControlMode, never on isCharging alone:
notChargingReason narrows it further: vehicle (the car declined or has finished), charger (limiting or curtailing), authorization (waiting on an RFID card or app approval), schedule (the charger’s own program vetoes it), or unknown. Of those, only authorization is something the driver can act on. Both activeControlMode and notChargingReason are absent on a charger that does not report them. Absent is not a value; check the key exists before you read it.

Why a strategy takes no deadline

A window on charge bounds a command you own. A window on a strategy would mean something else: “be ready by then”. Meeting that takes a planner that watches the car’s level, decides when to draw, and confirms it arrived, and the platform has none of that. What the window machinery would actually do is turn the strategy on at start and send idle at end. That stops the charge at exactly the moment the driver asked for the car to be finished, which is the opposite of the request. So auto.* declares immediate and scheduled only, and a window on one returns 422 EXECUTION_NOT_SUPPORTED. A ready-by parameter is refused for the same reason: 422 UNSUPPORTED_PARAMETER. If you need a hard deadline, own the timing yourself with a windowed charge.

Resolving a collision

One non-terminal action targets a charger at a time. A second push without onConflict returns 409 CONFLICT naming the conflicting action and the strategies that would resolve it. cancel_and_replace always works. queue_after needs the conflicting action to have an end to queue behind, so it works behind a windowed charge and not behind a strategy, which runs open-ended. Queue behind a strategy and you get 409 with reason: conflicting_action_not_windowed, pointing at cancel_and_replace. An action already dispatched and awaiting completion returns 409 CONFLICT_IN_EXECUTION with an empty strategy list, which means wait. See handle a 409 conflict.

What next

Read charging sessions

What each charge actually delivered, and how it was measured.

Cap an EV charger's power

The standing ceiling every session runs under.

EV charger cheat sheet

The whole charger surface in one page.

Canonical actions

Where these commands sit in the shared model.