Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

bmw-cardata - BMW CarData Python Library

Async Python client for the BMW CarData customer API (REST) and the customer MQTT streaming feed.

[!IMPORTANT] The CarData REST API is rate-limited to 50 requests per day per user (BMW-side limit, not enforced by this library). Once exceeded, calls return HTTP 403 CU-429 API rate limit reached until the next day. For frequent updates use the MQTT streaming feed instead.

Prerequisites (one-time setup in the BMW customer portal)

Before this library can talk to the API you must complete a few steps in the BMW CarData customer portal:

  1. Generate a CarData client ID — Portal → CarData → Create CarData Client. Note the client ID; you will pass it to DeviceCodeFlowClient.
  2. Subscribe to services — subscribe the client to both CarData API and CarData Stream. Without this the OAuth scopes (cardata:api:read, cardata:streaming:read) will not be granted and the API/stream calls will be rejected.
  3. For REST telematic data: create a container selecting the telematic keys you want. See spec/telematic_catalogue.json for valid technical_descriptor values. You can also create containers from code via CarDataClient.create_container(...).
  4. For MQTT streaming: open Configure data stream and pick the streamable keys (those with "streamable": true in spec/telematic_catalogue.json). Without this step the MQTT broker will reject the subscribe with code:128.

Notes:

  • The REST API has a daily rate limit of 50 requests per user. Prefer streaming for frequent updates.
  • Only one streaming connection per gcid is allowed at a time.
  • Refresh tokens are valid for 14 days; access/id tokens for 1 hour.

Authentication (OAuth 2.0 Device Code Flow with PKCE)

import asyncio

from bmw_cardata import DeviceCodeFlowClient


async def main() -> None:
    async with DeviceCodeFlowClient(client_id="<your-client-id>") as auth:
        device = await auth.request_device_code()
        print(f"Open {device.verification_uri} and enter code {device.user_code}")
        token = await auth.poll_for_token(device.device_code, interval=device.interval)
        print("access_token:", token.access_token)
        print("id_token:", token.id_token)
        print("gcid:", token.gcid)
        print("refresh_token:", token.refresh_token)


asyncio.run(main())

Persist the refresh_token and use it to resume the session without prompting the user again:

auth = DeviceCodeFlowClient(client_id="...", refresh_token="<stored-refresh-token>")
token = await auth.refresh()  # new access/id/refresh tokens

REST client

import asyncio

from bmw_cardata import CarDataClient
from bmw_cardata.models import CreateContainerRequest


async def main() -> None:
    async with CarDataClient(access_token="<bearer-access-token>") as client:
        containers = await client.list_containers()
        for c in containers.containers:
            print(c.container_id, c.name, c.state)

        new = await client.create_container(
            CreateContainerRequest(
                name="my-container",
                purpose="example",
                technical_descriptors=["vehicle.powertrain.electric.battery.stateOfCharge"],
            )
        )
        data = await client.get_telematic_data("WBA...", container_id=new.container_id or "")
        for key, entry in data.telematic_data.items():
            print(key, entry.value, entry.unit, entry.timestamp)


asyncio.run(main())

You can also pass an async callable that returns a fresh token (handy for refresh flows):

async def token_provider() -> str:
    return await refresh_if_needed()

client = CarDataClient(access_token=token_provider)

Streaming (MQTT)

The customer MQTT broker authenticates with the user's gcid as username and the OAuth id_token (issued with the openid scope) as password.

import asyncio

from bmw_cardata import StreamingClient


async def main() -> None:
    async with StreamingClient(gcid="<gcid>", id_token="<id-token>") as stream:
        async for message in stream.stream():  # all VINs of this gcid
            print(message.vin, message.data)


asyncio.run(main())

To subscribe to a single VIN:

async for message in stream.stream(vin="WBA..."):
    ...

Endpoints covered

REST (CarDataClient):

  • list_containers, create_container, get_container, delete_container
  • get_mappings
  • get_basic_data(vin)
  • get_telematic_data(vin, container_id)
  • get_vehicle_image(vin) → raw bytes
  • get_smart_maintenance_tyre_diagnosis(vin)
  • get_charging_history(vin, from_, to, next_token=...)
  • get_location_based_charging_settings(vin, next_token=...)

Streaming (StreamingClient):

  • stream(vin=None) — async iterator of StreamingMessage

Development

pip install -e .[dev]
ruff format src
ruff check src
ty check src

License

MIT

Metadata

Release files for bmw-cardata 0.1.0a3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bmw-cardata 0.1.0a3
File Size Uploaded Provenance
bmw_cardata-0.1.0a3.tar.gz 67.4 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for bmw-cardata 0.1.0a3
File Interpreter ABI Platform
bmw_cardata-0.1.0a3-py3-none-any.whl Python 3 none any Details

Total release size: 114.5 kB

Release files / bmw_cardata-0.1.0a3.tar.gz

Download URL bmw_cardata-0.1.0a3.tar.gz
Size 67.4 kB
Tags Source
SHA-256 checksum
How to use checksums
2632da3ff86e18e503865bd5f0a0b8308009d1667ab722f02800c825ab7f30b5
BLAKE2b-256 checksum
How to use checksums
e3139ae5b6d3bc28d16bc37aea1c6b07bbf9ee9d19e380686224f544e337b72e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 3, 2026.

Transparency log

Release files / bmw_cardata-0.1.0a3-py3-none-any.whl

Download URL bmw_cardata-0.1.0a3-py3-none-any.whl
Size 47.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4ddd68ff3a356b6b779e6dec9f33ce1f15c874d9aefe9c2d014624da786ac48d
BLAKE2b-256 checksum
How to use checksums
3b443fb73f85f0207ffe1287d516c2289c6421f98f71b27f5be74deca14fe7c6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 3, 2026.

Transparency log

Security for bmw-cardata 0.1.0a3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for bmw_cardata-0.1.0a3.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 3, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page