@eiguudewie/node-red-contrib-bmw-cardata 0.10.1
BMW CarData API integration for Node-RED – OAuth2 Device Flow with PKCE, SoC and telemetry access for electric vehicles
@eiguudewie/node-red-contrib-bmw-cardata
Node-RED integration for the BMW CarData REST API. Reads vehicle telemetry such as State of Charge (SoC) via OAuth2 and forwards it to other systems.
Table of Contents
- Overview
- Prerequisites
- BMW CarData Portal – Setup
- Installation
- Configuration
- Nodes
- Rate Limit
- API Endpoints
- License
Overview
This package provides three Node-RED nodes for the BMW CarData REST API:
- bmw-cardata-config – Central config node. Manages OAuth2 authentication (Device Flow with PKCE), automatic token refresh, and container lifecycle. Shared by all other nodes.
- bmw-cardata-soc – Reads the battery State of Charge (SoC). Simple, fixed datapoints, output as integer or full object.
- bmw-cardata-query – Generic query node. Configurable datapoints and container name, returns the full raw telemetry response.
Authentication is handled once via a browser-based BMW account confirmation. Tokens are stored and refreshed automatically. Container management (required by the BMW API) is fully automatic and cached locally.
Prerequisites
- Node-RED >= 3.0
- Node.js >= 16
- BMW vehicle with an active ConnectedDrive account
- Registered BMW CarData API client (see below)
BMW CarData Portal – Setup
Before using the nodes you need to create an API client in the BMW CarData Portal. This is a one-time step.
1. Open the BMW CarData Portal
→ https://bmw-cardata.bmwgroup.com/customer
Sign in with your BMW ConnectedDrive account.
2. Create a Client ID
- Navigate to "API Clients" → "Create CarData Client"
- Enter a name (e.g.
HomeAutomation) - Select the scope
cardata:api:read - Confirm the creation
- Copy the displayed Client ID (format:
XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)
⚠️ The Client ID is only shown in full once – save it immediately.
3. Find your VIN
The VIN (Vehicle Identification Number) is 17 characters long. Where to find it:
- Dashboard (base of the windshield, visible from outside) or driver's door jamb sticker
- Vehicle registration or title document
- BMW ConnectedDrive app or online portal
- Vehicle registration certificate (Zulassungsbescheinigung Teil I, field E) — Germany
Installation
Via the Node-RED Palette Manager: search for @eiguudewie/node-red-contrib-bmw-cardata and click Install.
Via npm:
cd ~/.node-red
npm install @eiguudewie/node-red-contrib-bmw-cardata
Then restart Node-RED:
sudo systemctl restart nodered
# or
node-red
Configuration
All nodes share a single bmw-cardata-config node that holds credentials and manages the API session. Configure it once and reuse it across all BMW nodes in your flow.
Authentication (OAuth2 Device Flow with PKCE)
- Open the config node, enter Client ID and VIN, then save
- Click "Authenticate now"
- Open the displayed link in your browser and enter the user code
- Sign in with your BMW account and confirm access
- Node-RED detects the confirmation automatically and stores the token
The access token is renewed automatically using the stored refresh token. The session is persisted in ~/.node-red/bmw-cardata-session-{nodeId}.json.
Containers
The BMW CarData API requires a container that declares which datapoints to return. The plugin manages containers automatically:
- On first use, a suitable ACTIVE container is located or a new one is created
- Container keys and IDs are cached locally — subsequent requests need no extra API calls
- The Inspect containers button in the config node shows all containers and their cached keys
- Individual containers can be deleted from the UI
- Clear container cache forces a fresh lookup on the next request
Default keys used when no custom keys are configured:
| Key | Description |
|---|---|
vehicle.drivetrain.batteryManagement.header |
State of Charge (%) |
vehicle.drivetrain.electricEngine.charging.status |
Charging status |
vehicle.powertrain.electric.battery.charging.power |
Charging power (kW) |
API Call Counter
The config node tracks every API call and shows the running total in the UI. The counter and last-call timestamp are persisted across Node-RED restarts.
- Resets automatically when a rate-limit response is received (HTTP 403, error code
CU-429) - Can be reset manually via the Reset counter button or by sending
msg.resetCallCounter = true - Can be reset automatically on a daily schedule via the Reset counter at field (
HH:MM, 24h format, e.g.04:00)
Debug Mode
When Debug Mode is enabled, verbose trace and info messages appear in the Node-RED log, prefixed with [bmw-cardata]. Warnings and errors are always logged.
| Level | When logged |
|---|---|
trace |
Debug mode only — token TTL, raw API responses, container lookup steps |
info |
Debug mode only — session loaded, token refreshed, container found/created |
warn |
Always — recoverable errors, 404 retries, rate limit hit |
error |
Always — failures that stop an operation |
Nodes
bmw-cardata-config
Central configuration node. Manages authentication, token refresh, and container lifecycle.
| Field | Description |
|---|---|
| Client ID | API Client ID from the BMW CarData Portal |
| VIN | 17-character Vehicle Identification Number |
| Debug Mode | Enable verbose log output |
bmw-cardata-soc
Reads the vehicle's State of Charge (SoC). Always uses the three built-in default datapoints. For custom datapoints use bmw-cardata-query instead.
Input
| Property | Description |
|---|---|
| any message | Triggers the request |
msg.vin |
Override the configured VIN |
msg.resetCallCounter = true |
Reset the API call counter before the request |
Output
| Property | Description |
|---|---|
msg.payload |
SoC as integer, e.g. 75 (SoC only mode) |
msg.payload |
{ soc, vin, timestamp, raw, apiCalls } (Full object mode) |
msg.bmw |
Object with all fields above |
msg.apiCalls |
{ count, lastCallAt } |
msg.topic |
bmw/{VIN}/soc |
Settings
| Field | Description |
|---|---|
| Output mode | SoC only (integer) or Full object |
| Show call count | Append API call count to node status text |
bmw-cardata-query
Generic query node. Returns the full raw telemetry response for a configurable set of datapoints.
Container modes
| Configuration | Behaviour |
|---|---|
| Keys + Name | Finds or creates a container with those keys, named as specified |
| Keys only | Finds or creates a container with those keys, named NR_Default |
| Name only | Looks up an existing ACTIVE container by name, returns all its data |
| Neither | Uses the three built-in default keys |
An existing container whose keys are a superset of the requested keys will be reused — no new container is created unnecessarily.
Input
| Property | Description |
|---|---|
| any message | Triggers the request |
msg.vin |
Override the configured VIN |
msg.resetCallCounter = true |
Reset the API call counter before the request |
Output
| Property | Description |
|---|---|
msg.payload |
Full raw telematic data response object |
msg.apiCalls |
{ count, lastCallAt } |
msg.topic |
bmw/{VIN}/query |
Settings
| Field | Description |
|---|---|
| Container Name | Name for new containers, or name to look up (name-only mode). Active container names are suggested as you type. |
| Container Keys | Datapoints to request, one per line. Leave empty for defaults or name-only mode. |
| Show call count | Append API call count to node status text |
Rate Limit
⚠️ The BMW CarData API allows a maximum of 50 calls per 24 hours. The exact daily reset time is not documented by BMW.
Recommendations:
- Trigger SoC requests at an interval of at least 30 minutes (≤ 48 calls/day)
- Container list and detail requests also count against the limit — use the local cache
- Monitor the API call counter in the config node UI
API Endpoints
All endpoints are based on the official BMW CarData Swagger spec.
| Purpose | Endpoint |
|---|---|
| Device code | POST https://customer.bmwgroup.com/gcdm/oauth/device/code |
| Token | POST https://customer.bmwgroup.com/gcdm/oauth/token |
| Create container | POST https://api-cardata.bmwgroup.com/customers/containers |
| List containers | GET https://api-cardata.bmwgroup.com/customers/containers |
| Container details | GET https://api-cardata.bmwgroup.com/customers/containers/{containerId} |
| Delete container | DELETE https://api-cardata.bmwgroup.com/customers/containers/{containerId} |
| Telematic data | GET https://api-cardata.bmwgroup.com/customers/vehicles/{vin}/telematicData?containerId=... |
| Vehicle mappings | GET https://api-cardata.bmwgroup.com/customers/vehicles/mappings |
License
MIT