> ## 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 your battery fleet directly with the Axle VPP

This pathway is for battery manufacturers (OEMs) who run their own cloud platform and
want their users to be able to join the Axle VPP.
You send us telemetry, we handle optimisation, market participation and customer relations.
We'll send dispatch instructions to an endpoint you provide for you to execute on your own fleet.

```mermaid theme={null}
sequenceDiagram
    participant OEM
    participant Axle

    Note over OEM,Axle: Setup
    OEM->>Axle: Register assets (onboarding)

    Note over OEM,Axle: Ongoing
    OEM->>Axle: POST /data/readings (telemetry)

    Note over OEM,Axle: Grid Event
    Axle->>OEM: POST dispatch instruction to your webhook
    OEM->>OEM: Apply target power to each asset
```

The integration has three parts:

1. [Onboarding](#1-onboarding)
2. [Telemetry](#2-telemetry)
3. [Dispatch](#3-dispatch)

## 1. Onboarding

Each battery needs a `site_id` and `asset_id` in Axle's system before you can send telemetry or
receive dispatch for it — these are the identifiers used throughout the rest of the integration.
There are two ways to get there.

<Tabs>
  <Tab title="Through your app">
    If you already collect address, consent and asset details yourself, call Axle's onboarding API
    directly.

    <Card title="Onboard site and asset" icon="rectangle-terminal" href="./api-reference/onboard">
      Register a site and battery, returns `site_id` and `asset_id`.
    </Card>

    Example request

    ```json theme={null}
    {
      "site": {
        "mpan": "1234567890123",
        "postcode": "SW1A 1AA",
        "street_address": "10 Downing Street",
        "gave_boundary_meter_consent_at": "2025-01-01T12:00:00Z"
      },
      "asset": {
        "external_id": "battery-001",
        "type": "battery",
        "properties": {
          "power_kw": 5.0,
          "capacity_kwh": 13.5
        }
      },
      "dispatch_consent": {
        "dispatch_methods": ["vpp_limited_control"]
      }
    }
    ```

    Your backend authenticates as described in [Authentication](./api-reference/auth).

    <Note>
      For events only mode you should use `vpp_limited_control` in the `dispatch_methods` array.
      If you want to allow full control of the battery, use `full_asset_schedule_control` instead.
    </Note>
  </Tab>

  <Tab title="Through Axle's signup flow">
    If you'd rather not build a signup UI, your customers can sign up on a flow Axle hosts and
    connect their battery by signing in with their existing account on your platform. Your
    platform acts as the OAuth2 provider (authorisation server) and Axle is the client — a
    standard authorisation-code flow, the same way we integrate with manufacturers today.

    <Steps>
      <Step title="Customer starts on Axle's signup page">
        The customer lands on Axle's signup page and begins signup. Axle creates the site at this
        point.
      </Step>

      <Step title="Customer selects your brand and connects">
        The customer picks your brand as their battery manufacturer and clicks "Connect". Axle
        redirects them to your OAuth2 authorisation page with `client_id`, `redirect_uri`, `scope`
        and `state`.
      </Step>

      <Step title="Customer signs in with you">
        The customer signs in with their existing account and authorises access — no Axle password
        needed. You redirect them back to Axle's callback with an authorisation code, which Axle
        exchanges for an access token server-to-server at your token endpoint.
      </Step>

      <Step title="Axle identifies the battery">
        Axle calls your device-list API with the access token to find the customer's devices. The
        customer confirms their battery and completes address, MPAN and consent — staying on Axle
        throughout, finishing on an Axle-hosted welcome page. Axle creates the asset with your
        device serial recorded against it.
      </Step>

      <Step title="Axle registers the asset with you">
        Axle POSTs the new asset to an endpoint on your API, authenticated with the same access
        token. The payload carries the `asset_id` you'll use for [Telemetry](#2-telemetry) and
        [Dispatch](#3-dispatch), together with the device serial so you can match it to your
        customer:

        ```json theme={null}
        {
          "asset_id": "3c361164-5187-4b4b-8e8a-7b3f67c4d5a8",
          "device_serial": "OEM-SERIAL-12345"
        }
        ```
      </Step>
    </Steps>

    ```mermaid theme={null}
    sequenceDiagram
        participant Customer
        participant Axle
        participant OEM

        Note over Axle,OEM: You are the OAuth2 provider
        Customer->>Axle: Start signup on Axle's page
        Axle->>Axle: Create site
        Customer->>Axle: Select manufacturer, click "Connect"
        Axle-->>Customer: Redirect to your OAuth2 sign-in
        Customer->>OEM: Sign in & authorise access
        OEM-->>Customer: Redirect back to Axle with auth code
        Axle->>OEM: Exchange code for access token
        Axle->>OEM: Fetch customer's devices (device-list API)
        Customer->>Axle: Confirm device, address & consent (stays on Axle)
        Axle->>Axle: Create asset
        Axle->>OEM: POST asset (asset_id + device serial)
        Axle-->>Customer: Show Axle welcome page
    ```

    ### What you need to provide

    * A standard OAuth2 authorisation-code flow: a hosted sign-in page and a token endpoint
    * A `client_id` and `client_secret` issued to Axle
    * Axle's redirect URI whitelisted: `https://api.axle.energy/vpp/oauth/{provider}/callback`
    * A scope granting access to the customer's devices
    * A device-list API returning the customer's devices (serial, power/capacity) for a given
      access token
    * An endpoint on your API that accepts the asset registration shown above
  </Tab>
</Tabs>

## 2. Telemetry

Send regular readings for each battery so we can optimise it and verify delivery. We rely mainly
on two readings:

* **Battery state of charge** — `battery_state_of_charge_pct` (0–100)
* **Grid import/export** at the site boundary — `boundary_import_kw`

Grid power is bidirectional, so the sign tells us the direction: **positive = import** from the
grid, **negative = export** to the grid. If you can also send inverter power
(`battery_inverter_import_kw`) and solar generation (`solar_power_kw`), we'll use them to improve
optimisation and determine event earnings.

Push readings to the readings endpoint, which lists every accepted `label` and its sign
convention.

<Card title="Send telemetry" icon="rectangle-terminal" href="./api-reference/telemetry">
  Push battery and boundary readings to Axle.
</Card>

<Note>
  If pushing readings doesn't suit your platform, we can also pull readings from custom endpoints
  you provide — [get in touch](mailto:hello@axle.energy) to discuss your setup.
</Note>

## 3. Dispatch

During a grid event we send a dispatch instruction to a webhook URL you provide. Each instruction
covers a single event and sets a target power for every affected asset over a fixed window.

You supply the webhook URL when you set up your integration — [get in
touch](mailto:hello@axle.energy) to register it.

```json theme={null}
{
  "event_id": "eab8c867-7c4d-4116-a587-02c9d1f13a16",
  "issued_timestamp": "2026-06-29T17:02:37.448917+00:00",
  "start_time": "2026-06-30T20:30:00+00:00",
  "end_time": "2026-06-30T21:30:00+00:00",
  "assets": [
    { "asset_id": "3c361164-5187-4b4b-8e8a-7b3f67c4d5a8", "power_kw": -6.915 },
    { "asset_id": "1a161164-5187-4b4b-8e8a-7b3f67c4d5a8", "power_kw": -4.915 }
  ]
}
```

`power_kw` uses the same sign convention as telemetry: **positive = charge** (import into the
battery), **negative = discharge** (export). Apply the target power to each asset for the window
between `start_time` and `end_time`.

<Card title="Dispatch webhook" icon="webhook" href="./api-reference/dispatch">
  Full schema for the dispatch instruction we send to your webhook.
</Card>

<Note>
  If you already have your own dispatch API, we can work with custom dispatch endpoints instead of
  the webhook above — [get in touch](mailto:hello@axle.energy) to discuss your setup.
</Note>

### Important points

* Customers should be able to override dispatch instructions at any time.
* The battery should return to its original mode of operation after the dispatch event has
  finished
