Nissan

Developer Documentation

A complete integration guide for onboarding your app and using the APIs, with the live Swagger reference at the end.

Developer Documentation

Request and receive connected-vehicle data directly from our APIs — with owner consent at the core.

What Programmatic Access is

Programmatic Access lets your application request and receive vehicle data — historical, last-known, and real-time — directly from our APIs through the platform. You register an integration once, receive credentials, and then call the data-request APIs to create requests, track their status, and retrieve delivered data.

Three things are true of every integration, and they shape everything else in this guide:

  • Access is read-only. The business integration realm is a zero-trust, read-only environment. You can request data about a vehicle; you cannot send commands to a vehicle (no door unlock, no engine start). Those capabilities live in a separate fleet realm and are not exposed here.
  • The vehicle owner is always in control. Data only flows after the owner has explicitly consented to the specific data you asked for, for the specific purpose you stated. You initiate; the owner approves. There is no path that bypasses owner consent.
  • The platform meters and bills automatically. Pricing, payment, and invoicing are enforced by the platform before any backend service runs. Your backend never handles pricing logic — you register a payment method and the platform does the rest.

If you have integrated with OAuth providers or other consent-gated data APIs before, the overall shape will feel familiar. The one concept that is easy to under-estimate — and the one that causes the most integration bugs — is consent as a first-class, owner-controlled lifecycle that is independent of your access tokens. The Consent section is the most important in this guide; read it before you write code.

How a data request works (the mental model)

There are three actors:

ActorWhoRole
You (the integrator)A business organization: insurer, leasing co., energy aggregator, repairer, mobility operator, data intermediaryInitiates data requests on behalf of, or with the permission of, a vehicle owner
The vehicle ownerThe natural person linked to the VINGrants, denies, or revokes consent in their own secure portal
The platformMyNissanData, the data-access platform on top of the connected-vehicle infrastructureValidates, gates, meters, bills, and delivers

Every request follows the same arc, regardless of integration model or data family:

Create request — VIN + package(s)
Owner consents in secure portal
3-Gate authorization (governance, scope, ownership)
Deliver data (file / JSON / stream)

The request does not return data synchronously at creation time. Creating a request returns a requestId and a status. You then either poll the status or subscribe to a webhook to learn when consent is granted and data is ready. Only when the request reaches APPROVED with consent GRANTED does data become retrievable.

The three authorization gates

Before any data is read, every request passes through a centralized compliance engine — three sequential gates. If any gate fails, the request is terminated immediately. You don't call these gates; they run for you. Knowing they exist explains why a request can be rejected even when your call is well-formed.

Data access request
Gate 1: Governance — entity allowed?
Gate 2: Consent scope — granted?
Gate 3: Ownership window — valid for dates?
Authorized — deliver
Any gate failing terminates the request immediately — no data is returned.
GateQuestion it answersWhat it checks
1 — GovernanceIs this business entity legally allowed to receive data?Global sanctions lists and the MyNissanData "gatekeeper" blocklist. Restricted entities are blocked.
2 — Policy (consent)Has the owner granted this specific scope?The requested package/scope against the active consent ledger for that VIN. Enforces data minimization.
3 — Dynamic (entitlement)Did this owner own this vehicle during the requested window?The temporal intersection of your request window and the owner's vehicle-ownership window, plus privacy-mode filters. Prevents leakage across previous/subsequent owners.

Gate 3 is why a historical request can succeed but return less data than the full date range you asked for: only the portion of the window during which the consenting owner actually owned the vehicle is eligible.

Data families: what you can request

Every service package belongs to one of three families. The family determines the delivery mechanism, the request endpoint, and the billing model. List the packages available to your account before creating a request (see the service-package catalog); use the returned package id values in your request body.

FamilyWhat it providesHow it's deliveredBilling
HistoricalTime-series history over a date range — one-off or recurring (periodic)Async file: zipped CSVs via a time-limited pre-signed download URLPrepaid per request (one-off); subscription (periodic)
Last Known ValueThe most recent known value(s); no date rangeSynchronous JSON, last-known valuePrepaid per call
Real-TimeLive telematics for an approved vehiclePull: read a resource snapshot on demand. Push: webhook events on state changeSubscription (aggregated monthly)

Notes that matter in practice:

  • Data availability is vehicle-dependent. For retrieving recorded values, a given vehicle supports either the Historical (time-series over a date range) option or the Last Known Value option — not necessarily both. Some vehicle models expose only the last-known-value service. Always rely on the service-package catalog and the package type to see what is actually available for your account and the vehicles you query, rather than assuming a vehicle supports historical.
  • Real-time delivery is event-driven, not a raw firehose. Subscriptions surface meaningful events — e.g., journey completed, charge-state changed, safety fault — rather than continuous raw pings. This protects your receiving infrastructure. Pull reads give you the latest known state on demand.
  • A resource can legitimately return no dataif the vehicle doesn't support it. For example, the charging resource returns 404 for non-EV (ICE) vehicles.
  • Very high-volume continuous telemetry is out of scope here. Webhook-based delivery is designed for self-serve SME-to-mid scale. If your run-rate or frequency needs grow past the threshold for managed streaming, that is a managed high-throughput streaming tier conversation — contact your account team rather than working around webhook limits.

Billing: how and when you are charged

Billing is enforced by the platform, not your backend. The model depends entirely on the data family / request type — not on whether the call came from an M2M backend or an app.

The prerequisite: a valid payment method

Your API credentials remain suspended until your business account has a complete billing profile and a valid primary payment method (a credit or debit card). Until then, data-request calls are blocked. Add a payment method in account settings to activate.

Pricing tier

Pricing is rendered dynamically by account type:

  • SME — margin-free rate.
  • Large Enterprise — commercial rate.

You don't pass a price; the platform computes it from your account type and the requested package.

Workflow A — One-off historical & last-known (strict prepaid)

Request created
Pre-authorization hold for exact price
Owner consents
Payment captured + invoice issued
Extraction runs — download URL returned

A pre-authorization hold is placed for the exact price when the request is created. Payment is captured only at the moment consent is granted; if the owner never consents, the hold is released and nothing is charged.

Workflow B — Recurring subscriptions (periodic & real-time, postpaid aggregated)

Payment method validated
Owner consents
Subscription active — routing rule per VIN
1st of month: sum active consented VINs
Single consolidated charge

Because consented VINs can be added or revoked organically throughout the month, individual VINs are not charged per transaction. Instead, on the 1st of each month, an aggregated billing job sums all active, consented VINs for your account over the prior month and raises a single consolidated charge.

Invoices & retention

Invoices are generated at capture (Workflow A) or at the monthly aggregation (Workflow B) and are available in the portal. Financial records are retained for tax-compliance purposes independently of account deletion.

Design takeaway: for one-off/historical, expect a hold→capture sequence tied to consent; for subscriptions, expect a single monthly charge and design your reconciliation around the 1st-of-month aggregation rather than per-VIN events. If your app derives the requested period dynamically, read Cost control before you ship.

Cost control: dynamic date ranges & repeat requests

The platform prices the request, not the vehicle. How your app derives the requested period therefore decides how often you are charged — see Billing for the charging mechanics.

Design for this before you launch. If the period is computed dynamically — “the last 30 days from today” — every submission asks for a different window, so each one is a new billable one-off request. A vehicle user who re-submits daily can generate a charge every day. Only a repeat over an identical period with the same package set is the same request.

Worked example

A quotation app sends periodStartDate = today - 30 days and periodEndDate = today. A user who submits on Monday and again on Tuesday creates two requests over two different windows — two pre-authorization holds, and two captures once each is consented.

Pattern 1 — check existing coverage before you create

Before every POST .../historical/data-requests, list what already exists for that VIN:

curl
curl -G "{API_BASE}/cms/m2m/accounts/{account_id}/historical/data-requests" \
  -H "Authorization: Bearer <access_token>" \
  --data-urlencode "vin=VF1AAAAA000000001" \
  --data-urlencode "requestType=ONE_OFF" \
  --data-urlencode "requestStatus=PENDING" \
  --data-urlencode "requestStatus=APPROVED" \
  --data-urlencode "requestStatus=COMPLETED" \
  --data-urlencode "pageSize=100"

The list endpoint filters on vin, requestType, requestStatus and consentStatus — there is no date-range filter. Each item returns periodStartDate, periodEndDate, packages, reference and createdAt, so do the window comparison in your own code:

  1. Fetch the VIN's ONE_OFF requests in the statuses that can still cost you money — PENDING, APPROVED, ACTIVE, COMPLETED.
  2. Compare the window you are about to ask for against each request's periodStartDateperiodEndDate and package set.
  3. Already covered and consented? Re-read the existing deliveries instead of requesting the same data again.
  4. Still PENDING for that window? Wait for the owner to act rather than stacking a second hold on your payment method.
  5. Nothing covers it? Then create the request.

Pattern 2 — snap dynamic windows to a stable grid

Rather than anchoring the range to the wall clock, quantize it: a whole calendar month, or a window that only moves once a week. Repeat submissions inside the same slot then resolve to the identical period, which is what makes the Pattern 1 coverage check actually hit. Show the resolved window in your UI so the user sees the period they are paying for.

Pattern 3 — guardrails in your own application

  • Cap creation yourself. A hard ceiling per VIN and per end-user — for example one one-off request per VIN per calendar month — is the only limit fully under your control. Enforce it in your backend, before the API call.
  • Stamp a correlation key in reference (up to 255 characters) — for example a digest of VIN + package set + period. It is returned on the list response, so detecting a repeat is a string comparison rather than a field-by-field diff.
  • Serve data you already hold. A delivered extract stays usable for its retention window; re-requesting the same window buys nothing but another charge.
  • Make submission deliberate. Confirm window, packages and cost in the UI behind an explicit user action. Never create a request as a side effect of a page load, a refresh, or a client-side retry.
  • Reconcile continuously.Subscribe to the consent & billing webhooks and alert on requests-per-day run-rate anomalies, rather than discovering them on the invoice.

Pattern 4 — use PERIODIC when the need is recurring

If the use case genuinely needs a rolling window on an ongoing basis, a PERIODIC request with MONTHLY frequency is billed through the aggregated monthly charge (Workflow B) on one consent round, instead of a fresh prepaid request per submission. That is far more predictable per VIN than repeated ONE_OFF calls — see Data families.

A request that never receives consent is never charged — the hold is released (Workflow A). Treating PENDING requests as coverage therefore also stops you stacking holds against your payment method while the owner decides.

Choose your integration model: M2M vs. App (PKCE)

You pick the authorization model when you create the integration, and it cannot be changed afterwards. If you need both, create two integrations.

Server-to-Server (M2M)Authorization Code + PKCE (App)
Best forBackend services acting on behalf of your organizationApps acting on behalf of an individual vehicle owner
Grantclient_credentialsauthorization_code
Credentialsclient_id + client_secretclient_id only (public client + PKCE; no secret)
User loginNot requiredRequired (owner consents via browser redirect)
Redirect URLsNot usedRequired at registration; exact-match enforced
How consent is capturedOwner approves via emailed secure deep-linkOwner approves inline on the Nissan IdP login / Consent Screen
Tokens used on readsaccess_token onlyaccess_token + X-Id-Token (dual-token)
API base path/cms/m2m/.../cms/oauth/...

Rule of thumb: if a human owner is present in your UX and you want them to authenticate and consent in the moment, use App (PKCE). If you're running unattended backend jobs against VINs your organization is permitted to act for, use M2M and rely on email-link consent capture. Both share the same package catalog, the same data-request lifecycle, and the same billing model.

Before you begin

Make sure the following are in place for your business account. Data requests are blocked until every gate below passes.

  • An active business account (not suspended), and your organization is not on a sanctions/gatekeeper blocklist (Gate 1).
  • A complete billing profile with a valid primary payment method (a credit or debit card). Until this exists, your API credentials are suspended.
  • Accepted platform terms and Data Terms & Conditions.
If a request is rejected for account, billing, or T&C reasons, resolve it in account settings and retry. These are not transient errors — retrying without fixing the gate will fail again.

Development vs. production: a development account is sandboxed and vehicle-count-limited for PoC and pre-prod validation; a primary account runs live, contracted services. Build and validate against development first.

Create an integration & get credentials

From the Programmatic Access tab, choose Create Integration and complete the form:

  • Application name (3–50 characters).
  • Authorization model — M2M or Authorization Code. Immutable after creation.
  • Redirect URLs — required for Authorization Code. These are the only URLs the authorize step will redirect back to (exact match).
  • Purpose of the integration (shown to owners in the consent prompt).
  • Service packages you intend to request.
  • Accept the Data Terms & Conditions.

Submit to register. You can later update most fields, but the authorization model stays fixed.

Your credentials

After creation, credentials are shown once in a popup. Store them securely before closing it (you can also download a PDF summary).

  • M2M: a client_id and a client_secret (the secret is shown only once).
  • Authorization Code: a client_id only (no secret — security comes from PKCE).
Treat the client secret like a password.Never embed it in browser or mobile apps. If it's lost or leaked, regenerate it from the integration's actions menu — the old secret stops working immediately.

Browse the service-package catalog

A service package defines the data a request can access, and which family/billing it falls under. List what's available to your account before creating a request:

M2M

GET {API_BASE}/cms/m2m/accounts/{account_id}/service-packages?dataType=HISTORICAL|REAL_TIME

App (PKCE) — same shape, OAuth path + dual-token headers:

GET {API_BASE}/cms/oauth/accounts/{account_id}/service-packages?dataType=HISTORICAL|REAL_TIME

Each package returns at least an id, name, description, and type. Use the package id values in the packages array when you create a data request. The catalog is the source of truth for what a given vehicle/account supports — including whether historical time-series or only last-known-value reads are available (see Data families).

Quickstart A — Server-to-Server (M2M)

Backend service, no interactive login. Consent is captured via an emailed secure link to the owner.

  1. Your backend → Platform API: POST /cms/m2m/token (client credentials)
  2. Platform API → Your backend: access_token
  3. Your backend → Platform API: POST data-request (VIN, package, owner email)
  4. Platform API → Vehicle owner: Email secure consent link
  5. Platform API → Your backend: requestId, status = PENDING
  6. Vehicle owner → Platform API: Approve in secure portal
  7. Platform API → Your backend: Webhook CONSENT_GRANTED (or poll status)
  8. Your backend → Platform API: GET data (deliveries / resource)
  9. Platform API → Your backend: Pre-signed download URL or JSON

Step 1 — Get an access token

Exchange your account ID and client credentials for a bearer token:

curl
curl -X POST "{API_BASE}/cms/m2m/token" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "YOUR_ACCOUNT_ID",
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET"
  }'

The response contains an access_token and its expires_in lifetime. Send it on every subsequent call:

http
Authorization: Bearer <access_token>
Remember: a valid token is necessary but not sufficient to read data. Entitlement is consent-gated (see Consent).

Step 2 — Create a data request

Use the endpoint that matches the package family:

POST/cms/m2m/accounts/{account_id}/realtime/data-requests
POST/cms/m2m/accounts/{account_id}/historical/data-requests

A request identifies a vehicle (17-character vin), the vehicle user's email (used to notify the owner for consent), and one or more package id values. Historical requests also take requestType (ONE_OFF or PERIODIC), a date range, and — for periodic — a frequency. The exact field names and validation rules are in the API reference.

What happens behind the scenes: the platform runs synchronous validations (valid VIN, resolvable user, active ownership pairing, temporal limits — see Compliance constraints), creates a PENDING record, sets up the billing hold (Workflow A) or validates the payment method (Workflow B), and emails the owner a secure approval link. The call returns a requestId and status — no data yet.

A one-off historical request is held at creation and charged once consent is granted, so each distinct period you ask for is a separate charge. Read Cost control before deriving the period from a dynamic expression.

Step 3 — Monitor the request

Poll the list endpoints (filter by vin, requestStatus, consentStatus, with paging), or subscribe to a webhook to be pushed status changes:

GET/cms/m2m/accounts/{account_id}/realtime/data-requests
GET/cms/m2m/accounts/{account_id}/historical/data-requests

Wait for requestStatus = APPROVED and consentStatus = GRANTED. See Data-request lifecycle & statuses.

Step 4 — Retrieve data

Historical — list deliveries, then fetch a time-limited download URL:

GET/cms/m2m/accounts/{account_id}/historical/data-requests/{requestId}/data-deliveries
GET/cms/m2m/accounts/{account_id}/historical/.../data-deliveries/{dataDeliveryId}/download

Real-time — once approved, read a telematics resource directly:

GET/cms/m2m/accounts/{account_id}/realtime/vehicles/{vin}/{resource}

See the real-time telematics catalog for valid {resource} values.

Quickstart B — Authorization Code + PKCE (App)

Use this when an individual owner authorizes your app. PKCE means no client secret.

  1. Your app: Generate PKCE verifier + challenge
  2. Your app → Platform API: Redirect owner to /authorize (challenge)
  3. Platform API → Nissan IdP: Redirect for login
  4. Vehicle owner → Nissan IdP: Authenticate
  5. Nissan IdP → Vehicle owner: Consent prompt
  6. Vehicle owner → Nissan IdP: Approve
  7. Platform API → Your app: Redirect to callback (auth code)
  8. Your app → Platform API: POST /cms/oauth/token (code + verifier)
  9. Platform API → Your app: access_token + id_token + refresh_token
  10. Your app → Platform API: GET data (Authorization + X-Id-Token)
  11. Platform API → Your app: Data

Step 1 — Generate a PKCE verifier and challenge (per authorization attempt)

javascript
// Keep the verifier private; send only the challenge to /authorize.
const verifier = base64url(crypto.getRandomValues(new Uint8Array(32)));
const digest = await crypto.subtle.digest(
  "SHA-256",
  new TextEncoder().encode(verifier)
);
const codeChallenge = base64url(new Uint8Array(digest));

Step 2 — Redirect the owner to the authorize endpoint

GET/cms/oauth/authorize
text
{API_BASE}/cms/oauth/authorize
  ?account_id=YOUR_ACCOUNT_ID
  &client_id=YOUR_CLIENT_ID
  &redirectUri=https://your-app.example.com/callback
  &codeChallenge=BASE64URL_SHA256_OF_VERIFIER
  &codeChallengeMethod=S256

The owner logs in via the Nissan IdP, sees the plain-language consent prompt for the scopes you requested, approves, and is redirected back to your redirectUri with an auth code.

redirectUri must exactly match one of the redirect URLs registered for the integration, or the request is rejected.

Step 3 — Exchange the code for tokens (on your callback, using the original verifier)

POST/cms/oauth/token
curl
curl -X POST "{API_BASE}/cms/oauth/token" \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "authorization_code",
    "code": "AUTH_CODE_FROM_CALLBACK",
    "redirect_uri": "https://your-app.example.com/callback",
    "client_id": "YOUR_CLIENT_ID",
    "code_verifier": "ORIGINAL_VERIFIER"
  }'

You receive an access_token, an id_token, and a refresh_token.

Step 4 — Call owner-scoped APIs with dual tokens

Every /cms/oauth/accounts/... call requires both headers:

http
Authorization: Bearer <access_token>
X-Id-Token: <id_token>

The owner-scoped endpoints mirror the M2M ones:

GET/cms/oauth/accounts/{account_id}/realtime/data-requests
GET/cms/oauth/accounts/{account_id}/historical/data-requests
POST/cms/oauth/accounts/{account_id}/realtime/data-requests
POST/cms/oauth/accounts/{account_id}/historical/data-requests
GET/cms/oauth/accounts/{account_id}/realtime/vehicles/{vin}/{resource}

Step 5 — Refresh tokens before they expire

The refresh token rotates on each use — store the new one each time:

POST/cms/oauth/token/refresh
curl
curl -X POST "{API_BASE}/cms/oauth/token/refresh" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "YOUR_CLIENT_ID",
    "refreshToken": "YOUR_REFRESH_TOKEN"
  }'
Refreshing a token has no effect on consent.If the owner revoked consent or the term expired, refreshed tokens still won't return data — handle that as an expected condition, not a bug.

Data-request lifecycle & statuses

A request moves through several states as the owner consents and data is delivered. Poll the list endpoints or use webhooks to track it. These are the authoritative enums returned by the API:

FieldValues
requestStatusPENDING, ACTIVE, APPROVED, DECLINED, COMPLETED, REVOKED, CANCELLED, INVALID, EXPIRED
consentStatusPENDING, GRANTED, REVOKED, EXPIRED, DENIED, SUPERSEDED
package statusPENDING, GRANTED, DENIED, EXPIRED, REVOKED
requestTypeHISTORICAL, REAL_TIME, ONE_OFF, PERIODIC
frequencyMONTHLY, WEEKLY (periodic only)

The consent lifecycle, in brief:

TransitionWhen
PENDING → APPROVEDOwner grants
PENDING → DECLINEDOwner denies
PENDING → EXPIREDNo action in window
APPROVED → COMPLETEDOne-off delivered
APPROVED → REVOKEDOwner revokes
APPROVED → EXPIREDTerm ends

How to read the statuses together:

  • PENDING / consentStatus = PENDING — created, owner notified, awaiting action. No data.
  • APPROVED + GRANTED — the only state in which data is retrievable. Real-time reads and historical deliveries are available here.
  • DECLINED / consentStatus = DENIED — owner rejected. Terminal; initiate a new request if still needed.
  • EXPIRED (request) / consentStatus = EXPIRED — either the request lapsed before the owner acted, or the consent term ended. Terminal; create a fresh request.
  • REVOKED — owner revoked an active grant; data stops immediately. Terminal for that grant.
  • SUPERSEDED (consent) — a newer consent grant has replaced this one (e.g., re-scoped request).
  • COMPLETED — a one-off request whose delivery has been fulfilled.
  • INVALID / CANCELLED — failed validation (bad VIN, no ownership link, etc.) or was cancelled.
Don't gate your data reads on your token state. Gate them on requestStatus = APPROVED and consentStatus = GRANTED.

Retrieving data

Historical (file delivery)

Historical results are prepared asynchronously and delivered as zipped CSVs via a time-limited pre-signed download URL (session/IP- restricted). The flow:

  1. Request reaches APPROVED + GRANTED and (Workflow A) payment is captured.
  2. List deliveries: GET .../historical/data-requests/{requestId}/data-deliveries.
  3. Fetch the download URL: GET .../data-deliveries/{dataDeliveryId}/download.
  4. Download promptly — the URL expires.

If you created the request via API and subscribed to webhooks, you'll receive a delivery-ready event instead of needing to poll.

Last-known value

Last-known packages return the most recent known value(s) synchronously as JSON — no date range, no async file. Availability is vehicle-dependent (see Data families); expect a single response per call.

Real-time (pull)

Once APPROVED + GRANTED, read the latest known state of a resource on demand:

GET {API_BASE}/cms/{m2m|oauth}/accounts/{account_id}/realtime/vehicles/{vin}/{resource}

Real-time (push)

Subscribe a webhook to receive events on state change instead of polling. Real-time push is event-driven (e.g., journey completed, charge-state changed, safety fault).

Real-time telematics catalog

Real-time resources are read per vehicle via .../realtime/vehicles/{vin}/{resource}. Available {resource} values:

ResourceDescription
locationCurrent GPS position
cockpitOdometer, fuel/energy and cockpit readouts
chargingEV charging state (EV only; 404 for ICE vehicles)
hvacClimate / HVAC state
tirepressureTire pressure readings
occupancySeat occupancy / belt status
visibilityLights and visibility-related state
adasAdvanced driver-assistance state
behaviorDriving-behavior signals
securityDoors, locks and alarm state
healthstatusVehicle health / diagnostic status
A resource may return no data if the vehicle doesn't support it. charging returns 404 for non-EV (ICE) vehicles. This is expected, not an error in your integration.

Webhooks

Instead of polling, subscribe a webhook and the platform pushes events to your endpoint. Two payload families are delivered: real-time telemetry push and consent & billing lifecycle events. Both arrive as HTTPS POSTs signed with HMAC-SHA256 — register once, verify the signature, then route on the payload.

Register your endpoint

You can register from the portal UI or the webhook API. In the portal:

  1. Log in to the Portal.
  2. Open the Data Catalog tab in the top navigation.
  3. Switch to the Programmatic Access tab.
  4. In the Advanced Programmatic Access card, click Configure Webhook.
Configure Webhook appears only once you have at least one integration. If you don't see it, create one first via Create Integration in the same card.

In the dialog you provide:

  • A publicly reachable HTTPS callback URL.
  • An HMAC key (up to 32 characters) used to sign and verify payloads.

Subscriptions are managed against your business account:

One subscription per account. A single active webhook subscription is maintained per business account. Registering again updates the existing subscription rather than adding a second endpoint — use PUT to rotate the URL or HMAC key.

Deliveries originate from the platform's (MyNissanData) webhook delivery service over HTTPS. If your infrastructure requires source IP allow-listing, request the current egress range for your environment from your account team.

Registration handshake (ownership challenge)

When you register a callback URL, the platform verifies you own it before it will send events:

  1. The platform sends a challenge to your URL.
  2. Your endpoint must echo the challenge back in the response.
  3. On a match, the subscription is saved and set active.

Type 1 — Real-time telemetry push (telemetry-push)

Delivered when a subscribed vehicle emits a real-time event. Every delivery uses the same envelope; the event data is carried in payload:

json
{
  "eventId":   "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
  "eventType": "telemetry-push",
  "eventTime": "2026-06-01T12:34:56.000Z",
  "vin":       "SJNJ12TDXU2117834",
  "payload":   { "soc": 80 }
}
FieldMeaning
eventIdUnique per delivery — use as your idempotency key.
eventTypeAlways telemetry-push. A single subscription covers charge, journey, and fault events alike — infer the specific kind from the payload contents (e.g. chargeStatusData, tripInformation, safetyAlertData), not from this field.
eventTimeISO-8601 UTC timestamp of delivery.
vinVehicle identification number.
payloadThe event data.

Signature verification (X-MND-Sig)

Each delivery carries an HMAC-SHA256 signature in the X-MND-Sig header (lowercase hex, 64 characters). Compute it over the eventTime, a literal dot, and the raw request body:

text
signed string = <eventTime> + "." + <raw request body>
X-MND-Sig     = HMAC_SHA256(signed string, your_hmac_key)   // lowercase hex
  • eventTime — the top-level eventTime value from the body, used verbatim.
  • raw body — the exact bytes you received; do not re-serialize the JSON before hashing.
  • Compare case-sensitively and in constant time.

Test vector — verify your implementation against this:

text
signing key : whsec_sample_key_do_not_use_in_prod
eventTime   : 2026-06-01T12:34:56.000Z
raw body    : {"eventId":"3f2504e0-4f89-41d3-9a0c-0305e82c3301","eventType":"telemetry-push","eventTime":"2026-06-01T12:34:56.000Z","vin":"SJNJ12TDXU2117834","payload":{"soc":80}}
signed str  : 2026-06-01T12:34:56.000Z.{"eventId":"3f2504e0-4f89-41d3-9a0c-0305e82c3301","eventType":"telemetry-push","eventTime":"2026-06-01T12:34:56.000Z","vin":"SJNJ12TDXU2117834","payload":{"soc":80}}

X-MND-Sig   = 9ba0f7246a45239eeccf4bf3a5e7833aed475e3b56a4865c65478c2d956b6d2a
Common verification failures (→ 401): (1) signing only the raw body and forgetting the <eventTime>. prefix; (2) re-serializing the body before hashing instead of using the exact received bytes.

Type 2 — Consent & billing events

Consent-lifecycle and download-payment notifications use a different envelope: match on the top-level event and read the data object. Validate the X-MND-Sig signature the same way before processing.

timestamp is Unix epoch milliseconds (UTC). Optional fields are omitted entirely when absent (never sent as null) — a VIN-less request omits vin; a package with no stored display name omits name.

CONSENT_GRANTED — consent granted (example shows a partial grant, one package denied):

json
{
  "event": "CONSENT_GRANTED",
  "data": {
    "requestId": "3f1c8e2a-9b4d-4f7a-8c21-0d5e6f7a8b90",
    "appId": "9a2b7c3d-1e4f-4a5b-9c8d-2e3f4a5b6c7d",
    "accountId": "acct-10023",
    "consentStatus": "GRANTED",
    "requestStatus": "APPROVED",
    "requestType": "REAL_TIME",
    "timestamp": 1752566400000,
    "vin": "WVWZZZ1KZAW000001",
    "packages": [
      { "id": "PKG_LOCATION", "name": "Location Data", "status": "GRANTED" },
      { "id": "PKG_TELEMATICS", "name": "Telematics", "status": "DENIED" }
    ]
  }
}

CONSENT_DENIED — vehicle user declines the request:

json
{
  "event": "CONSENT_DENIED",
  "data": {
    "requestId": "7b2d1f04-3c6e-4a19-b0f2-5a8c9d1e2f30",
    "appId": "9a2b7c3d-1e4f-4a5b-9c8d-2e3f4a5b6c7d",
    "accountId": "acct-10023",
    "consentStatus": "DENIED",
    "requestStatus": "DECLINED",
    "requestType": "HISTORICAL",
    "timestamp": 1752570000000,
    "vin": "WVWZZZ1KZAW000001",
    "packages": [
      { "id": "PKG_TRIPS", "name": "Trip History", "status": "DENIED" }
    ]
  }
}

CONSENT_REVOKED — a previously granted consent is revoked or cancelled (example reflects app termination: request → CANCELLED, consent + packages → REVOKED):

json
{
  "event": "CONSENT_REVOKED",
  "data": {
    "requestId": "c4a9e6b1-8d20-4f3c-9a7e-1b2c3d4e5f60",
    "appId": "9a2b7c3d-1e4f-4a5b-9c8d-2e3f4a5b6c7d",
    "accountId": "acct-10023",
    "consentStatus": "REVOKED",
    "requestStatus": "CANCELLED",
    "requestType": "REAL_TIME",
    "timestamp": 1752573600000,
    "vin": "WVWZZZ1KZAW000001",
    "packages": [
      { "id": "PKG_LOCATION", "name": "Location Data", "status": "REVOKED" }
    ]
  }
}

CONSENT_EXPIRED — consent auto-expired (no user action within the consent window):

json
{
  "event": "CONSENT_EXPIRED",
  "data": {
    "requestId": "e1f2a3b4-5c6d-4e7f-8a9b-0c1d2e3f4a5b",
    "appId": "9a2b7c3d-1e4f-4a5b-9c8d-2e3f4a5b6c7d",
    "accountId": "acct-10023",
    "consentStatus": "EXPIRED",
    "requestStatus": "EXPIRED",
    "requestType": "HISTORICAL",
    "timestamp": 1752577200000,
    "vin": "WVWZZZ1KZAW000001",
    "packages": [
      { "id": "PKG_TRIPS", "name": "Trip History", "status": "EXPIRED" }
    ]
  }
}

PAYMENT_FAILED — a download-time invoice payment could not be resolved (the API call is rejected with HTTP 402):

json
{
  "event": "PAYMENT_FAILED",
  "data": {
    "requestId": "a8b7c6d5-e4f3-4a2b-9c8d-7e6f5a4b3c2d",
    "accountId": "acct-10023",
    "appId": "9a2b7c3d-1e4f-4a5b-9c8d-2e3f4a5b6c7d",
    "invoiceId": "inv-2026-000789",
    "status": "FAILED",
    "message": "Payment could not be completed",
    "requestType": "ONE_OFF",
    "vin": "WVWZZZ1KZAW000001"
  }
}
Real-time push is intentionally event-driven (aggregated, meaningful events) rather than raw high-frequency telemetry, to protect your receiving infrastructure.

Real-time packages: overview & trigger matrix

Real-time connected-vehicle data reaches you in one of two ways: you pull the last-known value of a resource whenever you ask, or you receive a signed webhook push the instant an event happens. Your subscribed package decides which data groups you are entitled to — see Webhooks for the delivery mechanics.

What triggers a delivery

DeliveryTypeFires when
On-demand pullPullYou call the endpoint for a resource; it returns the last-known value.
JOURNEY.COMPLETEDPushThe vehicle ends a journey — at ignition off.
CHARGE.STATE.CHANGEDPushThe charge plug connects or disconnects, or the charge status changes.
SYSTEM.SAFETY.FAULTPushA new hardware safety or health fault is detected — delivered immediately.

Package × trigger matrix

delivered by webhook  ·  available on pull  ·  not applicable

PackageOn-demand pullJOURNEY.COMPLETEDCHARGE.STATE.CHANGEDSYSTEM.SAFETY.FAULT
Telemetry Snapshotlocation · odometer · energy
Usage-Based Insurance
Smart Chargingenergy
Remote Diagnosticssafety alerts

The four real-time packages

  • Telemetry Snapshot (pkg.rt.telemetry_snapshot) — current position, mileage and energy/fuel level for a vehicle. On-demand pull only — no webhook.Unlocks Geolocation, Odometer and Fuel & Energy.
  • Usage-Based Insurance (pkg.rt.ubi_insurance) — a completed-journey summary with driving-behaviour metrics, for pay-how-you-drive products. Pushes on JOURNEY.COMPLETED. Unlocks Driver Behaviour, Tire Pressure, Geolocation and Odometer.
  • Smart Charging (pkg.rt.smart_charging) — EV state-of-charge and charging-session events, for energy and charging platforms. Pushes on CHARGE.STATE.CHANGED, plus on-demand pull of energy state. Unlocks Fuel & Energy and Geolocation.
  • Remote Diagnostics (pkg.rt.remote_diagnostics) — safety and health faults, for repair and roadside providers. Pushes on SYSTEM.SAFETY.FAULT, plus on-demand pull of safety alerts. Unlocks System Safety, ADAS, Engine Health and EV Health.

Real-time data dictionary (pull API & webhook)

Every real-time field, grouped by data group: the signal received from the vehicle, the field delivered in the message, its type and unit, an official description, and the complete value-to-meaning mapping. Read it alongside the package × trigger matrix to know which fields a given package actually delivers.

Pull API endpoints

GET {base}/vehicles/{vin}/{section}
Authorization: Bearer <access_token>

The pull API returns the last-known value for a section. The platform serves these sections (public path names are assigned by the API gateway):

SectionData returned
locationGeolocation
cockpitOdometer · Fuel level · Distance-to-empty · Speed
chargingCharge status · Plug status · Charge session (Fuel & Energy)
behaviorDriver Behaviour
tirepressureTire Pressure
occupancyOccupancy · Seat belts
securityLocks · Doors · Windows · Sunroof · Anti-theft
hvacHVAC · Cabin / External temperature
visibilityLighting · Wipers
healthstatusHealth alerts · System safety alerts · MIL · Oil pressure · Faults (Engine Health · EV Health · System Safety)
adasADAS — FCW · AEB · LDW · ACC · Driver monitoring

Webhook events

Delivery is a signed POST to your registered endpoint.

EventData delivered in the payload
JOURNEY.COMPLETEDGeolocation · Odometer · Driver Behaviour (journey summary) · Tire Pressure
CHARGE.STATE.CHANGEDGeolocation · Fuel & Energy
SYSTEM.SAFETY.FAULTGeolocation · ADAS · System Safety

Message shapes

Pull response:

json
{
  "vin": "...",
  "serviceName": "geolocation",
  "data": { "geolocation": { ... } },
  "metaData": {
    "responseStatus": "SUCCESS",
    "message": "..."
  }
}

Webhook body:

json
{
  "eventId": "...",
  "eventType": "CHARGE.STATE.CHANGED",
  "eventTime": "2026-06-01T12:34:56.000Z",
  "vin": "...",
  "payload": {
    "chargeSession": { ... },
    "location": { ... }
  }
}
Every webhook is signed with X-MND-Signature = HMAC_SHA256(secret, eventTime + "." + rawBody) (lowercase hex) — verify it before trusting the payload. Field names are identical between the pull data block and the webhook payload block. Fields the vehicle did not report are omitted from the message rather than sent as null.

How to read this dictionary

Signal received is the raw vehicle signal; Field delivered is the JSON key you actually receive, and it is the authoritative name — it is not always a mechanical camelCase of the signal (StatusDistanceTotalizerComputed arrives as mileage, VCMEVSOCStatusDisplay as stateOfCharge). Numeric fields pass through unchanged. Coded fields carry both the integer code and its enum label — the Value column lists each code with the exact label delivered (e.g. 1 = ECO). A suppressedcode is the vehicle's "no data" marker: that field is dropped rather than sent.

A note on value polarity. Most alert flags read 0 = OK, 1 = active — but brake fluid low, 12V battery low and HV battery high invert to 1 = OK, 2 = active. Status fields (doors, tyres, charge, gearbox…) are multi-state rather than simple on/off — check each row.

Push vs pull — which groups go where

A webhook is not a full vehicle snapshot; each event pushes only the fields listed below. The pull API serves every group on demand.

GroupWebhook (push)Pull
GeolocationIncluded in every event (as context)location
OdometerJOURNEY.COMPLETEDcockpit
Driver BehaviourJOURNEY.COMPLETEDbehavior
Tire PressureJOURNEY.COMPLETEDtirepressure
Fuel & EnergyCHARGE.STATE.CHANGEDcharging
System Safety & FaultsSYSTEM.SAFETY.FAULThealthstatus
EV HealthSYSTEM.SAFETY.FAULThealthstatus
ADAS— not pushed —adas
Engine Health— not pushed —healthstatus · cockpit
Access, Security & Cabin— not pushed —security · occupancy · hvac
Lighting & Visibility— not pushed —visibility
Faults ride the webhook as codes, not as readings. On SYSTEM.SAFETY.FAULT a fault is delivered as an alert code — e.g. OIL_PRESSURE_WARNING, MIL_ON. The matching descriptive fields (healthAlert.oilPressure, statusMilLampRequest) are pull-only and live under Engine Health. This is why oil pressure / MIL appear in two places.
CCS1 / CCS2 availability. Unless a group notes otherwise, each field is delivered on both CCS1 and CCS2. The following are CCS2 / EVO only (not populated on CCS1):
  • Whole groups: Doors, Locks, Windows, Sunroof, Occupancy, HVAC, ADAS (FCW / AEB / LDW), and most Lighting status fields (brake lamp, low beam, flashing indicator, warning lights).
  • Individual fields: averageTripSpeed, statusSpeedUnit, per-wheel average speeds, lastKnownLocationAltitude, driveModeState, ePedalModeDisplayRequest, engine RPM & torque averages, fuelGaugeDisplayValue, charge-session detail (remaining time, power estimate), oilLevel, gearbox lever position, per-wheel tyre pressure state, and engine air / coolant temperature warnings.

Geolocation

Pull: section location  ·  Webhook: included in every event for context

Signal receivedField deliveredTypeUnitDescriptionValue → label / meaning
LocationLatitudelocationLatitudeNumberdegreesLatitude position of the vehicle−90.0 … 90.0 (WGS-84 decimal degrees)
LocationLongitudelocationLongitudeNumberdegreesLongitude position of the vehicle−180.0 … 180.0 (WGS-84 decimal degrees)
LocationHeadinglocationHeadingNumberdegreesDirection heading of the vehicle0 … 360 (0 = north, 90 = east, clockwise)
LastKnownlocationaltitudelastKnownLocationAltitudeNumbermetresAltitude position of the vehicleHeight above sea level
LocationSourcelocationSourceEnumSource of the reported position (connectivity module or infotainment)0 = A_IVC · 1 = A_IVI · 2 = UNAVAILABLE (suppressed)
LocationValiditylocationValidityEnumWhether the location data was received correctly from the IVI/IVC. While this signal is NOT_VALID, the position from the last successful read continues to be recorded.0 = VALID · 1 = NOT_VALID · 2 = UNAVAILABLE (suppressed)

Odometer

Pull: section cockpit  ·  Webhook: JOURNEY.COMPLETED

Signal receivedField deliveredDelivered inTypeUnitDescriptionValue → label / meaning
StatusDistanceTotalizerComputedmileagePull onlyNumberkmTotal corrected vehicle mileage, computed from the A-IVC StatusDistanceTotalizer signal. The correction covers an IVC mile-to-km conversion defect affecting vehicles whose trip-distance unit is set to miles.Cumulative odometer (0 … 2,600,000)
TotalDistanceStartTriptotalDistanceStartTripJOURNEY.COMPLETEDNumberkmOdometer reading at the start of the tripCumulative odometer at trip start
TotalDistanceEndTriptotalDistanceEndTripJOURNEY.COMPLETEDNumberkmOdometer reading at the end of the trip (the trip-end total mileage)Cumulative odometer at trip end
MileageCoveredInTripmileageCoveredInTripPull · JOURNEY.COMPLETEDNumberkmDistance covered on the current or last tripDistance covered on the current/last trip
Note. mileage (cumulative odometer) is delivered on the pull API only. In JOURNEY.COMPLETED the trip-end odometer arrives as totalDistanceEndTrip (with totalDistanceStartTrip and mileageCoveredInTrip) — there is no mileage field in the journey payload.

Driver Behaviour

Pull: section behavior  ·  Webhook: JOURNEY.COMPLETED

CCS availability: the journey trip-summary metrics are on both CCS1 & CCS2 (except averageTripSpeed — CCS2 / EVO only). The live per-signal fields in the first table are CCS2 / EVO only, except speedDisplayedValue (both).

Signal receivedField deliveredTypeUnitDescriptionValue → label / meaning
SpeedDisplayedValueinkmhspeedDisplayedValueNumberkm/hSpeed of the vehicle as displayed on the instrument panelCluster-displayed speed (0 … 409.4)
StatusSpeedUnitstatusSpeedUnitEnumUnit of speed measurement for the vehicle0 = KM/H · 1 = MPH
EngineRawSensorengineRawSensorNumber%Percentage of engine torque on a 0–125% scale. The value can exceed the nominal 100% maximum for a short time, for example in an overboost situation.Engine torque (0 … 125)
ESCBrakingPedalInformationescBrakingPedalInformationEnumPress status of the brake pedal1 = BRAKE_PEDAL_NOT_PRESSED · 2 = BRAKE_PEDAL_PRESSED · 4 = BRAKE_PEDAL_CONFIRMED_PRESSED
DriveModeStatedriveModeStateEnumDriving mode status0 = NORMAL_STANDARD_AUTO · 1 = ECO · 2 = SPORT_TRACK · 3 = SPORT_PLUS_POWER · 4 = COMFORT · 5 = PERSONAL · 6 = SNOW · 8 = OFF_ROAD_GRAVEL · 9 = MUD_RUT · 10 = SAND · 11 = TOW · 12 = ALL_ROAD_ROCK · 13 = EXTREM · 14 = PERFO · 15 = VITAMIN · 16 = RACE · 31 = UNAVAILABLE (suppressed)
ePedalModeDisplayRequestePedalModeDisplayRequestEnumStatus of the e-Pedal mode0 = NO_DISPLAY · 1 = EPEDAL_MODE_ACTIVE_ON
AdaptativeCruiseControlDisplayDistanceSettingadaptiveCruiseControlDisplayDistanceSettingEnumDistance setting from the vehicle in front for Adaptive Cruise Control0 = NO_DISPLAY · 1 = SHORT_DISTANCE · 2 = MIDDLE_DISTANCE · 3 = LONG_DISTANCE · 4 = REGLEMENTARY_DETECTED_DISTANCE · 5 = VERY_LONG_DISTANCE · 6 = RESERVED_6 · 7 = RESERVED_7
ACCTargetDistanceDisplayaccTargetDistanceDisplayEnumVisual indication on the display of the distance from the vehicle in front, for Adaptive Cruise Control0 = NO_DETECTED_TARGET · 1 = LONG_DETECTED_DISTANCE · 2 = MIDDLE_DETECTED_DISTANCE · 3 = SHORT_DETECTED_DISTANCE · 4 = REGLEMENTARY_DETECTED_DISTANCE · 5 = RESERVED_5 · 6 = RESERVED_6 · 7 = RESERVED_7
Journey summary — JOURNEY.COMPLETED only. The journey webhook delivers, in addition to the per-signal fields above, a set of trip-scoped metrics computed at journey end (payload nested by subdoc):
Field deliveredSubdocTypeUnitDescription
journeyId(root)StringUnique identifier for the journey
status(root)EnumJourney status — COMPLETED
closeReason(root)EnumWhy the journey closed — IGN_OFF
stopTripTimestampheaderStringISO-8601Timestamp when the journey ended
durationTripLifetripCountersNumbersTotal trip duration
mileageCoveredInTripodometerNumberkmDistance covered during the trip
totalDistanceStartTrip · totalDistanceEndTripodometerNumberkmOdometer reading at trip start / end
averageTripSpeedspeedNumberkm/hAverage speed over the trip
speedDisplayedValuespeedNumberkm/hCluster-displayed speed
acceleratorPedalOpeningRatiodriveDynamicsNumberAccelerator-pedal opening ratio
rapidDecelerationAcceleration[]harshAccelDecelArrayRapid acceleration / deceleration events during the trip — each entry: timestamp, latitude, longitude, speedAtStart
idlingTimeInTripidlingNumbersTime spent idling during the trip
frequency3000RpmTripdata … frequency6000RpmTripdatarpmBandExceedanceNumbercountNumber of times each RPM band (3000 / 4000 / 5000 / 6000) was exceeded during the trip

Fuel & Energy

Pull: section charging  ·  Webhook: CHARGE.STATE.CHANGED

Signal receivedField deliveredTypeUnitDescriptionValue → label / meaning
FuelGaugeDisplayValuefuelGaugeDisplayValueNumber%Remaining amount of fuel in the tank, as shown on the fuel indicator in the instrument panelFuel level (0 … 100)
FuelGaugeIndicatorfuelGaugeIndicatorNumberLFuel remaining shown on the gauge, in litresFuel remaining in litres
VCMEVSOCStatusDisplaystateOfChargeNumber%Battery state of charge shown to the driverBattery state of charge (0.01 … 100)
ChargeStatuschargeStatusEnumCharging-session status0 = No charge · 1 = Waiting a planned charge · 2 = Ended charge · 3 = Charge in progress · 4 = Charge failure · 5 = Waiting for current charge · 6 = Energy Flap opened: welcome MMI · 7 = Stopped charge (SOC is not full) · 8 = Charging is continue with full SOC · 9 = V2G · 10 = V2L Outside · 11 = V2G in discharge · 12 = V2G in charge · 13 = Not used · 14 = Not used · 15 = Not used
HVBatteryChargeTypehvBatteryChargeTypeEnumType of charge. V2H (Vehicle-to-Home) powers a house from the vehicle; V2G (Vehicle-to-Grid) returns energy to the grid to help stabilise it at peak demand. V2G is not in use as of 2025.0 = NO_CHARGE · 1 = NORMAL_CHARGE · 2 = ACCELERATED_CHARGE · 3 = FAST_CHARGE · 4 = QUICK_CHARGE · 5 = ULTRA_FAST · 6 = NOT_USED · 7 = UNAVAILABLE (suppressed) · 8 = V2H · 9 = V2G
EVChargePlugConnectedevChargePlugConnectedEnumCharging-cable connection status0 = No display request (Charging Plug is NOT Connected) · 1 = Charging Plug is Connected · 2 = Powertrain Start impossible - Plug Connected · 3 = Unavailable value
ChargeDurationchargeDurationNumbersecondsElapsed time of the charging session (push only)Duration of the charging session
ChargeEnergychargeEnergyNumberkWhEnergy added to the battery during the session (push only)Energy added during the session

ADAS (Driver Assistance)

Pull only — section adas. Not delivered on any webhook: the SYSTEM.SAFETY.FAULT payload carries only the alert-code fields, not the ADAS subdocs. CCS2 / EVO only

Signal receivedField deliveredTypeDescriptionValue → label / meaning
ActivationStateFCWactivationStateFcwEnumON/OFF status of Automatic Emergency Braking (AEB) and Forward Collision Warning (FCW)0 = AEB_OFF_FCW_OFF · 1 = AEB_OFF_FCW_ON · 3 = AEB_ON_FCW_ON
AEBStatusDisplayaebStatusDisplayEnumAutomatic Emergency Braking (AEB) system status0 = No display · 1 = AEB off · 2 = Operation · 3 = Not operation · 4 = Temporary failure · 5 = Permanent failure · 6 = Initial
StateActivationstateActivationEnumActivation status of Lane Departure Warning (LDW)0 = Unavailable · 1 = Activated · 2 = Deactivated · 3 = Not used

Engine Health

Pull only — sections healthstatus · cockpit. The descriptive health fields (healthAlert.*, statusMilLampRequest, gearbox, air/coolant temp) are not on the webhook; only their alert-code equivalents (OIL_PRESSURE_WARNING, MIL_ON…) ride SYSTEM.SAFETY.FAULT.

Signal receivedField deliveredTypeUnitDescriptionValue → label / meaning
EngineAirTemperatureengineAirTemperatureNumber°CEngine intake-air temperatureIntake-air temperature
EngineCoolantTempengineCoolantTempNumber°CTemperature of the engine coolant for an internal-combustion engine (not available for electric vehicles)Coolant temperature
OilPressureWarninghealthAlert.oilPressureEnumIndicator that warns when oil pressure is under an alert threshold0 = OK · 1 = WARNING
OilLevelhealthAlert.oilLevelEnumEngine oil level on the 0–15 oil-condition scale8–15 = OK · 0–7 = low (0–15 scale)
EngineWaterTempWarninghealthAlert.coolantTempEnumEngine coolant over-temperature warning0 = OK · 1 = high (fallback: coolant ≥ 115 °C = high)
StatusMIL_LampRequeststatusMilLampRequestEnumRequest to switch on the MIL lamp on the meter0 = OFF · 1 = ON
GearBoxAutoLeverPositiongearBoxAutoLeverPositionEnumGearbox lever selection0 = Parking · 1 = Reverse · 2 = Neutral · 3 = Drive · 4 = Manual mode · 5 = Low gear · 6 = Drive sport · 7 = Confirmed · 8 = Brake
GearBoxAutomaticRangeIndicationgearBoxAutomaticRangeIndicationEnumGear or mode of the gearbox that is currently in operation0 = Off · 1 = Parking · 2 = Reverse · 3 = Neutral · 4 = Drive · 5 = Sport · 6 = Low gear · 7 = Brake · 8 = 1st gear · 9 = 2nd gear · 10 = 3rd gear · 11 = 4th gear · 12 = 5th gear · 13 = 6th gear · 14 = 7th gear · 15 = 8th gear · 16 = 9th gear · 17 = 10th gear · 20 = Manual 1st · 21 = Manual 2nd · 22 = Manual 3rd · 23 = Manual 4th · 24 = Manual 5th · 25 = Manual 6th · 26 = Manual 7th · 27 = Manual 8th · 28 = Manual 9th · 29 = Manual 10th · 32 = Auto 1st · 33 = Auto 2nd · 34 = Auto 3rd · 35 = Auto 4th · 36 = Auto 5th · 37 = Auto 6th · 38 = Auto 7th · 39 = Auto 8th · 40 = Auto 9th · 41 = Auto 10th

Tire Pressure

Pull: section tirepressure  ·  Webhook: JOURNEY.COMPLETED  ·  per-wheel state CCS2 / EVO only

Signal receivedField deliveredTypeUnitDescriptionValue → label / meaning
StatusWheelStateFrontLeft (per wheel)statusWheelState… (per wheel)EnumTyre inflation status, reported per wheel0 = OK · 1 = LOW_PRESSURE · 2 = FLAT_TIRE · 3 = ERROR_FAILURE · 4 = LOW_PRESSURE_AND_FAILURE · 5 = NOT_AVAILABLE
StatusWheelPressureFrontLeft (per wheel)statusWheelPressure… (per wheel)NumbermbarPer-wheel tyre pressure reading. The tyre-pressure monitoring system only updates while the vehicle is moving, so a long-parked vehicle keeps reporting the previous values until it runs again.Per-wheel pressure
StatusWheelPressureFrontAxle / RearAxlestatusWheelPressure…AxleNumberkPaAxle-level tyre-pressure monitoring system readingAxle-level pressure
StatusWheelTPMSTpmsWarningLampRequeststatusWheelTpmsTpmsWarningLampRequestEnumRequest to switch on the tyre-pressure warning lamp0 = TPMS warning lamp is OFF · 1 = TPMS warning lamp is ON

EV Health

Pull: section healthstatus  ·  Webhook: SYSTEM.SAFETY.FAULT (both fields are alert codes, so they do ride the webhook)

Signal receivedField deliveredTypeDescriptionValue → label / meaningSeverity
HVBatteryLowAlertHV_BATTERY_LOWEnumLow-level alert for the traction battery (xEV)0 = OK · 1 = LOWWARN
BatteryHighLevelAlertHV_HIGH_LEVELEnumBattery high-level warning; the customer can check it in their smartphone app from server data.1 = OK · 2 = HIGHWARN

System Safety & Faults

Pull: section healthstatus  ·  Webhook: SYSTEM.SAFETY.FAULT — this is the only group delivered in full on the fault webhook (these are the alert-code fields + location)

Signal receivedDelivered asDescriptionValue → label / meaningSeverity
ESCABSMalfunctionABS_FAILMalfunction status of the ABS (Anti-lock Braking System) feature0 = OK · 1 = FAILUREHIGH
ESCEBDStateDisplayEBD_FAILUREFailure status of the EBD (Electronic Brakeforce Distribution) system0 = OK · 1 = FAILUREHIGH
AFUFailureAFU_FAILUREMalfunction status of the emergency braking system0 = OK · 1 = FAILUREWARN
EV_AlertCRBS_FailureDisplayCRBS_FAILUREFailure alert for CRBS (cooperative regenerative braking at the brake pedal)0 = OK · 1 = FAILUREWARN
CrashAirbagMalfunctionAIRBAG_FAILUREMalfunction status of the airbag0 = OK · 1 = MALFUNCTIONCRITICAL
SteeringStatusSTEERING_WARNINGWarning status of the EPS (Electronic Power Steering) system0 = NO_EPS_WARNING · 1 = EPS_FAILURE_LEVEL_1 · 2 = EPS_FAILURE_LEVEL_2 · 3 = EPS_METER_LAMP_CHECKHIGH
ParkFailurePARK_FAILUREAT park failure status; the customer can check it in their smartphone app from server data.0 = OK · 1 = FAILUREWARN
PowerLimitationAlertPOWER_LIMITATIONSLOW lamp status; the customer can check it in their smartphone app from server data.0 = OK · 1 = LIMITEDWARN
StatusBrakeLowFluidLevelBRAKE_LOW_FLUIDLevel status of the brake fluid1 = OK · 2 = LOWHIGH
BatteryLowLevelAlertLOW_VEHICLE_BATTERYInforms the user of a low 12V battery level on the meter1 = OK · 2 = LOWWARN
FuelLowLevelFUEL_LOWIndicates whether the fuel level is low0 = OK · 1 = LOWINFO
StatusMIL_LampRequestMIL_ONRequest to switch on the MIL lamp on the meter0 = OFF · 1 = ONWARN
OilPressureWarningOIL_PRESSURE_WARNINGIndicator that warns when oil pressure is under an alert threshold0 = OK · 1 = WARNINGHIGH
StatusOilPressureSwitchOIL_PRESSURE_SWITCHEngine oil-pressure switch warning0 = OK · 1 = WARNINGHIGH
ESCBrakingFailureStatusESC_BRAKING_FAILUREElectronic Stability Control braking failure0 = OK · 1 = FAILUREHIGH
CrashDetectionOutOfOrderAIRBAG_OUT_OF_ORDERAirbag / crash-detection unit reporting a malfunction (out of order)0 = OK · 1 = REAR_CRASH_MALFUNCTION · 2 = SIDE_FRONT_CRASH_MALFUNCTION · 3 = REAR_AND_SIDE_FRONTHIGH
StatusWheelTPMSTpmsWarningLampRequestTPMS_WARNINGRequest to switch on the tyre-pressure warning lamp0 = OFF · 1 = ONWARN
StatusWheelStateFrontLeft / FrontRight / RearLeft / RearRightWHEEL_FL · WHEEL_FR · WHEEL_RL · WHEEL_RRPer-wheel tyre-state safety alert (one code per wheel)0 = OK · 1 = FAILURE · 2 = UNDERINFLATION · 3 = UNDERINFLATION_AND_FAILURE · 4 = PUNCTURE · 5 = PUNCTURE_AND_FAILURE · 6 = PUNCTURE_AND_UNDERINFLATION · 7 = PUNCTURE_AND_UNDERINFLATION_AND_FAILUREWARN
Reading the alerts payload. Safety alerts arrive in the alerts subdoc: a map keyed by alert code, each value { active, severity, label, rawValue }.
  • Use the active flagto decide whether an alert is on. Don't derive it from rawValue yourself — the raw-to-active rule differs by code (most 1 = active; BRAKE_LOW_FLUID / LOW_VEHICLE_BATTERY / HV_HIGH_LEVEL are 2 = active; AIRBAG_OUT_OF_ORDER and WHEEL_* are active on any non-zero). We apply the correct rule and set active for you.
  • Each code appears once, even if more than one vehicle signal can raise it.

Access, Security & Cabin

Pull only — sections security · occupancy · hvac. CCS2 / EVO only (doors, locks, windows, sunroof, occupancy, HVAC are not populated on CCS1)

GroupFields deliveredDescriptionValue → meaning
DoorsstatusDoorDriver, statusDoorPassenger, statusDoorFrontLeft, statusDoorFrontRight, statusDoorRearLeft, statusDoorRearRight, statusDoorTailGateOpen/closed status of each door0 = unavailable · 1 = closed · 2 = open
LocksdoorsDriverLocked, doorsPassengerLocked, doorsBackLocked, doorsRearLeftLocked, doorsRearRightLockedLock status of each door0 = unlocked · 1 = locked
WindowswindowsFrontLeftPosition, windowsFrontRightPosition, windowsRearLeftPosition, windowsRearRightPositionInstantaneous window position0 = invalid (suppressed) · 1 = closed · 2–5 = partly open · 6–7 = fully open
SunroofsunroofPositionSunroof position0 = invalid (suppressed) · 1 = closed · 3 = 14% · 5 = 28% · 7 = 42% · 9 = 57% · 11 = 71% · 13 = 85% · 15 = 100% open (even codes = moving)
Seat beltsseatBeltFirstRow (Driver / Center / Passenger), seatBeltSecondRow…, seatBeltThirdRow…Seat-belt fastened status per seat0 = unfastened · 1 = fastened
OccupancypresencePassenger, customerPresenceFirstRowCenter, customerPresenceSecondRow…, customerPresenceThirdRow…Seat occupancy (weight sensed)0 = not present · 1 = present
IgnitionstatusIgnitionSwitchPositionVehicle ignition-switch status0 = out of ignition · 1 = ignition or starting
ClimatehvacFanBlowerMotorStatus, hvacRecyclingAutoDisplayHVAC blower and auto-recirculation status0 = off · 1 = on
Climate — blower leveliceHvacDisplayClimBlowerLevelHVAC blower speed level0 = no display (suppressed) · 1–14 = level 1–14 · 15 = blower off
Climate — external temperatureexternalTempValue, externalTempDisplayUnitExternal temperature and its display unitValue in °C; unit 0 = Celsius · 1 = Fahrenheit

Lighting & Visibility

Pull only — section visibility. most fields CCS2 / EVO only (brake lamp, low beam, flashing indicator, warning lights)

Signal receivedField deliveredTypeDescriptionValue → label / meaning
BrakeLampStatusbrakeLampStatusEnumStatus of the brake light lamp, either manual or automatic (during emergency braking, for example)0 = OFF · 1 = ON
LightingWarningLightsStatuslightingWarningLightsStatusEnumWarning-light status, either manual or automatic (during emergency braking, for example)0 = OFF · 1 = ON
LightningLowBeamlightningLowBeam, lightningHighBeam, lightningFrontFogLight, lightningExternalDrlEnumStatus of the low-beam, high-beam, front fog and daytime-running-light requests0 = OFF · 1 = ON
RearFogLightsStatusrearFogLightsStatus, positionLightsStatusEnumStatus of the rear fog and position lights0 = OFF · 1 = ON
LightningFlashingIndicatorlightningFlashingIndicatorEnumStatus of the flashing turn indicators0 = BOTH_OFF · 1 = LEFT_ON_RIGHT_OFF · 2 = LEFT_OFF_RIGHT_ON · 3 = BOTH_ON · 4 = UNAVAILABLE
Field values come from the platform signal registry (what the service emits); descriptions and value meanings come from the Data Mapping. For package access or field questions, contact the Platform team.

Compliance constraints you must design for

These are data-protection constraints enforced by the platform. Designing for them up front avoids confusing rejections and partial results.

Temporal limits on historical requests

  • Earliest requestable date: 12 September 2025 (the effective date). You cannot request data older than this.
  • Maximum 90 days per historical request. Split longer ranges into multiple requests.
  • Lookback limited to ~3 years. Older history is not available.

Ownership / entitlement (Gate 3)

  • Data is only eligible for the portion of your requested window during which the consenting owner actually owned the vehicle. A valid request can therefore return a shorter window than asked.
  • Entitlement resolution differs by vehicle generation: for older generations an active ownership link suffices; newer generations additionally verify the active driver against the linked owner. The net effect for you: don't assume every request yields the full range — handle partial results.

Data minimization (Gate 2)

  • You receive exactly the packages/scopes the owner approved. Need more? Initiate a new request.

Governance (Gate 1)

  • Sanctioned or gatekeeper-designated entities are blocked at login and at request time.

Retention & deletion

  • Delivered files and decisions are retained as audit records under the platform's retention policy. Financial records persist for tax compliance even after account deletion.

Errors & troubleshooting

SymptomLikely cause / fix
401On /cms/oauth/accounts/... calls: missing or invalid X-Id-Token. Owner-scoped calls need both the access token and the id token.
401 token expiredRefresh with /cms/oauth/token/refresh (App) or request a new token (M2M).
Real-time read returns 4xx / no dataNo APPROVED request with GRANTED consent exists for that VIN/package yet — or consent was revoked/expired. Check requestStatus + consentStatus, not your token.
charging returns 404The vehicle is ICE (non-EV); charging is EV-only. Expected.
Historical result smaller than requested rangeGate 3 trimmed the window to the consenting owner's ownership period. Expected under the platform rules.
Authorize rejects the redirectredirectUri does not exactly match a registered redirect URL.
Request blocked at creationAn onboarding gate failed: suspended account, incomplete billing / no valid payment method, unaccepted Data T&C, or a gatekeeper/sanctions block. Fix in settings; retrying without fixing will fail again.
Request goes INVALID immediatelyValidation failed — invalid VIN, unresolvable user email, or no active owner–VIN pairing.
Consent never granted, request EXPIREDOwner didn't act within the consent window. The link is dead; initiate a new request.
Download link doesn't workPre-signed URLs are time- and session/IP-limited. Re-fetch a fresh URL from the deliveries endpoint.
Webhook events not arrivingRegistration challenge wasn't echoed correctly, or your URL isn't reachable over HTTPS. Re-verify the subscription.
More one-off charges than expectedA dynamically derived period makes every submission a new billable request. See Cost control.
Charged differently than expectedOne-off/historical is prepaid (hold→capture on consent); subscriptions are billed via a single aggregated charge on the 1st. SME vs. Large rates differ.

Rate limits & operational notes

  • The API Gateway applies rate-limiting policies. Build in retry-with-backoff and treat 429 as transient.
  • Validate against a development account (sandboxed, vehicle-count-limited) before going to production.
  • Real-time/webhook delivery suits self-serve SME-to-mid volumes. If sustained run-rate or frequency grows beyond the platform's managed-streaming threshold, that's a managed high-throughput streaming tier conversation — contact your account team rather than working around webhook limits.
  • Token hygiene: store the rotating refresh token after every refresh (App); never ship the client secret to a client device (M2M).

Glossary

TermMeaning
Account IDYour business account identifier, used in API paths and the M2M token request.
Client ID / SecretIntegration credentials. The secret applies to M2M only.
VIN17-character Vehicle Identification Number.
PackageA catalog entry defining the data a request can access; consent and billing are granted at the package level.
Data familyHistorical, Last Known Value, or Real-Time — determines delivery and billing.
ConsentThe vehicle owner's explicit, scope-specific, time-bounded, revocable approval for a data request.
Consent vs. tokenTwo independent lifecycles. Tokens authenticate your client; consent authorizes data. Both must be valid.
3-Gate engineThe sequential governance → consent-scope → ownership-time authorization run on every data access.
EntitlementWhether the consenting owner owned the vehicle during the requested window (Gate 3).
Gatekeeper / blocklistdesignated restricted entities blocked from receiving data (Gate 1).
PKCEProof Key for Code Exchange — secures the Authorization Code flow without a client secret.
Dual-tokenSending both Authorization: Bearer and X-Id-Token on owner-scoped (/cms/oauth/...) calls.
Pre-auth hold / captureA hold is placed at request time and captured when the owner consents (one-off/historical).
Aggregated billingA single monthly charge on the 1st covering all active, consented VINs (subscriptions).
SME / Large EnterpriseAccount tiers; SME gets the margin-free rate, Large the commercial rate.
Pre-signed URLA time- and session-limited download link for historical file deliveries.

API reference (Swagger)

The reference below is generated from the live OpenAPI specification. Use it for exact request/response schemas and to try endpoints interactively.

In the portal, the interactive Swagger UI is embedded below. The OpenAPI document is served (per environment) from: