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

# Quickstart

> Authenticate, create a program, enroll a device with Connect, read its state and commit it to a VPP event.

Enroll a test device and commit it to a VPP event. You need a [Console account](https://flatpeak.com/signup) with a trial: [contact support](https://console.flatpeak.com/support) to activate one.

### 1. Authenticate

Copy your **Account ID** and **secret key** from [Console](https://console.flatpeak.com/keys/api) > **API Keys**. Use a test mode key, which starts with `sk_test_`. Base64 encode `account_id:secret_key` and call [authentication](/docs/fleet-api/reference/authentication.md).

```bash Request example theme={"system"}
curl --request POST \
  --url https://fleet-api.flatpeak.com/auth/tokens \
  --header 'Authorization: Basic <base64 encoded account_id:secret_key>'
```

```json Response example theme={"system"}
{
  "bearer_token": "eyJhbGciOiJIUzI1NiIsInR5cC",
  "expires_in": 3600,
  "live_mode": false
}
```

The token lasts one hour, after which you request another.

### 2. Create a program

You see a device only through an enrollment in one of your programs, so start by [creating a VPP program](/docs/fleet-api/reference/vpp-programs/create.md). Set `listed` to `false`: an unlisted program is offered only from your app and needs no OEM approval.

```bash Request example theme={"system"}
curl --request POST \
  --url https://fleet-api.flatpeak.com/vpp-programs \
  --header 'Authorization: Bearer <bearer_token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "display_name": "Quickstart program",
  "listed": false,
  "currency_code": "GBP",
  "estimate": { "amount": 120, "period": "YEAR" },
  "terms": { "rewards": [{ "basis": "DELIVERED_KWH", "rate": 0.25 }] },
  "enrollment": { "dispatch_test_required": false }
}'
```

The program starts in `DRAFT`. Set `status` to `LIVE` with [update a VPP program](/docs/fleet-api/reference/vpp-programs/update.md); an unlisted program goes live at once. Keep its `id` for the next step.

### 3. Create a Connect session

You do not create devices: the customer signs in to their OEM account in Connect, and the device appears in the API. [Create a Connect session](/docs/fleet-api/reference/connect-sessions/create.md) with:

| Field | Value |
| :- | :- |
| `oem_id` | The OEM the customer signs in with, from [list all OEMs](/docs/fleet-api/reference/oems/list.md). Use `oem_6a3a8dada72cd0a249ff9528` to simulate an OEM and a device |
| `program_id` | The `id` of your program |
| `callback_url` | Where the customer returns. Use `myapp://flatpeak/complete` |

```bash Request example theme={"system"}
curl --request POST \
  --url https://fleet-api.flatpeak.com/connect-sessions \
  --header 'Authorization: Bearer <bearer_token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "oem_id": "oem_6a3a8dada72cd0a249ff9528",
  "program_id": "vpr_5c8d1f2a7b3e4d6c9a0f1b2c",
  "callback_url": "myapp://flatpeak/complete"
}'
```

```json Response example theme={"system"}
{
  "id": "cos_6a3196d6e61a44f33f7307ed",
  "object": "connect_session",
  "live_mode": false,
  "oem_id": "oem_6a3a8dada72cd0a249ff9528",
  "program_id": "vpr_5c8d1f2a7b3e4d6c9a0f1b2c",
  "device_id": null,
  "target_url": "https://universal.flatpeak.com",
  "callback_url": "myapp://flatpeak/complete",
  "time_created": "2026-07-08T18:37:27Z",
  "time_expiry": "2026-07-10T18:37:27Z",
  "account_id": "acc_6a5e504c3b98d0d6739b5f72"
}
```

The session expires 48 hours after creation.

### 4. Launch Connect

Open `https://universal.flatpeak.com` with the session ID as the `connect_session` query parameter:

```http theme={"system"}
https://universal.flatpeak.com/?connect_session=cos_6a3196d6e61a44f33f7307ed
```

The customer signs in with their OEM account, grants the `TELEMETRY`, `CONTROL`, `LOCATION` and `SETTINGS` scopes, and returns to your `callback_url`. The OEM app opens if installed, otherwise the OEM's web portal.

![Flatpeak Connect flow](https://mintcdn.com/flatpeak-d495c19e/2B6nWUU4-c2pSD3E/images/fleet/connect/connect-flow.png?fit=max\&auto=format\&n=2B6nWUU4-c2pSD3E\&q=85\&s=80d49f30ff49758cefffba42c7403534)

Left and right: your app. Middle: the OEM app or web portal.

### 5. Handle the callback

The customer lands on your `callback_url` with the session ID in the `connect_session` query parameter. [Retrieve the Connect session](/docs/fleet-api/reference/connect-sessions/retrieve.md) and read `device_id`, which is `null` if the customer left without connecting a device.

### 6. Retrieve the device

Call [retrieve a device](/docs/fleet-api/reference/devices/retrieve.md) with that `device_id`.

```bash Request example theme={"system"}
curl --request GET \
  --url https://fleet-api.flatpeak.com/devices/dev_63a6087272941ef077a8fd3e \
  --header 'Authorization: Bearer <bearer_token>'
```

```json Response example (truncated) theme={"system"}
{
  "id": "dev_63a6087272941ef077a8fd3e",
  "object": "device",
  "live_mode": false,
  "device_type": "BATTERY_STORAGE",
  "oem_id": "oem_6a3a8dada72cd0a249ff9528",
  "location_id": "loc_641b90b758fb8e6293716e40",
  "consent_scopes": ["TELEMETRY", "CONTROL", "LOCATION", "SETTINGS"],
  "dispatch_limits": {
    "max_import_power_kw": 8.4,
    "max_export_power_kw": 8.4,
    "storage_capacity_kwh": 14.2,
    "pv_peak_power_kw": null
  }
}
```

`enrollment_state` on the [enrollment](/docs/fleet-api/reference/vpp-enrollments/list.md) says whether you can dispatch the device. Change it with the [enrollment actions](/docs/fleet-api/guides/programs/enrollment-states.md#actions).

### 7. Connect a tariff

A device cannot enroll until its location has an `IMPORT` and an `EXPORT` `COMMODITY` tariff. Until then the enrollment waits in `PENDING`, at step `AWAITING_TARIFF`. See [Tariffs](/docs/fleet-api/guides/devices/tariffs.md).

* If your account supplies energy, create both tariffs at the device's `location_id` with [create a tariff](/docs/fleet-api/reference/tariffs/create.md).
* If it does not, the customer connects their own tariff in Connect and the step clears.

```bash Request example (account that supplies energy) theme={"system"}
curl --request POST \
  --url https://fleet-api.flatpeak.com/tariffs \
  --header 'Authorization: Bearer <bearer_token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "location_id": "loc_641b90b758fb8e6293716e40",
  "tariff_type": "COMMODITY",
  "direction": "IMPORT",
  "display_name": "Two-rate home tariff",
  "contract_start_date": "2026-07-01T00:00:00Z",
  "contract_end_date": "2027-06-30T23:59:59Z",
  "schedule": [
    {
      "months": ["All"],
      "days_and_hours": [
        {
          "days": ["All"],
          "hours": [
            {
              "valid_from": "00:00:00",
              "valid_to": "07:00:00",
              "rate": { "vat_included": "YES", "vat_percentage": 0.05, "variables": { "price": 0.12 }, "expression": "$price" }
            },
            {
              "valid_from": "07:00:00",
              "valid_to": "00:00:00",
              "rate": { "vat_included": "YES", "vat_percentage": 0.05, "variables": { "price": 0.29 }, "expression": "$price" }
            }
          ]
        }
      ]
    }
  ]
}'
```

Repeat with `"direction": "EXPORT"`. With no dispatch test and no approval required, the enrollment is then `ACTIVE`.

### 8. Retrieve device state

Call [retrieve a device state](/docs/fleet-api/reference/device-state/retrieve.md).

```bash Request example theme={"system"}
curl --request GET \
  --url https://fleet-api.flatpeak.com/devices/dev_63a6087272941ef077a8fd3e/state \
  --header 'Authorization: Bearer <bearer_token>'
```

```json Response example theme={"system"}
{
  "object": "device_state",
  "device_id": "dev_63a6087272941ef077a8fd3e",
  "oem_id": "oem_6a3a8dada72cd0a249ff9528",
  "time_recorded": "2026-07-08T19:30:00Z",
  "available": true,
  "power_kw": -3.4,
  "state_of_charge_percent": 34.2,
  "available_import_energy_kwh": 5.9,
  "available_export_energy_kwh": 5.5
}
```

Negative `power_kw` means the device is discharging. `available_export_energy_kwh` is already net of the customer's backup reserve, which is never dispatched.

### 9. Create a VPP event

A VPP event commits a group of devices to a power target per interval. First [create a group](/docs/fleet-api/reference/groups/create.md) that holds the device:

```bash Request example theme={"system"}
curl --request POST \
  --url https://fleet-api.flatpeak.com/groups \
  --header 'Authorization: Bearer <bearer_token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "Quickstart",
  "device_ids": ["dev_63a6087272941ef077a8fd3e"]
}'
```

```json Response example (truncated) theme={"system"}
{
  "id": "grp_2f6a9c1d8e3b5a7c4d0e9f1a",
  "object": "group",
  "live_mode": false,
  "name": "Quickstart",
  "filter": null,
  "device_count": 1
}
```

Then [create a VPP event](/docs/fleet-api/reference/vpp-events/create.md) for the group, to charge the device at 4.3 kW overnight. `power_kw` is positive for import and negative for export, up to `max_import_power_kw` and `max_export_power_kw` in `dispatch_limits`.

```bash Request example theme={"system"}
curl --request POST \
  --url https://fleet-api.flatpeak.com/vpp-events \
  --header 'Authorization: Bearer <bearer_token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "event_type": "TEST",
  "group_id": "grp_2f6a9c1d8e3b5a7c4d0e9f1a",
  "intervals": [
    { "start_time": "2026-07-09T02:00:00Z", "end_time": "2026-07-09T04:30:00Z", "power_kw": 4.3 }
  ]
}'
```

```json Response example (truncated) theme={"system"}
{
  "id": "vpe_7d2a4c6e9b1f3a5c8e0d2f4b",
  "object": "vpp_event",
  "live_mode": false,
  "event_type": "TEST",
  "status": "ALLOCATION_OPEN",
  "group_id": "grp_2f6a9c1d8e3b5a7c4d0e9f1a",
  "device_count": 1,
  "start_time": "2026-07-09T02:00:00Z",
  "end_time": "2026-07-09T04:30:00Z",
  "time_created": "2026-07-08T19:45:22Z"
}
```

Flatpeak bounds the target to the device's limits and passes it to the OEM as a binding instruction, which the OEM confirms. `TEST` events do not affect settlement.

### 10. Check delivery

After the event, call [list device meter records](/docs/fleet-api/reference/meter-records/list-device.md). At 4.3 kW, each half hour records about 2.15 kWh of import.

```bash Request example theme={"system"}
curl --request GET \
  --url 'https://fleet-api.flatpeak.com/devices/dev_63a6087272941ef077a8fd3e/meter-records?start_time=2026-07-09T02:00:00Z&end_time=2026-07-09T04:30:00Z&aggregate_by=HALF_HOUR&order_by=OLDEST&limit=100' \
  --header 'Authorization: Bearer <bearer_token>'
```

```json Response example (truncated) theme={"system"}
{
  "object": "meter_records",
  "device_id": "dev_63a6087272941ef077a8fd3e",
  "oem_id": "oem_6a3a8dada72cd0a249ff9528",
  "count": 5,
  "next_cursor": null,
  "data": [
    {
      "start_time": "2026-07-09T02:00:00Z",
      "end_time": "2026-07-09T02:30:00Z",
      "energy_kwh": 2.15
    },
    {
      "start_time": "2026-07-09T02:30:00Z",
      "end_time": "2026-07-09T03:00:00Z",
      "energy_kwh": 2.15
    }
  ]
}
```

The [dispatch timeline](/docs/fleet-api/reference/plans/retrieve-timeline.md) shows what the device did per interval, with the VPP event behind it.

## Next steps

> [card] [Programs](/docs/fleet-api/guides/programs.md)
>
> Terms, eligibility, telemetry and publishing.

> [card] [VPP events](/docs/fleet-api/guides/dispatch/vpp-events.md)
>
> Commit a group and track delivery.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.