> ## 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.

# Integration

> Integrate Smart Charging into your platform

This guide walks you through the integration of Smart Charging into your EV charging platform.

Smart Charging works whether the asset is a **charger** or a **car**. If you're connecting via the vehicle, see [Cars](/assets/cars) for notes on the geofencing behaviour that determines when Axle controls charging.

There are three core workflows to support:

1. **Onboarding & offboarding**: registering the site & asset with Axle, and assigning responsibility for charging
2. **Charging**: sending information about the user's requirements, plug-in and plug-out events, and receiving charging schedules
3. **Reporting**: sending charging session data

<Accordion title="View end-to-end flow for smart charging integration">
  ```mermaid theme={null}
  %%{init: {'theme': 'neutral'}}%%
  sequenceDiagram
      participant Charger
      participant Your API
      participant Axle API

      Note over Your API,Axle API: One-time setup per user
      Your API->>Axle API: POST /entities/site/onboard<br/>{proposition: "full_asset_schedule_control"}
      Axle API-->>Your API: {site_id, asset_ids, enrolment: {status: "enrolled"}}

      Your API->>Axle API: POST /entities/asset/{asset_id}/event/tariff
      Axle API-->>Your API: 200 OK

      Note over Charger,Axle API: Each charging session
      Charger->>Your API: User plugs in
      Your API->>Axle API: POST /entities/asset/{asset_id}/event/plug-in
      Axle API-->>Your API: OCPP SetChargingProfile
      Your API->>Charger: Apply schedule

      Note over Charger,Axle API: Schedule may be re-sent if<br/>tariff or intent changes, or Axle reoptimises

      Charger->>Your API: User unplugs
      Your API->>Axle API: POST /entities/asset/{asset_id}/event/plug-out

      Note over Your API,Axle API: Reporting
      Your API->>Axle API: POST /data/readings<br/>(half-hourly consumption)

      Note over Your API,Axle API: User offboarding
      Your API->>Axle API: POST /entities/site/{site_id}/unenrol
      Axle API-->>Your API: {"site_id": "...", "status": "unenrolled"}

  ```
</Accordion>

# 1. Onboarding & offboarding

## Onboard your site and asset

Register the site and EV charger with Axle and enrol them in the `full_asset_schedule_control` proposition — the proposition that lets Axle issue full charging schedules to the asset.

<Card title="Onboard" icon="rectangle-terminal" href="./api-reference/onboard">
  Create or update a site and its assets, and enrol them in a proposition.
</Card>

If you plan to enable [payments](/workflows/payments/overview) for your users, include `site.email` in the onboard payload. A user email is required to process payments through our provider, Stripe. We also send payment-failure notifications and, if enabled, two-factor authentication codes to this address.

<Tip>
  Save `site.site_id` and each `assets[].asset_id` from the response — you'll need the asset ID to send tariff, intent, and plug-in/plug-out events, and the site ID for rewards and offboarding.
</Tip>

## Stop participation

There are two ways to stop a user's participation. Pick based on what's actually happening:

* **Unenrol** when the user is opting out of Smart Charging specifically — for example, they turn it off in your app or withdraw consent. The site and assets stay on the platform, any other propositions they're enrolled in (such as Capacity Market) are unaffected, and they can re-enrol later and still access their payments.
* **Offboard** when the user is leaving entirely — for example, they've moved house, or your support team is removing them. This unenrols from every proposition and deletes the site and its assets per data-retention policies. Payments can no longer be accessed afterwards, so prompt the user to withdraw any outstanding balance first.

If in doubt, use **unenrol**. For the full picture, see the [Site and asset lifecycle](/workflows/asset-lifecycle#opting-out).

<CardGroup cols={2}>
  <Card title="Unenrol site" icon="rectangle-terminal" href="./api-reference/unenrol">
    Stop this proposition without deleting the site
  </Card>

  <Card title="Offboard site and assets" icon="rectangle-terminal" href="./api-reference/offboard">
    Remove the site and its assets
  </Card>
</CardGroup>

***

# 2. Charging

To deliver Smart Charging, we need to know the customer's tariff, intent and plugin/plugout events. We also need you to be able to receive and implement updated charging schedules.

We will issue charging schedules when a user plugs in; when a user updates their tariff or intent; or in response to wider market changes.

## Tariff

We need to know the user's tariff in order to optimise charging. You should send an update whenever the tariff changes.

<Card title="Send tariff" icon="rectangle-terminal" href="./api-reference/tariff">
  Send or update a user's tariff
</Card>

## Collect and communicate intent

We need to know how much energy is required and when the vehicle needs to be ready. Together, we refer to this as the user's **intent**.

### Energy requirements

We need to know how much energy is required in kWh. There are different ways to arrive
at this number.

| User provides    | Notes                                                 |
| ---------------- | ----------------------------------------------------- |
| **kWh to add**   | User describes requirement in kWh                     |
| **Hours to add** | Requires approximation of charge power                |
| ***Nothing***    | Can be approximated or fixed to e.g. 4 hours charging |

### Ready-by time

We need to know the deadline to deliver the energy requirements. You can collect ready-by with a standard time picker.

For more customisation, you can collect separate ready-by times for different:

* days of the week
* vehicles

And communicate these via API when the relevant vehicle plugs in.

### Sending intent

Our recommendation is to communicate intent whenever it changes, to ensure Axle scheduling always uses the most recent values.

<Card title="Send intent" icon="rectangle-terminal" href="./api-reference/intent">
  Send or update a user's charging intent
</Card>

Changes to intent while the car is plugged in can be issued to the same endpoint.

## Plugin and plugout events

Notify Axle when the vehicle plugs in and unplugs.

<Note>
  **Controlling via car?** Axle relies on a **"car is home" signal from the car manufacturer** before acting on plug-in events — no location or GPS data is needed, only a boolean indicating the vehicle is at home. In practice, this often means your API only forwards plug-in events to Axle when the car is at home; Axle treats every plug-in it receives as a home charge.
</Note>

<Card title="Plug-in event" icon="rectangle-terminal" href="./api-reference/plug-in">
  Notify Axle when a vehicle plugs in.
</Card>

<Card title="Plug-out event" icon="rectangle-terminal" href="./api-reference/plug-out">
  Notify Axle when a vehicle unplugs.
</Card>

## Receiving charging schedules

Axle will issue new schedules:

* When the user first plugs in
* When the user is already plugged in and one of the following events happens:
  * The user's tariff is updated
  * The user's intent changes
  * Axle reoptimises in response to changes in the wider market

In all cases, these schedules are issued `async`.

To issue schedules, we need you to make an endpoint available to which we can send API requests.

<Note>
  If you already have an existing API that you think will support smart charging,
  we can discuss integrating with that directly. However, our recommendation is
  to integrate with our OCPP style request format.
</Note>

We've developed an OCPP-based format to support smart charging, which provides the most robust, flexible solution. You can see an example of the dispatch events we send [here](/api-reference/examples/get-example-ocpp-charging-profile).

The benefits of building according to OCPP include:

* Specification of charge energy in an industry-standard format
* Stacking of schedules allows fallbacks in case devices go offline. For instance, our schedules should be overlaid
  upon a "default" schedule which always charges consumers during off-peak times

<Card title="Charging scenarios" icon="bolt" href="/workflows/smart-charging/scenarios">
  Worked examples showing how different intents and tariffs affect the schedules Axle sends
</Card>

## Special case: Communicating parameters upon enrolment

At the time of enrolment, we expect to immediately receive the information we need to schedule a charge. This means you should:

* Call either plug-in or plug-out to communicate the plug state of the charger at the moment of enrolment
* Set the user's tariff
* Set the intent — this can be a default value or the user's first input

Once we have these 3 pieces of information, we can schedule a charge.

***

# 3. Reporting

## Send readings

Send half-hourly consumption readings so Axle can verify delivery and calculate rewards.

<Card title="Send readings" icon="rectangle-terminal" href="./api-reference/readings">
  Notify Axle of asset consumption readings
</Card>

***

## Next Steps

<Card title="Earning from EV Charging" icon="coins" href="/workflows/ev-charging/paying-users/earning">
  Learn how to manage user payments and withdrawals
</Card>

```
```
