> ## Documentation Index
> Fetch the complete documentation index at: https://docs.axle.energy/llms.txt
> Use this file to discover all available pages before exploring further.

# Charging scenarios

> Worked examples showing how intents and tariffs affect the schedules Axle sends

This page walks through concrete examples of the charging schedules Axle sends for different intents and tariffs. Use it to reason about what your users will experience, and how to handle the edge cases.

## Scenario 1: Overnight charge

The user plugs in after work and wants the car ready by morning. This is the default happy path.

| [Intent](/workflows/smart-charging/api-reference/intent) | Value                                |
| -------------------------------------------------------- | ------------------------------------ |
| Energy required                                          | 30 kWh                               |
| May charge at peak                                       | `false` *(default)*                  |
| Charging mode                                            | `maximise_charging_time` *(default)* |

<Frame>
  <img src="https://mintcdn.com/fascinating-teal-alpaca/NpZW09GRbdgnto5J/images/scenarios/scenario-1.svg?fit=max&auto=format&n=NpZW09GRbdgnto5J&q=85&s=5edc3900369e8d14a6af38962e5ab90e" alt="Scenario 1 timeline. Axle charges through the full off-peak window from 23:30 to 05:30, with the user plugged in from 22:00 until ready-by at 07:00. An intent marker on the Schedule band shows where cumulative charging reaches the stated intent." width="600" height="136" data-path="images/scenarios/scenario-1.svg" />
</Frame>

Axle charges throughout the off-peak window, comfortably meeting the 30 kWh intent. The charger idles during peak rates before and after.

<Accordion title="OCPP ChargingProfile payload">
  Axle sets `limit` to `99999.0` as an "unlimited" signal. The charger draws at its rated power during each charging period. See the [integration guide](/workflows/smart-charging/integration#receiving-charging-schedules) for how to receive these payloads.

  ```json theme={null}
  {
    "chargingProfileId": null,
    "transactionId": null,
    "stackLevel": 1100,
    "chargingProfilePurpose": "TxProfile",
    "chargingProfileKind": "Absolute",
    "recurrencyKind": null,
    "validFrom": null,
    "validTo": null,
    "chargingSchedule": {
      "duration": 32400,
      "startSchedule": "2026-04-14T22:00:00+00:00",
      "chargingRateUnit": "W",
      "chargingSchedulePeriod": [
        { "startPeriod": 0, "limit": 0.0, "numberPhases": 1 },
        { "startPeriod": 5400, "limit": 99999.0, "numberPhases": 1 },
        { "startPeriod": 27000, "limit": 0.0, "numberPhases": 1 }
      ],
      "minChargingRate": 0.0
    }
  }
  ```
</Accordion>

***

## Scenario 2: Minimising energy delivered

`charging_mode` controls whether Axle fills the full off-peak window or stops once the stated intent is met.

| [Intent](/workflows/smart-charging/api-reference/intent) | Value               |
| -------------------------------------------------------- | ------------------- |
| Energy required                                          | 10 kWh              |
| May charge at peak                                       | `false` *(default)* |

<Tabs>
  <Tab title="Fill all off-peak (default)">
    <Frame>
      <img src="https://mintcdn.com/fascinating-teal-alpaca/NpZW09GRbdgnto5J/images/scenarios/scenario-3-maximise.svg?fit=max&auto=format&n=NpZW09GRbdgnto5J&q=85&s=433f7b304381665c36ebfbd3db98ea0f" alt="Scenario 2 (maximise charging time). Axle charges throughout the full off-peak window from 23:30 to 05:30, delivering more energy than the user's stated intent." width="600" height="136" data-path="images/scenarios/scenario-3-maximise.svg" />
    </Frame>

    Under the default `charging_mode: maximise_charging_time`, Axle treats the energy intent as a minimum, not a cap, and charges through all remaining off-peak slots.

    <Accordion title="OCPP ChargingProfile payload">
      ```json theme={null}
      {
        "chargingProfileId": null,
        "transactionId": null,
        "stackLevel": 1100,
        "chargingProfilePurpose": "TxProfile",
        "chargingProfileKind": "Absolute",
        "recurrencyKind": null,
        "validFrom": null,
        "validTo": null,
        "chargingSchedule": {
          "duration": 32400,
          "startSchedule": "2026-04-14T22:00:00+00:00",
          "chargingRateUnit": "W",
          "chargingSchedulePeriod": [
            { "startPeriod": 0, "limit": 0.0, "numberPhases": 1 },
            { "startPeriod": 5400, "limit": 99999.0, "numberPhases": 1 },
            { "startPeriod": 27000, "limit": 0.0, "numberPhases": 1 }
          ],
          "minChargingRate": 0.0
        }
      }
      ```
    </Accordion>
  </Tab>

  <Tab title="Match intent exactly">
    <Frame>
      <img src="https://mintcdn.com/fascinating-teal-alpaca/NpZW09GRbdgnto5J/images/scenarios/scenario-3-minimise.svg?fit=max&auto=format&n=NpZW09GRbdgnto5J&q=85&s=bb508b435051833cbddfe247b882e3d0" alt="Scenario 2 (minimise charging time). Axle charges only at the start of the off-peak window from 23:30 to 01:00, stopping once the stated intent is met." width="600" height="136" data-path="images/scenarios/scenario-3-minimise.svg" />
    </Frame>

    With `charging_mode: minimise_charging_time`, Axle charges for just long enough to meet the 10 kWh intent, starting at the beginning of the off-peak window. Axle adds a small safety factor on top to account for variable charging efficiency, so the scheduled energy will be slightly above the stated intent.

    <Accordion title="OCPP ChargingProfile payload">
      ```json theme={null}
      {
        "chargingProfileId": null,
        "transactionId": null,
        "stackLevel": 1100,
        "chargingProfilePurpose": "TxProfile",
        "chargingProfileKind": "Absolute",
        "recurrencyKind": null,
        "validFrom": null,
        "validTo": null,
        "chargingSchedule": {
          "duration": 32400,
          "startSchedule": "2026-04-14T22:00:00+00:00",
          "chargingRateUnit": "W",
          "chargingSchedulePeriod": [
            { "startPeriod": 0, "limit": 0.0, "numberPhases": 1 },
            { "startPeriod": 5400, "limit": 99999.0, "numberPhases": 1 },
            { "startPeriod": 10800, "limit": 0.0, "numberPhases": 1 }
          ],
          "minChargingRate": 0.0
        }
      }
      ```
    </Accordion>
  </Tab>
</Tabs>

***

## Scenario 3: Intent larger than the off-peak window

The user's energy requirement cannot be met using the off-peak window alone.

| [Intent](/workflows/smart-charging/api-reference/intent) | Value                                |
| -------------------------------------------------------- | ------------------------------------ |
| Energy required                                          | 45 kWh                               |
| Charging mode                                            | `maximise_charging_time` *(default)* |

<Tabs>
  <Tab title="Off-peak only (default)">
    <Frame>
      <img src="https://mintcdn.com/fascinating-teal-alpaca/NpZW09GRbdgnto5J/images/scenarios/scenario-4-false.svg?fit=max&auto=format&n=NpZW09GRbdgnto5J&q=85&s=a281a9eabc38eb518478943df4aabb62" alt="Scenario 3 (may_charge_peak false). Axle fills the entire off-peak window from 23:30 to 05:30 but leaves peak slots idle and therefore falls short of the user's full intent." width="600" height="136" data-path="images/scenarios/scenario-4-false.svg" />
    </Frame>

    Axle uses every off-peak slot available but falls short of the 45 kWh intent. Peak slots are left idle because `may_charge_peak` is `false`.

    <Accordion title="OCPP ChargingProfile payload">
      ```json theme={null}
      {
        "chargingProfileId": null,
        "transactionId": null,
        "stackLevel": 1100,
        "chargingProfilePurpose": "TxProfile",
        "chargingProfileKind": "Absolute",
        "recurrencyKind": null,
        "validFrom": null,
        "validTo": null,
        "chargingSchedule": {
          "duration": 32400,
          "startSchedule": "2026-04-14T22:00:00+00:00",
          "chargingRateUnit": "W",
          "chargingSchedulePeriod": [
            { "startPeriod": 0, "limit": 0.0, "numberPhases": 1 },
            { "startPeriod": 5400, "limit": 99999.0, "numberPhases": 1 },
            { "startPeriod": 27000, "limit": 0.0, "numberPhases": 1 }
          ],
          "minChargingRate": 0.0
        }
      }
      ```
    </Accordion>
  </Tab>

  <Tab title="Allow peak charging">
    <Frame>
      <img src="https://mintcdn.com/fascinating-teal-alpaca/NpZW09GRbdgnto5J/images/scenarios/scenario-4-true.svg?fit=max&auto=format&n=NpZW09GRbdgnto5J&q=85&s=d67cb9e9ef1a06c8fda437be5dba3887" alt="Scenario 3 (may_charge_peak true). Axle fills the entire off-peak window and adds a single peak slot at 22:00 to meet the user's full intent." width="600" height="136" data-path="images/scenarios/scenario-4-true.svg" />
    </Frame>

    With `may_charge_peak: true`, Axle fills the off-peak window and tops up with the earliest available peak slot to reach the 45 kWh intent.

    <Accordion title="OCPP ChargingProfile payload">
      ```json theme={null}
      {
        "chargingProfileId": null,
        "transactionId": null,
        "stackLevel": 1100,
        "chargingProfilePurpose": "TxProfile",
        "chargingProfileKind": "Absolute",
        "recurrencyKind": null,
        "validFrom": null,
        "validTo": null,
        "chargingSchedule": {
          "duration": 32400,
          "startSchedule": "2026-04-14T22:00:00+00:00",
          "chargingRateUnit": "W",
          "chargingSchedulePeriod": [
            { "startPeriod": 0, "limit": 99999.0, "numberPhases": 1 },
            { "startPeriod": 1800, "limit": 0.0, "numberPhases": 1 },
            { "startPeriod": 5400, "limit": 99999.0, "numberPhases": 1 },
            { "startPeriod": 27000, "limit": 0.0, "numberPhases": 1 }
          ],
          "minChargingRate": 0.0
        }
      }
      ```
    </Accordion>
  </Tab>
</Tabs>

***

## Scenario 4: Mid-session re-scheduling

Axle may re-issue schedules during a session. Each new schedule fully replaces the previous one at the same stack level.

| [Intent](/workflows/smart-charging/api-reference/intent) | Value                                |
| -------------------------------------------------------- | ------------------------------------ |
| Energy required                                          | 30 kWh                               |
| May charge at peak                                       | `false` *(default)*                  |
| Charging mode                                            | `maximise_charging_time` *(default)* |

<Frame>
  <img src="https://mintcdn.com/fascinating-teal-alpaca/NpZW09GRbdgnto5J/images/scenarios/scenario-5.svg?fit=max&auto=format&n=NpZW09GRbdgnto5J&q=85&s=b6aa58b556d856a2904d523d0e0b4e0e" alt="Scenario 4 timeline. Axle sends an initial schedule charging the full off-peak window from 23:30 to 05:30, then at 00:30 sends a revised schedule that pauses charging from 00:30 to 01:30 and resumes until 05:30. The Actual row shows the resulting delivery: charging from 23:30 to 00:30 under the initial schedule, idle from 00:30 to 01:30 once the revised schedule lands, then charging again from 01:30 to 05:30." width="600" height="224" data-path="images/scenarios/scenario-5.svg" />
</Frame>

At 00:30 a market change makes it more valuable for Axle to insert a one-hour pause, so Axle sends a revised schedule covering the remainder of the session. The Actual row shows what the charger actually delivers — the initial schedule applies until the update lands, and the revised schedule applies from then on.

<Accordion title="Initial ChargingProfile payload (sent at 19:00)">
  ```json theme={null}
  {
    "chargingProfileId": null,
    "transactionId": null,
    "stackLevel": 1100,
    "chargingProfilePurpose": "TxProfile",
    "chargingProfileKind": "Absolute",
    "recurrencyKind": null,
    "validFrom": null,
    "validTo": null,
    "chargingSchedule": {
      "duration": 54000,
      "startSchedule": "2026-04-14T19:00:00+00:00",
      "chargingRateUnit": "W",
      "chargingSchedulePeriod": [
        { "startPeriod": 0, "limit": 0.0, "numberPhases": 1 },
        { "startPeriod": 16200, "limit": 99999.0, "numberPhases": 1 },
        { "startPeriod": 37800, "limit": 0.0, "numberPhases": 1 }
      ],
      "minChargingRate": 0.0
    }
  }
  ```
</Accordion>

<Accordion title="Revised ChargingProfile payload (sent at 00:30)">
  ```json theme={null}
  {
    "chargingProfileId": null,
    "transactionId": null,
    "stackLevel": 1100,
    "chargingProfilePurpose": "TxProfile",
    "chargingProfileKind": "Absolute",
    "recurrencyKind": null,
    "validFrom": null,
    "validTo": null,
    "chargingSchedule": {
      "duration": 34200,
      "startSchedule": "2026-04-15T00:30:00+00:00",
      "chargingRateUnit": "W",
      "chargingSchedulePeriod": [
        { "startPeriod": 0, "limit": 0.0, "numberPhases": 1 },
        { "startPeriod": 3600, "limit": 99999.0, "numberPhases": 1 },
        { "startPeriod": 18000, "limit": 0.0, "numberPhases": 1 }
      ],
      "minChargingRate": 0.0
    }
  }
  ```
</Accordion>

***

## Scenario 5: No off-peak slots before ready-by

The user plugs in at 07:00 and needs the car ready by 11:00. There are no off-peak slots between now and the deadline.

| [Intent](/workflows/smart-charging/api-reference/intent) | Value                                |
| -------------------------------------------------------- | ------------------------------------ |
| Energy required                                          | 10 kWh                               |
| Charging mode                                            | `maximise_charging_time` *(default)* |

<Tabs>
  <Tab title="Off-peak only (default)">
    <Frame>
      <img src="https://mintcdn.com/fascinating-teal-alpaca/NpZW09GRbdgnto5J/images/scenarios/scenario-2-false.svg?fit=max&auto=format&n=NpZW09GRbdgnto5J&q=85&s=ace8b7c31ca995378f1464f2370d2742" alt="Scenario 5 (may_charge_peak false). Schedule is entirely idle because no off-peak slots fall within the window between plug-in at 07:00 and ready-by at 11:00." width="600" height="136" data-path="images/scenarios/scenario-2-false.svg" />
    </Frame>

    With `may_charge_peak: false`, Axle cannot use peak slots. With no off-peak slots available, Axle cannot deliver any energy toward the 10 kWh intent. We still send a schedule (a single 0 W period) to tell the charger explicitly not to charge.

    If the user needs to override this and charge immediately, initiate the charge on your side and notify Axle with a [charge-now event](/api-reference/entities/asset/event/charge-now).

    <Accordion title="OCPP ChargingProfile payload">
      ```json theme={null}
      {
        "chargingProfileId": null,
        "transactionId": null,
        "stackLevel": 1100,
        "chargingProfilePurpose": "TxProfile",
        "chargingProfileKind": "Absolute",
        "recurrencyKind": null,
        "validFrom": null,
        "validTo": null,
        "chargingSchedule": {
          "duration": 14400,
          "startSchedule": "2026-04-15T07:00:00+00:00",
          "chargingRateUnit": "W",
          "chargingSchedulePeriod": [
            { "startPeriod": 0, "limit": 0.0, "numberPhases": 1 }
          ],
          "minChargingRate": 0.0
        }
      }
      ```
    </Accordion>
  </Tab>

  <Tab title="Allow peak charging">
    <Frame>
      <img src="https://mintcdn.com/fascinating-teal-alpaca/NpZW09GRbdgnto5J/images/scenarios/scenario-2-true.svg?fit=max&auto=format&n=NpZW09GRbdgnto5J&q=85&s=a8056228d3de402e06912c554ab37869" alt="Scenario 5 (may_charge_peak true). Axle charges on peak from 07:00 to 08:30 to meet the user intent, then idles until ready-by at 11:00." width="600" height="136" data-path="images/scenarios/scenario-2-true.svg" />
    </Frame>

    With `may_charge_peak: true`, Axle charges at peak rate for just long enough to meet the 10 kWh intent, then idles.

    <Accordion title="OCPP ChargingProfile payload">
      ```json theme={null}
      {
        "chargingProfileId": null,
        "transactionId": null,
        "stackLevel": 1100,
        "chargingProfilePurpose": "TxProfile",
        "chargingProfileKind": "Absolute",
        "recurrencyKind": null,
        "validFrom": null,
        "validTo": null,
        "chargingSchedule": {
          "duration": 14400,
          "startSchedule": "2026-04-15T07:00:00+00:00",
          "chargingRateUnit": "W",
          "chargingSchedulePeriod": [
            { "startPeriod": 0, "limit": 99999.0, "numberPhases": 1 },
            { "startPeriod": 5400, "limit": 0.0, "numberPhases": 1 }
          ],
          "minChargingRate": 0.0
        }
      }
      ```
    </Accordion>
  </Tab>
</Tabs>

***

## Interpreting schedules

A few things to know when handling the schedules Axle sends you.

<AccordionGroup>
  <Accordion title="Stack a default profile behind Axle's schedule">
    Axle sends schedules at OCPP `stackLevel: 1100` with `chargingProfilePurpose: TxProfile`. You should install a long-running `TxDefaultProfile` at a lower stack level (e.g. `0`) representing your fallback charging policy. When Axle's `TxProfile` expires or is superseded, the charger falls back to your default rather than continuing an old Axle schedule.

    It also acts as a failsafe: if the charger ever loses connectivity or hasn't yet received a schedule, it falls back to your default rather than charging at full rate immediately.
  </Accordion>

  <Accordion title="Each new Axle schedule replaces the previous one">
    Axle's schedules at a given `stackLevel` fully replace the previous schedule at that level. Don't try to merge them. Treat the most recent schedule as authoritative.
  </Accordion>

  <Accordion title="A schedule with only 0 W periods is valid">
    An Axle schedule containing a single `chargingSchedulePeriod` with `limit: 0.0` is an explicit instruction: hold the charger at 0 W for the schedule's duration. It's not an empty or invalid payload. Apply it like any other schedule. The user can always supersede it by triggering an immediate overriding charge.

    This happens when Axle cannot schedule any charging between the plug-in time and ready-by, typically when `may_charge_peak` is `false` and no off-peak slots are available, or when the intent is already satisfied.
  </Accordion>
</AccordionGroup>

***

## Next steps

<Card title="Integration guide" icon="code" href="/workflows/smart-charging/integration">
  Back to the full Smart Charging integration walkthrough
</Card>

<Card title="OCPP example payload" icon="rectangle-terminal" href="/api-reference/examples/get-example-ocpp-charging-profile">
  See the full JSON shape of a schedule Axle sends
</Card>
