API reference
Vehicles
Your Tesla vehicles and your organization's fleet: live state, commands, drives, charging, parked periods, keys and drivers, places, tariffs and sharing.
See Vehicles. A vehicle belongs to one space, your Personal space or an organization's, and routes take that space in their path. A key needs vehicles:read to read, vehicles:write to change settings, places and tariffs, and vehicles:control to send commands; each command also needs the matching capability on that vehicle. A vehicle's position is only in answers where its sharing allows it.
GET /v1/vehicles/tesla/callback
Tesla's registered redirect after sign-in (no token): spends the one-time state, hands the code to Vehicles' worker and redirects the browser to the app's finish page with a ticket or a reason. Never shows a page of its own.
Auth: none
Errors
| Status | Message |
|---|---|
404 | Vehicles isn't available here. |
GET /v1/platform/vehicles/pictures
The switch, every rule (with what is wrong with one that fails validation, and overlaps) and the misses.
Auth: user access token or platform agent key · Scope: platform:admin in the platform organization
Response 200
{
switch: {
enabled: boolean
rev: number
epoch: number
}
rules: {
invalid?: string
ruleId: string
carType: string
fromYear?: number
toYear?: number
slot: "trim" | "base" | "paint" | "wheels" | "roof" | "spoiler" | "exteriorTrim"
value: string
codes: string[]
enabled: boolean
note?: string
model?: string
defaults?: {
trim?: string[]
paint?: string[]
wheels?: string[]
roof?: string[]
spoiler?: string[]
exteriorTrim?: string[]
}
}[]
warnings: {
ruleId: string
other: string
message: string
}[]
misses: {
carType: string
slot: string
value: string
count: number
firstSeen: number
lastSeen: number
}[]
}Errors
| Status | Message |
|---|---|
503 | The platform table isn't available here. |
GET /v1/platform/vehicles/pictures/rules
The picture rules, and the warnings about them (platform staff).
Auth: user access token or platform agent key · Scope: platform:admin in the platform organization
Response 200
{
rules: {
invalid?: string
ruleId: string
carType: string
fromYear?: number
toYear?: number
slot: "trim" | "base" | "paint" | "wheels" | "roof" | "spoiler" | "exteriorTrim"
value: string
codes: string[]
enabled: boolean
note?: string
model?: string
defaults?: {
trim?: string[]
paint?: string[]
wheels?: string[]
roof?: string[]
spoiler?: string[]
exteriorTrim?: string[]
}
}[]
warnings: {
ruleId: string
other: string
message: string
}[]
}Errors
| Status | Message |
|---|---|
503 | The platform table isn't available here. |
PUT /v1/platform/vehicles/pictures/rules/:ruleId
Writes a rule (creating or replacing it by id). Raises rev.
Auth: user access token or platform agent key · Scope: platform:admin in the platform organization
| Path parameter | Description |
|---|---|
:ruleId | Rule id: a storage lifecycle rule (as returned by the settings or lifecycle routes), an issue automation rule (rul_…) or a Mirage AutoMod rule (mar_…). |
Request body
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
carType | string | Yes | up to 40 characters | |
fromYear | integer | No | can be null | |
toYear | integer | No | can be null | |
slot | string | Yes | up to 20 characters | |
value | string | Yes | up to 200 characters | |
codes | string[] | Yes | up to 50 items; each up to 20 characters | |
enabled | boolean | No | true | |
note | string | No | up to 1,000 characters; can be null | |
model | string | No | up to 20 characters; can be null | |
defaults | object | No | keys up to 20 characters; values: string[] (up to 50 items, each up to 20 characters); can be null |
Also checked: Unknown fields are rejected.
Response 200
{
rule: {
ruleId: string
carType: string
fromYear?: number
toYear?: number
slot: "trim" | "base" | "paint" | "wheels" | "roof" | "spoiler" | "exteriorTrim"
value: string
codes: string[]
enabled: boolean
note?: string
model?: string
defaults?: {
trim?: string[]
paint?: string[]
wheels?: string[]
roof?: string[]
spoiler?: string[]
exteriorTrim?: string[]
}
}
warnings: {
ruleId: string
other: string
message: string
}[]
switch: {
enabled: boolean
rev: number
epoch: number
}
}Errors
| Status | Message |
|---|---|
503 | The platform table isn't available here. |
DELETE /v1/platform/vehicles/pictures/rules/:ruleId
Removes a picture rule. Raises rev.
Auth: user access token or platform agent key · Scope: platform:admin in the platform organization
| Path parameter | Description |
|---|---|
:ruleId | Rule id: a storage lifecycle rule (as returned by the settings or lifecycle routes), an issue automation rule (rul_…) or a Mirage AutoMod rule (mar_…). |
Response 200
{
ok: true
switch: {
enabled: boolean
rev: number
epoch: number
}
}Errors
| Status | Message |
|---|---|
404 | Rule not found |
503 | The platform table isn't available here. |
GET /v1/platform/vehicles/pictures/misses
The values no rule covers, most recent first: what to map next.
Auth: user access token or platform agent key · Scope: platform:admin in the platform organization
Response 200
{
misses: {
carType: string
slot: string
value: string
count: number
firstSeen: number
lastSeen: number
}[]
}Errors
| Status | Message |
|---|---|
503 | The platform table isn't available here. |
DELETE /v1/platform/vehicles/pictures/misses
Dismisses a miss (?carType=&slot=&value=); audited.
Auth: user access token or platform agent key · Scope: platform:admin in the platform organization
Response 200
{
ok: true
}Errors
| Status | Message |
|---|---|
503 | The platform table isn't available here. |
GET /v1/platform/vehicles/pictures/switch
Whether car pictures are on.
Auth: user access token or platform agent key · Scope: platform:admin in the platform organization
Response 200
{
switch: {
enabled: boolean
rev: number
epoch: number
}
}Errors
| Status | Message |
|---|---|
503 | The platform table isn't available here. |
PUT /v1/platform/vehicles/pictures/switch
Turns pictures on or off. Off: no picture anywhere and no fetch, within a minute (the API's cache).
Auth: user access token or platform agent key · Scope: platform:admin in the platform organization
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
enabled | boolean | Yes |
Also checked: Unknown fields are rejected.
Response 200
{
switch: {
enabled: boolean
rev: number
epoch: number
}
}Errors
| Status | Message |
|---|---|
503 | The platform table isn't available here. |
POST /v1/platform/vehicles/pictures/refresh-all
Refresh all: new keys in the bucket (a new epoch), fetched as cars are seen, and every car resolved again.
Auth: user access token or platform agent key · Scope: platform:admin in the platform organization
Response 200
{
switch: {
enabled: boolean
rev: number
epoch: number
}
}Errors
| Status | Message |
|---|---|
503 | The platform table isn't available here. |
POST /v1/platform/vehicles/pictures/preview
Resolves submitted values through the worker: { year?, config: { carType, exteriorColor, … }, include?: [ruleId] } (include: disabled rows to use for this preview only). ready carries signed links on our CDN for each view, the model and the codes it sent; every other outcome carries a message.
Auth: user access token or platform agent key · Scope: platform:admin in the platform organization
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
year | integer | No | |
config | object | Yes | keys up to 40 characters; values: string (up to 200 characters) |
include | string[] | No | up to 20 items; each up to 80 characters |
Also checked: Unknown fields are rejected.
Response 200
{
model?: string
codes?: string[]
misses?: {
carType: string
slot: string
value: string
}[]
outcome: "busy" | "no_rule" | "mapping" | "fetch" | "timeout"
message: string
}
| {
views: {
"3qtr"?: {
srcset: {
url: string
width: number
height: number
}[]
box: {
x: number
y: number
w: number
h: number
}
}
side?: {
srcset: {
url: string
width: number
height: number
}[]
box: {
x: number
y: number
w: number
h: number
}
}
}
approximate?: string[]
outcome: string
model: string
codes: string[]
}Errors
| Status | Message |
|---|---|
403 | The preview is for people in Admin. |
503 | The platform table isn't available here. |
503 | The picture CDN isn't on here, so there is nothing to show a preview from. |
POST /v1/me/vehicles/connections/tesla/authorize
Starts connecting your Tesla account: send the consent you gave (each data category, and precise location as its own choice); returns Tesla's sign-in url and a browserValue for the app to keep as an HttpOnly cookie and send back to finish. Only from the Vehicles and phone apps.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
returnTo | string | No | up to 300 characters |
reconnect | string | No | up to 80 characters |
consent | object | Yes | |
consent.categories | ("vehicle_state" | "commands" | "charging")[] | Yes | |
consent.location | boolean | Yes |
Response 200
{
url: string
browserValue: string
expiresAt: number
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
403 | Connect a Tesla account in the Vehicles app. |
404 | Not found |
POST /v1/me/vehicles/connections/tesla/finish
Finishes the connection with the ticket from the redirect and the browserValue. Kept only for the person and browser that started it, otherwise the tokens are discarded. 202 pending while the exchange is still running (ask again in a second).
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
ticket | string | Yes | 1–200 characters |
browserValue | string | Yes | 1–200 characters |
Response 200
{
connection: {
connectionId: string
provider: "tesla"
status: "ok" | "revoked" | "reconnect" | "disconnecting"
region: "na-apac" | "eu"
scopes: string[]
location: boolean
createdAt: number
createdBy?: string
lastRefreshAt?: number
notice?: string
}
returnTo?: string
reconnected: boolean
sameAccount: boolean
}Response 202
{
status: string
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
403 | Connect a Tesla account in the Vehicles app. |
404 | Not found |
GET /v1/me/vehicles/connections
Your Tesla connections: status (ok, reconnect), region, granted scopes and whether precise location is on. Never a token.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
Response 200
{
connections: {
connectionId: string
provider: "tesla"
status: "ok" | "revoked" | "reconnect" | "disconnecting"
region: "na-apac" | "eu"
scopes: string[]
location: boolean
createdAt: number
createdBy?: string
lastRefreshAt?: number
notice?: string
}[]
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
DELETE /v1/me/vehicles/connections/:connectionId
Disconnects a Tesla account: its tokens are removed at once and its telemetry stops. Returns Tesla's page for withdrawing the app's access there too (consentUrl).
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:connectionId | A Tesla connection's id (vconn_…); under vehicles the connection to end, rediscover or list the cars of. |
Response 200
{
consentUrl: string
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
403 | Connect a Tesla account in the Vehicles app. |
404 | Not found |
GET /v1/me/vehicles
The garage: the cars of this space the caller holds anything on, each with their capabilities and a status summary ({ vehicles }). In a Personal space also the cars shared with them. An organisation's members see the cars they have been granted, a fleet admin all of them.
Auth: user access token or platform agent key · Scopes: vehicles:read (when orgId), vehicles:read (when actor.type === "user")
Response 200
{
vehicles: {
[key: string]: unknown
}[]
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
GET /v1/me/vehicles/connections/:connectionId/vehicles
Every car Tesla shows for a connection, and which can be added: status available, claimed_here, claimed_elsewhere or unavailable, the last two with a reason in words ({ vehicles }; asks Tesla, so it is limited and 503 where that isn't wired). For a person in the app, a car in another space they manage, which this account owns, is movable with that space's fromSpaceName and fromSpaceKind: a claim moves it here. Of any other space nothing is said.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:connectionId | A Tesla connection's id (vconn_…); under vehicles the connection to end, rediscover or list the cars of. |
Response 200
{
vehicles: {
fromSpaceKind?: "org" | "personal"
fromSpaceName?: string
movable?: boolean
providerVehicleId?: string
reason?: string
vehicleId?: string
vin: string
name?: string
model?: string
accessType?: "OWNER" | "DRIVER"
state?: string
status: "unavailable" | "available" | "claimed_here" | "claimed_elsewhere"
}[]
}Errors
| Status | Message |
|---|---|
400 | Not a connection id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
POST /v1/me/vehicles/connections/:connectionId/sync
Rediscover a connection's cars: queued for the worker (the API never calls Tesla), 202. List them again a moment later.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:connectionId | A Tesla connection's id (vconn_…); under vehicles the connection to end, rediscover or list the cars of. |
Response 202
{
queued: true
}Errors
| Status | Message |
|---|---|
400 | Not a connection id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Connection not found |
409 | Reconnect this Tesla account first. |
POST /v1/me/vehicles/claim
Adds a car the connection lists to this space and starts key pairing. The VIN is only ever accepted if the connection lists it now. 201 { outcome: "claimed" | "took_over", vehicle }, 200 for exists and moved, and 409 grant_request with the holder's vehicleId when someone else holds the car and this account may not take it.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
connectionId | string | Yes | |
vin | string | Yes | matches ^[A-HJ-NPR-Z0-9]{17}$; trimmed; uppercased |
name | string | No | 1–60 characters; trimmed |
Response 200
{
outcome: "exists" | "moved"
vehicle: {
vehicleId: string
model?: string
trim?: string
vinTail: string
accessType?: "OWNER" | "DRIVER"
keyStatus: "pending" | "lost" | "paired" | "unpaired" | "not_required"
periodStart?: string
}
}Response 201
{
outcome: string
vehicle: {
vehicleId: string
model?: string
trim?: string
vinTail: string
accessType?: "OWNER" | "DRIVER"
keyStatus: "pending" | "lost" | "paired" | "unpaired" | "not_required"
periodStart?: string
}
ended: {
vehicleId: string
}
}
| {
outcome: string
vehicle: {
vehicleId: string
model?: string
trim?: string
vinTail: string
accessType?: "OWNER" | "DRIVER"
keyStatus: "pending" | "lost" | "paired" | "unpaired" | "not_required"
periodStart?: string
}
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
409 | Someone else holds this car. Ask them to share it with you. |
GET /v1/me/vehicles/api-access
Whether API keys (yours, and your organizations' keys made by you) may use your Personal Vehicles. Off until you turn it on.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
Response 200
{
enabled: boolean
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
403 | Change this in the Vehicles app. |
404 | Vehicles isn't available here. |
404 | Not found |
PUT /v1/me/vehicles/api-access
Turns API key access to your Personal Vehicles on or off. Only you, in the Vehicles app.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
enabled | boolean | Yes |
Response 200
{
enabled: boolean
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
403 | Connect a Tesla account in the Vehicles app. |
404 | Not found |
GET /v1/me/vehicles/display
The display units you chose, the same in every space: distance (km, mi), temperature (C, F), pressure (kPa, bar, psi), efficiency (Wh/km, km/kWh, Wh/mi, mi/kWh), battery (percent, range) and map (standard, satellite). Only what you chose; the rest follows your language. Every other answer stays metric.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
Response 200
{
display: {
distance?: "km" | "mi"
temperature?: "C" | "F"
pressure?: "kPa" | "bar" | "psi"
efficiency?: "Wh/km" | "km/kWh" | "Wh/mi" | "mi/kWh"
battery?: "range" | "percent"
map?: "standard" | "satellite"
}
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
PUT /v1/me/vehicles/display
Replaces your display units ({ display: { … } }); {} goes back to your language's. Only you, in the Vehicles or phone app.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
display | object | Yes | |
display.distance | "km" | "mi" | No | |
display.temperature | "C" | "F" | No | |
display.pressure | "kPa" | "bar" | "psi" | No | |
display.efficiency | "Wh/km" | "km/kWh" | "Wh/mi" | "mi/kWh" | No | |
display.battery | "percent" | "range" | No | |
display.map | "standard" | "satellite" | No |
Response 200
{
display: {
distance?: "km" | "mi"
temperature?: "C" | "F"
pressure?: "kPa" | "bar" | "psi"
efficiency?: "Wh/km" | "km/kWh" | "Wh/mi" | "mi/kWh"
battery?: "range" | "percent"
map?: "standard" | "satellite"
}
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
403 | Connect a Tesla account in the Vehicles app. |
404 | Not found |
GET /v1/me/vehicles/profile
The space's units, currency, default tariff and the trim around a home place on shared routes.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
Response 200
{
units: "metric" | "imperial"
currency: string
defaultTariffId: null | string
homeTrimRadiusM: null | number
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
PUT /v1/me/vehicles/profile
Changes those that are given; null clears the default tariff or the trim. The default tariff is one of the space's.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
units | "metric" | "imperial" | No | |
currency | string | No | matches ^[A-Z]{3}$ |
defaultTariffId | string | No | can be null |
homeTrimRadiusM | integer | No | 0–2000; can be null |
Also checked: Say what to change.
Response 200
{
units: "metric" | "imperial"
currency: string
defaultTariffId: null | string
homeTrimRadiusM: null | number
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Tariff not found |
GET /v1/me/vehicles/places
The space's charging places (a centre and a radius in metres), by name.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
Response 200
{
places: {
placeId: string
name?: string
kind: "home" | "other" | "work"
lat: number
lon: number
radiusM: number
tariffId: null | string
}[]
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
POST /v1/me/vehicles/places
Adds a charging place: a name, a centre and a radius in metres (default 100), a kind and a tariff if it has one. 201; 409 limit_reached at the space's limit.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
Request body
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
name | any JSON | Yes | ||
kind | any JSON | No | "other" | |
lat | number | Yes | -90–90 | |
lon | number | Yes | -180–180 | |
radiusM | any JSON | No | 100 | |
tariffId | any JSON | No |
Response 201
{
placeId: string
name: string
kind: "home" | "other" | "work"
lat: number
lon: number
radiusM: number
tariffId: null | string
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Tariff not found |
PATCH /v1/me/vehicles/places/:placeId
Changes the fields given on a place; tariffId: null clears its tariff.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:placeId | A place's id: in Maps a saved place (plc_…), in Vehicles a space's charging place (vpl_…). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
name | any JSON | No | |
kind | any JSON | No | |
lat | number | No | -90–90 |
lon | number | No | -180–180 |
radiusM | any JSON | No | |
tariffId | any JSON | No |
Also checked: Say what to change.
Response 200
{
placeId: string
name?: string
kind: "home" | "other" | "work"
lat: number
lon: number
radiusM: number
tariffId: null | string
}Errors
| Status | Message |
|---|---|
400 | Not a place id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Place not found |
404 | Tariff not found |
DELETE /v1/me/vehicles/places/:placeId
Removes a place; an automation that names it stops it, so the place stays until that automation is changed (409).
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:placeId | A place's id: in Maps a saved place (plc_…), in Vehicles a space's charging place (vpl_…). |
Response 204 with no body.
Errors
| Status | Message |
|---|---|
400 | Not a place id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Place not found |
GET /v1/me/vehicles/tariffs/plans
Retailer plans for a postcode, from the AER's reference data (cached a day; the NECF states only). plans is empty for a postcode no plan serves.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
| Query parameter | Type | Required | Notes |
|---|---|---|---|
postcode | string | Yes | matches ^\d{4}$ |
retailer | string | Yes | matches ^[a-z0-9][a-z0-9-]{1,38}$ |
Response 200
{
fetchedAt: string
truncated?: true
postcode: string
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA"
retailer: string
plans: {
planId: string
name: string
brand: string
customerType: string
type: string
}[]
}Errors
| Status | Message |
|---|---|
400 | Not an Australian postcode. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
GET /v1/me/vehicles/tariffs
The space's tariffs, by name.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
Response 200
{
tariffs: {
[key: string]: unknown
[key: number]: unknown
}[]
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
POST /v1/me/vehicles/tariffs
Adds a tariff: flat, or time of use with windows that tile the day for weekdays and weekends. 201; 409 limit_reached.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
Request body
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
name | any JSON | Yes | ||
kind | "flat" | "tou" | Yes | ||
flatTenthsCents | integer | No | 0–10000 | |
zone | string | No | up to 64 characters | |
periods | object[] | No | 1–12 items | |
periods[].name | "peak" | "shoulder" | "offpeak" | Yes | ||
periods[].days | "weekday" | "weekend" | "all" | Yes | ||
periods[].from | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
periods[].to | string | "24:00" | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
periods[].tenthsCents | integer | Yes | 0–10000 | |
exportTenthsCents | integer | No | 0–10000 | |
supplyCentsPerDay | integer | No | 0–10000 | |
supplyShare | boolean | No | false |
Also checked: A flat tariff has flatTenthsCents; a time-of-use tariff has zone and periods. Sharing the supply charge needs supplyCentsPerDay.
Response 201
{
tariffId: string
name: string
kind: "flat" | "tou"
supplyShare: boolean
flatTenthsCents?: number
zone?: string
periods?: {
name: "peak" | "shoulder" | "offpeak"
days: "all" | "weekday" | "weekend"
from: string
to: string
tenthsCents: number
}[]
exportTenthsCents?: number
supplyCentsPerDay?: number
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
PUT /v1/me/vehicles/tariffs/:tariffId
Replaces a tariff with the one given.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:tariffId | A tariff's id (vtf_…). |
Request body
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
name | any JSON | Yes | ||
kind | "flat" | "tou" | Yes | ||
flatTenthsCents | integer | No | 0–10000 | |
zone | string | No | up to 64 characters | |
periods | object[] | No | 1–12 items | |
periods[].name | "peak" | "shoulder" | "offpeak" | Yes | ||
periods[].days | "weekday" | "weekend" | "all" | Yes | ||
periods[].from | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
periods[].to | string | "24:00" | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
periods[].tenthsCents | integer | Yes | 0–10000 | |
exportTenthsCents | integer | No | 0–10000 | |
supplyCentsPerDay | integer | No | 0–10000 | |
supplyShare | boolean | No | false |
Also checked: A flat tariff has flatTenthsCents; a time-of-use tariff has zone and periods. Sharing the supply charge needs supplyCentsPerDay.
Response 200
{
tariffId: string
name: string
kind: "flat" | "tou"
supplyShare: boolean
flatTenthsCents?: number
zone?: string
periods?: {
name: "peak" | "shoulder" | "offpeak"
days: "all" | "weekday" | "weekend"
from: string
to: string
tenthsCents: number
}[]
exportTenthsCents?: number
supplyCentsPerDay?: number
}Errors
| Status | Message |
|---|---|
400 | Not a tariff id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Tariff not found |
DELETE /v1/me/vehicles/tariffs/:tariffId
Removes a tariff; the default tariff and a place that uses it keep it from going (409).
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:tariffId | A tariff's id (vtf_…). |
Response 204 with no body.
Errors
| Status | Message |
|---|---|
400 | Not a tariff id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Tariff not found |
GET /v1/me/vehicles/geofences
The space's geofences: a circle (metres) or a polygon of up to 500 points. Enter and leave are told with the fence's name, never its coordinates.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
Response 200
{
geofences: {
fenceId: string
name?: string
shape: {
type: "circle"
lat: number
lon: number
radiusM: number
} | {
type: "polygon"
points: number[][]
}
enabled: boolean
notifyOn: "both" | "leave" | "enter"
}[]
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
POST /v1/me/vehicles/geofences
Adds a geofence: a circle or a polygon, sealed at rest. 201; 400 for an antimeridian crossing; 409 limit_reached.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
Request body
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
name | any JSON | Yes | ||
shape | object | object | Yes | ||
enabled | boolean | No | true | |
notifyOn | "enter" | "leave" | "both" | No | "both" |
Response 201
{
fenceId: string
name: string
shape: {
type: "circle"
lat: number
lon: number
radiusM: number
} | {
type: "polygon"
points: number[][]
}
enabled: boolean
notifyOn: "both" | "leave" | "enter"
}Errors
| Status | Message |
|---|---|
400 | A fence can't cross the antimeridian. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
PATCH /v1/me/vehicles/geofences/:fenceId
Changes the fields given on a geofence.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:fenceId | A geofence's id (vfn_…). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
name | any JSON | No | |
shape | object | object | No | |
enabled | boolean | No | |
notifyOn | "enter" | "leave" | "both" | No |
Also checked: Say what to change.
Response 200
{
fenceId: string
name?: string
shape: {
type: "circle"
lat: number
lon: number
radiusM: number
} | {
type: "polygon"
points: number[][]
}
enabled: boolean
notifyOn: "both" | "leave" | "enter"
}Errors
| Status | Message |
|---|---|
400 | Not a geofence id. |
400 | A fence can't cross the antimeridian. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Geofence not found |
DELETE /v1/me/vehicles/geofences/:fenceId
Removes a geofence; an automation triggered by it keeps it from going (409).
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:fenceId | A geofence's id (vfn_…). |
Response 204 with no body.
Errors
| Status | Message |
|---|---|
400 | Not a geofence id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Geofence not found |
GET /v1/me/vehicles/automations
The space's automations: a trigger, conditions and up to five actions on the cars named, run with the creator's capabilities. The engine that runs them is not built, so these are stored and shown, and none fires yet.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
Response 200
{
automations: {
[key: string]: unknown
[key: number]: unknown
}[]
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
POST /v1/me/vehicles/automations
Adds an automation. Command actions follow the confirmation table: a tap is stored, a hold needs a fresh step-up, a step-up command is refused. 201.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
Request body
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
name | any JSON | Yes | ||
enabled | boolean | Yes | ||
vehicleIds | string[] | Yes | 1–50 items | |
trigger | object | object | object | object | object | object | object | object | object | Yes | ||
conditions | object | Yes | ||
conditions.insidePlaceId | string | No | ||
conditions.window | object | No | ||
conditions.window.from | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
conditions.window.to | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
conditions.window.zone | string | Yes | up to 64 characters | |
conditions.socMin | integer | No | 0–100 | |
conditions.socMax | integer | No | 0–100 | |
conditions.plugged | boolean | No | ||
conditions.nobodyInside | boolean | No | ||
actions | (object | object)[] | Yes | 1–5 items | |
enabled | any JSON | No | true | |
conditions | object | No | {} | |
conditions.insidePlaceId | string | No | ||
conditions.window | object | No | ||
conditions.window.from | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
conditions.window.to | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
conditions.window.zone | string | Yes | up to 64 characters | |
conditions.socMin | integer | No | 0–100 | |
conditions.socMax | integer | No | 0–100 | |
conditions.plugged | boolean | No | ||
conditions.nobodyInside | boolean | No |
Response 201
{
automationId: string
name: string
createdBy: string
enabled: boolean
vehicleIds: string[]
trigger: {
type: "schedule"
at: string
days: ("sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat")[]
zone: string
} | {
type: "once"
at: string
} | {
type: "geofence"
fenceId: string
on: "leave" | "enter"
} | {
type: "plugged"
on: "out" | "in"
} | {
type: "charge_reached"
socPct: number
} | {
type: "soc_below"
socPct: number
} | {
type: "outside_temp"
aboveC?: number
belowC?: number
} | {
type: "drive_ended"
} | {
type: "left_unlocked"
minutes: number
}
conditions: {
insidePlaceId?: string
window?: {
from: string
to: string
zone: string
}
socMin?: number
socMax?: number
plugged?: boolean
nobodyInside?: boolean
}
actions: {
type: "command"
command: string
args: {
[key: string]: unknown
}
confirmedAt?: number
} | {
type: "notify"
message: string
confirmedAt?: number
}[]
createdAt: number
updatedAt: number
}Errors
| Status | Message |
|---|---|
400 | "…" isn't a command. |
400 | …: … |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Vehicle not found |
404 | Geofence not found |
404 | Place not found |
PATCH /v1/me/vehicles/automations/:automationId
Changes an automation. Only its creator changes the cars, trigger, conditions or actions (403 not_creator); another admin may switch or rename it.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:automationId | An automation's id (vau_…). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
name | any JSON | No | |
enabled | any JSON | No | |
vehicleIds | any JSON | No | |
trigger | object | object | object | object | object | object | object | object | object | No | |
conditions | object | No | |
conditions.insidePlaceId | string | No | |
conditions.window | object | No | |
conditions.window.from | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ |
conditions.window.to | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ |
conditions.window.zone | string | Yes | up to 64 characters |
conditions.socMin | integer | No | 0–100 |
conditions.socMax | integer | No | 0–100 |
conditions.plugged | boolean | No | |
conditions.nobodyInside | boolean | No | |
actions | any JSON | No |
Also checked: Say what to change.
Response 200
{
[key: string]: unknown
}Errors
| Status | Message |
|---|---|
400 | Not a automation id. |
400 | "…" isn't a command. |
400 | …: … |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Automation not found |
404 | Vehicle not found |
404 | Geofence not found |
404 | Place not found |
DELETE /v1/me/vehicles/automations/:automationId
Removes an automation. 204.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:automationId | An automation's id (vau_…). |
Response 204 with no body.
Errors
| Status | Message |
|---|---|
400 | Not a automation id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Automation not found |
POST /v1/orgs/:orgId/vehicles/connections/tesla/authorize
Starts connecting a Tesla account to the organization (owners and admins, from the app): returns Tesla's sign-in url and the browserValue to keep and send back to finish.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
returnTo | string | No | up to 300 characters |
reconnect | string | No | up to 80 characters |
consent | object | Yes | |
consent.categories | ("vehicle_state" | "commands" | "charging")[] | Yes | |
consent.location | boolean | Yes |
Response 200
{
url: string
browserValue: string
expiresAt: number
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
403 | Connect a Tesla account in the Vehicles app. |
404 | Not found |
POST /v1/orgs/:orgId/vehicles/connections/tesla/finish
Finishes the organization's Tesla connection with the redirect's ticket and the browserValue; 202 pending while the exchange is running.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
ticket | string | Yes | 1–200 characters |
browserValue | string | Yes | 1–200 characters |
Response 200
{
connection: {
connectionId: string
provider: "tesla"
status: "ok" | "revoked" | "reconnect" | "disconnecting"
region: "na-apac" | "eu"
scopes: string[]
location: boolean
createdAt: number
createdBy?: string
lastRefreshAt?: number
notice?: string
}
returnTo?: string
reconnected: boolean
sameAccount: boolean
}Response 202
{
status: string
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
403 | Connect a Tesla account in the Vehicles app. |
404 | Not found |
GET /v1/orgs/:orgId/vehicles/connections
The organization's Tesla connections: status, region, granted scopes and whether precise location is on. Never a token.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
connections: {
connectionId: string
provider: "tesla"
status: "ok" | "revoked" | "reconnect" | "disconnecting"
region: "na-apac" | "eu"
scopes: string[]
location: boolean
createdAt: number
createdBy?: string
lastRefreshAt?: number
notice?: string
}[]
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
DELETE /v1/orgs/:orgId/vehicles/connections/:connectionId
Disconnects the organization's Tesla account: tokens removed at once, telemetry stopped; returns Tesla's page for withdrawing access (consentUrl).
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:connectionId | A Tesla connection's id (vconn_…); under vehicles the connection to end, rediscover or list the cars of. |
Response 200
{
consentUrl: string
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
403 | Connect a Tesla account in the Vehicles app. |
404 | Not found |
GET /v1/orgs/:orgId/vehicles
The garage: the cars of this space the caller holds anything on, each with their capabilities and a status summary ({ vehicles }). In a Personal space also the cars shared with them. An organisation's members see the cars they have been granted, a fleet admin all of them.
Auth: user access token or platform agent key · Scopes: vehicles:read (when orgId), vehicles:read (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
vehicles: {
[key: string]: unknown
}[]
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
GET /v1/orgs/:orgId/vehicles/connections/:connectionId/vehicles
Every car Tesla shows for a connection, and which can be added: status available, claimed_here, claimed_elsewhere or unavailable, the last two with a reason in words ({ vehicles }; asks Tesla, so it is limited and 503 where that isn't wired). For a person in the app, a car in another space they manage, which this account owns, is movable with that space's fromSpaceName and fromSpaceKind: a claim moves it here. Of any other space nothing is said.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:connectionId | A Tesla connection's id (vconn_…); under vehicles the connection to end, rediscover or list the cars of. |
Response 200
{
vehicles: {
fromSpaceKind?: "org" | "personal"
fromSpaceName?: string
movable?: boolean
providerVehicleId?: string
reason?: string
vehicleId?: string
vin: string
name?: string
model?: string
accessType?: "OWNER" | "DRIVER"
state?: string
status: "unavailable" | "available" | "claimed_here" | "claimed_elsewhere"
}[]
}Errors
| Status | Message |
|---|---|
400 | Not a connection id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
POST /v1/orgs/:orgId/vehicles/connections/:connectionId/sync
Rediscover a connection's cars: queued for the worker (the API never calls Tesla), 202. List them again a moment later.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:connectionId | A Tesla connection's id (vconn_…); under vehicles the connection to end, rediscover or list the cars of. |
Response 202
{
queued: true
}Errors
| Status | Message |
|---|---|
400 | Not a connection id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Connection not found |
409 | Reconnect this Tesla account first. |
POST /v1/orgs/:orgId/vehicles/claim
Adds a car the connection lists to this space and starts key pairing. The VIN is only ever accepted if the connection lists it now. 201 { outcome: "claimed" | "took_over", vehicle }, 200 for exists and moved, and 409 grant_request with the holder's vehicleId when someone else holds the car and this account may not take it.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
connectionId | string | Yes | |
vin | string | Yes | matches ^[A-HJ-NPR-Z0-9]{17}$; trimmed; uppercased |
name | string | No | 1–60 characters; trimmed |
Response 200
{
outcome: "exists" | "moved"
vehicle: {
vehicleId: string
model?: string
trim?: string
vinTail: string
accessType?: "OWNER" | "DRIVER"
keyStatus: "pending" | "lost" | "paired" | "unpaired" | "not_required"
periodStart?: string
}
}Response 201
{
outcome: string
vehicle: {
vehicleId: string
model?: string
trim?: string
vinTail: string
accessType?: "OWNER" | "DRIVER"
keyStatus: "pending" | "lost" | "paired" | "unpaired" | "not_required"
periodStart?: string
}
ended: {
vehicleId: string
}
}
| {
outcome: string
vehicle: {
vehicleId: string
model?: string
trim?: string
vinTail: string
accessType?: "OWNER" | "DRIVER"
keyStatus: "pending" | "lost" | "paired" | "unpaired" | "not_required"
periodStart?: string
}
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
409 | Someone else holds this car. Ask them to share it with you. |
GET /v1/orgs/:orgId/vehicles/profile
The space's units, currency, default tariff and the trim around a home place on shared routes.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
units: "metric" | "imperial"
currency: string
defaultTariffId: null | string
homeTrimRadiusM: null | number
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
PUT /v1/orgs/:orgId/vehicles/profile
Changes those that are given; null clears the default tariff or the trim. The default tariff is one of the space's.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
units | "metric" | "imperial" | No | |
currency | string | No | matches ^[A-Z]{3}$ |
defaultTariffId | string | No | can be null |
homeTrimRadiusM | integer | No | 0–2000; can be null |
Also checked: Say what to change.
Response 200
{
units: "metric" | "imperial"
currency: string
defaultTariffId: null | string
homeTrimRadiusM: null | number
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Tariff not found |
GET /v1/orgs/:orgId/vehicles/places
The space's charging places (a centre and a radius in metres), by name.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
places: {
placeId: string
name?: string
kind: "home" | "other" | "work"
lat: number
lon: number
radiusM: number
tariffId: null | string
}[]
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
POST /v1/orgs/:orgId/vehicles/places
Adds a charging place: a name, a centre and a radius in metres (default 100), a kind and a tariff if it has one. 201; 409 limit_reached at the space's limit.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Request body
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
name | any JSON | Yes | ||
kind | any JSON | No | "other" | |
lat | number | Yes | -90–90 | |
lon | number | Yes | -180–180 | |
radiusM | any JSON | No | 100 | |
tariffId | any JSON | No |
Response 201
{
placeId: string
name: string
kind: "home" | "other" | "work"
lat: number
lon: number
radiusM: number
tariffId: null | string
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Tariff not found |
PATCH /v1/orgs/:orgId/vehicles/places/:placeId
Changes the fields given on a place; tariffId: null clears its tariff.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:placeId | A place's id: in Maps a saved place (plc_…), in Vehicles a space's charging place (vpl_…). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
name | any JSON | No | |
kind | any JSON | No | |
lat | number | No | -90–90 |
lon | number | No | -180–180 |
radiusM | any JSON | No | |
tariffId | any JSON | No |
Also checked: Say what to change.
Response 200
{
placeId: string
name?: string
kind: "home" | "other" | "work"
lat: number
lon: number
radiusM: number
tariffId: null | string
}Errors
| Status | Message |
|---|---|
400 | Not a place id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Place not found |
404 | Tariff not found |
DELETE /v1/orgs/:orgId/vehicles/places/:placeId
Removes a place; an automation that names it stops it, so the place stays until that automation is changed (409).
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:placeId | A place's id: in Maps a saved place (plc_…), in Vehicles a space's charging place (vpl_…). |
Response 204 with no body.
Errors
| Status | Message |
|---|---|
400 | Not a place id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Place not found |
GET /v1/orgs/:orgId/vehicles/tariffs/plans
Retailer plans for a postcode, from the AER's reference data (cached a day; the NECF states only). plans is empty for a postcode no plan serves.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
postcode | string | Yes | matches ^\d{4}$ |
retailer | string | Yes | matches ^[a-z0-9][a-z0-9-]{1,38}$ |
Response 200
{
fetchedAt: string
truncated?: true
postcode: string
state: "ACT" | "NSW" | "NT" | "QLD" | "SA" | "TAS" | "VIC" | "WA"
retailer: string
plans: {
planId: string
name: string
brand: string
customerType: string
type: string
}[]
}Errors
| Status | Message |
|---|---|
400 | Not an Australian postcode. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
GET /v1/orgs/:orgId/vehicles/tariffs
The space's tariffs, by name.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
tariffs: {
[key: string]: unknown
[key: number]: unknown
}[]
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
POST /v1/orgs/:orgId/vehicles/tariffs
Adds a tariff: flat, or time of use with windows that tile the day for weekdays and weekends. 201; 409 limit_reached.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Request body
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
name | any JSON | Yes | ||
kind | "flat" | "tou" | Yes | ||
flatTenthsCents | integer | No | 0–10000 | |
zone | string | No | up to 64 characters | |
periods | object[] | No | 1–12 items | |
periods[].name | "peak" | "shoulder" | "offpeak" | Yes | ||
periods[].days | "weekday" | "weekend" | "all" | Yes | ||
periods[].from | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
periods[].to | string | "24:00" | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
periods[].tenthsCents | integer | Yes | 0–10000 | |
exportTenthsCents | integer | No | 0–10000 | |
supplyCentsPerDay | integer | No | 0–10000 | |
supplyShare | boolean | No | false |
Also checked: A flat tariff has flatTenthsCents; a time-of-use tariff has zone and periods. Sharing the supply charge needs supplyCentsPerDay.
Response 201
{
tariffId: string
name: string
kind: "flat" | "tou"
supplyShare: boolean
flatTenthsCents?: number
zone?: string
periods?: {
name: "peak" | "shoulder" | "offpeak"
days: "all" | "weekday" | "weekend"
from: string
to: string
tenthsCents: number
}[]
exportTenthsCents?: number
supplyCentsPerDay?: number
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
PUT /v1/orgs/:orgId/vehicles/tariffs/:tariffId
Replaces a tariff with the one given.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:tariffId | A tariff's id (vtf_…). |
Request body
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
name | any JSON | Yes | ||
kind | "flat" | "tou" | Yes | ||
flatTenthsCents | integer | No | 0–10000 | |
zone | string | No | up to 64 characters | |
periods | object[] | No | 1–12 items | |
periods[].name | "peak" | "shoulder" | "offpeak" | Yes | ||
periods[].days | "weekday" | "weekend" | "all" | Yes | ||
periods[].from | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
periods[].to | string | "24:00" | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
periods[].tenthsCents | integer | Yes | 0–10000 | |
exportTenthsCents | integer | No | 0–10000 | |
supplyCentsPerDay | integer | No | 0–10000 | |
supplyShare | boolean | No | false |
Also checked: A flat tariff has flatTenthsCents; a time-of-use tariff has zone and periods. Sharing the supply charge needs supplyCentsPerDay.
Response 200
{
tariffId: string
name: string
kind: "flat" | "tou"
supplyShare: boolean
flatTenthsCents?: number
zone?: string
periods?: {
name: "peak" | "shoulder" | "offpeak"
days: "all" | "weekday" | "weekend"
from: string
to: string
tenthsCents: number
}[]
exportTenthsCents?: number
supplyCentsPerDay?: number
}Errors
| Status | Message |
|---|---|
400 | Not a tariff id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Tariff not found |
DELETE /v1/orgs/:orgId/vehicles/tariffs/:tariffId
Removes a tariff; the default tariff and a place that uses it keep it from going (409).
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:tariffId | A tariff's id (vtf_…). |
Response 204 with no body.
Errors
| Status | Message |
|---|---|
400 | Not a tariff id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Tariff not found |
GET /v1/orgs/:orgId/vehicles/geofences
The space's geofences: a circle (metres) or a polygon of up to 500 points. Enter and leave are told with the fence's name, never its coordinates.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
geofences: {
fenceId: string
name?: string
shape: {
type: "circle"
lat: number
lon: number
radiusM: number
} | {
type: "polygon"
points: number[][]
}
enabled: boolean
notifyOn: "both" | "leave" | "enter"
}[]
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
POST /v1/orgs/:orgId/vehicles/geofences
Adds a geofence: a circle or a polygon, sealed at rest. 201; 400 for an antimeridian crossing; 409 limit_reached.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Request body
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
name | any JSON | Yes | ||
shape | object | object | Yes | ||
enabled | boolean | No | true | |
notifyOn | "enter" | "leave" | "both" | No | "both" |
Response 201
{
fenceId: string
name: string
shape: {
type: "circle"
lat: number
lon: number
radiusM: number
} | {
type: "polygon"
points: number[][]
}
enabled: boolean
notifyOn: "both" | "leave" | "enter"
}Errors
| Status | Message |
|---|---|
400 | A fence can't cross the antimeridian. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
PATCH /v1/orgs/:orgId/vehicles/geofences/:fenceId
Changes the fields given on a geofence.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:fenceId | A geofence's id (vfn_…). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
name | any JSON | No | |
shape | object | object | No | |
enabled | boolean | No | |
notifyOn | "enter" | "leave" | "both" | No |
Also checked: Say what to change.
Response 200
{
fenceId: string
name?: string
shape: {
type: "circle"
lat: number
lon: number
radiusM: number
} | {
type: "polygon"
points: number[][]
}
enabled: boolean
notifyOn: "both" | "leave" | "enter"
}Errors
| Status | Message |
|---|---|
400 | Not a geofence id. |
400 | A fence can't cross the antimeridian. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Geofence not found |
DELETE /v1/orgs/:orgId/vehicles/geofences/:fenceId
Removes a geofence; an automation triggered by it keeps it from going (409).
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:fenceId | A geofence's id (vfn_…). |
Response 204 with no body.
Errors
| Status | Message |
|---|---|
400 | Not a geofence id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Geofence not found |
GET /v1/orgs/:orgId/vehicles/automations
The space's automations: a trigger, conditions and up to five actions on the cars named, run with the creator's capabilities. The engine that runs them is not built, so these are stored and shown, and none fires yet.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:read (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
automations: {
[key: string]: unknown
[key: number]: unknown
}[]
}Errors
| Status | Message |
|---|---|
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:read on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
POST /v1/orgs/:orgId/vehicles/automations
Adds an automation. Command actions follow the confirmation table: a tap is stored, a hold needs a fresh step-up, a step-up command is refused. 201.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Request body
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
name | any JSON | Yes | ||
enabled | boolean | Yes | ||
vehicleIds | string[] | Yes | 1–50 items | |
trigger | object | object | object | object | object | object | object | object | object | Yes | ||
conditions | object | Yes | ||
conditions.insidePlaceId | string | No | ||
conditions.window | object | No | ||
conditions.window.from | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
conditions.window.to | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
conditions.window.zone | string | Yes | up to 64 characters | |
conditions.socMin | integer | No | 0–100 | |
conditions.socMax | integer | No | 0–100 | |
conditions.plugged | boolean | No | ||
conditions.nobodyInside | boolean | No | ||
actions | (object | object)[] | Yes | 1–5 items | |
enabled | any JSON | No | true | |
conditions | object | No | {} | |
conditions.insidePlaceId | string | No | ||
conditions.window | object | No | ||
conditions.window.from | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
conditions.window.to | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ | |
conditions.window.zone | string | Yes | up to 64 characters | |
conditions.socMin | integer | No | 0–100 | |
conditions.socMax | integer | No | 0–100 | |
conditions.plugged | boolean | No | ||
conditions.nobodyInside | boolean | No |
Response 201
{
automationId: string
name: string
createdBy: string
enabled: boolean
vehicleIds: string[]
trigger: {
type: "schedule"
at: string
days: ("sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat")[]
zone: string
} | {
type: "once"
at: string
} | {
type: "geofence"
fenceId: string
on: "leave" | "enter"
} | {
type: "plugged"
on: "out" | "in"
} | {
type: "charge_reached"
socPct: number
} | {
type: "soc_below"
socPct: number
} | {
type: "outside_temp"
aboveC?: number
belowC?: number
} | {
type: "drive_ended"
} | {
type: "left_unlocked"
minutes: number
}
conditions: {
insidePlaceId?: string
window?: {
from: string
to: string
zone: string
}
socMin?: number
socMax?: number
plugged?: boolean
nobodyInside?: boolean
}
actions: {
type: "command"
command: string
args: {
[key: string]: unknown
}
confirmedAt?: number
} | {
type: "notify"
message: string
confirmedAt?: number
}[]
createdAt: number
updatedAt: number
}Errors
| Status | Message |
|---|---|
400 | "…" isn't a command. |
400 | …: … |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Vehicle not found |
404 | Geofence not found |
404 | Place not found |
PATCH /v1/orgs/:orgId/vehicles/automations/:automationId
Changes an automation. Only its creator changes the cars, trigger, conditions or actions (403 not_creator); another admin may switch or rename it.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:automationId | An automation's id (vau_…). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
name | any JSON | No | |
enabled | any JSON | No | |
vehicleIds | any JSON | No | |
trigger | object | object | object | object | object | object | object | object | object | No | |
conditions | object | No | |
conditions.insidePlaceId | string | No | |
conditions.window | object | No | |
conditions.window.from | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ |
conditions.window.to | string | Yes | matches ^([01]\d|2[0-3]):[0-5]\d$ |
conditions.window.zone | string | Yes | up to 64 characters |
conditions.socMin | integer | No | 0–100 |
conditions.socMax | integer | No | 0–100 |
conditions.plugged | boolean | No | |
conditions.nobodyInside | boolean | No | |
actions | any JSON | No |
Also checked: Say what to change.
Response 200
{
[key: string]: unknown
}Errors
| Status | Message |
|---|---|
400 | Not a automation id. |
400 | "…" isn't a command. |
400 | …: … |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Automation not found |
404 | Vehicle not found |
404 | Geofence not found |
404 | Place not found |
DELETE /v1/orgs/:orgId/vehicles/automations/:automationId
Removes an automation. 204.
Auth: user access token or platform agent key · Scopes: vehicles:admin (when orgId), vehicles:write (when actor.type === "user")
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:automationId | An automation's id (vau_…). |
Response 204 with no body.
Errors
| Status | Message |
|---|---|
400 | Not a automation id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
403 | Its owner hasn't let API keys use their Personal Vehicles (Vehicles → Privacy). |
403 | Vehicles needs vehicles:write on a key made by a person. |
404 | Vehicles isn't available here. |
404 | Not found |
404 | Automation not found |
GET /v1/vehicles/:vehicleId
META and LIVE with the caller's capabilities, telemetry health and key status. The position only with location.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
Response 200
{
restorableUntil?: string
ended?: {
at?: string
reason?: "removed" | "access_lost" | "new_owner" | "ownership_changed"
}
pictureMode?: "tesla" | "drawing"
vehicleId: string
name: string
model?: string
trim?: string
capabilities: string[]
health?: {
key: string
connection: string
checkedAt?: string
profile?: "standard" | "economy"
telemetry: "error" | "pending" | "off" | "configured" | "streaming" | "waiting_for_key" | "firmware_too_old" | "limit_reached" | "unsupported" | "suspended" | "unsigned"
telemetryLabel: string
polling: boolean
}
position?: {
[key: string]: unknown
}
state?: "offline" | "charging" | "parked" | "driving" | "asleep"
lastSeen?: string
battery?: {
soc?: number
rangeKm?: number
estRangeKm?: number
}
charge?: {
plugged?: boolean
portOpen?: boolean
kw?: number
limit?: number
etaMin?: number
}
locks?: {
locked?: boolean
doorsOpen?: string[]
windowsOpen?: string[]
trunk?: "open" | "closed"
frunk?: "open" | "closed"
powerLiftgate?: boolean
}
climate?: {
setpoint?: {
driverC?: number
passengerC?: number
}
on?: boolean
insideC?: number
outsideC?: number
}
sentry?: boolean
odometerKm?: number
speedKmh?: number
gear?: "N" | "D" | "R" | "P"
tyres?: {
kpa?: number[]
}
software?: {
update?: null | {
status: "available" | "scheduled" | "downloading" | "installing"
version: string
minutes?: number
percent?: number
}
version?: string
}
colour?: string
art?: string
picture?: {
views: {
"3qtr"?: {
srcset: {
url: string
width: number
height: number
}[]
box: {
x: number
y: number
w: number
h: number
}
}
side?: {
srcset: {
url: string
width: number
height: number
}[]
box: {
x: number
y: number
w: number
h: number
}
}
}
approximate?: true
}
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
POST /v1/vehicles/:vehicleId/watch
Renews the live lease (open apps send it every 30 s while the car is on screen). 204.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
Response 204 with no body.
Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
409 | This car's period has ended. |
GET /v1/vehicles/:vehicleId/key
Pairing status, the pairing link and what to do next; opening it restarts the key checks when they have lapsed.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
Response 200
{
checkedAt?: string
status: "pending" | "lost" | "paired" | "unpaired" | "not_required"
required: boolean
link?: string
requirements: ("tesla_app_same_account" | "car_online")[]
keyCount?: number
keysFull: boolean
keyListUrl?: string
firmware?: string
pollMs?: number
vehicleId: string
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
409 | This car's period has ended. |
GET /v1/vehicles/:vehicleId/trips
Drives, newest first. class, tag, driver, min (km) filter; cursor resumes across months.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
from | string | No | up to 40 characters |
to | string | No | up to 40 characters |
cursor | string | No | up to 700 characters |
limit | integer | No | 1–100; coerced from a string |
class | "business" | "personal" | "commute" | "private" | No | |
tag | string | No | 1–40 characters; trimmed |
driver | string | No | up to 60 characters |
min | number | No | 0–100000; coerced from a string |
near | string | No | matches ^-?\d{1,2}(\.\d{1,7})?,-?\d{1,3}(\.\d{1,7})?(,\d{2,5})?$ |
Response 200
{
next?: string
trips: {
hasTrack: boolean
path?: {
lat: number
lon: number
}[]
startPlace?: string
endPlace?: string
score?: number
secondsOver?: {
[key: string]: number
}
kmOver?: {
[key: string]: number
}
harshAccel?: number
harshBraking?: number
harshCornering?: number
tripId: string
startedAt?: string
endedAt?: string
distanceKm?: number
energyKwh?: number
whPerKm?: number
socFrom?: number
socTo?: number
maxSpeedKmh?: number
avgMovingSpeedKmh?: number
class?: "private" | "personal" | "business" | "commute"
purpose?: string
tags?: string[]
driverId?: string
outsideCMin?: number
outsideCMax?: number
elevationGainM?: number
elevationLossM?: number
assistedKm?: number
weather?: string
mine: boolean
}[]
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | near: not a position. |
400 | near: 50 to 50,000 metres. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
GET /v1/vehicles/:vehicleId/trips/current
The drive still open, as far as the car has gone: its points after since, for the app that draws it while it goes (it asks every 5 s, and only for what is new). Needs trips and location (shown always: a grant that shows the position only while the holder drives never does, as in the detail), and a grant whose trips filter shows the open drive, which has no class or driver yet: only every drive, with no class tag. Without one, or without a drive open, the answer is the same open: false.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
since | string | No | up to 40 characters |
Response 200
{
open: false
points: []
}
| {
truncated?: true
through?: number
open: true
tripId: string
startedAt?: string
points: {
t: number
lat: number
lon: number
speedKmh: number
headingDeg: number
soc: number
powerKw: number
limitKmh?: number
}[]
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
GET /v1/vehicles/:vehicleId/trips/:tripId
A drive: the summary and, for those who may see where it went, the thumbnail path. ?points=1 adds the decoded track (the server opens it), after since when given.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
:tripId | A drive's id (drv_…), as the drives list gives it. |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
points | "0" | "1" | No | |
since | string | No | up to 40 characters |
Response 200
{
trip: {
hasTrack: boolean
path?: {
lat: number
lon: number
}[]
startPlace?: string
endPlace?: string
score?: number
secondsOver?: {
[key: string]: number
}
kmOver?: {
[key: string]: number
}
harshAccel?: number
harshBraking?: number
harshCornering?: number
tripId: string
startedAt?: string
endedAt?: string
distanceKm?: number
energyKwh?: number
whPerKm?: number
socFrom?: number
socTo?: number
maxSpeedKmh?: number
avgMovingSpeedKmh?: number
class?: "private" | "personal" | "business" | "commute"
purpose?: string
tags?: string[]
driverId?: string
outsideCMin?: number
outsideCMax?: number
elevationGainM?: number
elevationLossM?: number
assistedKm?: number
weather?: string
mine: boolean
}
events: {
eventId: string
kind: string
at?: string
severity?: string
values?: {
[key: string]: boolean | number
}
}[]
track: {
available: boolean
count?: number
points?: {
[key: string]: undefined | number
}[]
}
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Not a drive id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
GET /v1/vehicles/:vehicleId/stats/today
Today's drives: the distance and energy, and the count for those who see every drive, as totals and nothing finer. The day is cut in the zone asked for (?tz=, a place's IANA name) for those who see every drive, else in the car's space's. view is enough for the distance and energy, whatever the grant's trip filters hide, because a sum names no drive, time or place (docs/vehicles/api.md → Today's totals).
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
tz | string | No | 1–64 characters; trimmed |
Response 200
{
drives?: number
day: string
timeZone: string
from?: string
to?: string
distanceKm: number
energyKwh: number
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
GET /v1/vehicles/:vehicleId/charges
Charging sessions: with trips, the places; with costs, what they cost. Either opens the list.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
from | string | No | up to 40 characters |
to | string | No | up to 40 characters |
cursor | string | No | up to 700 characters |
limit | integer | No | 1–100; coerced from a string |
Response 200
{
next?: string
charges: {
place?: string
costCents?: number
costSource?: string
tariffId?: string
chargeId: string
startedAt?: string
endedAt?: string
kind?: "home" | "other" | "work" | "supercharger"
kwhAdded?: number
kwhDrawn?: number
socFrom?: number
socTo?: number
maxKw?: number
}[]
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
GET /v1/vehicles/:vehicleId/idles
Parked periods (battery lost while parked, with Sentry and climate shares).
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
from | string | No | up to 40 characters |
to | string | No | up to 40 characters |
cursor | string | No | up to 700 characters |
limit | integer | No | 1–100; coerced from a string |
Response 200
{
idles: []
hidden: true
}
| {
next?: string
idles: {
place?: string
idleId: string
startedAt?: string
endedAt?: string
socLostPct?: number
kwhLost?: number
sentryFraction?: number
climateFraction?: number
asleepFraction?: number
}[]
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
POST /v1/vehicles/:vehicleId/commands/:commandName
Sends a command through K2's command service (docs/vehicles/commands.md → The service): the capability each needs, its arguments, the grant's terms, the confirmation (a nonce for a hold, the token's step-up), the limits and the queue are the service's, from commandDef. Idempotency-Key is required and makes a repeat return the first result. 200 { commandId, status: "succeeded" }, 202 { commandId, status, approvalId } while it is queued or waits for approval, and the service's refusals with their status and code: 409 confirm (with a nonce), 403 terms, step_up, approval_required, 409 boot_open (a lock while the boot or front trunk is open) and no_update (a software update the car hasn't got ready), 424 vehicle (with Tesla's reason), 429 (Retry-After), 422 bad_args and unsupported (Close Trunk on a boot that closes by hand).
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
:commandName | A command's name, such as lock, climate_on or charge_limit; its capability decides who may send it. |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
args | object | No | keys up to 40 characters; values: any JSON |
nonce | string | No | 1–100 characters |
fix | object | No | |
fix.lat | number | Yes | -90–90 |
fix.lon | number | Yes | -180–180 |
fix.fixAt | integer | Yes | 0–8640000000000000 |
Response 200
{
commandId: string
status: string
}Response 202
{
commandId: string
status: "unknown" | "queued" | "failed" | "sent" | "succeeded" | "needs_approval" | "waking"
approvalId: null | string
}Errors
| Status | Message |
|---|---|
400 | Send an Idempotency-Key header, so a repeated request returns the first result. |
400 | Not a vehicle id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Unknown command. |
404 | Vehicles isn't available here. |
409 | This car's period has ended. |
GET /v1/vehicles/:vehicleId/commands/:commandId
A command's state: your own, or anyone's with share.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
:commandId | A command's id (cmd_…), as sending it returned it. |
Response 200
{
at?: string
approvalId: null | string
reason?: string
commandId: string
command: string
status: "unknown" | "queued" | "failed" | "sent" | "succeeded" | "needs_approval" | "waking"
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Not a command id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
DELETE /v1/vehicles/:vehicleId
/** Removes a car with a 7-day undo. For a period that ended some other way (sold, access lost), ?history=delete deletes its history for good.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
history | "delete" | No |
Response 200
{
vehicleId: string
removedAt?: string
restorableUntil?: string
}
| {
vehicleId: string
historyDeletion: string
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
409 | This car's period has ended. |
POST /v1/vehicles/:vehicleId/restore
Undoes a removal within 7 days (the connection must still list the car and the VIN be free).
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
Response 200
{
vehicle: {
vehicleId: string
model?: string
trim?: string
vinTail: string
accessType?: "OWNER" | "DRIVER"
keyStatus: "pending" | "lost" | "paired" | "unpaired" | "not_required"
periodStart?: string
}
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
PUT /v1/vehicles/:vehicleId/settings
The car's settings: its name (1 to 60 characters, no control or invisible formatting characters) and its picture, Tesla's or our drawing (pictureMode on both rows; docs/vehicles/pictures.md). Audited as vehicle.settings_update with the change, never the value.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | No | up to 200 characters |
picture | "tesla" | "drawing" | No |
Also checked: Send a name or a picture.
Response 200
{
pictureMode?: "tesla" | "drawing"
name?: string
vehicleId: string
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
404 | Vehicle not found |
409 | This car's period has ended. |
POST /v1/vehicles/:vehicleId/picture
Reads the car's configuration again and resolves its picture (the owner's Refresh picture): 202, queued for the worker, which alone reads Tesla and only when the car is online. 429 with Retry-After within a day of the last read, 409 for a finished period.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
Response 202
{
lastReadAt?: string
queued: true
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
409 | This car's period has ended. |
GET /v1/vehicles/:vehicleId/events
What happened to the car, newest first: alerts and the car being moved while parked, and with the drives' events (speeding, harsh braking) for those who see every drive and hold behaviour. kind narrows it. An event the caller may not see is left out as if it were not there, and so is an alert raised while the car was in a drive they do not see (its time would place that drive); next is sealed.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
from | string | No | up to 40 characters |
to | string | No | up to 40 characters |
cursor | string | No | up to 700 characters |
limit | integer | No | 1–100; coerced from a string |
kind | string | No | 1–60 characters; matches ^[A-Za-z0-9_.:-]+$; trimmed |
Response 200
{
next?: string
events: {
tripId?: string
eventId: string
kind: string
at?: string
severity?: "warning" | "critical" | "info"
values?: {
[key: string]: boolean | number
}
}[]
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
GET /v1/vehicles/:vehicleId/battery
The battery now, and its capacity over time as the charges give it: each charge that took the state of charge up by 20 points or more says what the battery holds (kWh added over the points gained), and a month's figure is the median. It is an estimate from charging, not a measurement of the pack; there is no health percentage until the car's original capacity is known.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
from | any JSON | Yes | |
to | any JSON | Yes |
Response 200
{
truncated?: true
now: {
soc?: number
rangeKm?: number
estRangeKm?: number
odometerKm?: number
plugged?: boolean
chargeLimitPct?: number
chargeKw?: number
}
capacity: {
cycles?: number
latestKwh?: number
method: string
unit: string
months: {
charges?: number
month: string
kwh: number
}[]
}
from?: string
to?: string
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Ask for at most 730 days at a time. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
GET /v1/vehicles/:vehicleId/tyres
The four tyre pressures as the car last reported them (kPa), and the tyre alerts of the last 90 days (left out when raised during a drive the caller does not see, as in the events). There is no history yet.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
Response 200
{
warnings: {
eventId: string
kind: string
at?: string
ongoing: boolean
}[]
reportedAt?: string
kpa?: {
fl?: number
fr?: number
rl?: number
rr?: number
}
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
GET /v1/vehicles/:vehicleId/efficiency
Wh/km by outside temperature and speed, from the drives the caller sees (so a holder of some drives gets their own picture, and the count says how many that was): each cell is the distance-weighted average of the drives in that 5 °C and 20 km/h band, with the distance and drives in it. The real-world range is the battery's estimated capacity at the state of charge over the average. There is no model of what a drive should have used, nor climate, wind or tyre effects, yet.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
from | any JSON | Yes | |
to | any JSON | Yes |
Response 200
{
truncated?: true
method: string
realWorldRangeKm?: number
matrix: {
outsideC: [number, number]
speedKmh: [number, number]
whPerKm: number
km: number
drives: number
}[]
whPerKm?: number
from?: string
to?: string
drives: number
distanceKm: number
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Ask for at most 365 days at a time. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
GET /v1/vehicles/:vehicleId/costs
What charging has cost in a range (default 90 days): the priced charges' cost, energy and count, by where the price came from and by kind of charge. A charge nobody priced counts in unpriced, not as free. The same for every holder of costs (no routes or places, and the drive filters don't apply to charges); cost per km only for a caller who sees every drive (with any other range a caller could difference two ranges into a day's distance). There are no tariffs or fuel comparison yet, so a price is whatever was set on the charge.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
from | any JSON | Yes | |
to | any JSON | Yes |
Response 200
{
truncated?: true
centsPerKwh?: number
centsPerKm?: number
from?: string
to?: string
currency: string
charges: number
kwhAdded: number
priced: {
charges: number
kwh: number
costCents: number
}
unpriced: {
charges: number
kwh: number
}
bySource: {
[key: string]: string | number
charges: number
kwh: number
costCents: number
}[]
byKind: {
[key: string]: string | number
charges: number
kwh: number
costCents: number
}[]
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Ask for at most 366 days at a time. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
GET /v1/vehicles/:vehicleId/logbook
The business drives of a range for an ATO logbook (default 90 days, at most 15 months): each one's date, odometer at the start and end, kilometres and purpose, oldest first, from the drives the caller sees. The summary says how many lack a purpose. Only a caller who sees every drive of every class gets what needs them all: business-use percent, the whole period's kilometres and odometer span, and the gaps (14 days or more with no drive); partial: true says the rest is from what they see. Whether the range is a valid logbook period (12 continuous weeks) is weeks and meetsTwelveWeeks. Storing a period is not built yet.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
from | any JSON | Yes | |
to | any JSON | Yes |
Response 200
{
truncated?: true
openingOdometerKm?: number
closingOdometerKm?: number
totalKm?: number
businessPercent?: number
gaps?: {
from: string
to: string
}[]
from?: string
to?: string
weeks: number
meetsTwelveWeeks: boolean
partial: boolean
trips: {
tripId: string
date?: string
startOdometerKm?: number
endOdometerKm?: number
km?: number
purpose: null | string
}[]
businessTrips: number
businessKm: number
missingPurpose: number
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Ask for at most 456 days at a time. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
GET /v1/vehicles/:vehicleId/settings
The car's settings that exist so far: its name and colour, whether its PINs are set (never the PINs), the key's state and the telemetry profile. PINs and the key are the owner's to know.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
Response 200
{
pinsSet?: {
speedLimit: boolean
valet: boolean
}
keyStatus?: "pending" | "lost" | "paired" | "unpaired" | "not_required"
telemetryProfile?: "standard" | "economy"
vehicleId: string
name: string
model?: string
colour?: string
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
GET /v1/vehicles/:vehicleId/commands
The commands sent to the car, newest first: the caller's own, and everyone's for a holder of share. K2's history; actor is named only for someone else's. next is sealed.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
from | any JSON | Yes | |
to | any JSON | Yes | |
cursor | any JSON | Yes | |
limit | any JSON | Yes |
Response 200
{
next?: string
commands: {
actor?: string
mine: boolean
parameterClasses?: string[]
at?: string
code?: string
reason?: string
commandId: string
command: string
via: "key" | "app" | "caity" | "automation"
status: string
}[]
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Ask for at most 366 days at a time. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
PATCH /v1/vehicles/:vehicleId/trips
Classifies and tags drives in bulk: { ids (up to 50), class?, purpose? (null clears), tags? (replaces) }. Needs manage and trips, and only drives the caller sees change: an id that is missing, outside the car's period or hidden from the caller is in missing, the same for all three. Audited in an organisation's log (the change and how many, never the purpose).
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
ids | string[] | Yes | 1–50 items; each matches ^drv_[0-9a-z]{8,40}$ |
class | "business" | "personal" | "commute" | "private" | No | |
purpose | any JSON | No | can be null |
tags | any JSON[] | No | up to 10 items |
Also checked: Say what to change: class, purpose or tags.
Response 200
{
updated: string[]
missing: string[]
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Send drives from at most 12 separate stretches at a time. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
409 | This car's period has ended. |
GET /v1/vehicles/:vehicleId/charges/:chargeId
One charge session: its summary (the place only for those who see places, the cost only for costs), how long, the average power and the charging efficiency (energy added over drawn), and its curve, power in kW and the state of charge every 30 seconds from curve.startedAt. For trips or costs, as the list. The curve carries no position. The cost by tariff period needs the tariff engine, which is not built, so a price is the one the charge has.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
:chargeId | A charge's id (chg_…), as the charges list gives it. |
Response 200
{
curve: null | {
startedAt?: string
stepS: number
kw: number[]
soc: number[]
}
centsPerKwh?: number
efficiencyPct?: number
avgKw?: number
durationMin?: number
place?: string
costCents?: number
costSource?: string
tariffId?: string
chargeId: string
startedAt?: string
endedAt?: string
kind?: "home" | "other" | "work" | "supercharger"
kwhAdded?: number
kwhDrawn?: number
socFrom?: number
socTo?: number
maxKw?: number
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Not a charge id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
404 | Charge not found |
PATCH /v1/vehicles/:vehicleId/charges/:chargeId
Overrides a charge's price or place: { costCents?, place? (null clears) }. Needs manage; a price needs costs and a place needs the sight of places (every drive of every class, or the owner). A price set by hand says costSource: "manual". Audited in an organisation's log.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
:chargeId | A charge's id (chg_…), as the charges list gives it. |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
costCents | integer | No | 0–1000000 |
place | any JSON | No | can be null |
Also checked: Say what to change: costCents or place.
Response 200
{
place?: null | string
costCents?: number
costSource?: string
chargeId: string
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Not a charge id. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
404 | Charge not found |
409 | This car's period has ended. |
GET /v1/vehicles/:vehicleId/keys
The keychain as last read, labelled, and the state of the read. The table only: open apps poll it while a read runs.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
Response 200
{
vehicleId: string
keyCount: null | number
maxKeys: number
readable: boolean
entries: {
keyId: string
slot: number
kind: "phone" | "app" | "unread" | "this_app" | "key_card" | "driver_phone" | "fob_or_phone"
label: string
role: null | string
driverId: null | string
leaving: boolean
firstSeenAt?: string
}[]
readAt: null | string
reading: boolean
lastOutcome: null | "ok" | "partial" | "failed" | "reconnect" | "asleep" | "refused" | "rate_limited"
lastTriedAt: null | string
countChanged: boolean
nextReadAt: null | string
howToUrl: string
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
409 | This car's period has ended. |
POST /v1/vehicles/:vehicleId/keys/read
Reads the car's keychain again: 202 and a vehicles.keys_read job. Tesla bills each question and the car must be awake (it is never woken for this). 429 with Retry-After inside the cooldown or while a read runs; 409 for a car that doesn't use Tesla's command protocol (pre-2021 Model S and X).
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
Response 202
{
queued: true
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
409 | This car's period has ended. |
GET /v1/vehicles/:vehicleId/drivers
The car's Tesla drivers and pending invitations (Tesla's sharing in its own app), each driver with how many of their keys were on the car when it was last read. A car added with a driver's account (not_owner), a connection whose scopes Tesla refuses (not_allowed) or one that needs signing in again (reconnect) is available: false with the reason, so the page still shows the rest.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
Response 200
{
available: false
reason: string
drivers: []
invitations: []
}
| {
available: true
drivers: {
driverId: string
name: string
keysOnCar: number
}[]
invitations: {
inviteId: string
link: null | string
expiresAt: null | string
}[]
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
409 | This car's period has ended. |
POST /v1/vehicles/:vehicleId/drivers/invitations
A single-use link to Tesla's app that makes its account a driver of the car for good (it lapses unused after 24 hours). Step-up; audited.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
Response 201
{
inviteId: string
link?: string
expiresAt: null | string
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
409 | This car's period has ended. |
POST /v1/vehicles/:vehicleId/drivers/invitations/:inviteId/revoke
Revokes a pending invitation: its link stops working. It only takes access away, so no step-up; audited.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
:inviteId | Invite id (inv_…); under vehicles, Tesla's id for a driver invitation, as the drivers list gives it. |
Response 200
{
revoked: true
}Errors
| Status | Message |
|---|---|
400 | Not a invitation id. |
400 | Not a vehicle id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
409 | This car's period has ended. |
DELETE /v1/vehicles/:vehicleId/drivers/:driverId
Removes a Tesla driver: their access in Tesla's app, and their phone keys on the car when it is next online. Step-up; audited.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
:driverId | A Tesla driver's id, as Tesla gives it (digits): the car's drivers list names it. |
Response 200
{
removed: true
}Errors
| Status | Message |
|---|---|
400 | Not a driver id. |
400 | Not a vehicle id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
409 | This car's period has ended. |
GET /v1/vehicles/:vehicleId/imports
The car's imports, newest first.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
Response 200
{
imports: {
importId: string
source: "tessie_export" | "tessie_template" | "vehicles_csv"
status: "ready" | "expired" | "done" | "failed" | "cancelled" | "uploading" | "refused" | "checking" | "importing" | "undoing" | "undone"
version: number
progress: number
files: {
name: string
bytes: number
}[]
fileNames: string[]
options: {
timeZone?: string
currency?: string
businessTags?: string[]
}
summary: null | {
from?: string
to?: string
kinds: {
drive: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
idle: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
battery: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
charge: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
tyre: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
}
rows: number
invalidRows: number
distanceKm: number
kwhUsed: number
kwhAdded: number
drivesByMonth: {
[key: string]: number
}
carCheck: "vin" | "odometer"
locations: boolean
units?: "km" | "mi"
timeZone?: string
repeatedHour: number
trimmed: number
}
problems: {
file: number
row: number
column?: string
code: string
}[]
problemCount: number
refusal: null | {
at?: string
code: string
file?: number
missing?: string[]
unexpected?: string[]
limit?: string
}
from: null | string
to: null | string
written: number
createdAt?: string
checkedAt: null | string
committedAt: null | string
undoneAt: null | string
}[]
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
POST /v1/vehicles/:vehicleId/imports
A new import and an upload link per file (one key, length and SHA-256, an hour). 413 over a limit, 409 import_open, 429 past the day's.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
source | "tessie_export" | "tessie_template" | "vehicles_csv" | Yes | |
files | object[] | Yes | 1–1,000 items |
files[].name | string | Yes | 1–200 characters; trimmed |
files[].bytes | integer | Yes | 1–17179869184 |
files[].sha256 | string | Yes | matches ^[A-Za-z0-9+/]{43}=$ |
Response 201
{
importId: string
import: {
importId: string
source: "tessie_export" | "tessie_template" | "vehicles_csv"
status: "ready" | "expired" | "done" | "failed" | "cancelled" | "uploading" | "refused" | "checking" | "importing" | "undoing" | "undone"
version: number
progress: number
files: {
name: string
bytes: number
}[]
fileNames: string[]
options: {
timeZone?: string
currency?: string
businessTags?: string[]
}
summary: null | {
from?: string
to?: string
kinds: {
drive: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
idle: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
battery: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
charge: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
tyre: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
}
rows: number
invalidRows: number
distanceKm: number
kwhUsed: number
kwhAdded: number
drivesByMonth: {
[key: string]: number
}
carCheck: "vin" | "odometer"
locations: boolean
units?: "km" | "mi"
timeZone?: string
repeatedHour: number
trimmed: number
}
problems: {
file: number
row: number
column?: string
code: string
}[]
problemCount: number
refusal: null | {
at?: string
code: string
file?: number
missing?: string[]
unexpected?: string[]
limit?: string
}
from: null | string
to: null | string
written: number
createdAt?: string
checkedAt: null | string
committedAt: null | string
undoneAt: null | string
}
uploads: {
url: string
headers: {
[key: string]: string
}
}[]
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
POST /v1/vehicles/:vehicleId/imports/:importId/check
Checks each upload's size and checksum, then queues the check (again with new options): 202.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
:importId | Takeout import id (imp_…); under me/food a Food import (fim_…); under vehicles an import of a car's history (vim_…), as the imports list gives it. |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
timeZone | string | No | 1–64 characters; trimmed |
currency | string | No | matches ^[A-Z]{3}$ |
businessTags | string[] | No | up to 20 items; each 1–40 characters, trimmed |
Response 202
{
import: {
importId: string
source: "tessie_export" | "tessie_template" | "vehicles_csv"
status: "ready" | "expired" | "done" | "failed" | "cancelled" | "uploading" | "refused" | "checking" | "importing" | "undoing" | "undone"
version: number
progress: number
files: {
name: string
bytes: number
}[]
fileNames: string[]
options: {
timeZone?: string
currency?: string
businessTags?: string[]
}
summary: null | {
from?: string
to?: string
kinds: {
drive: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
idle: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
battery: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
charge: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
tyre: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
}
rows: number
invalidRows: number
distanceKm: number
kwhUsed: number
kwhAdded: number
drivesByMonth: {
[key: string]: number
}
carCheck: "vin" | "odometer"
locations: boolean
units?: "km" | "mi"
timeZone?: string
repeatedHour: number
trimmed: number
}
problems: {
file: number
row: number
column?: string
code: string
}[]
problemCount: number
refusal: null | {
at?: string
code: string
file?: number
missing?: string[]
unexpected?: string[]
limit?: string
}
from: null | string
to: null | string
written: number
createdAt?: string
checkedAt: null | string
committedAt: null | string
undoneAt: null | string
}
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Not a import id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
GET /v1/vehicles/:vehicleId/imports/:importId
Status, progress, the summary and the problems.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
:importId | Takeout import id (imp_…); under me/food a Food import (fim_…); under vehicles an import of a car's history (vim_…), as the imports list gives it. |
Response 200
{
import: {
importId: string
source: "tessie_export" | "tessie_template" | "vehicles_csv"
status: "ready" | "expired" | "done" | "failed" | "cancelled" | "uploading" | "refused" | "checking" | "importing" | "undoing" | "undone"
version: number
progress: number
files: {
name: string
bytes: number
}[]
fileNames: string[]
options: {
timeZone?: string
currency?: string
businessTags?: string[]
}
summary: null | {
from?: string
to?: string
kinds: {
drive: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
idle: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
battery: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
charge: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
tyre: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
}
rows: number
invalidRows: number
distanceKm: number
kwhUsed: number
kwhAdded: number
drivesByMonth: {
[key: string]: number
}
carCheck: "vin" | "odometer"
locations: boolean
units?: "km" | "mi"
timeZone?: string
repeatedHour: number
trimmed: number
}
problems: {
file: number
row: number
column?: string
code: string
}[]
problemCount: number
refusal: null | {
at?: string
code: string
file?: number
missing?: string[]
unexpected?: string[]
limit?: string
}
from: null | string
to: null | string
written: number
createdAt?: string
checkedAt: null | string
committedAt: null | string
undoneAt: null | string
}
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Not a import id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
404 | Import not found. |
GET /v1/vehicles/:vehicleId/imports/:importId/rows
The first 200 new rows of a kind, as they will read; places only with location.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
:importId | Takeout import id (imp_…); under me/food a Food import (fim_…); under vehicles an import of a car's history (vim_…), as the imports list gives it. |
| Query parameter | Type | Required | Notes |
|---|---|---|---|
kind | "drive" | "charge" | "idle" | Yes |
Response 200
{
rows: {
start?: {
name: null | string
lat: null | number
lon: null | number
}
end?: {
name: null | string
lat: null | number
lon: null | number
}
track?: boolean
id: string
kind: "drive" | "idle" | "charge"
startedAt?: string
endedAt?: string
chargeKind?: unknown
place?: {
name: null | string
lat: null | number
lon: null | number
}
}[]
places: boolean
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Not a import id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
404 | Import not found. |
POST /v1/vehicles/:vehicleId/imports/:importId/commit
Commits the check named by version: 202; 409 stale for an older one, confirm_skip until invalid rows' skipping is confirmed.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
:importId | Takeout import id (imp_…); under me/food a Food import (fim_…); under vehicles an import of a car's history (vim_…), as the imports list gives it. |
Request body
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
version | integer | Yes | ≥ 1 | |
skipInvalid | boolean | No | false |
Response 202
{
import: {
importId: string
source: "tessie_export" | "tessie_template" | "vehicles_csv"
status: "ready" | "expired" | "done" | "failed" | "cancelled" | "uploading" | "refused" | "checking" | "importing" | "undoing" | "undone"
version: number
progress: number
files: {
name: string
bytes: number
}[]
fileNames: string[]
options: {
timeZone?: string
currency?: string
businessTags?: string[]
}
summary: null | {
from?: string
to?: string
kinds: {
drive: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
idle: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
battery: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
charge: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
tyre: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
}
rows: number
invalidRows: number
distanceKm: number
kwhUsed: number
kwhAdded: number
drivesByMonth: {
[key: string]: number
}
carCheck: "vin" | "odometer"
locations: boolean
units?: "km" | "mi"
timeZone?: string
repeatedHour: number
trimmed: number
}
problems: {
file: number
row: number
column?: string
code: string
}[]
problemCount: number
refusal: null | {
at?: string
code: string
file?: number
missing?: string[]
unexpected?: string[]
limit?: string
}
from: null | string
to: null | string
written: number
createdAt?: string
checkedAt: null | string
committedAt: null | string
undoneAt: null | string
}
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Not a import id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
POST /v1/vehicles/:vehicleId/imports/:importId/undo
Undoes a committed import: its rows go, edits since included. 202.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
:importId | Takeout import id (imp_…); under me/food a Food import (fim_…); under vehicles an import of a car's history (vim_…), as the imports list gives it. |
Response 202
{
import: {
importId: string
source: "tessie_export" | "tessie_template" | "vehicles_csv"
status: "ready" | "expired" | "done" | "failed" | "cancelled" | "uploading" | "refused" | "checking" | "importing" | "undoing" | "undone"
version: number
progress: number
files: {
name: string
bytes: number
}[]
fileNames: string[]
options: {
timeZone?: string
currency?: string
businessTags?: string[]
}
summary: null | {
from?: string
to?: string
kinds: {
drive: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
idle: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
battery: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
charge: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
tyre: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
}
rows: number
invalidRows: number
distanceKm: number
kwhUsed: number
kwhAdded: number
drivesByMonth: {
[key: string]: number
}
carCheck: "vin" | "odometer"
locations: boolean
units?: "km" | "mi"
timeZone?: string
repeatedHour: number
trimmed: number
}
problems: {
file: number
row: number
column?: string
code: string
}[]
problemCount: number
refusal: null | {
at?: string
code: string
file?: number
missing?: string[]
unexpected?: string[]
limit?: string
}
from: null | string
to: null | string
written: number
createdAt?: string
checkedAt: null | string
committedAt: null | string
undoneAt: null | string
}
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Not a import id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
DELETE /v1/vehicles/:vehicleId/imports/:importId
Cancels an import before it commits. 202.
Auth: user access token or platform agent key
| Path parameter | Description |
|---|---|
:vehicleId | A vehicle's id (veh_…): one owner's period with one VIN. Another owner of the same car has another id. |
:importId | Takeout import id (imp_…); under me/food a Food import (fim_…); under vehicles an import of a car's history (vim_…), as the imports list gives it. |
Response 202
{
import: {
importId: string
source: "tessie_export" | "tessie_template" | "vehicles_csv"
status: "ready" | "expired" | "done" | "failed" | "cancelled" | "uploading" | "refused" | "checking" | "importing" | "undoing" | "undone"
version: number
progress: number
files: {
name: string
bytes: number
}[]
fileNames: string[]
options: {
timeZone?: string
currency?: string
businessTags?: string[]
}
summary: null | {
from?: string
to?: string
kinds: {
drive: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
idle: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
battery: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
charge: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
tyre: {
new: number
duplicate: number
short: number
recent: number
invalid: number
incomplete: number
}
}
rows: number
invalidRows: number
distanceKm: number
kwhUsed: number
kwhAdded: number
drivesByMonth: {
[key: string]: number
}
carCheck: "vin" | "odometer"
locations: boolean
units?: "km" | "mi"
timeZone?: string
repeatedHour: number
trimmed: number
}
problems: {
file: number
row: number
column?: string
code: string
}[]
problemCount: number
refusal: null | {
at?: string
code: string
file?: number
missing?: string[]
unexpected?: string[]
limit?: string
}
from: null | string
to: null | string
written: number
createdAt?: string
checkedAt: null | string
committedAt: null | string
undoneAt: null | string
}
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
400 | Not a import id. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |
GET /v1/me/widgets/vehicle
The Vehicle widget's numbers for a car the person holds view on: state, state of charge, range, charging, locks and cabin temperature; no position. People only.
Auth: user access token or platform agent key
| Query parameter | Type | Required | Notes |
|---|---|---|---|
vehicleId | string | Yes | up to 60 characters |
Response 200
{
vehicleId: string
name: string
ended: {
at?: string
}
}
| {
vehicleId: string
name: string
state?: "offline" | "charging" | "parked" | "driving" | "asleep"
lastSeen?: string
soc?: number
rangeKm?: number
plugged?: boolean
chargeKw?: number
chargeLimitPct?: number
etaMin?: number
locked?: boolean
insideC?: number
}Errors
| Status | Message |
|---|---|
400 | Not a vehicle id. |
403 | Widgets belong to people. |
403 | Widgets are read by the app. |
403 | Vehicles isn't available to the phone assistant. |
403 | Vehicles is reachable from the Vehicles and phone apps. |
403 | Vehicles needs a key made by a person. |
404 | Vehicles isn't available here. |