Login

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.

Upcoming session

{
  "policyId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "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 }
}

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.

Active session with regular charging

{
  "policyId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "state": "ACTIVE:REGULAR",
  "pluggedInAt": "2025-06-10T22:15:00Z",
  "pluggedOutAt": null,
  "blocks": [
    {
      "type": "BATTERY_RESERVE",
      "kwhSum": 3.2,
      "startAt": "2025-06-11T00:00:00Z",
      "endAt": "2025-06-11T00:30:00Z"
    },
    {
      "type": "REGULAR",
      "kwhSum": 9.2,
      "startAt": "2025-06-11T01:00:00Z",
      "endAt": "2025-06-11T02:30:00Z"
    },
    {
      "type": "REGULAR",
      "kwhSum": 7.4,
      "startAt": "2025-06-11T03:30:00Z",
      "endAt": "2025-06-11T04:30:00Z"
    }
  ],
  "statistics": {
    "aggregated": {
      "kwhSum": 12.4,
      "batteryFrom": 35,
      "batteryTo": 52
    },
    "timeseries": [
      { "startAt": "2025-06-10T22:15:00Z", "kwh": 0 },
      { "startAt": "2025-06-10T23:45:00Z", "kwh": 0 },
      { "startAt": "2025-06-11T00:00:00Z", "kwh": 6.8 },
      { "startAt": "2025-06-11T00:15:00Z", "kwh": 6.5 },
      { "startAt": "2025-06-11T00:30:00Z", "kwh": 0 },
      { "startAt": "2025-06-11T00:45:00Z", "kwh": 0 },
      { "startAt": "2025-06-11T01:00:00Z", "kwh": 7.2 },
      { "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 }
}

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.

Settled session

{
  "id": "c3d4e5f6-a7b8-4012-9def-012345678902",
  "policyId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "state": "SETTLED",
  "pluggedInAt": "2025-06-09T21:45:00Z",
  "pluggedOutAt": "2025-06-10T07:20:00Z",
  "blocks": [
    {
      "type": "REGULAR",
      "kwhSum": 18.5,
      "startAt": "2025-06-10T00:00:00Z",
      "endAt": "2025-06-10T03:45:00Z"
    },
    {
      "type": "IMMEDIATE_START",
      "kwhSum": 5.5,
      "startAt": "2025-06-10T03:45:00Z",
      "endAt": "2025-06-10T04:15:00Z"
    },
    {
      "type": "REGULAR",
      "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": [
      { "startAt": "2025-06-09T21:45:00Z", "kwh": 0 },
      { "startAt": "2025-06-10T00:00:00Z", "kwh": 7.4 },
      { "startAt": "2025-06-10T03:30:00Z", "kwh": 4.8 },
      { "startAt": "2025-06-10T03:45:00Z", "kwh": 11.0 },
      { "startAt": "2025-06-10T04:00:00Z", "kwh": 11.0 },
      { "startAt": "2025-06-10T04:15:00Z", "kwh": 0 },
      { "startAt": "2025-06-10T04:45:00Z", "kwh": 0 },
      { "startAt": "2025-06-10T05:00:00Z", "kwh": 6.0 },
      { "startAt": "2025-06-10T06:15:00Z", "kwh": 4.5 },
      { "startAt": "2025-06-10T06:30:00Z", "kwh": 0 }
    ]
  },
  "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 }
}

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.

Upcoming with immediate start

{
  "policyId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "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 }
}

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.

Upcoming with schedule override

{
  "policyId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "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 }
}

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.

Active session with START_FAIL error

{
  "policyId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "state": "ACTIVE:REGULAR",
  "pluggedInAt": "2025-06-10T22:15:00Z",
  "pluggedOutAt": null,
  "blocks": [
    {
      "type": "REGULAR",
      "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 },
      { "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" }
  }
}

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.

Unmanaged session

{
  "id": "d1e2f3a4-b5c6-7890-abcd-ef0123456789",
  "policyId": 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 },
      { "startAt": "2025-06-10T15:30:00Z", "kwh": 12.1 }
    ]
  },
  "target": { "latest": null },
  "outcome": { "latest": null },
  "error": { "latest": 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.

Previous articleAnatomy of a session
Was this article helpful?