This document defines the Tesla data architecture for Car Pulse Tracker.
It should be read together with:
doc/md/bnc-cpt-api.CORE-DATA-ARCHITECTURE.mdThis document remains Tesla-specific. The core-data architecture document defines the provider-agnostic target model that Tesla must fit into.
It is not an endpoint catalog. It defines:
Current Tesla report generation is still centered on per-vehicle fetch/build logic.
That is wrong for multi-vehicle accounts because:
The main example is charging history:
vin_build_vehicle_report(...)That is not reliable enough for enterprise use.
The source-of-truth chain must be:
requestRawvehiclesByVinRenderers must never solve vehicle attribution.
Inputs:
Output:
requestContextFetch once per order/report request:
GET /api/1/users/regionGET /api/1/vehiclesGET /api/1/dx/charging/historyPurpose:
Create one root object per VIN:
vehiclesByVin[vin]Populate root identity from:
GET /api/1/vehiclesGET /api/1/vehicles/{vin}Fetch per selected VIN:
GET /api/1/vehicles/{vin}/vehicle_dataGET /api/1/vehicles/{vin}/recent_alertsGET /api/1/vehicles/{vin}/service_dataGET /api/1/vehicles/{vin}/release_notesGET /api/1/dx/vehicles/options?vin={vin}GET /api/1/dx/warranty/details?vin={vin}Conditional:
GET /api/1/vehicles/{vin}/specs only when a partner token is availableNormalize raw Tesla payloads into:
requestRawvehiclesByVinThis is the only phase where:
Build:
These must all derive from vehiclesByVin, not from live Tesla calls.
Use for current customer-authorized flows.
Use for:
users/regionvehiclesvehicles/{vin}vehicle_datarecent_alertsservice_datarelease_notesoptionswarranty_detailscharging_historycharging_invoiceUse where Tesla explicitly requires it.
Current known case:
GET /api/1/vehicles/{vin}/specsFuture fleet mode only.
Relevant Tesla endpoint:
GET /api/1/dx/charging/sessions{
"requestContext": {
"tokenType": "third_party",
"fleetApiBaseUrl": "https://fleet-api.prd.eu.vn.cloud.tesla.com",
"selectedVins": [
"LRW3E7EK1RC988948"
],
"fetchedAt": "2026-03-07T18:00:00Z"
},
"requestRaw": {
"userRegion": {},
"vehicles": {},
"chargingHistory": {}
},
"vehiclesByVin": {
"LRW3E7EK1RC988948": {
"vehicle": {},
"vehicleData": {},
"recentAlerts": [],
"serviceData": {},
"releaseNotes": [],
"options": {},
"warrantyDetails": {},
"vehicleSpecs": {},
"chargingHistory": []
}
}
}
vehicle_data is enrichment, not root identity.requestRaw.vehiclesByVin.Charging sessions already carry their own vin.
So the correct rule is:
vehiclesByVin[session.vin].chargingHistoryThe wrong rule is:
_build_vehicle_report(...)That late filter can remain as a sanity guard, but it must not be the architecture.
generate_reports() loops selected vehicles_build_vehicle_report() fetches Tesla modules per vehicleMeaning:
_build_vehicle_report() should stop being a Tesla fetch functionThe architecture change is complete only when all are true:
vehiclesByVin[vin] rootoptions uses GET /api/1/dx/vehicles/options?vin={vin}specs is fetched only through a partner-token path or is explicitly absentservice_data empty responses remain non-breakingFor Tesla integration:
No further report expansion should depend on the old per-vehicle fetch/build architecture.