Examples
Annotated JSON examples walking through the session lifecycle, starting with the simplest case and layering in complexity.
Copy link1. Upcoming Session
The simplest session. The vehicle hasn't been plugged in yet — the system is just waiting, with a target inherited from the policy's weekly schedule.
{
"id": "e1f2a3b4-c5d6-4789-abcd-ef0123456789",
"policyId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"vehicleId": "b2c3d4e5-f6a7-4890-bcde-f01234567890",
"locationId": "a1b2c3d4-e5f6-4789-abcd-ef0123456789",
"state": "UPCOMING",
"pluggedInAt": null,
"pluggedOutAt": null,
"blocks": [],
"statistics": {
"aggregated": null,
"timeseries": []
},
"target": {
"latest": {
"id": 1,
"type": "REGULAR",
"source": "POLICY",
"batteryReserve": 20,
"minimumChargeTarget": 50,
"readyBy": "2025-06-11T07:00:00Z"
}
},
"outcome": { "latest": null },
"error": { "latest": null },
"restrictions": { "current": null, "all": [] }
}
While UPCOMING, blocks is always [] and statistics.aggregated is always null — there is no charge plan or data yet. outcome.latest is null because the system doesn't know when the vehicle will plug in.
The target.latest here is a REGULAR target with source: "POLICY" (inherited from the weekly schedule).
Copy link2. Active Session — Regular Charging
The core happy path. The vehicle plugged in at 22:15 with 35% battery. The system scheduled a battery reserve block first (charges to the reserve floor), then a regular block optimized against energy prices. It is currently 02:30 AM.
{
"id": "f2a3b4c5-d6e7-4890-bcde-f01234567890",
"policyId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"vehicleId": "b2c3d4e5-f6a7-4890-bcde-f01234567890",
"locationId": "a1b2c3d4-e5f6-4789-abcd-ef0123456789",
"state": "ACTIVE:REGULAR",
"pluggedInAt": "2025-06-10T22:15:00Z",
"pluggedOutAt": null,
"blocks": [
{
// Completed — kwhSum is the actual energy delivered
"mode": "CHARGING",
"type": "BATTERY_RESERVE",
"source": "POLICY",
"flexibility": "NONE",
"kwhSum": 3.2,
"startAt": "2025-06-11T00:00:00Z",
"endAt": "2025-06-11T00:30:00Z",
},
{
// In progress — kwhSum is the actual energy delivered so far
"mode": "CHARGING",
"type": "REGULAR",
"source": "POLICY",
"flexibility": "FULL",
"kwhSum": 9.2,
"startAt": "2025-06-11T01:00:00Z",
"endAt": "2025-06-11T02:30:00Z",
},
{
// Future (tentative) — kwhSum is the system's estimate
"mode": "CHARGING",
"type": "REGULAR",
"source": "POLICY",
"flexibility": "FULL",
"kwhSum": 7.4,
"startAt": "2025-06-11T03:30:00Z",
"endAt": "2025-06-11T04:30:00Z",
},
],
"statistics": {
"aggregated": {
// Actual delivered so far; excludes the future block
"kwhSum": 12.4,
"batteryFrom": 35,
"batteryTo": 52,
},
"timeseries": [
// Zeros from plug-in until first block
{ "startAt": "2025-06-10T22:15:00Z", "kwh": 0 },
// ... every 15 min ...
{ "startAt": "2025-06-10T23:45:00Z", "kwh": 0 },
// Battery reserve block
{ "startAt": "2025-06-11T00:00:00Z", "kwh": 6.8 },
{ "startAt": "2025-06-11T00:15:00Z", "kwh": 6.5 },
// Gap between blocks
{ "startAt": "2025-06-11T00:30:00Z", "kwh": 0 },
{ "startAt": "2025-06-11T00:45:00Z", "kwh": 0 },
// Regular block (in progress — timeseries only covers elapsed intervals)
{ "startAt": "2025-06-11T01:00:00Z", "kwh": 7.2 },
// ... continues as charging progresses ...
{ "startAt": "2025-06-11T02:15:00Z", "kwh": 6.7 },
],
},
"target": {
"latest": {
"id": 1,
"type": "REGULAR",
"source": "POLICY",
"batteryReserve": 20,
"minimumChargeTarget": 50,
"readyBy": "2025-06-11T07:00:00Z",
},
},
"outcome": {
"latest": {
"type": "REGULAR",
"targetId": 1,
"state": "ON_TARGET",
"batteryLevelAtReadyBy": null,
"minimumChargeTargetReachedAt": null,
},
},
"error": { "latest": null },
"restrictions": { "current": null, "all": [] },
}
The blocks array shows three charging windows: a completed BATTERY_RESERVE block, an in-progress REGULAR block, and a future tentative REGULAR block. kwhSum on each block reflects its state: actual energy delivered for completed and in-progress blocks, and the system's estimate for future blocks. The gap between block 1 and block 2 (00:30–01:00) appears as kwh: 0 entries in the timeseries.
The timeseries starts at pluggedInAt with zeros and only covers elapsed intervals — future block intervals are not included. statistics.aggregated.kwhSum (12.4) reflects actual delivered energy and does not include the estimated future block.
outcome.latest is a REGULAR ON_TARGET outcome. state: "ON_TARGET" means the system estimates it will reach 50% by the 07:00 deadline — batteryLevelAtReadyBy and minimumChargeTargetReachedAt are null because projections are unnecessary when the target will be met.
Copy link3. Settled Session
A completed session. The vehicle charged overnight using the flexible schedule, then the user triggered an immediate start override mid-session (the IMMEDIATE_START block at 03:45), before the system resumed flexible charging. The vehicle was unplugged at 07:20.
Once SETTLED, blocks and timeseries are final — they represent what actually happened, not a plan.
{
"id": "c3d4e5f6-a7b8-4012-9def-012345678902",
"policyId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"vehicleId": "b2c3d4e5-f6a7-4890-bcde-f01234567890",
"locationId": "a1b2c3d4-e5f6-4789-abcd-ef0123456789",
"state": "SETTLED",
"pluggedInAt": "2025-06-09T21:45:00Z",
"pluggedOutAt": "2025-06-10T07:20:00Z",
"blocks": [
{
// Planned before the user triggered the override at 03:45.
// Per-block `source` is stamped at construction time, so this
// block keeps `POLICY` even though the latest target below is
// an override.
"mode": "CHARGING",
"type": "REGULAR",
"source": "POLICY",
"flexibility": "FULL",
"kwhSum": 18.5,
"startAt": "2025-06-10T00:00:00Z",
"endAt": "2025-06-10T03:45:00Z",
},
{
"mode": "CHARGING",
"type": "IMMEDIATE_START",
"source": "USER_OVERRIDE",
"flexibility": "NONE",
"kwhSum": 5.5,
"startAt": "2025-06-10T03:45:00Z",
"endAt": "2025-06-10T04:15:00Z",
},
{
// Re-planned with the override target still active (`target.latest`
// below is `IMMEDIATE_START`), so this block reports `USER_OVERRIDE`.
"mode": "CHARGING",
"type": "REGULAR",
"source": "USER_OVERRIDE",
"flexibility": "LIMITED",
"kwhSum": 9.2,
"startAt": "2025-06-10T05:00:00Z",
"endAt": "2025-06-10T06:30:00Z",
},
],
"statistics": {
"aggregated": {
"kwhSum": 33.2,
"batteryFrom": 22,
"batteryTo": 85,
},
"timeseries": [
// Idle from plug-in
{ "startAt": "2025-06-09T21:45:00Z", "kwh": 0 },
// ... zeros every 15 min until 00:00 ...
// Regular block 1
{ "startAt": "2025-06-10T00:00:00Z", "kwh": 7.4 },
// ... ~7 kW, gradually declining ...
{ "startAt": "2025-06-10T03:30:00Z", "kwh": 4.8 },
// Immediate start override — full power
{ "startAt": "2025-06-10T03:45:00Z", "kwh": 11.0 },
{ "startAt": "2025-06-10T04:00:00Z", "kwh": 11.0 },
// Gap — idle
{ "startAt": "2025-06-10T04:15:00Z", "kwh": 0 },
// ... zeros ...
{ "startAt": "2025-06-10T04:45:00Z", "kwh": 0 },
// Regular block 2
{ "startAt": "2025-06-10T05:00:00Z", "kwh": 6.0 },
// ... declining ...
{ "startAt": "2025-06-10T06:15:00Z", "kwh": 4.5 },
// Idle until plug-out
{ "startAt": "2025-06-10T06:30:00Z", "kwh": 0 },
// ... zeros until 07:15 ...
],
},
"target": {
"latest": {
"id": 2,
"type": "IMMEDIATE_START",
"minimumChargeTarget": 50,
},
},
"outcome": {
"latest": {
"type": "IMMEDIATE_START",
"targetId": 2,
"minimumChargeTargetReachedAt": "2025-06-10T06:10:00Z",
},
},
"error": { "latest": null },
"restrictions": { "current": null, "all": [] },
"valuation": {
"currency": "EUR",
"tariffCost": { "actual": 3.45, "baseline": 5.12, "savings": 1.67 },
},
}
The timeseries tells the full story from plug-in (21:45) to plug-out (07:20): idle zeros → flexible charging at ~7 kW → the immediate start spike at 11 kW (03:45–04:15) → an idle gap (04:15–05:00) → more flexible charging → trailing zeros until unplug.
Three blocks appear, two types. The IMMEDIATE_START block in the middle is where the user triggered an override — the charge rate jumped to 11 kW (full power). Each block's kwhSum tracks the energy delivered during that window.
target.latest shows IMMEDIATE_START because the immediate start override was still active when the session settled. Once an immediate start override completes (the target is reached), the system reverts to the regular schedule target. In this case the vehicle was unplugged before that happened, so the override is what's captured.
Copy link4. Upcoming Session with Immediate Start Override
The user triggered an "immediate start" override while the vehicle is still unplugged. Once plugged in, it will charge immediately to 70% with no flexibility.
{
"id": "a3b4c5d6-e7f8-4901-8def-012345678901",
"policyId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"vehicleId": "b2c3d4e5-f6a7-4890-bcde-f01234567890",
"locationId": "a1b2c3d4-e5f6-4789-abcd-ef0123456789",
"state": "UPCOMING",
"pluggedInAt": null,
"pluggedOutAt": null,
"blocks": [],
"statistics": { "aggregated": null, "timeseries": [] },
"target": {
"latest": {
"id": 2,
"type": "IMMEDIATE_START",
"minimumChargeTarget": 70,
},
},
"outcome": { "latest": null },
"error": { "latest": null },
"restrictions": { "current": null, "all": [] },
}
Compare with Example 1 — the structure is identical except for target.latest, which is IMMEDIATE_START instead of REGULAR.
Copy link5. Upcoming Session with Schedule Override
The user adjusted the target for the upcoming session — raising the charge target to 90% and pushing the deadline to 08:00. The session is still UPCOMING but the target now reflects the user's custom settings instead of the policy defaults.
{
"id": "b4c5d6e7-f8a9-4012-8ef0-123456789012",
"policyId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"vehicleId": "b2c3d4e5-f6a7-4890-bcde-f01234567890",
"locationId": "a1b2c3d4-e5f6-4789-abcd-ef0123456789",
"state": "UPCOMING",
"pluggedInAt": null,
"pluggedOutAt": null,
"blocks": [],
"statistics": { "aggregated": null, "timeseries": [] },
"target": {
"latest": {
"id": 2,
"type": "REGULAR",
"source": "USER_OVERRIDE",
"batteryReserve": 20,
"minimumChargeTarget": 90,
"readyBy": "2025-06-11T08:00:00Z",
},
},
"outcome": { "latest": null },
"error": { "latest": null },
"restrictions": { "current": null, "all": [] },
}
The difference from Example 1 is inside target.latest: source is "USER_OVERRIDE" instead of "POLICY", and minimumChargeTarget and readyBy reflect the user's custom values. The batteryReserve stays at 20% — it's a policy-level setting, not something the user adjusts per-session. Schedule overrides are temporary and expire after the session settles, at which point the next session reverts to "POLICY".
Copy link6. Active Session with Error
The vehicle is plugged in and a charge block is scheduled, but the system failed to start charging. No energy has been delivered.
{
"id": "c5d6e7f8-a9b0-4123-8f01-234567890123",
"policyId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"vehicleId": "b2c3d4e5-f6a7-4890-bcde-f01234567890",
"locationId": "a1b2c3d4-e5f6-4789-abcd-ef0123456789",
"state": "ACTIVE:REGULAR",
"pluggedInAt": "2025-06-10T22:15:00Z",
"pluggedOutAt": null,
"blocks": [
{
"mode": "CHARGING",
"type": "REGULAR",
"source": "POLICY",
"flexibility": "FULL",
"kwhSum": 0,
"startAt": "2025-06-11T01:00:00Z",
"endAt": "2025-06-11T04:30:00Z",
},
],
"statistics": {
"aggregated": { "kwhSum": 0, "batteryFrom": 35, "batteryTo": 35 },
"timeseries": [
{ "startAt": "2025-06-10T22:15:00Z", "kwh": 0 },
// ... all zeros — no energy delivered ...
{ "startAt": "2025-06-11T01:15:00Z", "kwh": 0 },
],
},
"target": {
"latest": {
"id": 1,
"type": "REGULAR",
"source": "POLICY",
"batteryReserve": 20,
"minimumChargeTarget": 50,
"readyBy": "2025-06-11T07:00:00Z",
},
},
"outcome": {
"latest": {
"type": "REGULAR",
"targetId": 1,
"state": "OFF_TARGET",
"batteryLevelAtReadyBy": 35,
"minimumChargeTargetReachedAt": "2025-06-11T09:30:00Z",
},
},
"error": {
"latest": { "type": "START_FAIL" },
},
"restrictions": { "current": null, "all": [] },
}
error.latest is non-null — START_FAIL means the system tried to start charging but the vehicle didn't respond.
The impact is visible everywhere: kwhSum is 0, batteryTo equals batteryFrom (35%), the timeseries is entirely zeros, and the outcome is OFF_TARGET with batteryLevelAtReadyBy showing the estimated battery at the deadline.
Copy link7. Settled Unmanaged Session (Public Charging)
The vehicle charged at a public charger away from home. The system observed the session but did not control it — there are no blocks, no target, and no outcome. Unmanaged sessions appear in both Get Settled Session and List Settled Sessions.
While this session was happening, the policy's current session remained UPCOMING — still waiting for the vehicle to return to the policy's location.
{
"id": "d1e2f3a4-b5c6-7890-abcd-ef0123456789",
"policyId": null,
"vehicleId": "b2c3d4e5-f6a7-4890-bcde-f01234567890",
"locationId": null,
"state": "SETTLED",
"pluggedInAt": "2025-06-10T14:30:00Z",
"pluggedOutAt": "2025-06-10T15:45:00Z",
"blocks": [],
"statistics": {
"aggregated": {
"kwhSum": 18.5,
"batteryFrom": 30,
"batteryTo": 62,
},
"timeseries": [
{ "startAt": "2025-06-10T14:30:00Z", "kwh": 45.2 },
// ... DC fast charging, high kW ...
{ "startAt": "2025-06-10T15:30:00Z", "kwh": 12.1 },
],
},
"target": { "latest": null },
"outcome": { "latest": null },
"error": { "latest": null },
"restrictions": { "current": null, "all": [] },
"valuation": null,
}
policyId is null — this session is not associated with any policy. blocks is empty because the system wasn't controlling the charge. target.latest and outcome.latest are both null — there was no goal to track against.
Statistics are still available: aggregated shows total energy and battery progression, and the timeseries captures the charge rate. Note the higher kW values typical of DC fast charging compared to the home AC charging in the managed examples.
Copy link8. Active Session with Restriction
The vehicle plugged in at 22:00 with 30% battery. The system started a regular charging block, but the user paused charging at 01:00 via a restriction until 04:00. The system planned charging around the restriction window. It is currently 01:30 AM.
{
"id": "d6e7f8a9-b0c1-4234-9012-345678901234",
"policyId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"vehicleId": "b2c3d4e5-f6a7-4890-bcde-f01234567890",
"locationId": "a1b2c3d4-e5f6-4789-abcd-ef0123456789",
"state": "ACTIVE:REGULAR",
"pluggedInAt": "2025-06-10T22:00:00Z",
"pluggedOutAt": null,
"blocks": [
{
// Completed — charged before the restriction
"mode": "CHARGING",
"type": "REGULAR",
"source": "POLICY",
"flexibility": "FULL",
"kwhSum": 8.1,
"startAt": "2025-06-10T23:00:00Z",
"endAt": "2025-06-11T01:00:00Z",
},
{
// In progress — restriction is active, no energy delivered
"mode": "RESTRICTION",
"type": "RESTRICTION",
"source": "USER_OVERRIDE",
"flexibility": "NONE",
"kwhSum": 0,
"startAt": "2025-06-11T01:00:00Z",
"endAt": "2025-06-11T04:00:00Z",
},
{
// Future (tentative) — charging resumes after the restriction ends
"mode": "CHARGING",
"type": "REGULAR",
"source": "POLICY",
"flexibility": "FULL",
"kwhSum": 12.3,
"startAt": "2025-06-11T04:00:00Z",
"endAt": "2025-06-11T06:30:00Z",
},
],
"statistics": {
"aggregated": {
"kwhSum": 8.1,
"batteryFrom": 30,
"batteryTo": 42,
},
"timeseries": [
{ "startAt": "2025-06-10T22:00:00Z", "kwh": 0 },
{ "startAt": "2025-06-10T22:45:00Z", "kwh": 0 },
// Regular block
{ "startAt": "2025-06-10T23:00:00Z", "kwh": 7.0 },
{ "startAt": "2025-06-10T23:15:00Z", "kwh": 6.8 },
// ... continues ...
{ "startAt": "2025-06-11T00:45:00Z", "kwh": 6.2 },
// Normally zero unless charging continues during the restriction
{ "startAt": "2025-06-11T01:00:00Z", "kwh": 0 },
{ "startAt": "2025-06-11T01:15:00Z", "kwh": 0 },
],
},
"target": {
"latest": {
"id": 1,
"type": "REGULAR",
"source": "POLICY",
"batteryReserve": 20,
"minimumChargeTarget": 80,
"readyBy": "2025-06-11T07:00:00Z",
},
},
"outcome": {
"latest": {
"type": "REGULAR",
"targetId": 1,
"state": "ON_TARGET",
"batteryLevelAtReadyBy": null,
"minimumChargeTargetReachedAt": null,
},
},
"error": { "latest": null },
"restrictions": {
"current": {
"type": "FULL",
"source": "USER_OVERRIDE",
"startsAt": "2025-06-11T01:00:00Z",
"endsAt": "2025-06-11T04:00:00Z",
},
"all": [
{
"type": "FULL",
"source": "USER_OVERRIDE",
"startsAt": "2025-06-11T01:00:00Z",
"endsAt": "2025-06-11T04:00:00Z",
},
],
},
}
The blocks array shows three windows: a completed CHARGING block, an in-progress RESTRICTION block (the user's requested pause), and a tentative future CHARGING block planned after the restriction ends. The RESTRICTION block has mode: "RESTRICTION", type: "RESTRICTION", source: "USER_OVERRIDE", flexibility: "NONE", and kwhSum: 0. Restriction blocks normally carry no energy, but may have positive kwhSum when charging continued anyway, for example because a stop command failed or was delayed.
restrictions.current shows the active restriction: type: "FULL" (all planned charging is restricted), source: "USER_OVERRIDE", and the time window. The session state remains ACTIVE:REGULAR — the restriction doesn't change the session state, it adds a restriction block to the timeline.
The system still expects to reach the target on time (outcome.latest.state: "ON_TARGET") by scheduling the remaining charging after the restriction window.