# Make Specific Endpoints
Source: https://smartcar.com/docs/api-reference/about-brand-specific



<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

In cases where there are many differences in how each OEM provides the same data, Smartcar would provide you with a make-specific endpoint before making it widely available to all supported makes.

This allowed customers to take advantage of these endpoints and share feedback with Smartcar. Based on the feedback, we realized that these endpoints often required customers to write make-specific code, which is not ideal for a standardized API.

These endpoints will be deprecated along with API V2.0.

<Info>When using make specific endpoints, please ensure to specify the [make](/docs/api-reference/makes) in lower case format. Using upper case letters will result in a PERMISSION error.</Info>


# Errors Overview
Source: https://smartcar.com/docs/api-reference/api-errors

A comprehensive breakout of all Smartcar errors.

# Connect Errors

| Error Type           | Error Code                                                           | Description                                                                                                                     |
| -------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Access Denied        | [access\_denied](/docs/errors/connect-errors/access-denied)               | This error occurs when a user denies your application access to the requested scope of permissions.                             |
| Invalid Subscription | [invalid\_subscription](/docs/errors/connect-errors/invalid-subscription) | This error occurs when a user’s vehicle is compatible but their connected services subscription is inactive or never activated. |
| Configuration Error  | [configuration\_error](/docs/errors/connect-errors/configuration-error)   | This error occurs when the user has encountered an Error page in Connect and has chosen to return to your application.          |
| No Vehicles          | [no\_vehicles](/docs/errors/connect-errors/no-vehicles)                   | This error occurs when a vehicle owner has a connected services account, but there are no vehicles associated with the account. |
| Vehicle Incompatible | [vehicle\_incompatible](/docs/errors/connect-errors/vehicle-incompatible) | This error occurs when a user tries to authorize an incompatible vehicle in Smartcar Connect.                                   |
| Server Error         | [server\_error](/docs/errors/connect-errors/server-error)                 | If there is a server error, the user will return to your application.                                                           |

<br />

# API Errors

API errors are returned from requests made via Smartcar API.
Smartcar uses HTTP status codes to indicate success or failure of API requests. This includes:

* `2XX`: indicates success
* `4XX`: indicates an invalid request (e.g. a required parameter is missing from the request body)
* `5XX`: indicates Smartcar-related issues (e.g. a vehicle is not capable of fulfilling a request).

## Error Response

All Smartcar errors contain the following fields:

| Name                 | Type   | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| -------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| type                 | string | A unique identifier that groups codes into broad categories of errors                                                                                                                                                                                                                                                                                                                                                                                        |
| code                 | string | A short, descriptive identifier for the error that occurred                                                                                                                                                                                                                                                                                                                                                                                                  |
| title                | string | A human readable representation of the code                                                                                                                                                                                                                                                                                                                                                                                                                  |
| detail               | string | A short description of the code that provides additional information about the error. Always provided in English.                                                                                                                                                                                                                                                                                                                                            |
| status               | number | The HTTP status code (In long running commands, may differ from http response header)                                                                                                                                                                                                                                                                                                                                                                        |
| resolution           | object | An object with at least one enumerated property named as "type" that specifies which action can be taken to resolve this error. There are three possible values for the property "type": `RETRY_LATER` - Retry the request at a later time; `REAUTHENTICATE` - Prompt the user to re-authenticate in Smartcar Connect; and `CONTACT_SUPPORT` - Contact Smartcar’s support team. This object could contain other properties depending on the "type" of error. |
| suggestedUserMessage | object | A friendly message to describe transient errors to application users                                                                                                                                                                                                                                                                                                                                                                                         |
| links                | object | Links to error documentation                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| meta                 | object | Contains debugging information useful when contacting customer support                                                                                                                                                                                                                                                                                                                                                                                       |

<br />

| Error Type                   | Error Code                                                                                               | Status | Description                                                                                                                                                                                                   |
| ---------------------------- | -------------------------------------------------------------------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `AUTHENTICATION`             | [UNAUTHORIZED](/docs/errors/api-errors/v3/authentication-errors#UNAUTHORIZED)                                 | 401    | Thrown when there is an issue with your authorization headers.                                                                                                                                                |
| `AUTHENTICATION`             | [ACCESS\_DENIED](/docs/errors/api-errors/v3/authentication-errors#ACCESS_DENIED)                              | 403    | Thrown when the presented token does not have access to the requested resource.                                                                                                                               |
| `BILLING`                    | [INVALID\_PLAN](/docs/errors/api-errors/v3/billing-errors#invalid-plan)                                       | 430    | Thrown when limits have been reached based on your plan or if the feature is not available.                                                                                                                   |
| `BILLING`                    | [VEHICLE\_LIMIT](/docs/errors/api-errors/v3/billing-errors#vehicle-limit)                                     | 430    | Thrown when limits have been reached based on your plan or if the feature is not available.                                                                                                                   |
| `BILLING`                    | [VEHICLE\_REQUEST\_LIMIT](/docs/errors/api-errors/v3/billing-errors#vehicle-request-limit)                    | 430    | Thrown when limits have been reached based on your plan or if the feature is not available.                                                                                                                   |
| `BILLING`                    | [ACCOUNT\_SUSPENDED](/docs/errors/api-errors/v3/billing-errors#account-suspended)                             | 430    | Thrown when limits have been reached based on your plan or if the feature is not available.                                                                                                                   |
| `COMPATIBILITY`              | [MAKE\_NOT\_COMPATIBLE](/docs/errors/api-errors/v3/compatibility-errors#make-not-compatible)                  | 501    | Thrown when Smartcar does not support a make or feature for a vehicle.                                                                                                                                        |
| `COMPATIBILITY`              | [SMARTCAR\_NOT\_CAPABLE](/docs/errors/api-errors/v3/compatibility-errors#smartcar-not-capable)                | 501    | Thrown when Smartcar does not support a make or feature for a vehicle.                                                                                                                                        |
| `COMPATIBILITY`              | [VEHICLE\_NOT\_CAPABLE](/docs/errors/api-errors/v3/compatibility-errors#vehicle-not-capable)                  | 501    | Thrown when Smartcar does not support a make or feature for a vehicle.                                                                                                                                        |
| `COMPATIBILITY`              | [PLATFORM\_NOT\_CAPABLE](/docs/errors/api-errors/v3/compatibility-errors#platform-not-capable)                | 501    | Thrown when the OEM integration does not support this endpoint. The vehicle owner may need to reauthenticate.                                                                                                 |
| `CONNECTED_SERVICES_ACCOUNT` | [ACCOUNT\_ISSUE](/docs/errors/api-errors/v3/connected-services-account-errors#account-issue)                  | 400    | Thrown when there are issues with the user's connected service account.                                                                                                                                       |
| `CONNECTED_SERVICES_ACCOUNT` | [AUTHENTICATION\_FAILED](/docs/errors/api-errors/v3/connected-services-account-errors#authentication-failed)  | 400    | Thrown when there are issues with the user's connected service account.                                                                                                                                       |
| `CONNECTED_SERVICES_ACCOUNT` | [NO\_VEHICLES](/docs/errors/api-errors/v3/connected-services-account-errors#no-vehicles)                      | 400    | Thrown when there are issues with the user's connected service account.                                                                                                                                       |
| `CONNECTED_SERVICES_ACCOUNT` | [SUBSCRIPTION](/docs/errors/api-errors/v3/connected-services-account-errors#subscription)                     | 400    | Thrown when there are issues with the user's connected service account.                                                                                                                                       |
| `CONNECTED_SERVICES_ACCOUNT` | [VEHICLE\_MISSING](/docs/errors/api-errors/v3/connected-services-account-errors#vehicle-missing)              | 400    | Thrown when there are issues with the user's connected service account.                                                                                                                                       |
| `CONNECTED_SERVICES_ACCOUNT` | [PERMISSION](/docs/errors/api-errors/v3/connected-services-account-errors#permission)                         | 400    | Thrown when there are permission issues with the user's connected service account.                                                                                                                            |
| `CONNECTED_SERVICES_ACCOUNT` | [VIRTUAL\_KEY\_REQUIRED](/docs/errors/api-errors/v3/connected-services-account-errors#virtual-key-required)   | 400    | Thrown when a virtual key is required to complete the request.                                                                                                                                                |
| `RATE_LIMIT`                 | [SMARTCAR\_API](/docs/errors/api-errors/v3/rate-limit-errors#smartcar-api)                                    | 429    | Thrown when there is an issue with the frequency of your requests.                                                                                                                                            |
| `RATE_LIMIT`                 | [VEHICLE](/docs/errors/api-errors/v3/rate-limit-errors#vehicle)                                               | 429    | Thrown when there is an issue with the frequency of your requests.                                                                                                                                            |
| `RESOURCE_NOT_FOUND`         | [PATH](/docs/errors/api-errors/v3/resource-not-found-errors)                                                  | 404    | Thrown if the requested path does not exist.                                                                                                                                                                  |
| `RESOURCE_NOT_FOUND`         | [VERSION](/docs/errors/api-errors/v3/resource-not-found-errors#version)                                       | 404    | Thrown if the requested path does not exist.                                                                                                                                                                  |
| `SERVER`                     | [INTERNAL](/docs/errors/api-errors/v3/server-errors#internal)                                                 | 500    | Thrown when Smartcar runs into an unexpected issue and was unable to process the request.                                                                                                                     |
| `SERVER`                     | [MULTIPLE\_RECORDS\_FOUND](/docs/errors/api-errors/v3/server-errors#multiple-records-found)                   | 500    | Thrown when multiple records are found but only one was expected.                                                                                                                                             |
| `SERVER`                     | [RECORD\_NOT\_FOUND](/docs/errors/api-errors/v3/server-errors#record-not-found)                               | 500    | Thrown when a required record could not be found.                                                                                                                                                             |
| `UPSTREAM`                   | [INVALID\_DATA](/docs/errors/api-errors/v3/upstream-errors#invalid-data)                                      | 502    | Thrown when the OEM or vehicle failed to process the request.                                                                                                                                                 |
| `UPSTREAM`                   | [KNOWN\_ISSUE](/docs/errors/api-errors/v3/upstream-errors#known-issue)                                        | 502    | Thrown when the OEM or vehicle failed to process the request.                                                                                                                                                 |
| `UPSTREAM`                   | [NO\_RESPONSE](/docs/errors/api-errors/v3/upstream-errors#no-response)                                        | 502    | Thrown when the OEM or vehicle failed to process the request.                                                                                                                                                 |
| `UPSTREAM`                   | [RATE\_LIMIT](/docs/errors/api-errors/v3/upstream-errors#rate-limit)                                          | 502    | Thrown when the OEM or vehicle failed to process the request.                                                                                                                                                 |
| `UPSTREAM`                   | [UNKNOWN\_ISSUE](/docs/errors/api-errors/v3/upstream-errors#unknown-issue)                                    | 502    | Thrown when the OEM or vehicle failed to process the request.                                                                                                                                                 |
| `VALIDATION`                 | [INVALID\_INPUT\_FORMAT](/docs/errors/api-errors/v3/validation-errors#INVALID_INPUT_FORMAT)                   | 400    | Thrown if there is an issue with the format of the request or body.                                                                                                                                           |
| `VEHICLE_STATE`              | [ASLEEP](/docs/errors/api-errors/v3/vehicle-state-errors#asleep)                                              | 409    | Thrown when a request fails due to the state of a vehicle or logically cannot be completed—for example, you can't retrieve vehicle data because the vehicle is asleep and not responding to network requests. |
| `VEHICLE_STATE`              | [CHARGING\_IN\_PROGRESS](/docs/errors/api-errors/v3/vehicle-state-errors#charging-in-progress)                | 409    | Thrown when a request fails due to the state of a vehicle or logically cannot be completed—for example, you can't unlock the charge port while the vehicle is actively charging.                              |
| `VEHICLE_STATE`              | [CHARGING\_PLUG\_NOT\_CONNECTED](/docs/errors/api-errors/v3/vehicle-state-errors#charging-plug-not-connected) | 409    | Thrown when a request fails due to the state of a vehicle or logically cannot be completed—for example, you can't start charging the vehicle if the cable is not plugged in.                                  |
| `VEHICLE_STATE`              | [DOOR\_OPEN](/docs/errors/api-errors/v3/vehicle-state-errors#door-open)                                       | 409    | Thrown when a request fails due to the state of a vehicle or logically cannot be completed—for example, you can't lock the vehicle if a door is open.                                                         |
| `VEHICLE_STATE`              | [FULLY\_CHARGED](/docs/errors/api-errors/v3/vehicle-state-errors#fully-charged)                               | 409    | Thrown when a request fails due to the state of a vehicle or logically cannot be completed—for example, you can't start charging because the battery is already fully charged.                                |
| `VEHICLE_STATE`              | [NOT\_CHARGING](/docs/errors/api-errors/v3/vehicle-state-errors#not-charging)                                 | 409    | Thrown when a request fails due to the state of a vehicle or logically cannot be completed—for example, you can't stop charging because the vehicle is not currently charging.                                |
| `VEHICLE_STATE`              | [CHARGE\_FAULT](/docs/errors/api-errors/v3/vehicle-state-errors#charge-fault)                                 | 409    | Thrown when a request fails due to the state of a vehicle or logically cannot be completed—for example, you can't start charging because the vehicle has detected a charging system fault.                    |
| `VEHICLE_STATE`              | [HOOD\_OPEN](/docs/errors/api-errors/v3/vehicle-state-errors#hood-open)                                       | 409    | Thrown when a request fails due to the state of a vehicle or logically cannot be completed—for example, you can't start the engine if the hood is open.                                                       |
| `VEHICLE_STATE`              | [IGNITION\_ON](/docs/errors/api-errors/v3/vehicle-state-errors#ignition-on)                                   | 409    | Thrown when a request fails due to the state of a vehicle or logically cannot be completed—for example, you can't perform certain remote actions while the ignition is on.                                    |
| `VEHICLE_STATE`              | [IN\_MOTION](/docs/errors/api-errors/v3/vehicle-state-errors#in-motion)                                       | 409    | Thrown when a request fails due to the state of a vehicle or logically cannot be completed—for example, you can't lock the doors while the vehicle is in motion.                                              |
| `VEHICLE_STATE`              | [REMOTE\_ACCESS\_DISABLED](/docs/errors/api-errors/v3/vehicle-state-errors#remote-access-disabled)            | 409    | Thrown when a request fails due to the state of a vehicle or logically cannot be completed—for example, you can't send remote commands because remote access is disabled in the vehicle settings.             |
| `VEHICLE_STATE`              | [TRUNK\_OPEN](/docs/errors/api-errors/v3/vehicle-state-errors#trunk-open)                                     | 409    | Thrown when a request fails due to the state of a vehicle or logically cannot be completed—for example, you can't lock the vehicle if the trunk is open.                                                      |
| `VEHICLE_STATE`              | [UNKNOWN](/docs/errors/api-errors/v3/vehicle-state-errors#unknown)                                            | 409    | Thrown when a request fails due to the state of a vehicle or logically cannot be completed—for example, the vehicle reports an unknown state that prevents the requested action.                              |
| `VEHICLE_STATE`              | [UNREACHABLE](/docs/errors/api-errors/v3/vehicle-state-errors#unreachable)                                    | 409    | Thrown when a request fails due to the state of a vehicle or logically cannot be completed—for example, you can't send commands because the vehicle is offline or out of network range.                       |
| `VEHICLE_STATE`              | [VEHICLE\_OFFLINE\_FOR\_SERVICE](/docs/errors/api-errors/v3/vehicle-state-errors#vehicle-offline-for-service) | 409    | Thrown when a request fails due to the state of a vehicle or logically cannot be completed—for example, you can't access vehicle data because the vehicle is offline for maintenance or service.              |


# SDKs
Source: https://smartcar.com/docs/api-reference/api-sdks



Smartcar's backend SDKs are in maintenance mode. They receive security patches through December 1, 2026. After that date they will not be updated, including for security. The packages stay published and existing integrations keep working. For new integrations, call the API directly over HTTP with v3. If you rely on a backend SDK, move to direct HTTP before December 1, 2026 if you need continued security coverage, fixes, or capabilities the SDK does not support. See [Making API Requests](/docs/getting-started/how-to/making-api-requests) for per-language examples of each common task.

<Snippet />

<br />

For the vehicle connection flow, see [Connect SDKs](/docs/connect/connect-sdks) (JavaScript, iOS, and Android), which are fully supported.


# Permissions
Source: https://smartcar.com/docs/api-reference/application-permissions

GET https://api.smartcar.com/v2.0/vehicles/{id}/permissions
Returns a list of the permissions that have been granted to your application in relation to this vehicle.

## Request

<ParamField type="string">
  The vehicle id.
</ParamField>

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="permissions" type="[permissions]">
  An array of [permissions](/docs/api-reference/permissions).
</ResponseField>

<ResponseField name="paging" type="object">
  Metadata about the current list of elements.

  <Expandable>
    <ResponseField name="count" type="integer">
      The total number of elements for the entire query (not just the given page).
    </ResponseField>

    <ResponseField name="offset" type="integer">
      The current start index of the returned list of elements.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
  {
      "paging": {
          "count": 25,
          "offset": 10
      },
      "permissions": [
          "read_vehicle_info"
      ]
  } 
  ```
</ResponseExample>


# Audi: Charge Status
Source: https://smartcar.com/docs/api-reference/audi/get-charge

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge
Returns all charging related data for an Audi vehicle.

<Snippet />

## Permission

`read_charge`

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  charge =  vehicle.request(
        "GET", 
        "{make}/charge"
  )
  ```

  ```js Node theme={null}
  const charge =  await vehicle.request(
        "GET", 
        "{make}/charge"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/charge")
        .build();
  VehicleResponse charge =  vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  charge =  vehicle.request(
        "GET", 
        "{make}/charge"
  )
  ```
</RequestExample>

## Request

**Path**

<Snippet />

## Response

<ResponseField name="chargingStatus" type="string | null">
  Indicates the charging status of the vehicle
</ResponseField>

<ResponseField name="isPluggedIn" type="bool | null">
  Indicates if the vehicle is plugged in
</ResponseField>

<ResponseField name="wattage" type="number | null">
  The instant power measured by the vehicle (in kilowatts).
</ResponseField>

<ResponseField name="chargeRate" type="number | null">
  The rate of range added in the charging session (in kilometers added / hour).
</ResponseField>

<ResponseField name="chargeType" type="string | null">
  Indicates the type of charger.
</ResponseField>

<ResponseField name="chargePortColor" type="string | null">
  The indicator light color of the connector.
</ResponseField>

<ResponseField name="chargePortLatch" type="string | null">
  Indicates if the charge port latch status.
</ResponseField>

<ResponseField name="completionTime" type="string | null">
  An ISO8601 formatted datetime (YYYY-MM-DDTHH:mm:ss.SSSZ) for the time at which the vehicle expects to complete this charging session.
</ResponseField>

<ResponseField name="chargeMode" type="string | null">
  Indicates if the vehicle is set to charge on a timer. One of `manual` or `timer`.
</ResponseField>

<ResponseField name="socLimit" type="number | null">
  Indicates the level at which the vehicle will stop charging and be considered fully charged as a percentage.
</ResponseField>

<ResponseField name="externalPowerStatus" type="string | null">
  When plugged in indicates if the charging station is able to provide power to the vehicle.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
      {
            "chargingStatus": "CHARGING",
            "isPluggedIn": null,
            "chargeRate": 21,
            "chargeType": "ac",
            "chargePortColor": "green",
            "chargePortLatch": "locked",
            "completionTime": "2022-01-13T22:52:55.358Z",
            "chargeMode": "manual",
            "socLimit": 0.8,
            "externalPowerStatus": "active",
            "wattage" : 1.5
      }
  ```
</ResponseExample>


# Auth Code Exchange
Source: https://smartcar.com/docs/api-reference/authorization/auth-code-exchange

POST https://auth.smartcar.com/oauth/token
To interact with the Smartcar API, you will need to exchange your authorization code from the [Connect redirect](https://smartcar.com/docs/connect/handle-the-response) for an access token. Check the [overview](https://smartcar.com/docs/api-reference/authorization/overview) page for how to manage your tokens.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

This is the per-vehicle OAuth token flow used with the v2.0 API; the authorization code exchanged here comes from a Connect session launched with `response_type=code`. For the v3 API, applications authenticate with [application-level M2M tokens](/docs/api-reference/authorization/overview) (client credentials) and have no authorization code to exchange.

## Requesting Access Tokens

**Headers**

<Snippet />

<ParamField type="string">
  Must be set to `application/x-www-form-urlencoded`, matching the format of the request body.
</ParamField>

<ParamField type="string">
  A valid HTTP User Agent value. This value is typically included in the HTTP requests by the client that is making the request. You usually don't have to set this manually.
</ParamField>

**Body**

<ParamField type="string">
  The authorization code received in the handle response step.
</ParamField>

<ParamField type="string">
  This value must be set to `authorization_code`
</ParamField>

<ParamField type="string">
  The `redirect_uri` provided in the redirect to Connect step. This value is checked to match the URI sent when the user was directed to Connect.
</ParamField>

<Info>
  If you launch Connect from a single-page or mobile application, `redirect_uri` **must** match the URI passed in your Connect URL, not the redirect for your backend.
</Info>

<RequestExample>
  ```bash cURL theme={null}
  curl https://auth.smartcar.com/oauth/token \
  -X POST \
  -H 'Authorization: Basic base64({client_id}:{client_secret})' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=authorization_code&code=35a59c0b-745c-436c-a8a2-7758e718dcb8&redirect_uri=https://example.com/home'
  ```

  ```python Python SDK theme={null}
    access = client.exchange_code('{code}')
  ```

  ```node Node SDK theme={null}
    access = client.exchangeCode('{code}');;
  ```

  ```java Java SDK theme={null}
    Auth access = authClient.exchangeCode("{code}");
  ```

  ```ruby Ruby SDK theme={null}
    access = client.exchange_code("{code}")
  ```
</RequestExample>

## Response

<Snippet />


# API Authentication Overview
Source: https://smartcar.com/docs/api-reference/authorization/overview

Learn how API Authentication works for server-to-server communication with the Smartcar API.

API Authentication is an authentication method for server-to-server communication with Smartcar. Your application obtains a single application-level access token using the OAuth 2.0 Client Credentials flow.

## How It Works

API Authentication uses the OAuth 2.0 Client Credentials flow, designed for server-to-server scenarios where no user interaction occurs.

```mermaid theme={null}
sequenceDiagram
    participant App as Your Backend
    participant SC as Smartcar API

    App->>SC: Request access token (Client ID + Secret)
    SC-->>App: Access token
    App->>SC: API request + Authorization header
    SC-->>App: Vehicle data
```

Here's the flow:

1. **Authenticate**: Exchange your Client ID and Secret for an access token
2. **Make Requests**: Use the access token for all subsequent API calls

The access token is valid for 1 hour. When it expires, request a new one from the token endpoint.

## Key Concepts

### API Credentials

Your API credentials consist of:

* **Client ID** — Public identifier for your application (safe to hardcode)
* **Client Secret** — Private credential for authentication (must be stored securely)

Treat your Client Secret like a password. Never commit it to version control or expose it in client-side code.

### User ID (userId)

The `userId` is a unique identifier within the Smartcar platform representing a specific user's vehicle connection. You obtain this ID from the Connections API when a user grants access to their vehicle.

### sc-user-id Header

The `sc-user-id` header is required when accessing vehicle signals and issuing commands. It tells the API which user's vehicle connection to operate on. You obtain the `userId` from the Connect redirect URL when a user completes the authorization flow.

```bash theme={null}
GET https://vehicle.api.smartcar.com/v3/vehicles/{id}/signals
Authorization: Bearer YOUR_ACCESS_TOKEN
sc-user-id: {userId}
```

The header is also accepted on the `/connections` endpoint to filter results by user.

### Connections API

The Connections API manages vehicle connections at the application level. With API Authentication, you use this API to:

* Retrieve connected vehicle IDs (`userId` values)
* Manage vehicle connections
* Handle subscription events

## Security Considerations

<Warning>
  Never store your Client Secret in public clients, browser cookies, or plain text files. Your backend must securely store and manage API credentials.
</Warning>

Follow these security best practices:

* **Secure Storage** — Keep Client Secrets in environment variables, secrets management systems, or encrypted vaults
* **Secret Rotation** — Rotate your Client Secret on a regular schedule or immediately if compromised
* **Audit Trails** — Monitor your Smartcar Dashboard for API Credentials activity and audit logs
* **Least Privilege** — Restrict API credential access to backend services that require it
* **No Client-Side Usage** — Never use API credentials in mobile apps, web frontends, or any public-facing code

Your Smartcar Dashboard provides visibility into credential usage and security events. Review audit logs regularly to detect unauthorized activity.

## What's Next

Ready to implement API Authentication?

* **[Setup Guide](/docs/getting-started/how-to/api-authentication)** — Step-by-step setup and code examples
* **[Migration Guide](/docs/getting-started/how-to/m2m/migration-guide)** — Transition from per-vehicle tokens to API Authentication
* **[FAQ](/docs/getting-started/how-to/m2m/faq)** — Common questions and answers
* **[Connections API Reference](/docs/api-reference/list-connections)** — Complete endpoint documentation


# Refreshing Access Tokens
Source: https://smartcar.com/docs/api-reference/authorization/refreshing-access-token

POST https://auth.smartcar.com/oauth/token
Your access token will expire **2 hours** after it is issued. When this happens, your application can retrieve a new one by using the corresponding `refresh_token` without requiring the user to re-authenticate.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

This refresh flow applies to per-vehicle OAuth tokens in the v2.0 API. The v3 API uses [application-level M2M tokens](/docs/api-reference/authorization/overview), which are short-lived and re-requested with client credentials rather than refreshed.

<Warning>
  A refresh token is invalidated 10 minutes after use. If your first attempt at refreshing tokens fails, ensure you retry within 10 minutes.
  Please ensure you're persisting **both the newly minted access and refresh token**. Failure to do so will require the user to authenticate again after the access token has expired.
</Warning>

## Request

**Headers**

<Snippet />

<ParamField type="string">
  Must be set to `application/x-www-form-urlencoded`, matching the format of the request body.
</ParamField>

<ParamField type="string">
  A valid HTTP User Agent value. This value is typically included in the HTTP requests by the client that is making the request. You usually don't have to set this manually.
</ParamField>

<RequestExample>
  <Snippet />
</RequestExample>

**Body**

<ParamField type="string">
  This value must be set to `refresh_token`
</ParamField>

<ParamField type="string">
  The refresh token received in the response with the access token from an [auth code exchange](/docs/api-reference/authorization/auth-code-exchange)
  or prior token refresh.
</ParamField>

**Response**

<Snippet />


# Application Access Token
Source: https://smartcar.com/docs/api-reference/authorization/request-access-token

specs/auth.yaml POST /oauth2/token
Request an access token using client credentials grant type

Exchange your API credentials for an application-level access token using the OAuth 2.0 Client Credentials flow. The access token is valid for **1 hour** (3600 seconds). There is no refresh token — request a new token when the current one expires.

<Info>
  Generate your Client ID and Client Secret from the **API Credentials** tab in your [Smartcar Dashboard](https://dashboard.smartcar.com). See the [API Authentication Setup Guide](/docs/getting-started/how-to/api-authentication) for step-by-step instructions.
</Info>

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://iam.smartcar.com/oauth2/token \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data 'grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://iam.smartcar.com/oauth2/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      grant_type: 'client_credentials',
      client_id: process.env.SMARTCAR_CLIENT_ID,
      client_secret: process.env.SMARTCAR_CLIENT_SECRET,
    }),
  });

  const { access_token, token_type, expires_in } = await response.json();
  ```

  ```python Python theme={null}
  import requests, os

  response = requests.post(
      'https://iam.smartcar.com/oauth2/token',
      data={
          'grant_type': 'client_credentials',
          'client_id': os.environ['SMARTCAR_CLIENT_ID'],
          'client_secret': os.environ['SMARTCAR_CLIENT_SECRET'],
      }
  )

  token_data = response.json()
  access_token = token_data['access_token']
  ```
</RequestExample>

### Error Responses

| Status | Error             | Description                                                          |
| ------ | ----------------- | -------------------------------------------------------------------- |
| `400`  | `invalid_request` | Missing or malformed request parameters (e.g., missing `grant_type`) |
| `401`  | `invalid_client`  | Invalid `client_id` or `client_secret`                               |

### What's Next

Now that you have an access token, here's what you can do with it:

* [API Overview](/docs/api-reference/intro) — All endpoints available with your access token
* [Vehicle Data](/docs/api-reference/list-signals) — Read signals like battery level, odometer, and location
* [Vehicle Commands](/docs/api-reference/commands/overview) — Lock, unlock, start/stop charging, set destination, and more
* [Connections](/docs/api-reference/list-connections) — List and manage vehicle connections
* [Webhooks](/docs/integrations/webhooks/overview) — Subscribe vehicles to receive data on a schedule or when events occur


# Batch
Source: https://smartcar.com/docs/api-reference/batch

POST https://api.smartcar.com/v2.0/vehicles/{id}/batch
Returns a list of responses from multiple Smartcar `GET` endpoints, all combined into a single request.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

<Info>
  Each endpoint in the batch counts against your [request limit](/docs/errors/api-errors/billing-errors) for a vehicle.
</Info>

## Request

**Path**

<Snippet />

**Body**

<ParamField type="array">
  An array of requests to make.

  <Expandable>
    <ParamField type="string">
      The Smartcar endpoint to request data from.
    </ParamField>
  </Expandable>
</ParamField>

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="responses" type="array">
  The responses from Smartcar.

  <Expandable title="response">
    <ResponseField name="headers" type="object">
      The headers for this response.

      <Expandable title="headers">
        <ResponseField name="sc-unit-system" type="string">
          The unit system to use for the request.
        </ResponseField>

        <ResponseField name="sc-data-age" type="string">
          The timestamp (ISO-8601 format) of when the returned data was recorded by the vehicle.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="code" type="number">
      The HTTP response status code.
    </ResponseField>

    <ResponseField name="path" type="string">
      The Smartcar endpoint to request data from.
    </ResponseField>

    <ResponseField name="body" type="string">
      The response body of this request. The structure of this object will vary by endpoint. See the corresponding endpoint specification.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
    "responses": [
      {
        "path": "/odometer",
        "body": {
          "distance": 37829
        },
        "code": 200,
        "headers": {
          "sc-data-age": "2019-10-24T00:43:46.000Z",
          "sc-unit-system": "metric"
        }
      },
      {
        "path": "/location",
        "body": {
          "latitude": 37.4292,
          "longitude": 122.1381
        },
        "code": 200,
        "headers": {
          "sc-data-age": "2019-10-24T00:43:46.000Z"
        }
      }
    ]
  }
  ```
</ResponseExample>


# Charge Records
Source: https://smartcar.com/docs/api-reference/bmw/get-charge-records

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/records
Returns data associated with completed charging sessions for a vehicle. Limited to the last 30 days or when the owner first granted your application access, which ever is shorter.

<Note>
  This endpoint is currently available for `bmw` and `mini`
</Note>

## Permission

`read_charge_records`

## Request

**Path**

<Snippet />

**Query**

<ParamField>
  Date of the first record to return in YYYY-MM-DD format.
  Defaults to 30 days prior  or when the owner first granted your application access, whichever is shorter.
</ParamField>

<ParamField>
  Date of the final record to return in YYYY-MM-DD format. Defaults to the date of the request.
</ParamField>

## Response

<ResponseField name="records" type="[object]">
  An array of charge records for the vehicle.

  <Expandable>
    <ResponseField name="chargeStart" type="string">
      The start date of the charging record, formatted in ISO 8601 standard
    </ResponseField>

    <ResponseField name="chargeEnd" type="string">
      The end date of the charging record, formatted in ISO 8601 standard
    </ResponseField>

    <ResponseField name="location" type="string">
      Location of the charge session.
    </ResponseField>

    <ResponseField name="energy" type="number">
      The amount of energy consumed during the charging session.
    </ResponseField>

    <ResponseField name="isPublic" type="bool">
      Indicates whether the charging location is public or not.
    </ResponseField>

    <ResponseField name="startPercentRemaining" type="number">
      The remaining battery soc at the start of the charging session.
    </ResponseField>

    <ResponseField name="endPercentRemaining" type="number">
      The remaining battery soc at the end of the charging session.
    </ResponseField>

    <ResponseField name="chargingType" type="string">
      The type of charger used for the session.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
    "records": [
      {
        "chargeStart" : "2023-03-08T12:54:44Z",
        "chargeEnd" : "2023-03-08T14:14:44Z",
        "location": "Cockfosters Road, Barnet, EN4 0",
        "energy"  : 34.22998046875,
        "isPublic" : true,
        "startPercentRemaining" : 0.57,
        "endPercentRemaining" : 1, 
        "chargingType" : "DC" 
      }
    ]
  }
  ```
</ResponseExample>


# Delete charge schedule
Source: https://smartcar.com/docs/api-reference/charge-schedules/delete-charge-schedule

/specs/full-vehicle.yaml delete /vehicles/{vehicleId}/charge-schedules/{scheduleId}
Deletes a charge schedule by schedule id. The deletion request is sent to the vehicle; the response confirms whether it succeeded.



# Set daily charge schedule
Source: https://smartcar.com/docs/api-reference/charge-schedules/set-daily-charge-schedule

/specs/full-vehicle.yaml post /vehicles/{vehicleId}/charge-schedules/daily
Set daily charge schedule



# Set weekly charge schedule
Source: https://smartcar.com/docs/api-reference/charge-schedules/set-weekly-charge-schedule

/specs/full-vehicle.yaml post /vehicles/{vehicleId}/charge-schedules/weekly
Set weekly charge schedule with per-day time windows



# Set workweek charge schedule
Source: https://smartcar.com/docs/api-reference/charge-schedules/set-workweek-charge-schedule

/specs/full-vehicle.yaml post /vehicles/{vehicleId}/charge-schedules/workweek
Set workweek charge schedule with separate time windows for weekdays and weekends



# Set charge limit
Source: https://smartcar.com/docs/api-reference/charging/set-charge-limit

/specs/full-vehicle.yaml post /vehicles/{vehicleId}/commands/charge/set-limit
Sets the maximum charge percentage for the vehicle battery



# Start charging
Source: https://smartcar.com/docs/api-reference/charging/start-charging

/specs/full-vehicle.yaml post /vehicles/{vehicleId}/commands/charge/start
Initiates charging for the vehicle battery



# Stop charging
Source: https://smartcar.com/docs/api-reference/charging/stop-charging

/specs/full-vehicle.yaml post /vehicles/{vehicleId}/commands/charge/stop
Stops charging for the vehicle battery



# Commands Overview
Source: https://smartcar.com/docs/api-reference/commands/overview

Send commands to vehicles to control charging, security, navigation, and charge schedules.

Commands let your application take action on a vehicle. Unlike signals, which read vehicle state, commands write to it — they alter the data or state of the vehicle.

## Available Commands

* **Charge** — [Start charging](/docs/api-reference/charging/start-charging), [stop charging](/docs/api-reference/charging/stop-charging), [set charge limit](/docs/api-reference/charging/set-charge-limit)
* **Security** — [Lock](/docs/api-reference/security/lock-doors) and [unlock](/docs/api-reference/security/unlock-doors) vehicle doors
* **Navigation** — [Set a destination](/docs/api-reference/navigation/set-destination) in the vehicle's navigation system
* **Charge Schedules** — Configure daily, weekly, or workweek charging windows, or delete a schedule

Requests for vehicles from any other make return a [`VEHICLE_NOT_CAPABLE`](/docs/errors/api-errors/v3/compatibility-errors#vehicle_not_capable) compatibility error:

```json theme={null}
{
  "type": "COMPATIBILITY",
  "code": "VEHICLE_NOT_CAPABLE"
}
```

After creating a schedule, read it back from the [`ChargeTimers`](/docs/api-reference/signals/charge#chargetimers) signal. Timers with `"type": "LOCATION"` include a **scheduleType** and **scheduleId** — use the **scheduleId** to issue `DELETE` requests. The signal reflects all schedules on the vehicle, including any set outside of the API.

## Data State Changes

Commands do not return updated vehicle state. After issuing a command, confirm or monitor its effect by reading the corresponding [signal](/docs/api-reference/signals/schema) — via the [Vehicle Data API](/docs/api-reference/list-signals) or a [Webhooks](/docs/integrations/webhooks/overview). Signal updates may be delayed as the change propagates to the vehicle.

## Key Concepts

### sc-user-id Header

All command endpoints require the `sc-user-id` header. Your bearer token is application-level and does not carry per-user context, so this header must be provided on every request to identify which user's vehicle to act on.

```bash theme={null}
POST https://vehicle.api.smartcar.com/v3/vehicles/{vehicleId}/commands/charge/start
Authorization: Bearer YOUR_ACCESS_TOKEN
sc-user-id: {userId}
```

### 202 Response

Most commands resolve in under 175 seconds and return a single, complete response. If a command takes longer than that, Smartcar sends a `202 Accepted` status to keep the connection open while the command finishes, instead of timing out.

A `202` is not the final result — it's a signal that the command is still running. The connection stays open, and Smartcar streams the complete response body on that same connection once the command finishes. Always read the full response body to determine whether the command succeeded or failed.

<Warning>
  There's no `Content-Length` header on a `202` response, since the final size isn't known yet. Don't read a fixed number of bytes or treat the arrival of any bytes as the response being complete — wait for the connection to close (or the chunked stream to send its final chunk) before parsing the body.
</Warning>

Most HTTP clients (axios, node-fetch, `requests`, OkHttp, etc.) handle this correctly by default. If you've configured a client with a short read timeout, or one that returns as soon as the first bytes arrive, you may get a partial or empty result instead of the actual command outcome.

<Tip>
  If you're testing with `curl`, add `-N` (`--no-buffer`) to see the response stream in as it arrives — the `202`, then the final result once the command finishes — instead of `curl` waiting and printing everything at once when the connection closes. Add `-i` to also see the status line and headers along with the body:

  ```bash theme={null}
  curl -N -i https://vehicle.api.smartcar.com/v3/vehicles/{vehicleId}/commands/charge/start \
    -X POST \
    -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
    -H "sc-user-id: {userId}"
  ```
</Tip>


# Compatibility API overview
Source: https://smartcar.com/docs/api-reference/compatibility-api-intro

Vehicle compatibility data by make, model, region, and powertrain, updated daily from the Smartcar platform.

The Compatibility API tells you which signals and commands each vehicle supports. The data comes from real connections on the Smartcar platform and updates daily.

## Base URL

```
https://compatibility.api.smartcar.com/v3/compatible-vehicles
```

## Quick reference

* **No authentication required.** The endpoint is public — no credentials or headers needed.
* **Filter with JSON:API bracket syntax:** `?filter[make]=TESLA`, `?filter[region]=US`, `?filter[powertrainType]=PHEV`. Flat parameters (e.g. `?make=TESLA`) are silently ignored.
* **Returns the full matched dataset in a single response.** Pagination parameters are not honored — cache results locally and refresh daily.

See [Compatible Vehicles](/docs/api-reference/compatible-vehicles) for the full parameter list, response schema, and examples.

## Browse on the web

If you'd rather not hit the API, you can browse the full dataset and download it as a CSV:

<Card title="Compatible Vehicles on smartcar.com" icon="globe" href="https://smartcar.com/product/compatible-vehicles">
  Filter by make or region and export the full compatibility matrix.
</Card>

If you need the previous Compatibility Matrix experience, use the [legacy matrix](https://compatibility.smartcar.com/legacy).


# By Region and Make
Source: https://smartcar.com/docs/api-reference/compatibility/by-region-and-make

GET https://api.smartcar.com/v2.0/compatibility/matrix
Compatibility will vary by model, year, and trim. This API is for reference purposes only and it showcases vehicle makes and models that may be compatible with Smartcar and it does not guarantee that a specific vehicle will be compatible.

<Warning>
  **This endpoint is deprecated.** Please use the new [Compatible Vehicles](/docs/api-reference/compatible-vehicles) page for up-to-date, signal-based compatibility data that is dynamically updated from the Smartcar platform.
</Warning>

Compatibility by region and make allows developers to query the latest version of our Compatibility Matrix based on region, engine type, make, and permission.

## Request

**Headers**

<Snippet />

**Query**

<ParamField type="string">
  One of the following regions: `US`, `CA` or `EUROPE`
</ParamField>

<ParamField type="string">
  Queries for all engine types if none are specified.

  <Expandable>
    <ResponseField name="ICE" />

    <ResponseField name="BEV" />

    <ResponseField name="PHEV" />

    <ResponseField name="HEV" />
  </Expandable>
</ParamField>

<ParamField type="string">
  A space-separated list of [makes](/docs/api-reference/makes). This field is optional. If no make is specified, all makes will be returned.
</ParamField>

<ParamField type="string">
  A space-separated list of [permissions](/docs/api-reference/permissions).
  Queries for all permissions if none are specified.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl --request GET \
    --url 'https://api.smartcar.com/v2.0/compatibility/matrix?region=US&type=BEV&make=tesla&scope=read_battery%20read_charge' \
    --header 'Authorization: Basic bXktY2xpZW50LWlkOm15LWNsaWVudC1zZWNyZXQ='
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.smartcar.com/v2.0/compatibility/matrix?region=US&type=BEV&make=tesla&scope=read_battery%20read_charge', {
    method: 'GET',
    headers: {
      'Authorization': 'Basic bXktY2xpZW50LWlkOm15LWNsaWVudC1zZWNyZXQ='
    }
  });

  const data = await response.json();
  ```

  ```python Python theme={null}
  import requests

  url = "https://api.smartcar.com/v2.0/compatibility/matrix"
  params = {
      "region": "US",
      "type": "BEV", 
      "make": "tesla",
      "scope": "read_battery read_charge"
  }
  headers = {
      "Authorization": "Basic bXktY2xpZW50LWlkOm15LWNsaWVudC1zZWNyZXQ="
  }

  response = requests.get(url, params=params, headers=headers)
  data = response.json()
  ```
</RequestExample>

## Response

<ResponseField name="make" type="array">
  An array of models supported for the given `make`.

  <Expandable title="make">
    <ResponseField name="model" type="string">
      `model` for the given `make`.
    </ResponseField>

    <ResponseField name="startYear" type="number">
      The earliest model year supported by Smartcar.
    </ResponseField>

    <ResponseField name="endYear" type="number">
      The latest model year supported by Smartcar.
    </ResponseField>

    <ResponseField name="type" type="string">
      Engine type for the given `model`.

      <Expandable title="type">
        <ResponseField name="ICE" />

        <ResponseField name="BEV" />

        <ResponseField name="PHEV" />

        <ResponseField name="HEV" />
      </Expandable>
    </ResponseField>

    <ResponseField name="endpoints" type="array">
      An array of endpoints supported for the given `model`.
    </ResponseField>

    <ResponseField name="permissions" type="array">
      An array of `permissions` supported for the given `model`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
    {
      "NISSAN": [
        {
          "model": "LEAF",
          "startYear": 2018,
          "endYear": 2022,
          "type": "BEV",
          "endpoints": [
            "EV battery",
            "EV charging status",
            "Location",
            "Lock & unlock",
            "Odometer"
          ],
          "permissions": [
            "read_battery",
            "read_charge",
            "read_location",
            "control_security",
            "read_odometer"
          ]
        }
      ],
      "TESLA": [
        {
          "model": "3",
          "startYear": 2017,
          "endYear": 2023,
          "type": "BEV",
          "endpoints": [
            "EV battery",
            "EV charging status",
            "EV start & stop charge",
            "Location",
            "Lock & unlock",
            "Odometer",
            "Tire pressure"
          ],
          "permissions": [
            "read_battery",
            "read_charge",
            "control_charge",
            "read_location",
            "control_security",
            "read_odometer",
            "read_tires"
          ]
        }
      ]
    }
  ```
</ResponseExample>


# By VIN (Deprecated)
Source: https://smartcar.com/docs/api-reference/compatibility/by-vin

GET https://api.smartcar.com/v2.0/compatibility
Compatibility will vary by model, year, and trim. This API is for reference purposes only and it showcases vehicle makes and models that may be compatible with Smartcar and it does not guarantee that a specific vehicle will be compatible.

<Warning>
  **This endpoint is fully deprecated.** The Compatibility by VIN endpoint does not provide a true per-VIN compatibility check — results are based on make and model heuristics and do not guarantee that a specific vehicle will be compatible.

  We recommend checking compatibility against the new [Compatible Vehicles](/docs/api-reference/compatible-vehicles) data using a make and region filter. If the make and model of a given VIN is unknown, use a VIN decoding service to determine it, then look up compatibility from the matrix.
</Warning>

Compatibility by VIN allows developers to determine if a specific vehicle could be compatible with Smartcar.

A vehicle is capable of a given feature if:

1. The vehicle supports the feature (e.g., a Ford Escape supports /fuel but a Mustang Mach-e does not)
2. Smartcar supports the feature for the vehicle's make

This endpoint only supports checking capabilities for vehicles sold in the United States. It **does not** support checking `capabilities` for VINs in Canada and Europe.

## Request

**Headers**

<Snippet />

**Parameters**

<ParamField type="string">
  The VIN (Vehicle Identification Number) of the vehicle.
</ParamField>

<ParamField type="string">
  A space-separated list of permissions.
</ParamField>

<ParamField type="string">
  An optional country code string according to ISO 3166-1 alpha-2.
</ParamField>

<RequestExample />

## Response

<ResponseField name="compatible" type="boolean">
  `true` if the vehicle is likely compatible, `false` otherwise.
</ResponseField>

<ResponseField name="reason" type="string | null">
  One of the reasons described below if compatible is `false`, `null` otherwise

  <Expandable title="reasons">
    <ResponseField name="VEHICLE_NOT_COMPATIBLE">
      The vehicle does not have the hardware required for internet connectivity
    </ResponseField>

    <ResponseField name="MAKE_NOT_COMPATIBLE">
      Smartcar is not yet compatible with the vehicle's make in the specified country
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="capabilities" type="array">
  An array containing capability objects for the set of endpoints that the provided scope value can provide authorization for.
  This array will be empty if `compatible` is `false`.

  <Expandable title="Capability object">
    <ResponseField name="permission" type="string">
      One of the permissions provided in the scope parameter
    </ResponseField>

    <ResponseField name="endpoint" type="string">
      One of the endpoints that the permission authorizes access to
    </ResponseField>

    <ResponseField name="capable" type="boolean">
      `true` if the vehicle is likely capable of this feature, `false` otherwise
    </ResponseField>

    <ResponseField name="reason" type="string | null">
      One of the reasons described below if capable is `false`, `null` otherwise

      <Expandable title="reasons">
        <ResponseField name="VEHICLE_NOT_CAPABLE">
          The vehicle does not support this feature
        </ResponseField>

        <ResponseField name="SMARTCAR_NOT_CAPABLE">
          Smartcar is not capable of supporting the given feature on the vehicle's make
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
    {
    "compatible": true,
    "reason": null,
    "capabilities": [
      {
        "capable": false,
        "endpoint": "/engine/oil",
        "permission": "read_engine_oil",
        "reason": "SMARTCAR_NOT_CAPABLE"
      },
      {
        "capable": true,
        "endpoint": "/battery",
        "permission": "read_battery",
        "reason": null
      },
      {
        "capable": true,
        "endpoint": "/battery/capacity",
        "permission": "read_battery",
        "reason": null
      },
      {
        "capable": true,
        "endpoint": "/vin",
        "permission": "read_vin",
        "reason": null
      }
    ]
  }
  ```
</ResponseExample>

<Info>
  A vehicle's compatibility depends on many factors such as its make, model, model year, trim, etc. The API optimizes returning false positives.
</Info>


# Compatible Vehicles
Source: https://smartcar.com/docs/api-reference/compatible-vehicles

GET https://compatibility.api.smartcar.com/v3/compatible-vehicles
Learn how Smartcar determines vehicle compatibility and how to access compatibility data for your application.

Smartcar compatibility reflects which vehicles are compatible with specific signals and commands, updated dynamically based on real activity across the Smartcar platform.

## Browsing Compatibility Data

The most convenient way to explore compatibility is through our website, where you can browse and download a CSV of the full dataset:

<Card title="Compatible Vehicles" icon="car" href="https://smartcar.com/product/compatible-vehicles">
  Look up which vehicles support which signals and commands, filter by make or region, and export the full matrix as a CSV.
</Card>

## Accessing Compatibility Data Programmatically

If your application needs to consume this data dynamically, use the endpoint above.

<Warning>
  **Caching is strongly recommended.** We recommend caching the results for a minimum of **24 hours**. This endpoint is not intended to be queried prior to connecting a vehicle. The data is the same whether you fetch it in advance or at the time of connection, and drivers should not be waiting extra seconds while this data is fetched.

  Instead, cache the results locally and compute compatibility on your end. You can refresh the cache every 24 hours if desired, as the data changes dynamically each day based on activity across the Smartcar platform.
</Warning>

### Query Parameters

<ParamField type="string">
  Filter vehicles by market region. Omit to return all regions.

  <Expandable>
    <ResponseField name="US" />

    <ResponseField name="CA" />

    <ResponseField name="EUROPE" />
  </Expandable>
</ParamField>

<ParamField type="string">
  Filter vehicles by manufacturer (case-insensitive). Example: `TESLA`, `BMW`, `FORD`. Omit to return all makes.
</ParamField>

<ParamField type="string">
  Filter vehicles by powertrain type. Omit to return all types.

  <Expandable>
    <ResponseField name="ICE">
      Internal combustion engine vehicles only
    </ResponseField>

    <ResponseField name="BEV">
      Battery electric vehicles only
    </ResponseField>

    <ResponseField name="PHEV">
      Plug-in hybrid electric vehicles only
    </ResponseField>

    <ResponseField name="EV">
      BEV + PHEV combined
    </ResponseField>
  </Expandable>
</ParamField>

### Response Schema

The response follows [JSON:API](https://jsonapi.org/) format with a `data` array of vehicle compatibility entries, pagination metadata, and a self link.

<RequestExample>
  ```bash All vehicles theme={null}
  curl https://compatibility.api.smartcar.com/v3/compatible-vehicles
  ```

  ```bash US only theme={null}
  curl "https://compatibility.api.smartcar.com/v3/compatible-vehicles?filter[region]=US"
  ```

  ```bash Tesla in US theme={null}
  curl "https://compatibility.api.smartcar.com/v3/compatible-vehicles?filter[region]=US&filter[make]=TESLA"
  ```

  ```bash All EVs theme={null}
  curl "https://compatibility.api.smartcar.com/v3/compatible-vehicles?filter[powertrainType]=EV"
  ```

  ```bash BMW EVs in US theme={null}
  curl "https://compatibility.api.smartcar.com/v3/compatible-vehicles?filter[region]=US&filter[make]=BMW&filter[powertrainType]=EV"
  ```
</RequestExample>

<ResponseExample>
  ```json Example Response theme={null}
  {
    "data": [
      {
        "id": "TESLA-Model 3-2016-2026-BEV-US",
        "type": "vehicle-model-capability",
        "attributes": {
          "make": "Tesla",
          "model": "Model 3",
          "region": "US",
          "powertrainType": "BEV",
          "years": {
            "start": 2016,
            "end": 2026
          },
          "capabilities": [
            {
              "type": "signal",
              "name": "State Of Charge",
              "group": "TractionBattery",
              "code": "StateOfCharge",
              "capability": "tractionbattery-stateofcharge",
              "permission": "read_battery"
            },
            {
              "type": "signal",
              "name": "Range",
              "group": "TractionBattery",
              "code": "Range",
              "capability": "tractionbattery-range",
              "permission": "read_battery"
            },
            {
              "type": "signal",
              "name": "Location",
              "group": "Location",
              "code": "PreciseLocation",
              "capability": "location-preciselocation",
              "permission": "read_location"
            },
            {
              "type": "command",
              "name": "Start charge",
              "group": "",
              "code": "charge-start",
              "capability": "charge-start",
              "permission": ""
            },
            {
              "type": "command",
              "name": "Lock vehicle",
              "group": "",
              "code": "closure-lock",
              "capability": "closure-lock",
              "permission": ""
            }
          ]
        }
      }
    ],
    "meta": {
      "page": 1,
      "pageSize": 1384,
      "totalCount": 1384
    },
    "links": {
      "self": "https://compatibility.api.smartcar.com/v3/compatible-vehicles"
    }
  }
  ```
</ResponseExample>

#### Data Item

Each item in the `data` array represents a unique vehicle make/model/powertrain/region combination.

| Field                       | Type      | Description                                                           |
| --------------------------- | --------- | --------------------------------------------------------------------- |
| `id`                        | `string`  | Deterministic composite key (e.g., `TESLA-Model 3-2016-2026-BEV-US`). |
| `type`                      | `string`  | Always `vehicle-model-capability`.                                    |
| `attributes.make`           | `string`  | Vehicle manufacturer display name (e.g., `Tesla`, `Mercedes-Benz`).   |
| `attributes.model`          | `string`  | Vehicle model name.                                                   |
| `attributes.region`         | `string`  | Market region: `US`, `CA`, or `EUROPE`.                               |
| `attributes.powertrainType` | `string`  | Powertrain type: `ICE`, `BEV`, or `PHEV`.\*                           |
| `attributes.years.start`    | `integer` | First compatible model year.                                          |
| `attributes.years.end`      | `integer` | Last compatible model year.                                           |
| `attributes.capabilities`   | `array`   | Array of compatible signal and command objects.                       |

<sub>\*HEV (Hybrid Electric Vehicle) powertrain types are designated as `ICE` in Smartcar API responses.</sub>

#### Capability Object

Each capability in `attributes.capabilities` describes a signal or command the vehicle supports.

| Field        | Type     | Description                                                           |
| ------------ | -------- | --------------------------------------------------------------------- |
| `type`       | `string` | `signal` for data signals, `command` for executable commands.         |
| `name`       | `string` | Human-readable name (e.g., `State Of Charge`, `Start charge`).        |
| `group`      | `string` | Signal group (e.g., `TractionBattery`, `Charge`). Empty for commands. |
| `code`       | `string` | Internal code (e.g., `StateOfCharge`, `charge-start`).                |
| `capability` | `string` | Capability key (e.g., `tractionbattery-stateofcharge`).               |
| `permission` | `string` | Required Smartcar permission (e.g., `read_battery`).                  |

#### Pagination Metadata

| Field             | Type      | Description                                          |
| ----------------- | --------- | ---------------------------------------------------- |
| `meta.page`       | `integer` | Always `1` (all data returned in a single response). |
| `meta.pageSize`   | `integer` | Number of items returned.                            |
| `meta.totalCount` | `integer` | Total number of items (equals `pageSize`).           |

### Error Handling

| Status | Description                                                                                                 |
| ------ | ----------------------------------------------------------------------------------------------------------- |
| `200`  | Successful request. If no vehicles match the filters, `data` will be an empty array — this is not an error. |
| `404`  | Invalid path. Returned when the requested URL does not match any endpoint.                                  |
| `500`  | Server error. Retry with exponential backoff.                                                               |

Error responses follow the Smartcar [error format](/docs/errors/api-errors/v3):

```json theme={null}
{
  "errors": [
    {
      "status": "500",
      "type": "SERVER",
      "code": "INTERNAL",
      "title": "Internal Server Error",
      "detail": "An unexpected error occurred on the server.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/v3/server-errors"
      }
    }
  ]
}
```

## How Compatibility is Determined

Smartcar compatibility data is generated dynamically from real vehicle connections and API requests across the platform. When we mark a vehicle as compatible with a specific signal, it means we have confirmed successful requests to that signal on that vehicle.

Because this data is based on platform activity:

* **Unlisted vehicles** — If a particular make, model, or year is not listed, it may be because we have not yet seen one connected to our platform, or we do not yet have sufficient data to determine compatibility.
* **Dynamic updates** — The dataset is updated daily as new vehicles connect and new data flows through the platform.

<Info>
  While we strive for accuracy and comprehensiveness, it is important to acknowledge that the functional capabilities of individual vehicles can exhibit variability. Even if we have confirmed a particular make, model, and year as compatible with a specific signal, a slight trim variation could cause the same vehicle to not be compatible.
</Info>


# Lock & Unlock
Source: https://smartcar.com/docs/api-reference/control-lock-unlock

POST https://api.smartcar.com/v2.0/vehicles/{id}/security
Lock or unlock the vehicle.

<Note>
  Remote commands are now available in [API v3](/docs/api-reference/commands/overview). We recommend using v3 for new command integrations. Commands remain available in v2.0 until it is deprecated.
</Note>

## Permission

`control_security`

## Request

**Path**

<Snippet />

**Body**

<ParamField type="string">
  `LOCK` or `UNLOCK` the vehicle’s doors.
</ParamField>

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="status" type="string">
  If the request is successful, Smartcar will return “success” (HTTP 200 status).
</ResponseField>

<ResponseField name="message" type="string">
  If the request is successful, Smartcar will return a message (HTTP 200 status).
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
      "message": "Successfully sent request to vehicle",
      "status": "success"
  }
  ```
</ResponseExample>


# Create subscription
Source: https://smartcar.com/docs/api-reference/create-subscription

/specs/management.yaml post /subscriptions
Create a new webhook subscription.



# Start & Stop Charge
Source: https://smartcar.com/docs/api-reference/evs/control-charge

POST https://api.smartcar.com/v2.0/vehicles/{id}/charge
Start or stop the vehicle charging.

<Note>
  Remote commands are now available in [API v3](/docs/api-reference/commands/overview). We recommend using v3 for new command integrations. Commands remain available in v2.0 until it is deprecated.
</Note>

## Permission

`control_charge`

## Request

**Path**

<Snippet />

**Body**

<ParamField type="string">
  `START` or `STOP` the vehicle charging.
</ParamField>

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="status" type="string">
  If the request is successful, Smartcar will return “success”.
</ResponseField>

<ResponseField name="message" type="string">
  If the request is successful, Smartcar will return a message.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
      {
          "message": "Successfully sent request to vehicle",
          "status": "success"
      }   
  ```
</ResponseExample>

## Notes

**BMW and MINI**<br />
Vehicle needs to be on OS Version 8+

**Ford and Lincoln**<br />
Issuing a start command while the vehicle has a schedule in place for its current charging location will result in the vehicle charging to 100%.

Charging schedules on the vehicle can be read through the [`Charge.ChargeTimers`](/docs/api-reference/signals/charge#chargetimers) signal.

**Nissan**<br />
Currently only START charge commands are supported in the US. See the [Commands overview](/docs/api-reference/commands/overview) for details on setting a charge schedule for Nissan vehicles.

**Chevrolet, GMC, Buick and Cadillac**<br />
These vehicles require a minimum charge of 50% in order to be able to start or stop charging via the API.


# Battery Level
Source: https://smartcar.com/docs/api-reference/evs/get-battery-level

GET https://api.smartcar.com/v2.0/vehicles/{id}/battery
Returns the state of charge and the remaining range of an electric vehicle's high voltage battery.

## Permission

`read_battery`

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

<Note>
  This endpoint is only available for BEVs and PHEVs.
</Note>

## Request

**Path**

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="percentRemaining" type="number">
  The EV's state of charge as a percentage.
</ResponseField>

<ResponseField name="range" type="number">
  The estimated remaining distance the vehicle can travel powered by its high voltage battery.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
      "percentRemaining": 0.3,
      "range": 40.5
  }
  ```
</ResponseExample>


# Charge Limit
Source: https://smartcar.com/docs/api-reference/evs/get-charge-limit

GET https://api.smartcar.com/v2.0/vehicles/{id}/charge/limit
Returns the charge limit configuration for the vehicle.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

## Permission

`read_charge`

## Request

**Path**

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="limit" type="number">
  The level at which the vehicle will stop charging and be considered fully charged as a percentage.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
      "limit": 0.8,
  }
  ```
</ResponseExample>

## Notes

This endpoint will return a [`CHARGING_PLUG_NOT_CONNECTED`](/docs/errors/api-errors/vehicle-state-errors#charging-plug-not-connected)
error if the OEM is unable to provide a charge limit unless the vehicle is plugged in.

**Ford and Lincoln**<br />
If a vehicle starts charging as a result of a [start charge](/docs/api-reference/evs/control-charge) request, this endpoint will always return `1` if the charging location has a schedule in place.

Charging schedules on the vehicle can be read through the [`Charge.ChargeTimers`](/docs/api-reference/signals/charge#chargetimers) signal.

**BMW and MINI**<br />
Vehicle needs to be on OS Version 8+


# Charge Status
Source: https://smartcar.com/docs/api-reference/evs/get-charge-status

GET https://api.smartcar.com/v2.0/vehicles/{id}/charge
Returns the charge status for the vehicle.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

## Permission

`read_charge`

## Request

**Path**

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="isPluggedIn" type="bool">
  Indicates whether a charging cable is currently plugged into the vehicle’s charge port.
</ResponseField>

<ResponseField name="state" type="string">
  Returns the current charge status of a vehicle. A vehicle can be `FULLY_CHARGED` at less than 100% SoC if its [Charge Limit](/docs/api-reference/evs/get-charge-limit) is less than `1`.

  <Expandable title="states">
    <ResponseField name="CHARGING" />

    <ResponseField name="FULLY_CHARGED" />

    <ResponseField name="NOT_CHARGING" />
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
      "isPluggedIn": true,
      "state": "FULLY_CHARGED"
  }
  ```
</ResponseExample>


# Charge Limit
Source: https://smartcar.com/docs/api-reference/evs/set-charge-limit

POST https://api.smartcar.com/v2.0/vehicles/{id}/charge/limit
Set the  charge limit of an electric vehicle.

<Note>
  Remote commands are now available in [API v3](/docs/api-reference/commands/overview). We recommend using v3 for new command integrations. Commands remain available in v2.0 until it is deprecated.
</Note>

## Permission

`control_charge`

## Request

**Path**

<Snippet />

**Body**

<ParamField type="number">
  The level at which the vehicle should stop charging and be considered fully charged.
  Cannot be less than `0.5`, or greater than `1`.
</ParamField>

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="status" type="string">
  If the request is successful, Smartcar will return “success” (HTTP 200 status).
</ResponseField>

<ResponseField name="message" type="string">
  If the request is successful, Smartcar will return a message (HTTP 200 status).
</ResponseField>

## Notes

This endpoint will return a [`CHARGING_PLUG_NOT_CONNECTED`](/docs/errors/api-errors/vehicle-state-errors#charging-plug-not-connected) error if
the OEM is unable to set a charge limit while the vehicle is unpluged.

**Ford and Lincoln**<br />
If a vehicle starts charging as a result of a [start charge](/docs/api-reference/evs/control-charge) request it will always charge to 100%
if the charging location has a schedule in place.

Charging schedules on the vehicle can be read through the [`Charge.ChargeTimers`](/docs/api-reference/signals/charge#chargetimers) signal.

**BMW and MINI**<br />
Vehicle needs to be on OS Version 8+

<ResponseExample>
  ```json Example Response  theme={null}
  {
      "message": "Successfully sent request to vehicle",
      "status": "success"
  }   
  ```
</ResponseExample>


# Get connection
Source: https://smartcar.com/docs/api-reference/get-connection

/specs/full-vehicle.yaml get /connections/{connectionId}
Get a specific user/vehicle connection for the application



# Diagnostic Trouble Codes
Source: https://smartcar.com/docs/api-reference/get-dtcs

GET https://api.smartcar.com/v2.0/vehicles/{id}/diagnostics/dtcs
Provides a list of active Diagnostic Trouble Codes (DTCs) reported by the vehicle. Currently supporting GM brands including Chevrolet and GMC.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

## Permission

`read_diagnostics`

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/diagnostics/dtcs" \
      -H "Authorization: Bearer {token}" \
      -X "GET"
  ```

  ```python Python theme={null}
  diagnostic_trouble_codes = vehicle.diagnostic_trouble_codes()
  ```

  ```js Node theme={null}
  const diagnosticTroubleCodes = await vehicle.diagnosticTroubleCodes();
  ```

  ```java Java theme={null}
  VehicleDiagnosticTroubleCodes diagnosticTroubleCodes = vehicle.diagnosticTroubleCodes();
  ```

  ```ruby Ruby theme={null}
  diagnostic_trouble_codes = vehicle.diagnostic_trouble_codes
  ```
</RequestExample>

## Request

**Path**

<Snippet />

## Response

<ResponseField name="activeCodes" type="array">
  Array of active diagnostic trouble codes.

  <Expandable>
    <ResponseField name="code" type="string">
      The Diagnostic Trouble Code reported by the vehicle.
    </ResponseField>

    <ResponseField name="timestamp" type="timestamp">
      The date and time the trouble code last became active.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
    {
      "activeCodes": [
        {
          "code": "P302D",
          "timestamp": "2024-09-05T14:48:00.000Z"
        },
        {
          "code": "xxxxx",
          "timestamp": null
        }
        
        ... 
      ]
    }
  ```
</ResponseExample>


# Oil Life
Source: https://smartcar.com/docs/api-reference/get-engine-oil-life

GET https://api.smartcar.com/v2.0/vehicles/{id}/engine/oil
Returns the remaining life span of a vehicle’s engine oil.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

## Permission

`read_engine_oil`

## Request

**Path**

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="lifeRemaining" type="number">
  The engine oil’s remaining life span based on the current quality of the oil as a percentage.
  `1` indicates the oil was changed recently and `0` indicates the oil should be changed immediately.
  It is not a representation of how much oil is left in the vehicle.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
    "lifeRemaining": 0.35
  }
  ```
</ResponseExample>


# Fuel Tank
Source: https://smartcar.com/docs/api-reference/get-fuel-tank

GET https://api.smartcar.com/v2.0/vehicles/{id}/fuel
Returns the status of the fuel remaining in the vehicle’s fuel tank.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

## Permission

`read_fuel`

<Note>
  This endpoint may return `null` values for vehicles sold in Europe. Please see the [Notes](/docs/api-reference/get-fuel-tank#notes) section for details.
</Note>

## Request

**Path**

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="percentRemaining" type="number | null">
  The remaining level of fuel in the tank as a percentage.
</ResponseField>

<ResponseField name="amountRemaining" type="number | null">
  The amount of fuel in the tank.
</ResponseField>

<ResponseField name="range" type="number | null">
  The estimated remaining distance the car can travel.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
    "amountRemaining": 53.2,
    "percentRemaining": 0.3,
    "range": 40.5
  }
  ```
</ResponseExample>

## Notes

The table below indicates values Smartcar attempts to retrieve from vehicles sold in Europe.

|                                      | `range` | `percentRemaining` | `amountRemaining` |
| ------------------------------------ | ------- | ------------------ | ----------------- |
| Audi                                 | ✅       | ✅                  |                   |
| BMW, MINI                            | ✅       | ✅                  | ✅                 |
| Citroen, DS, Opel, Peugeot, Vauxhall | ✅       |                    | ✅                 |
| Ford                                 | ✅       | ✅                  |                   |
| Hyundai                              | ✅       |                    | ✅                 |
| Jaguar, Land Rover                   | ✅       | ✅                  |                   |
| Kia                                  | ✅       | ✅                  |                   |
| Mazda                                | ✅       | ✅                  |                   |
| Mercedes                             | ✅       | ✅                  |                   |
| Renault                              | ✅       |                    | ✅                 |
| Skoda, Volkswagen                    | ✅       | ✅                  |                   |
| Volvo                                | ✅       | ✅                  | ✅                 |


# Location
Source: https://smartcar.com/docs/api-reference/get-location

GET https://api.smartcar.com/v2.0/vehicles/{id}/location
Returns the vehicle's last known location.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

## Permission

`read_location`

## Request

**Path**

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="latitude" type="number">
  The latitude in degrees.
</ResponseField>

<ResponseField name="longitude" type="number">
  The longitude in degrees.
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
  {
    "latitude": 37.4292,
    "longitude": 122.1381
  }
  ```
</ResponseExample>


# Lock Status
Source: https://smartcar.com/docs/api-reference/get-lock-status

GET https://api.smartcar.com/v2.0/vehicles/{id}/security
Returns the lock status for a vehicle and the open status of its doors, windows, storage units, sunroof and charging port where available.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

## Permission

`read_security`

## Request

**Path**

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="isLocked" type="boolean">
  Indicates the current lock status of the vehicle as reported by the OEM.
</ResponseField>

<ResponseField name="doors" type="[object]">
  An array of the open status of the vehicle's doors.

  <Expandable title="doors">
    <ResponseField name="type" type="string">
      The location of the door.
    </ResponseField>

    <ResponseField name="status" type="string">
      Indicates the current state of the vehicle's door.
      `UNKNOWN` indicates the vehicle supports this status, but did not provide a valid status for the request
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="windows" type="[object]">
  An array of the open status of the vehicle's windows.

  <Expandable title="windows">
    <ResponseField name="type" type="string">
      The location of the window.
    </ResponseField>

    <ResponseField name="status" type="string">
      Indicates the current state of the vehicle's window.
      `UNKNOWN` indicates the vehicle supports this status, but did not provide a valid status for the request
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="sunroof" type="[object]">
  An array of the open status of the vehicle's sunroofs.

  <Expandable title="sunroofs">
    <ResponseField name="type" type="string">
      The location of the sunroof.
    </ResponseField>

    <ResponseField name="status" type="string">
      Indicates the current state of the vehicle's sunroof.
      `UNKNOWN` indicates the vehicle supports this status, but did not provide a valid status for the request
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="storage" type="[object]">
  An array of the open status of the vehicle's storages.
  For internal combustion and plug-in hybrid vehicles front refers to the engine hood.
  For battery vehicles, this will be the front trunk.

  <Expandable title="storage">
    <ResponseField name="type" type="string">
      The location of the storage.
    </ResponseField>

    <ResponseField name="status" type="string">
      Indicates the current state of the vehicle's storage.
      `UNKNOWN` indicates the vehicle supports this status, but did not provide a valid status for the request
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="chargingPort" type="[object]">
  An array of the open status of the vehicle's charging port.

  <Expandable title="chargingPort">
    <ResponseField name="type" type="string">
      The location of the charging port.
    </ResponseField>

    <ResponseField name="status" type="string">
      Indicates the current state of the vehicle's charging port.
      `UNKNOWN` indicates the vehicle supports this status, but did not provide a valid status for the request
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
  	"isLocked" : false,
  	"doors" : [
  		{"type": "frontLeft" , "status" : "CLOSED"},
  		{"type": "frontRight" , "status" : "OPEN"},
  		{"type": "backRight" , "status" : "CLOSED"},
  		{"type": "backLeft" , "status" : "CLOSED"}
  	],
  	"windows" : [
  		{"type": "frontLeft" , "status" : "CLOSED"},
  		{"type": "frontRight" , "status" : "CLOSED"},
  		{"type": "backRight" , "status" : "UNKNOWN"},
  		{"type": "backLeft" , "status" : "CLOSED"}
  	],
  	"sunroof" : [
  		{"type": "sunroof" , "status" : "CLOSED"}
  	], 	
  	"storage" : [
  		{"type": "rear" , "status" : "UNKNOWN"},
  		{"type": "front" , "status" : "CLOSED"}
  	],
  	"chargingPort" : [ 
  		{"type" : "chargingPort", "status" : "CLOSED" } 
  	]
  }
  ```
</ResponseExample>

# Notes

* The open status array(s) will be empty if a vehicle has partial support.
* The request will error if `lockStatus` can not be retrieved from the vehicle or the brand is not supported.


# Battery Capacity
Source: https://smartcar.com/docs/api-reference/get-nominal-capacity

GET https://api.smartcar.com/v2.0/vehicles/{id}/battery/nominal_capacity
Returns a list of nominal rated battery capacities for a vehicle.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

## Permission

`read_battery`

## Request

**Path**

<Snippet />

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/battery/nominal_capacity" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```
</RequestExample>

## Response

<ResponseField name="availableCapacities" type="[capacities Object]">
  An array of capacities Objects.

  <Expandable title="capacities">
    <ResponseField name="capacity" type="number | null">
      The rated nominal capacity for the vehicle's battery.
    </ResponseField>

    <ResponseField name="description" type="string | null">
      A description of the uniqueness for the nominal capacity and engine type of the vehicle in the form `{ENGINE_TYPE}:{TRIM}`, for example `"BEV:Extended Range"`.

      Engine type can be one of `BEV` or `PHEV`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="capacity" type="Object | null">
  <Expandable title="capacity">
    <ResponseField name="nominal" type="number | null">
      The rated nominal capacity for the vehicle's battery.
    </ResponseField>

    <ResponseField name="source" type="string | null">
      Indicates if this capacity was determined by a user or Smartcar.
      Options are `USER_SELECTED` or `SMARTCAR`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="url" type="string | null">
  A URL that will launch the flow for a vehicle owner to specify the correct
  battery capacity for a vehicle. **Please ensure you append a
  redirect URI** for us to send a response to once the user exits the flow.

  Please see [this article](/docs/connect/user-selected-batcap) on how to handle the URL callback.
</ResponseField>

<ResponseExample>
  ```json Response Example theme={null}
  {
      "availableCapacities": [
          {
              "capacity" :  70.9,
              "description" : null 
          },
          {
              "capacity" :  80.9,
              "description" : null
          },
          {
              "capacity" :  90.9,
              "description" : "BEV:Extended Range" 
          }
      ],
      "capacity": { 
  	    "nominal" :  80.9,
  	    "source": "USER_SELECTED" 
      },
      "url" : "https://connect.smartcar.com/battery-capacity?vehicle_id=36ab27d0-fd9d-4455-823a-ce30af709ffc&client_id=8229df9f-91a0-4ff0-a1ae-a1f38ee24d07&token=90abecb6-e7ab-4b85-864a-e1c8bf67f2ad&response_type=vehicle_id&redirect_uri="
  } 
  ```
</ResponseExample>

### Case 1: Smartcar has determined the battery capacity

```json Single capacity theme={null}
{
    "availableCapacities": [
        {
            "capacity" :  70.9,
            "description" : null  
        }
    ],
    "capacity": { 
        "nominal" :  70.9,
        "source": "SMARTCAR" 
    },
    "url" : null
} 
```

### Case 2: Unable to determine the battery capacity

```json Multiple capacities theme={null}
{
    "availableCapacities": [
        {
            "capacity" :  70.9,
            "description" : null 
        },
        {
            "capacity" :  80.9,
            "description" : null 
        },
        {
            "capacity" :  90.9,
            "description" : "BEV:Extended Range" 
        }
    ],
    "capacity": null,
    "url" : "https://connect.smartcar.com/battery-capacity?vehicle_id=36ab27d0-fd9d-4455-823a-ce30af709ffc&client_id=8229df9f-91a0-4ff0-a1ae-a1f38ee24d07&token=90abecb6-e7ab-4b85-864a-e1c8bf67f2ad&response_type=vehicle_id&redirect_uri="
} 
```

### Case 3: User selected battery capacity

Smartcar will sometimes return an `availableCapacities` object along side a Connect URL you can use to prompt users to select the battery capacity of their vehicle. This can occur when an accurate match could not be found, or vehicle owners purchased extension packs, or software upgrades specific to their vehicle.

When you redirect a vehicle owner to this Smartcar Connect url, they can select the battery capacity of their vehicle for cases where the battery capacity cannot be accurately determined.

<Frame>
  <img />
</Frame>

When a user selects an option, Smartcar will return this value with `USER_SELECTED` as the source.

```json Multiple capacities theme={null}
{
  "availableCapacities": [
    {
      "capacity": 70.9,
      "description": null 
    },
    {
      "capacity": 80.9,
      "description": null 
    },
    {
      "capacity": 90.9,
      "description": "BEV:Extended Range" 
    }
  ],
  "capacity": { 
    "nominal": 80.9,
    "source": "USER_SELECTED" 
  },
  "url": "https://connect.smartcar.com/battery-capacity?vehicle_id=36ab27d0-fd9d-4455-823a-ce30af709ffc&client_id=8229df9f-91a0-4ff0-a1ae-a1f38ee24d07&token=90abecb6-e7ab-4b85-864a-e1c8bf67f2ad&response_type=vehicle_id&redirect_uri="
}
```


# Odometer
Source: https://smartcar.com/docs/api-reference/get-odometer

GET https://api.smartcar.com/v2.0/vehicles/{id}/odometer
Returns the vehicle’s last known odometer reading.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

## Permission

`read_odometer`

## Request

**Path**

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="distance" type="number">
  The current odometer of the vehicle.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
    "distance": 104.32
  }
  ```
</ResponseExample>


# Service History
Source: https://smartcar.com/docs/api-reference/get-service-records

GET https://api.smartcar.com/v2.0/vehicles/{id}/service/history
Retrieve service records tracked by the vehicle's dealer or manually added by the vehicle owner. Currently supporting Ford, Lincoln, Toyota, Lexus, Mazda and Volkswagen (US)

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

## Permission

`read_service_history`

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/service/history" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  service = vehicle.request(
        "GET", 
        "service/history"
  )
  ```

  ```js Node theme={null}
  const service = await vehicle.request(
        "GET", 
        "service/history"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("service/history")
        .build();
  VehicleResponse service =vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  Service = vehicle.request(
        "GET", 
        "service/history"
  )
  ```
</RequestExample>

## Request

**Path**

<Snippet />

## Response

<ResponseField name="serviceID" type="string | null">
  A unique identifier of the service record.
</ResponseField>

<ResponseField name="serviceDate" type="timestamp | null">
  The date and time the vehicle was serviced
</ResponseField>

<ResponseField name="odometerDistance" type="string | null">
  The odometer of the vehicle at time of service in kilometers.
</ResponseField>

<Expandable title="serviceTasks" description="An overview of specific tasks completed in the service event.">
  <ResponseField name="taskID" type="string | null">
    The unique identifier of the tasks completed as part of the service event.
  </ResponseField>

  <ResponseField name="taskDescription" type="string | null">
    Tasks completed as part of the service event. Note that not all makes provide service tasks.
  </ResponseField>
</Expandable>

Additional service details.

<Expandable title="service details">
  <ResponseField name="type" type="string | null">
    Indicates if the service event was completed by a dealership or manually entered by the vehicle owner.
  </ResponseField>
</Expandable>

An overview of service costs.

<Expandable title="service cost">
  <ResponseField name="totalCost" type="string | null">
    The total cost of the service event. Note that not all makes provide service cost.
  </ResponseField>

  <ResponseField name="currency" type="string | null">
    Identifies the currency used for service cost.
  </ResponseField>
</Expandable>

<ResponseExample>
  ```json Example Response  theme={null}
  {
        "serviceId": null,
        "odometerDistance": 46047.22,
        "serviceDate": "2023-06-28T22:21:41.583Z",
        "serviceTasks": [
              {
              "taskId": "3262",
              "taskDescription": "Service Task 0"
              },
              {
              "taskId": "3041",
              "taskDescription": null
              },
              {
              "taskId": null,
              "taskDescription": null
              }
        ],
        "serviceDetails": [
              {
              "type": "Service Details Type 0",
              "value": "Service Details Value 0"
              },
              {
              "type": "Service Details Type 1",
              "value": null
              }
        ],
        "serviceCost": {
              "totalCost": null,
              "currency": null
        }
  }
  ```
</ResponseExample>


# Get signal
Source: https://smartcar.com/docs/api-reference/get-signal

/specs/full-vehicle.yaml get /vehicles/{vehicleId}/signals/{signalCode}
Get individual signal details by signal code.



# Get subscription
Source: https://smartcar.com/docs/api-reference/get-subscription

/specs/management.yaml get /subscriptions/{subscriptionId}
Retrieve details of a specific webhook subscription.



# System Status
Source: https://smartcar.com/docs/api-reference/get-system-status

GET https://api.smartcar.com/v2.0/vehicles/{id}/diagnostics/system_status
Provides a list of vehicle systems and their current health status. Currently supporting FCA and GM brands including RAM, Jeep, Chrysler, Dodge, Fiat, Alfa Romeo, Buick, Cadillac, Chevrolet and GMC. See [Diagnostic Systems](/docs/help/diagnostic-systems) for a complete list of Smartcar System IDs.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

## Permission

`read_diagnostics`

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/diagnostics/system_status" \\
      -H "Authorization: Bearer {token}" \\
      -X "GET"
  ```

  ```python Python theme={null}
  diagnostic_system_status = vehicle.diagnostic_system_status()
  ```

  ```js Node theme={null}
  const diagnosticSystemStatus = await vehicle.diagnosticSystemStatus();
  ```

  ```java Java theme={null}
  VehicleDiagnosticSystemStatus diagnosticSystemStatus = vehicle.diagnosticSystemStatus();
  ```

  ```ruby Ruby theme={null}
  diagnostic_system_status = vehicle.diagnostic_system_status
  ```
</RequestExample>

## Request

**Path**

<Snippet />

## Response

<ResponseField name="systems" type="array">
  An overview of systems reported by the vehicle.
</ResponseField>

<ResponseField name="systemID" type="string">
  The unique identifier of a system reported by the vehicle.
</ResponseField>

<ResponseField name="status" type="string">
  The status of a vehicle, expected as "OK" or "ALERT".
</ResponseField>

<ResponseField name="description" type="string | null">
  A plain-text description of the status, if available.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
        "systems": [
            {
                // System ID from Smartcar unified system definition list
                "systemId": "SYSTEM_TPMS",
                "status": "ALERT",
                "description": "Left rear tire sensor battery low"
            },
            {
                "systemId": "SYSTEM_AIRBAG",
                "status": "OK",
                "description": null
            },
            {
                "systemId": "SYSTEM_MIL",
                "status": "OK",
                "description": null
            },
            ...
        ]
  }
  ```
</ResponseExample>


# Tire Pressure
Source: https://smartcar.com/docs/api-reference/get-tire-pressure

GET https://api.smartcar.com/v2.0/vehicles/{id}/tires/pressure
Returns the air pressure of each of the vehicle’s tires.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

## Permission

`read_tires`

## Request

**Path**

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="frontLeft" type="number">
  The current air pressure of the front left tire.
</ResponseField>

<ResponseField name="frontRight" type="number">
  The current air pressure of the front right tire.
</ResponseField>

<ResponseField name="backLeft" type="number">
  The current air pressure of the back left tire.
</ResponseField>

<ResponseField name="backRight" type="number">
  The current air pressure of the back right tire.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
      "backLeft": 219.3,
      "backRight": 219.3,
      "frontLeft": 219.3,
      "frontRight": 219.3
  }
  ```
</ResponseExample>


# Get vehicle
Source: https://smartcar.com/docs/api-reference/get-vehicle

/specs/full-vehicle.yaml get /vehicles/{vehicleId}
Get Vehicle by ID.



# Vehicle Attributes
Source: https://smartcar.com/docs/api-reference/get-vehicle-info

GET https://api.smartcar.com/v2.0/vehicles/{id}
Returns a single vehicle object, containing identifying information.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

## Permission

`read_vehicle_info`

## Request

**Path**

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="id" type="string">
  The ID for the vehicle.
</ResponseField>

<ResponseField name="make" type="string">
  The manufacturer of the vehicle.
</ResponseField>

<ResponseField name="model" type="string">
  The model of the vehicle.
</ResponseField>

<ResponseField name="year" type="integer">
  The model year.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
      "id": "36ab27d0-fd9d-4455-823a-ce30af709ffc",
      "make": "TESLA",
      "model": "Model S",
      "year": "2014"
  }
  ```
</ResponseExample>


# VIN
Source: https://smartcar.com/docs/api-reference/get-vin

GET https://api.smartcar.com/v2.0/vehicles/{id}/vin
Returns the vehicle’s manufacturer identifier.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

## Permission

`read_vin`

## Request

**Path**

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="vin" type="string">
  The manufacturer unique identifier.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
    "vin": "5YJSA1CN5DFP00101"
  }
  ```
</ResponseExample>


# Get webhook
Source: https://smartcar.com/docs/api-reference/get-webhook

/specs/management.yaml get /webhooks/{webhookId}



# Charge Completion Time
Source: https://smartcar.com/docs/api-reference/gm/get-charge-completion-time

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/completion
When the vehicle is charging, returns the date and time the vehicle expects to "complete" this charging session.  When the vehicle is not charging, this endpoint results in a vehicle state error.

<Note>
  This endpoint is currently available for `cadillac` and `chevrolet`.
</Note>

## Permission

`read_charge`

## Request

<ParamField type="string">
  `vehicle_id` of the vehicle you are making the request to.
</ParamField>

<ParamField type="string">
  The make to pass in the URL.
</ParamField>

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="time" type="string">
  An ISO8601 formatted datetime (`YYYY-MM-DDTHH:mm:ss.SSSZ`) for the time at which the vehicle expects to complete this charging session.
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
  {
    "time": "2022-01-13T22:52:55.358Z"
  }
  ```
</ResponseExample>


# Voltage
Source: https://smartcar.com/docs/api-reference/gm/get-charge-voltmeter

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/voltmeter
When the vehicle is plugged in, returns the charging voltage measured by the vehicle. When the vehicle is not plugged in, this endpoint results in a vehicle state error.

<Note>
  This endpoint is currently available for `cadillac` and `chevrolet`.
</Note>

## Permission

`read_charge`

## Request

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="voltage" type="number">
  The potential difference measured by the vehicle in volts (V).
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
  {
    "voltage": 240
  }
  ```
</ResponseExample>


# Headers
Source: https://smartcar.com/docs/api-reference/headers



Smartcar uses the following headers for requests and responses.

## Request

<ParamField type="string">
  Smartcar supports both `metric` and `imperial` unit systems of measurement.
</ParamField>

<RequestExample>
  ```bash Request Headers theme={null}
  SC-Unit-System: metric
  ```
</RequestExample>

## Response

<ResponseField name="SC-Data-Age" type="string">
  Indicates the timestamp (ISO-8601 format) of when the returned data was recorded by the vehicle.
</ResponseField>

<ResponseField name="SC-Fetched-At" type="string">
  Indicates the timestamp (ISO-8601 format) of when Smartcar fetched the data from the OEM.
</ResponseField>

<ResponseField name="SC-Unit-System" type="string">
  Indicates whether the unit system used in the returned data is `imperial` or `metric`.
</ResponseField>

<ResponseField name="SC-Request-Id" type="string">
  Each response from Smartcar's API has a unique request identifier. If you need to contact us about a specific request, providing the request identifier will ensure the fastest possible resolution.
</ResponseField>

<ResponseExample>
  ```bash Response Headers theme={null}
  SC-Data-Age: 2018-06-20T01:33:37.078Z
  SC-Fetched-At: 2018-06-20T01:48:37.078Z
  SC-Unit-System: metric
  SC-Request-Id: 26c14915-0c26-43c5-8e42-9edfc2a66a0f
  ```
</ResponseExample>


# Smartcar API Overview
Source: https://smartcar.com/docs/api-reference/intro

The Smartcar API lets you read vehicle data, send commands, and manage connections across millions of vehicles through a single REST interface.

Smartcar provides two APIs: the **Vehicle API** and the **Management API**. Both use the same access token, obtained by exchanging your Client ID and Client Secret through [API Authentication](/docs/api-reference/authorization/overview). Tokens are valid for 1 hour.

* [API Authentication](/docs/api-reference/authorization/overview) — How it works
* [Request Access Token](/docs/api-reference/authorization/request-access-token) — Token endpoint reference

## Vehicle API

Path: `https://vehicle.api.smartcar.com/v3`

Read vehicle data, send commands, and manage connections.

### Connections

List, query, and remove vehicle connections for your application.

* [List Connections](/docs/api-reference/list-connections) — All vehicle connections
* [Get Connection](/docs/api-reference/get-connection) — A specific connection
* [Remove Connection](/docs/api-reference/remove-connection) — Disconnect a vehicle
* [Remove User](/docs/api-reference/remove-user) — Remove a user and all their connections

### Vehicle Data

Read standardized signals from connected vehicles, including battery level, odometer, location, tire pressure, and more.

* [Get Vehicle](/docs/api-reference/get-vehicle) — Vehicle attributes (make, model, year)
* [Get Signals](/docs/api-reference/list-signals) — Read one or more signals from a vehicle
* [Signal Schema](/docs/api-reference/signals/schema) — Full list of available signals
* [Permissions](/docs/api-reference/permissions) — Required permissions per signal

### Vehicle Commands

Send commands to connected vehicles like lock/unlock, start/stop charging, and set charge limits.

* [Start Charge](/docs/api-reference/charging/start-charging) — Start charging
* [Stop Charge](/docs/api-reference/charging/stop-charging) — Stop charging
* [Set Charge Limit](/docs/api-reference/charging/set-charge-limit) — Set the charge limit
* [Lock](/docs/api-reference/security/lock-doors) — Lock the vehicle
* [Unlock](/docs/api-reference/security/unlock-doors) — Unlock the vehicle
* [Set Destination](/docs/api-reference/navigation/set-destination) — Send a destination to the vehicle’s navigation

## Management API

Path: `https://management.api.smartcar.com/v3`

### Webhooks

Subscribe vehicles to webhooks to receive data on a schedule or when events occur. This is the recommended approach for most integrations.

* [Webhooks Overview](/docs/integrations/webhooks/overview) — How webhooks work
* [Subscribing Vehicles](/docs/integrations/webhooks/subscribing-vehicles) — Subscribe and unsubscribe vehicles
* [Receiving Webhooks](/docs/integrations/webhooks/receiving-webhooks) — Handle incoming payloads

***

<Card title="Starter app" icon="github-alt" href="https://github.com/smartcar/starter-app-react-node">
  Connect a vehicle and make API requests using our starter app.
</Card>

<Card title="Postman" icon="rocket" href="https://www.postman.com/smartcar/smartcar-api/collection/btrmn6x/smartcar-api-collection">
  Try the API using our Postman collection.
</Card>


# List connections
Source: https://smartcar.com/docs/api-reference/list-connections

/specs/full-vehicle.yaml get /connections
Get all vehicle connections for the application, with optional filters for user ID, vehicle ID, and mode. Results are paginated.



# List signals
Source: https://smartcar.com/docs/api-reference/list-signals

/specs/full-vehicle.yaml get /vehicles/{vehicleId}/signals
Get list of signals for a vehicle.



# List subscriptions
Source: https://smartcar.com/docs/api-reference/list-subscriptions

/specs/management.yaml get /subscriptions
Retrieve a list of webhook subscriptions with optional filtering and pagination.



# List webhooks
Source: https://smartcar.com/docs/api-reference/list-webhooks

/specs/management.yaml get /webhooks



# Management API Overview
Source: https://smartcar.com/docs/api-reference/management-api-intro

The Management API allows you to manage vehicle connections and webhook subscriptions at the application level. It is designed for administrative tasks that go beyond individual vehicle data access.

## What You Can Do

* List all vehicles connected to your application
* Remove (disconnect) vehicles from your app
* Manage webhook subscriptions (subscribe/unsubscribe vehicles)

## Authentication

The Management API uses a management token, which you can generate in your [Smartcar Dashboard](https://dashboard.smartcar.com/).

## Base URL

```
https://api.smartcar.com/management/v2.0
```

## Key Resources

* [Get Vehicle Connections](/docs/api-reference/management/get-vehicle-connections)
* [Delete Vehicle Connections](/docs/api-reference/management/delete-vehicle-connections)
* [Webhook Management](/docs/api-reference/webhooks/unsubscribe-webhook)

## Example Use Cases

* Removing vehicles when a user deletes their account
* Managing webhook event delivery
* Auditing connected vehicles for compliance

<Info>
  For more details on using the Management API, see [Management API Reference](/docs/api-reference/management/get-vehicle-connections).
</Info>


# Vehicle Connections
Source: https://smartcar.com/docs/api-reference/management/delete-vehicle-connections

DELETE https://management.smartcar.com/v2.0/management/connections
Deletes all vehicle connections associated with a Smartcar user ID or a specific vehicle.

## Request

**Header**

<ParamField type="string">
  In the format `Basic base64(default:{application_management_token})`. You can find your `application_management_token` under
  your Application Configuration in the Smartcar Dashboard.
</ParamField>

**Query**

<ParamField type="string" />

<ParamField type="string" />

You can delete connections in three ways:

* Provide a `vehicle_id` to remove all connections for that vehicle across all users.
* Provide a `user_id` to remove all vehicles linked to that user.
* Provide both a `vehicle_id` and `user_id` to remove only that vehicle for that specific user.

<RequestExample>
  ```bash cURL theme={null}
    curl -X DELETE "https://management.smartcar.com/v2.0/management/connections/?user_id=UUID12345&vehicle_id=UUID67890" \
    -H "Authorization: Basic $(echo -n "default:$SMARTCAR_APP_MANAGEMENT_TOKEN" | base64)"
  ```

  ```python Python theme={null}
    import os
    import base64
    import requests

    user_id = "UUID12345"
    vehicle_id = "UUID67890"
    token = os.getenv("SMARTCAR_APP_MANAGEMENT_TOKEN")

    auth_header = base64.b64encode(f"default:{token}".encode()).decode()
    headers = {
        "Authorization": f"Basic {auth_header}",
        "Content-Type": "application/json",
    }

    url = (
        "https://management.smartcar.com/v2.0/management/connections/"
        f"?user_id={user_id}&vehicle_id={vehicle_id}"
    )

    response = requests.delete(url, headers=headers)
  ```

  ```javascript Node theme={null}
    const basicAuth = Buffer.from(`default:${process.env.SMARTCAR_APP_MANAGEMENT_TOKEN}`).toString('base64');
    const disconnectResponse = await fetch(
    `https://management.smartcar.com/v2.0/management/connections/?user_id=${smartcar_user_id}&vehicle_id=${smartcar_vehicle_id}`,
    {
        method: 'DELETE',
        headers: {
          'Authorization': `Basic ${basicAuth}`,
          'Content-Type': 'application/json',
        },
      }
    );
  ```

  ```java Java theme={null}
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.util.Base64;

    String userId = "UUID12345";
    String vehicleId = "UUID67890";
    String token = System.getenv("SMARTCAR_APP_MANAGEMENT_TOKEN");
    String auth = Base64.getEncoder().encodeToString(("default:" + token).getBytes());

    URL url = new URL("https://management.smartcar.com/v2.0/management/connections/?user_id=" + userId + "&vehicle_id=" + vehicleId);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("DELETE");
    conn.setRequestProperty("Authorization", "Basic " + auth);
    conn.setRequestProperty("Content-Type", "application/json");

    int responseCode = conn.getResponseCode();
  ```

  ```ruby Ruby theme={null}
    require 'net/http'
    require 'uri'
    require 'base64'

    user_id = "UUID12345"
    vehicle_id = "UUID67890"
    token = ENV['SMARTCAR_APP_MANAGEMENT_TOKEN']
    auth = Base64.strict_encode64("default:#{token}")
    uri = URI("https://management.smartcar.com/v2.0/management/connections/?user_id=#{user_id}&vehicle_id=#{vehicle_id}")
    request = Net::HTTP::Delete.new(uri)
    request['Authorization'] = "Basic #{auth}"
    request['Content-Type'] = 'application/json'
    response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
    puts response.body
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={null}
  {
    "connections": [
      {
        "userId": "<string>",
        "vehicleId": "<string>"
      }
    ]
  }
  ```
</ResponseExample>

## Response

<ResponseField name="connections" type="array">
  An array of connections

  <Expandable title="connections">
    <ResponseField name="userId" type="string">
      ID of the user that authorized the deleted connection (UUID v4)
    </ResponseField>

    <ResponseField name="vehicleId" type="string">
      ID of the vehicle disconnected (UUID v4)
    </ResponseField>
  </Expandable>
</ResponseField>


# Vehicle Connections
Source: https://smartcar.com/docs/api-reference/management/get-vehicle-connections

GET https://management.smartcar.com/v2.0/management/connections
Returns a paged list of all vehicles that are connected to the application associated with the management API token used, sorted in descending order by connection date.

## Request

**Header**

<ParamField type="string">
  In the format `Basic base64(default:{application_management_token})`. You can find your `application_management_token` under
  your Application Configuration in the Smartcar Dashboard.
</ParamField>

**Query**

<ParamField type="integer">
  Number of connections to return per page. `Max: 100`
</ParamField>

<ParamField type="string">
  Used for accessing pages other than the first page. Each page returned has a cursor value
  that can be passed here to fetch the “next” page.
</ParamField>

<ParamField type="string">
  Filter for connections created by the provider user ID.
</ParamField>

<ParamField type="string">
  Filter for connections created with the provided [`external_id`](/docs/connect/redirect-to-connect), your application's own identifier for the vehicle owner.
</ParamField>

<ParamField type="string">
  Filter for connections to the provided vehicle ID.
</ParamField>

<ParamField type="string">
  Filter for connections by either `live`, `simulated`, or the deprecated `test` mode.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET "https://management.smartcar.com/v2.0/management/connections" \
    -H "Authorization: Basic $(echo -n "default:$SMARTCAR_APP_MANAGEMENT_TOKEN" | base64)" \
    -H "Content-Type: application/json"
  ```

  ```python Python theme={null}
  import os
  import base64
  import requests

  token = os.getenv("SMARTCAR_APP_MANAGEMENT_TOKEN")
  auth_header = base64.b64encode(f"default:{token}".encode()).decode()

  headers = {
      "Authorization": f"Basic {auth_header}",
      "Content-Type": "application/json"
  }

  response = requests.get(
      "https://management.smartcar.com/v2.0/management/connections",
      headers=headers
  )
  ```

  ```javascript Node theme={null}
  const basicAuth = Buffer.from(`default:${process.env.SMARTCAR_APP_MANAGEMENT_TOKEN}`).toString('base64');

  const response = await fetch(
      "https://management.smartcar.com/v2.0/management/connections",
      {
          method: 'GET',
          headers: {
              'Authorization': `Basic ${basicAuth}`,
              'Content-Type': 'application/json'
          }
      }
  );
  ```

  ```java Java theme={null}
  import java.net.HttpURLConnection;
  import java.net.URL;
  import java.util.Base64;

  String token = System.getenv("SMARTCAR_APP_MANAGEMENT_TOKEN");
  String auth = Base64.getEncoder().encodeToString(("default:" + token).getBytes());

  URL url = new URL("https://management.smartcar.com/v2.0/management/connections");
  HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  conn.setRequestMethod("GET");
  conn.setRequestProperty("Authorization", "Basic " + auth);
  conn.setRequestProperty("Content-Type", "application/json");

  int responseCode = conn.getResponseCode();
  ```

  ```ruby Ruby theme={null}
  require 'net/http'
  require 'uri'
  require 'base64'

  token = ENV['SMARTCAR_APP_MANAGEMENT_TOKEN']
  auth = Base64.strict_encode64("default:#{token}")

  uri = URI("https://management.smartcar.com/v2.0/management/connections")
  request = Net::HTTP::Get.new(uri)
  request['Authorization'] = "Basic #{auth}"
  request['Content-Type'] = 'application/json'

  response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
    http.request(request)
  end
  ```
</RequestExample>

## Response

<ResponseField name="connections" type="array">
  An array of connections

  <Expandable title="connections">
    <ResponseField name="userId" type="string">
      ID of the user that authorized this connection (UUID v4).
    </ResponseField>

    <ResponseField name="externalId" type="string">
      Your application's own identifier for the vehicle owner, if one was provided in the [Connect URL](/docs/connect/redirect-to-connect). `null` if none was set.
    </ResponseField>

    <ResponseField name="vehicleId" type="string">
      ID of the vehicle connected (UUID v4).
    </ResponseField>

    <ResponseField name="connectedAt" type="string">
      Time at which the connection was created in UTC.
    </ResponseField>

    <ResponseField name="mode" type="string">
      Vehicle mode: live, simulated, or test (deprecated).
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="paging" type="Object">
  Metadata about the current query

  <Expandable>
    <ResponseField name="cursor" type="string">
      The cursor parameter that should be used to fetch the next page of results.
      This field will be null if there are no more pages.
    </ResponseField>
  </Expandable>
</ResponseField>


# Set destination
Source: https://smartcar.com/docs/api-reference/navigation/set-destination

/specs/full-vehicle.yaml post /vehicles/{vehicleId}/commands/navigation/set-destination
Sets a destination in the vehicle's navigation system



# Charge Schedule
Source: https://smartcar.com/docs/api-reference/nissan/get-charge-schedule

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/schedule
Returns the charging schedule of a vehicle. The response contains the start time and departure time of the vehicle's charging schedule.

<Note>
  This endpoint is currently available for `nissan` EVs on the `MyNISSAN` platform.
</Note>

## Permission

`read_charge`

## Request

**Path**

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="chargeSchedules" type="array">
  An array of charge schedules. Maximum of 3 schedules, empty if no schedules are set.

  <Expandable>
    <ResponseField name="start" type="array">
      HH:mm in UTC for a schedule start time.
    </ResponseField>

    <ResponseField name="end" type="array">
      HH:mm in UTC for a schedule end time.
    </ResponseField>

    <ResponseField name="days" type="array">
      An array of days the schedule applies to.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
    "chargeSchedules": [
      {
        "end": "2020-01-01T02:00:00.000Z",
        "start": "2020-01-01T01:00:00.000Z",
        "days": [
          "MONDAY",
          "WEDNESDAY",
          "FRIDAY"
        ]
      }
    ]
  }
  ```
</ResponseExample>


# OpenAPI Specifications
Source: https://smartcar.com/docs/api-reference/openapi-specs

Download or view the raw OpenAPI documents that generate this API reference.

Smartcar publishes the raw OpenAPI (Swagger) documents behind this API reference. Use them to generate client code, feed the schema into your own tooling, or review the full API outside the browser.

<CardGroup>
  <Card title="Authentication API" icon="key" href="/specs/auth.yaml">
    OAuth2 client credentials token exchange — `auth.yaml`
  </Card>

  <Card title="Vehicle API" icon="car" href="/specs/full-vehicle.yaml">
    Vehicle data, signals, and commands — `full-vehicle.yaml`
  </Card>

  <Card title="Management API" icon="webhook" href="/specs/management.yaml">
    Webhooks, subscriptions, and applications — `management.yaml`
  </Card>
</CardGroup>

<Info>
  Each link opens the raw YAML file. Open it directly to view it in your browser, or right-click and choose **Save Link As** to download it.
</Info>

## Import into API tools

Most API clients can import an OpenAPI document directly from a URL. Copy one of the links above, then choose **Import** in Postman or Insomnia and paste it.

A collection generated this way contains every endpoint and schema, but no environment, credentials, or example values. To make live requests against a simulated vehicle instead, start with [Using the Vehicle Simulator with Postman](/docs/getting-started/using-vs-with-postman). It uses a prebuilt collection and environment, so you can send your first request without wiring anything up.


# Permissions
Source: https://smartcar.com/docs/api-reference/permissions

In order to use an endpoint or webhook, you'll need to request the associated permissions from your user in [Connect](/docs/connect/what-is-connect).

When requesting permissions, it's crucial to only ask for the data that is absolutely necessary for your application's functionality. Avoid collecting additional permissions "just in case" you might need them later. This practice not only protects vehicle owners' privacy but also increases the likelihood of users granting consent during the Connect flow. Users are more likely to trust and authorize applications that clearly demonstrate respect for their privacy by requesting minimal, purposeful access to their vehicle data.

## Vehicle Access

Smartcar's **Vehicle Access** configuration page (Dashboard → Configuration → Vehicle Access) lets you select the *vehicle data* (signals) and *commands* without needing to know which individual permission is needed for a given signal. Based on the signals you choose, Smartcar automatically determines the minimum set of OAuth permissions required and surfaces them during the Connect flow.

<Info>
  **Signals vs Permissions**: Permissions (e.g. `read_location`, `control_security`) are OAuth scopes requested from the user. Signals are the granular data points (e.g. state of charge, tire pressure) defined in the <a href="/api-reference/signals/schema">Signal Schema</a>. Vehicle Access starts from signals and derives the needed permissions for you.
</Info>

### Why use Vehicle Access?

* Enforces least-privilege automatically
* Reduces guesswork mapping data needs to permissions
* Prevents over-requesting and improves user trust
* Keeps configuration centralized in the Dashboard

### How it works

1. You open the Vehicle Access page in the Dashboard.
2. You search or browse for the signals you need (see the <a href="/api-reference/signals/schema">Signal Schema</a> for structure and definitions).
3. Smartcar instantly computes the required permissions for those signals.
4. You save the configuration; the derived permissions are locked in for subsequent Connect authorizations.
5. During Connect, Smartcar presents only those permissions—no need to manually maintain a scope list.

<Note>
  Updating Vehicle Access changes the permissions requested in **future** Connect authorizations. Existing vehicle connections retain their previously granted scopes until the user re-authenticates.
</Note>

<Note>
  Passing the `scope` parameter in the Connect URL overrides the permissions derived from Vehicle Access for that authorization. This allows you to request different permissions for specific Connect flows without changing your overall Vehicle Access configuration.
</Note>

### Example

Selecting signals for battery state of charge, charging status, and odometer will automatically derive permissions such as `read_battery`, `read_charge`, and \`read\_odometer. You don't need to add those manually.

## Required Permissions

Every permission you request appears on the Connect grant screen as a checkbox. You control whether the vehicle owner can uncheck it.

* **Required permissions** appear checked and locked. The owner cannot uncheck them.
* **Optional permissions** appear checked by default. The owner can uncheck them before connecting.

At least one permission must remain selected for the owner to complete the connection.

You can set this per signal in the Dashboard under **Configuration → Vehicle Access** using the **Required** toggle, or per Connect flow by adding the `required:` prefix to a permission in the [`scope` parameter](/docs/connect/redirect-to-connect) (e.g. `required:read_odometer`).

<Frame type="simple">
  <img alt="Smartcar Dashboard Vehicle Access tab with the Required toggle on for External Temperature and off for Internal Temperature." />
</Frame>

<Info>
  Marking a permission as required signals that your application needs it. It does not guarantee the vehicle supports it. If a connected vehicle does not support a permission, calls to that endpoint return a [VEHICLE\_NOT\_CAPABLE](/docs/errors/api-errors/compatibility-errors#vehicle-not-capable) error. To restrict which vehicles can connect by powertrain type, use [Connection Filters](/docs/connect/advanced-config/connection-filters).
</Info>

## Read Permissions

Permissions prefixed with `read_` allow your application to get data from a vehicle as part of `GET` requests.

|                              |                                                                                                                        |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `read_alerts`                | Read alerts from the vehicle                                                                                           |
| `read_battery`               | Read an EV's high voltage battery data                                                                                 |
| `read_charge`                | Read charging data                                                                                                     |
| `read_charge_locations`      | Access previous charging locations and their associated charging configurations                                        |
| `read_charge_records`        | Read charge records and associated billing information                                                                 |
| `read_charge_events`         | Receive notifications for events associated with charging                                                              |
| `read_climate`               | Read the status and settings of the vehicle's climate control system                                                   |
| `read_compass`               | Read the compass direction the vehicle is facing                                                                       |
| `read_diagnostics`           | Read a vehicle's system status and/or Diagnostic Trouble Codes                                                         |
| `read_engine_oil`            | Read vehicle engine oil health                                                                                         |
| `read_extended_vehicle_info` | Read vehicle configuration information from a vehicle                                                                  |
| `read_fuel`                  | Read fuel tank level                                                                                                   |
| `read_location`              | Access the vehicle's location                                                                                          |
| `read_odometer`              | Retrieve total distance traveled                                                                                       |
| `read_security`              | Read the lock status of doors, windows, charging port, etc.                                                            |
| `read_service_history`       | Read a vehicle's dealer service history                                                                                |
| `read_speedometer`           | Read a vehicle's speed                                                                                                 |
| `read_thermometer`           | Read temperatures from inside and outside the vehicle                                                                  |
| `read_tires`                 | Read a vehicle's tire status                                                                                           |
| `read_user_profile`          | Read the information associated with a user's connected services account profile such as their email and phone number. |
| `read_vehicle_info`          | Know make, model, and year                                                                                             |
| `read_vin`                   | Read VIN                                                                                                               |

## Control Permissions

Permissions prefixed with `control_` allow your application to issue commands or apply settings to a vehicle as part of `POST` or `PUT` requests.

|                      |                                                                     |
| -------------------- | ------------------------------------------------------------------- |
| `control_charge`     | Control a vehicle's charge state                                    |
| `control_climate`    | Set the status and settings of the vehicle's climate control system |
| `control_navigation` | Send commands to the vehicle's navigation system                    |
| `control_security`   | Lock or unlock the vehicle                                          |
| `control_pin`        | Modify a PIN and enable the PIN to Drive feature for the vehicle.   |
| `control_trunk`      | Open a vehicle's trunk or frunk                                     |


# Remove connection
Source: https://smartcar.com/docs/api-reference/remove-connection

/specs/full-vehicle.yaml delete /connections/{connectionId}
Delete a specific connection for the application



# Remove subscription
Source: https://smartcar.com/docs/api-reference/remove-subscription

/specs/management.yaml delete /subscriptions/{subscriptionId}
Delete a specific webhook subscription.



# Remove user
Source: https://smartcar.com/docs/api-reference/remove-user

/specs/full-vehicle.yaml delete /users/{userId}
Delete a specific user for the application. All connections and other data is purged.



# Lock doors
Source: https://smartcar.com/docs/api-reference/security/lock-doors

/specs/full-vehicle.yaml post /vehicles/{vehicleId}/commands/security/lock
Locks all vehicle doors



# Unlock doors
Source: https://smartcar.com/docs/api-reference/security/unlock-doors

/specs/full-vehicle.yaml post /vehicles/{vehicleId}/commands/security/unlock
Unlocks all vehicle doors



# Send Destination
Source: https://smartcar.com/docs/api-reference/send-destination-to-vehicle

POST https://api.smartcar.com/v2.0/vehicles/{id}/navigation/destination
Send destination coordinates to the vehicle's navigation system.

<Note>
  Remote commands are now available in [API v3](/docs/api-reference/commands/overview). We recommend using v3 for new command integrations. Commands remain available in v2.0 until it is deprecated.
</Note>

## Permission

`control_navigation`

## Request

**Path**

<Snippet />

**Body**

<ParamField type="number">
  The latitude of the location you wish to set the vehicle's navigation to.
</ParamField>

<ParamField type="number">
  The longitude of the location you wish to set the vehicle's navigation to.
</ParamField>

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="status" type="string">
  If the request is successful, Smartcar will return “success” (HTTP 200 status).
</ResponseField>

<ResponseField name="message" type="string">
  If the request is successful, Smartcar will return a message (HTTP 200 status).
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
      "message": "Successfully sent request to vehicle",
      "status": "success"
  }   
  ```
</ResponseExample>


# Charge Signals
Source: https://smartcar.com/docs/api-reference/signals/charge



### Amperage

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-amperage`

Current amperage flowing to the electric vehicle during a charging session, measured in amps.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 33,
      "unit": "ampere"
    }
    ```
  </Expandable>
</ParamField>

### AmperageMax

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-amperagemax`

The maximum available amps available to charge.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 48,
      "unit": "ampere"
    }
    ```
  </Expandable>
</ParamField>

### AmperageRequested

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-amperagerequested`

The requested amps to charge the vehicle.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 48,
      "unit": "ampere"
    }
    ```
  </Expandable>
</ParamField>

### ChargeLimits

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-chargelimits`

Object containing the default (global) charge limit configuration and configurations based on location, and charging type (AC or DC)

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="array" />

    <Expandable title="Array item properties">
      <ParamField type="string">
        **Possible values:** `GLOBAL`, `LOCATION`, `CHARGING_TYPE`
      </ParamField>

      <ParamField type="number" />

      <ParamField type="object" />

      <Expandable title="condition properties">
        <ParamField type="string" />

        <ParamField type="string" />

        <ParamField type="number" />

        <ParamField type="number" />

        <ParamField type="string" />
      </Expandable>
    </Expandable>

    <ParamField type="number">
      Maximum state of charge (SoC) limit currently configured, expressed as a percentage.
    </ParamField>

    <ParamField type="string" />

    ```json Example theme={null}
    {
      "activeLimit": 80,
      "values": [
        {
          "type": "GLOBAL",
          "limit": 80
        },
        {
          "type": "LOCATION",
          "condition": {
            "name": "Home",
            "address": "123 2nd street",
            "latitude": 90,
            "longitude": 90
          },
          "limit": 72
        },
        {
          "type": "CHARGING_TYPE",
          "condition": {
            "chargingType": "AC"
          },
          "limit": 52
        }
      ],
      "unit": "percent"
    }
    ```
  </Expandable>
</ParamField>

### ChargePortStatusColor

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-chargeportstatuscolor`

Current status indicator color displayed on or around the vehicle's charging port.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    ```json Example theme={null}
    {
      "value": "Green"
    }
    ```
  </Expandable>
</ParamField>

### ChargeRate

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-chargerate`

Current rate at which range is being added to the vehicle during an active charging session

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 48,
      "unit": "km/h"
    }
    ```
  </Expandable>
</ParamField>

### ChargeRecords

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-chargerecords`

Collection of historical charging session data stored by the vehicle.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="array" />

    <Expandable title="Array item properties">
      <ParamField type="string">
        Unique OEM identifier assigned to the specific charging session.
      </ParamField>

      <ParamField type="object" />

      <Expandable title="cost properties">
        <ParamField type="string">
          Three-letter currency code representing the monetary unit used for the charging session transaction.
        </ParamField>

        <ParamField type="number">
          Monetary value representing all non-energy related charges incurred during the charging session.
        </ParamField>

        <ParamField type="number">
          Monetary value representing the cost specifically for the electrical energy consumed during the charging session.
        </ParamField>
      </Expandable>

      <ParamField type="string">
        Timestamp marking when a charging session was completed or terminated.
      </ParamField>

      <ParamField type="object" />

      <Expandable title="location properties">
        <ParamField type="string">
          Descriptive text identifier for the facility or establishment where the charging session occurred.
        </ParamField>

        <ParamField type="string">
          Structured or formatted text representing the physical street address where the charging session took place.
        </ParamField>

        <ParamField type="number">
          Numerical value representing the north-south position of the charging location on Earth's surface.
        </ParamField>

        <ParamField type="number">
          Numerical value representing the east-west position of the charging location on Earth's surface.
        </ParamField>
      </Expandable>

      <ParamField type="string">
        Timestamp marking when a charging session was initiated.
      </ParamField>

      <ParamField type="number">
        Total amount of electrical energy drawn from the charging source during the charging session, measured in kilowatt-hours (kWh).
      </ParamField>

      <ParamField type="string">
        Type of charging used during the recorded charging session.
      </ParamField>

      <ParamField type="boolean">
        Boolean indicator that shows whether the charging session occurred at a public charging station rather than at a private or home charging location.
      </ParamField>

      <ParamField type="number">
        Percentage value indicating the vehicle's battery state of charge (SoC) at the conclusion of a charging session.
      </ParamField>

      <ParamField type="number">
        Percentage value indicating the vehicle's battery state of charge (SoC) at the beginning of a charging session.
      </ParamField>
    </Expandable>

    ```json Example theme={null}
    {
      "values": [
        {
          "startTime": "2023-10-15T19:30:00.000Z",
          "endTime": "2023-10-16T06:45:00.000Z",
          "startStateOfCharge": 25,
          "endStateOfCharge": 90,
          "energyAdded": 65.2,
          "isPublicCharger": false,
          "chargingType": "DC",
          "cost": {
            "currency": "GBP",
            "energyAmount": 12.56,
            "otherAmount": 0
          },
          "location": {
            "latitude": 51.5014,
            "longitude": -0.1419,
            "name": "Home",
            "address": "123 Park Lane, London SW1A 1AA"
          },
          "id": "CHG-20231015-A39B"
        }
      ]
    }
    ```
  </Expandable>
</ParamField>

### ChargerPhases

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-chargerphases`

The number of phases available from the connected charger.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="integer" />

    ```json Example theme={null}
    {
      "value": 3
    }
    ```
  </Expandable>
</ParamField>

### ChargeTimers

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-chargetimers`

Object containing the default (GLOBAL) charge timer configuration and configurations based on location, and charing type (AC or DC)

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="array" />

    <Expandable title="Array item properties">
      <ParamField type="string">
        **Possible values:** `GLOBAL`, `LOCATION`, `CHARGING_TYPE`
      </ParamField>

      <ParamField type="object" />

      <Expandable title="condition properties">
        <ParamField type="string" />

        <ParamField type="string" />

        <ParamField type="number" />

        <ParamField type="number" />

        <ParamField type="string" />
      </Expandable>

      <ParamField type="array" />

      <Expandable title="Array item properties">
        <ParamField type="string" />

        <ParamField type="array" />

        <ParamField type="string" />
      </Expandable>

      <ParamField type="array" />

      <Expandable title="Array item properties">
        <ParamField type="array" />

        <ParamField type="string" />
      </Expandable>

      <ParamField type="boolean" />

      <ParamField type="string" />

      <ParamField type="string">
        **Possible values:** `DAILY`, `WEEKLY`, `WORKWEEK`
      </ParamField>
    </Expandable>

    ```json Example theme={null}
    {
      "values": [
        {
          "type": "GLOBAL",
          "isOEMOptimizationEnabled": true,
          "schedules": [
            {
              "days": [
                "MONDAY",
                "TUESDAY",
                "WEDNESDAY",
                "THURSDAY",
                "FRIDAY"
              ],
              "start": "23:00:00",
              "end": "07:00:00"
            }
          ],
          "departureTimers": [
            {
              "days": [
                "MONDAY",
                "TUESDAY",
                "WEDNESDAY",
                "THURSDAY",
                "FRIDAY"
              ],
              "time": "08:30:00"
            }
          ]
        },
        {
          "type": "LOCATION",
          "condition": {
            "latitude": 51.5014,
            "longitude": -0.1419,
            "name": "Home",
            "address": "123 Main St, London"
          },
          "isOEMOptimizationEnabled": true,
          "schedules": [
            {
              "days": [
                "MONDAY",
                "TUESDAY",
                "WEDNESDAY",
                "THURSDAY",
                "FRIDAY"
              ],
              "start": "22:00:00",
              "end": "06:00:00"
            }
          ],
          "departureTimers": [
            {
              "days": [
                "MONDAY",
                "TUESDAY",
                "WEDNESDAY",
                "THURSDAY",
                "FRIDAY"
              ],
              "time": "08:00:00"
            }
          ],
          "scheduleId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
          "scheduleType": "DAILY"
        },
        {
          "type": "CHARGING_TYPE",
          "condition": {
            "chargingType": "DC"
          },
          "isOEMOptimizationEnabled": true,
          "schedules": [
            {
              "days": [
                "MONDAY",
                "TUESDAY",
                "WEDNESDAY",
                "THURSDAY",
                "FRIDAY"
              ],
              "start": "22:00:00",
              "end": "06:00:00"
            }
          ],
          "departureTimers": [
            {
              "days": [
                "MONDAY",
                "TUESDAY"
              ],
              "time": "08:00:00"
            }
          ]
        }
      ]
    }
    ```
  </Expandable>
</ParamField>

### ChargingConnectorType

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-chargingconnectortype`

Identifier for the type of charging connector/inlet equipped on the vehicle.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    ```json Example theme={null}
    {
      "value": "J1772"
    }
    ```
  </Expandable>
</ParamField>

### DetailedChargingStatus

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-detailedchargingstatus`

String value that provides detailed information about the current state of the charging process.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    ```json Example theme={null}
    {
      "value": "CHARGING"
    }
    ```
  </Expandable>
</ParamField>

### EnergyAdded

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-energyadded`

Cumulative amount of electrical energy delivered to the vehicle during the current or most recent charging session, measured in kilowatt-hours (kWh).

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 35.6,
      "unit": "kWh"
    }
    ```
  </Expandable>
</ParamField>

### FastChargerType

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-fastchargertype`

Identifier for the specific DC fast charging standard currently connected to the vehicle. Indicates the protocol being used for high-power charging

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    ```json Example theme={null}
    {
      "value": "CCS"
    }
    ```
  </Expandable>
</ParamField>

### IsCharging

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-ischarging`

Boolean indicator that shows whether the electric vehicle is actively receiving power from a charging station or outlet.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": true
    }
    ```
  </Expandable>
</ParamField>

### IsChargingCableConnected

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-ischargingcableconnected`

Boolean indicator that shows whether a charging cable is physically connected to the vehicle's charging port.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": true
    }
    ```
  </Expandable>
</ParamField>

### IsChargingCableLatched

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-ischargingcablelatched`

Boolean indicator that shows whether the charging cable is securely locked to the vehicle's charging port.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": true
    }
    ```
  </Expandable>
</ParamField>

### IsChargingPortFlapOpen

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-ischargingportflapopen`

Boolean indicator that shows whether the vehicle's charging port access door or flap is currently open.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": true
    }
    ```
  </Expandable>
</ParamField>

### IsFastChargerPresent

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-isfastchargerpresent`

Boolean indicator that shows whether the vehicle is connected to a DC fast charging station.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": false
    }
    ```
  </Expandable>
</ParamField>

### TimeToComplete

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-timetocomplete`

Estimated time remaining until the charging session reaches the activeLimit in minutes.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 100,
      "unit": "min"
    }
    ```
  </Expandable>
</ParamField>

### Voltage

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-voltage`

Current voltage level being supplied to the electric vehicle during a charging session, measured in volts.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 240,
      "unit": "volts"
    }
    ```
  </Expandable>
</ParamField>

### Wattage

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/charge-wattage`

Current power delivery rate to the electric vehicle during a charging session, measured in watts.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 10.7,
      "unit": "watts"
    }
    ```
  </Expandable>
</ParamField>


# Climate Signals
Source: https://smartcar.com/docs/api-reference/signals/climate



### ExternalTemperature

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/climate-externaltemperature`

The current temperature measured outside the vehicle.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 14.5,
      "unit": "celsius"
    }
    ```
  </Expandable>
</ParamField>

### InternalTemperature

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/climate-internaltemperature`

The current temperature measured inside the vehicle's cabin.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 21,
      "unit": "celsius"
    }
    ```
  </Expandable>
</ParamField>


# Closure Signals
Source: https://smartcar.com/docs/api-reference/signals/closure



### Doors

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/closure-doors`

An object containing information about the vehicle's doors.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="array">
      An array of objects containing information about the state of the vehicle's doors.
    </ParamField>

    <Expandable title="Array item properties">
      <ParamField type="number">
        Represents the row position of a specific door, front to back (0 to Doors.rowCount-1).
      </ParamField>

      <ParamField type="number">
        Represents the column position of a specific door, left to right (0 to Door.ColumnCount-1).
      </ParamField>

      <ParamField type="boolean">
        Indicates if the door is open.
      </ParamField>

      <ParamField type="boolean">
        Indicates if the door is locked.
      </ParamField>
    </Expandable>

    <ParamField type="number">
      Indicates the total number of door rows present in the vehicle. This field, along with columnCount, provides information about the vehicle's door layout and the total number of doors available.
    </ParamField>

    <ParamField type="number">
      Indicates the total number of door columns present in the vehicle. This field, along with rowCount, provides information about the vehicle's door layout and the total number of doors available.
    </ParamField>

    ```json Example theme={null}
    {
      "rowCount": 2,
      "columnCount": 2,
      "doors": [
        {
          "row": 0,
          "column": 0,
          "isOpen": false,
          "isLocked": true
        },
        {
          "row": 0,
          "column": 1,
          "isOpen": false,
          "isLocked": true
        },
        {
          "row": 1,
          "column": 0,
          "isOpen": false,
          "isLocked": true
        },
        {
          "row": 1,
          "column": 1,
          "isOpen": false,
          "isLocked": true
        }
      ]
    }
    ```
  </Expandable>
</ParamField>

### EngineCover

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/closure-enginecover`

An object containing information about the state of the vehicle's engine cover for ICE or PHEV vehicles.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean">
      Indicates if the trunk is open.
    </ParamField>

    ```json Example theme={null}
    {
      "isOpen": false
    }
    ```
  </Expandable>
</ParamField>

### FrontTrunk

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/closure-fronttrunk`

An object containing information about the state of the vehicle's front trunk.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean">
      Indicates if the trunk is open.
    </ParamField>

    <ParamField type="boolean">
      Indicates if the trunk is locked.
    </ParamField>

    ```json Example theme={null}
    {
      "isLocked": true,
      "isOpen": false
    }
    ```
  </Expandable>
</ParamField>

### IsLocked

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/closure-islocked`

A boolean value indicating whether the vehicle's closures are currently locked.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": true
    }
    ```
  </Expandable>
</ParamField>

### RearTrunk

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/closure-reartrunk`

An object containing information about the state of the vehicle's rear trunk.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean">
      Indicates if the trunk is open.
    </ParamField>

    <ParamField type="boolean">
      Indicates if the trunk is locked.
    </ParamField>

    ```json Example theme={null}
    {
      "isLocked": true,
      "isOpen": false
    }
    ```
  </Expandable>
</ParamField>

### Sunroof

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/closure-sunroof`

An object containing information about the state of the vehicle's sunroof.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean">
      Indicates if the trunk is open.
    </ParamField>

    ```json Example theme={null}
    {
      "isOpen": false
    }
    ```
  </Expandable>
</ParamField>

### Tailgate

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/closure-tailgate`

An object containing information about the state of the vehicle's tailgate.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean">
      Indicates if the tailgate is open.
    </ParamField>

    <ParamField type="boolean">
      Indicates if the tailgate is locked.
    </ParamField>

    ```json Example theme={null}
    {
      "isLocked": true,
      "isOpen": false
    }
    ```
  </Expandable>
</ParamField>

### Windows

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/closure-windows`

An object containing information about the vehicle's windows.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="array">
      An array of objects, where each object represents a specific window in the vehicle.
    </ParamField>

    <Expandable title="Array item properties">
      <ParamField type="number">
        Represents the row position of a specific window, front to back (0 to Windows.rowCount-1).
      </ParamField>

      <ParamField type="number">
        Represents the column position of a specific window, left to right (0 to Windows.columnCount-1).
      </ParamField>

      <ParamField type="boolean">
        Indicates if the window is open.
      </ParamField>
    </Expandable>

    <ParamField type="number">
      Indicates the total number of window rows present in the vehicle. This field, along with columnCount, provides information about the vehicle's window layout and the total number of windows available.
    </ParamField>

    <ParamField type="number">
      Indicates the total number of window columns present in the vehicle. This field, along with rowCount, provides information about the vehicle's window layout and the total number of windows available.
    </ParamField>

    ```json Example theme={null}
    {
      "rowCount": 2,
      "columnCount": 2,
      "windows": [
        {
          "row": 0,
          "column": 0,
          "isOpen": false
        },
        {
          "row": 0,
          "column": 1,
          "isOpen": false
        },
        {
          "row": 1,
          "column": 0,
          "isOpen": false
        },
        {
          "row": 1,
          "column": 1,
          "isOpen": false
        }
      ]
    }
    ```
  </Expandable>
</ParamField>


# ConnectivitySoftware Signals
Source: https://smartcar.com/docs/api-reference/signals/connectivitysoftware



### CurrentFirmwareVersion

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/connectivitysoftware-currentfirmwareversion`

Current version number of the firmware installed on the vehicle's telematics control unit or connected hardware.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    ```json Example theme={null}
    {
      "value": "2022.8.10.12"
    }
    ```
  </Expandable>
</ParamField>


# ConnectivityStatus Signals
Source: https://smartcar.com/docs/api-reference/signals/connectivitystatus



### IsAsleep

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/connectivitystatus-isasleep`

Boolean indicator that shows whether the vehicle is in a low-power or sleep state.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": false
    }
    ```
  </Expandable>
</ParamField>

### IsDigitalKeyPaired

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/connectivitystatus-isdigitalkeypaired`

Boolean indicator that shows whether a digital key has been successfully paired with the vehicle. Currently required for Tesla

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": false
    }
    ```
  </Expandable>
</ParamField>

### IsOnline

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/connectivitystatus-isonline`

Boolean indicator that shows the connectivity status of the vehicle.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": true
    }
    ```
  </Expandable>
</ParamField>


# Diagnostics Signals
Source: https://smartcar.com/docs/api-reference/signals/diagnostics



### ABS

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-abs`

A diagnostic category representing the Anti-lock Braking System (ABS).

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### ActiveSafety

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-activesafety`

Encompasses the vehicle's advanced safety technologies designed to prevent or mitigate potential accidents.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### Airbag

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-airbag`

The system that monitors the vehicle's airbag readiness and functionality.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### BrakeFluid

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-brakefluid`

The system that monitors the vehicle's brake fluid condition and levels.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### DriverAssistance

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-driverassistance`

The system that monitors the vehicle's advanced driver assistance technologies.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### DTCCount

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-dtccount`

The total number of active Diagnostic Trouble Codes (DTCs) currently present in the vehicle's systems.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="integer" />

    ```json Example theme={null}
    {
      "value": 5
    }
    ```
  </Expandable>
</ParamField>

### DTCList

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-dtclist`

An array containing detailed information about each active Diagnostic Trouble Code (DTC) in the vehicle.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="array">
      Array of Diagnostic Trouble Code (DTC) entries.
    </ParamField>

    <Expandable title="Array item properties">
      <ParamField type="string">
        The specific alphanumeric code identifying a particular diagnostic trouble code (DTC).
      </ParamField>

      <ParamField type="string">
        The precise date and time when the specific diagnostic trouble code (DTC) was first detected or logged by the vehicle's onboard diagnostic system.
      </ParamField>
    </Expandable>

    ```json Example theme={null}
    {
      "values": [
        {
          "code": "P302D",
          "timestamp": "2024-09-05T14:48:00.000Z"
        }
      ]
    }
    ```
  </Expandable>
</ParamField>

### Emissions

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-emissions`

The system that monitors the vehicle's exhaust emissions and pollution control mechanisms.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### EVBatteryConditioning

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-evbatteryconditioning`

The system that monitors the electric vehicle's high-voltage battery thermal management and conditioning.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### EVCharging

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-evcharging`

The system that monitors the electric vehicle's charging processes and infrastructure.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### EVDriveUnit

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-evdriveunit`

The system that monitors the electric vehicle's drive unit performance and functionality.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### EVHVBattery

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-evhvbattery`

The system that monitors the electric vehicle's high-voltage battery health and performance.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### Lighting

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-lighting`

The system that monitors the vehicle's exterior and interior lighting functionality.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### MIL

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-mil`

The system that monitors the vehicle's Malfunction Indicator Lamp (MIL) status.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### OilLife

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-oillife`

The system that monitors the vehicle's engine oil condition and remaining useful life.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### OilPressure

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-oilpressure`

The system that monitors the vehicle's engine oil pressure and lubrication system performance.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### OilTemperature

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-oiltemperature`

The system that monitors the vehicle's engine oil temperature and thermal conditions.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### Telematics

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-telematics`

The system that monitors a vehicle's connectivity

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### TirePressure

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-tirepressure`

The system that monitors tire pressure levels

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### TirePressureMonitoring

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-tirepressuremonitoring`

The status of the tire pressure monitoring system.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### Transmission

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-transmission`

The system that monitors the vehicle's transmission

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### WasherFluid

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-washerfluid`

The system that monitors the vehicle's washer fluid reservoir

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>

### WaterInFuel

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/diagnostics-waterinfuel`

The system that monitors the presence of water in the vehicle's fuel system

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      A ENUM indicating the current operational condition of the related system. (ALERT, OK)

      **Possible values:** `ALERT`, `OK`
    </ParamField>

    <ParamField type="string">
      A description of the system's status, if provided by the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "status": "OK",
      "description": ""
    }
    ```
  </Expandable>
</ParamField>


# HVAC Signals
Source: https://smartcar.com/docs/api-reference/signals/hvac



### CabinTargetTemperature

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/hvac-cabintargettemperature`

The target temperature set for the vehicle's cabin.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 22.5,
      "unit": "celsius"
    }
    ```
  </Expandable>
</ParamField>

### IsCabinHVACActive

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/hvac-iscabinhvacactive`

A boolean value indicating if the cabin HVAC system is active.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": true
    }
    ```
  </Expandable>
</ParamField>

### IsFrontDefrosterActive

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/hvac-isfrontdefrosteractive`

A boolean value indicating if the front windshield defroster is active.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": true
    }
    ```
  </Expandable>
</ParamField>

### IsRearDefrosterActive

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/hvac-isreardefrosteractive`

A boolean value indicating if the rear windshield defroster is active.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": true
    }
    ```
  </Expandable>
</ParamField>

### IsSteeringHeaterActive

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/hvac-issteeringheateractive`

A boolean value indicating if the steering wheel heater is active.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": false
    }
    ```
  </Expandable>
</ParamField>


# InternalCombustionEngine Signals
Source: https://smartcar.com/docs/api-reference/signals/internalcombustionengine



### AmountRemaining

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/internalcombustionengine-amountremaining`

The quantity of fuel remaining in the vehicle's tank

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 42.5,
      "unit": "liters"
    }
    ```
  </Expandable>
</ParamField>

### FuelLevel

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/internalcombustionengine-fuellevel`

The current amount of fuel in the vehicle's tank, expressed as a percentage (0 - 100)

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 65,
      "unit": "percent"
    }
    ```
  </Expandable>
</ParamField>

### OilLife

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/internalcombustionengine-oillife`

The engine oil’s remaining life span based on the current quality of the oil, expressed as a percentage. 100 indicates the oil was changed recently and 0 indicates the oil should be changed immediately. It is not a representation of how much oil is left in the vehicle.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 72,
      "unit": "percent"
    }
    ```
  </Expandable>
</ParamField>

### Range

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/internalcombustionengine-range`

The estimated driving distance possible with the current amount of fuel

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 385,
      "unit": "km"
    }
    ```
  </Expandable>
</ParamField>


# Location Signals
Source: https://smartcar.com/docs/api-reference/signals/location



### IsAtHome

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/location-isathome`

A boolean indicating if the vehicle is at home. Vehicle owners can set their home location in their OEM application.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": true
    }
    ```
  </Expandable>
</ParamField>

### PreciseLocation

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/location-preciselocation`

An object containing information about a vehicle's precise location.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="number">
      The precise angular heading of the vehicle.
    </ParamField>

    <ParamField type="number">
      The vehicle's current geographic latitude coordinate.
    </ParamField>

    <ParamField type="string">
      A cardinal or intercardinal direction representing the vehicle's current heading or orientation.

      **Possible values:** `N`, `NE`, `E`, `SE`, `S`, `SW`, `W`, `NW`
    </ParamField>

    <ParamField type="number">
      The vehicle's current geographic longitude coordinate.
    </ParamField>

    <ParamField type="string">
      Indicates whether the location-related fields are expected to update in real time or when the vehicle is parked.

      **Possible values:** `LAST_PARKED`, `CURRENT`
    </ParamField>

    ```json Example theme={null}
    {
      "latitude": 51.5014,
      "longitude": -0.1419,
      "direction": "NE",
      "heading": 45.3,
      "locationType": "CURRENT"
    }
    ```
  </Expandable>
</ParamField>


# LowVoltageBattery Signals
Source: https://smartcar.com/docs/api-reference/signals/lowvoltagebattery



### StateOfCharge

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/lowvoltagebattery-stateofcharge`

Indicates the current charge level of the low voltage battery as a percentage (0 - 100)

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 95,
      "unit": "percent"
    }
    ```
  </Expandable>
</ParamField>

### Status

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/lowvoltagebattery-status`

Represents the current operational status of the low voltage battery. (GOOD, WARN, BAD)

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    ```json Example theme={null}
    {
      "value": "GOOD"
    }
    ```
  </Expandable>
</ParamField>


# Motion Signals
Source: https://smartcar.com/docs/api-reference/signals/motion



### CurrentSpeed

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/motion-currentspeed`

The vehicle's current driving speed, or 0 if it is not currently driving.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 37,
      "unit": "km/h"
    }
    ```
  </Expandable>
</ParamField>


# Odometer Signals
Source: https://smartcar.com/docs/api-reference/signals/odometer



### TraveledDistance

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/odometer-traveleddistance`

The total distance the vehicle has traveled since its initial use

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 78432,
      "unit": "km"
    }
    ```
  </Expandable>
</ParamField>


# Smartcar Signals & Attributes Overview
Source: https://smartcar.com/docs/api-reference/signals/schema

Smartcar's standard list of vehicle signals and attributes across all compatible OEMs.

Below are the list of signals and attributes supported by Smartcar.

## Attributes

Attributes are static vehicle data that typically does not change in value.
Smartcar will include `make`, `model`, `year`, `mode`, and `powertrainType` in every API response and webhook delivery.
You can retrieve vehicle attributes using the [Get vehicle](/docs/api-reference/get-vehicle) endpoint.

## Signals

With Smartcar you can configure your application to receive a webhook when the value of any of these signals change. Some change more frequently than others.

Below you will find the signal groups and their respective signals. Each signal has a code that you can use to \[request the latest value] for that signal.

* [Charge](/docs/api-reference/signals/charge)
* [Climate](/docs/api-reference/signals/climate)
* [Closure](/docs/api-reference/signals/closure)
* [ConnectivitySoftware](/docs/api-reference/signals/connectivitysoftware)
* [ConnectivityStatus](/docs/api-reference/signals/connectivitystatus)
* [Diagnostics](/docs/api-reference/signals/diagnostics)
* [HVAC](/docs/api-reference/signals/hvac)
* [InternalCombustionEngine](/docs/api-reference/signals/internalcombustionengine)
* [Location](/docs/api-reference/signals/location)
* [LowVoltageBattery](/docs/api-reference/signals/lowvoltagebattery)
* [Motion](/docs/api-reference/signals/motion)
* [Odometer](/docs/api-reference/signals/odometer)
* [Service](/docs/api-reference/signals/service)
* [Surveillance](/docs/api-reference/signals/surveillance)
* [TractionBattery](/docs/api-reference/signals/tractionbattery)
* [Transmission](/docs/api-reference/signals/transmission)
* [VehicleIdentification](/docs/api-reference/signals/vehicleidentification)
* [VehicleUserAccount](/docs/api-reference/signals/vehicleuseraccount)
* [Wheel](/docs/api-reference/signals/wheel)

***

## Next Steps

Now that you know what vehicle data is available, learn how to receive it in your application:

<CardGroup>
  <Card title="Webhooks (Recommended)" icon="webhook" href="/integrations/webhooks/overview">
    Real-time vehicle data pushed to your application
  </Card>

  <Card title="REST API" icon="code" href="/api-reference/intro">
    Request vehicle data on-demand via HTTP requests
  </Card>

  <Card title="Integration Overview" icon="book" href="/getting-started/integration-overview">
    Compare webhooks vs REST API to choose the right approach
  </Card>

  <Card title="Check Compatibility" icon="car" href="/api-reference/compatibility-api-intro">
    See which vehicles support specific signals
  </Card>
</CardGroup>


# Service Signals
Source: https://smartcar.com/docs/api-reference/signals/service



### IsInService

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/service-isinservice`

A boolean that Indicates if the vehicle is currently in service

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": true
    }
    ```
  </Expandable>
</ParamField>

### Records

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/service-records`

An array containing records of service that has been performed on the vehicle.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="array">
      An array of service records.
    </ParamField>

    <Expandable title="Array item properties">
      <ParamField type="string">
        A unique identifier for the service record.
      </ParamField>

      <ParamField type="object">
        The monetary amount billed by the service provider for the service.
      </ParamField>

      <Expandable title="cost properties">
        <ParamField type="number">
          The numerical portion of the amount.
        </ParamField>

        <ParamField type="string">
          The currency for the amount.
        </ParamField>
      </Expandable>

      <ParamField type="string">
        The timestamp of when the service occurred.
      </ParamField>

      <ParamField type="array">
        An array containing information about tasks performed as part of the service.
      </ParamField>

      <Expandable title="Array item properties">
        <ParamField type="string">
          A unique identifier for the task.
        </ParamField>

        <ParamField type="string">
          A description of the task that was performed.
        </ParamField>
      </Expandable>

      <ParamField type="array">
        An array containing additional details about the service.
      </ParamField>

      <Expandable title="Array item properties">
        <ParamField type="string">
          A unique identifier for the additional detail item.
        </ParamField>

        <ParamField type="string">
          A text string describing the additional detail item.
        </ParamField>
      </Expandable>

      <ParamField type="number">
        The vehicle's odometer at the time of the service.
      </ParamField>
    </Expandable>

    ```json Example theme={null}
    {
      "values": [
        {
          "id": "SVC-20230427-001",
          "time": 1682591400000,
          "odometer": 45231,
          "tasks": [
            {
              "id": "task-001",
              "description": "Oil change"
            }
          ],
          "details": [
            {
              "id": "detail-001",
              "description": "Used synthetic oil"
            }
          ],
          "cost": {
            "currency": "USD",
            "amount": 349.95
          }
        }
      ]
    }
    ```
  </Expandable>
</ParamField>


# Surveillance Signals
Source: https://smartcar.com/docs/api-reference/signals/surveillance



### Brand

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/surveillance-brand`

Indicates the brand of surveillance available on the vehicle e.g. for Tesla this would be Sentry Mode

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    ```json Example theme={null}
    {
      "value": "SentryMode"
    }
    ```
  </Expandable>
</ParamField>

### IsEnabled

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/surveillance-isenabled`

Indicates if the surveillance system is enabled

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": true
    }
    ```
  </Expandable>
</ParamField>


# TractionBattery Signals
Source: https://smartcar.com/docs/api-reference/signals/tractionbattery



### IsHeaterActive

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/tractionbattery-isheateractive`

A boolean flag indicating whether the high voltage battery's heating system is currently operating.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="boolean" />

    ```json Example theme={null}
    {
      "value": false
    }
    ```
  </Expandable>
</ParamField>

### MaxRangeChargeCounter

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/tractionbattery-maxrangechargecounter`

A counter tracking the number of times the vehicle has been charged to its maximum range capacity.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="integer" />

    ```json Example theme={null}
    {
      "value": 42
    }
    ```
  </Expandable>
</ParamField>

### NominalCapacity

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/tractionbattery-nominalcapacity`

An object containing the gross battery capacity and a list of multiple available gross capacity configurations for the high voltage battery.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      Identifies the origin or method used to determine the battery's gross capacity.

      **Possible values:** `SMARTCAR`, `USER_SELECTED`
    </ParamField>

    <ParamField type="number">
      The total gross energy storage capacity of the high voltage battery, typically measured in kilowatt-hours (kWh).
    </ParamField>

    <ParamField type="array">
      An array containing multiple available gross capacity configurations for the high voltage battery.
    </ParamField>

    <Expandable title="Array item properties">
      <ParamField type="number">
        The total gross energy storage capacity of the high voltage battery, typically measured in kilowatt-hours (kWh).
      </ParamField>

      <ParamField type="string">
        A description of the specific battery capacity configuration, usually the trim of the vehicle.
      </ParamField>
    </Expandable>

    <ParamField type="string" />

    ```json Example theme={null}
    {
      "source": "SMARTCAR",
      "capacity": 75,
      "availableCapacities": [
        {
          "capacity": 55,
          "description": "Standard Range"
        },
        {
          "capacity": 75,
          "description": "Long Range"
        },
        {
          "capacity": 100,
          "description": "Performance"
        }
      ],
      "unit": "kWh"
    }
    ```
  </Expandable>
</ParamField>

### Range

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/tractionbattery-range`

Returns the most accurate real world estimate that is available. Estimated > Ideal > Rated.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      **Possible values:** `DEFAULT`
    </ParamField>

    <ParamField type="number" />

    <ParamField type="array" />

    <Expandable title="Array item properties">
      <ParamField type="string">
        **Possible values:** `IDEAL_CONDITIONS`, `ESTIMATED`, `RATED`
      </ParamField>

      <ParamField type="number" />
    </Expandable>

    <ParamField type="string" />

    ```json Example theme={null}
    {
      "value": 123.45,
      "type": "DEFAULT",
      "additionalValues": [
        {
          "type": "IDEAL_CONDITIONS",
          "value": 150
        },
        {
          "type": "ESTIMATED",
          "value": 140.75
        },
        {
          "type": "RATED",
          "value": 130.25
        }
      ],
      "unit": "km"
    }
    ```
  </Expandable>
</ParamField>

### StateOfCharge

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/tractionbattery-stateofcharge`

The current charge level of the high voltage battery, expressed as a percentage (0 - 100).

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    <ParamField type="number" />

    ```json Example theme={null}
    {
      "value": 78,
      "unit": "percent"
    }
    ```
  </Expandable>
</ParamField>


# Transmission Signals
Source: https://smartcar.com/docs/api-reference/signals/transmission



### DriveMode

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/transmission-drivemode`

Represents the current drive mode selected in the vehicle's transmission system

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      Normalized drive mode value for cross-OEM consistency.

      **Possible values:** `ECONOMY`, `NORMAL`, `SPORT`, `SNOW`, `TOW`, `OFF_ROAD`
    </ParamField>

    <ParamField type="string">
      Human-readable OEM-specific drive mode label, if available.
    </ParamField>

    ```json Example theme={null}
    {
      "canonical": "NORMAL",
      "oemDisplayName": "everyday"
    }
    ```
  </Expandable>
</ParamField>

### GearState

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/transmission-gearstate`

The current gear selection of the vehicle's transmission.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string">
      The current gear selection of the vehicle's transmission.

      **Possible values:** `PARK`, `DRIVE`, `REVERSE`, `NEUTRAL`
    </ParamField>

    ```json Example theme={null}
    {
      "value": "DRIVE"
    }
    ```
  </Expandable>
</ParamField>


# VehicleIdentification Signals
Source: https://smartcar.com/docs/api-reference/signals/vehicleidentification



### ExteriorColor

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/vehicleidentification-exteriorcolor`

The exterior paint color of the vehicle as specified by the manufacturer.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    ```json Example theme={null}
    {
      "value": "SolidBlack"
    }
    ```
  </Expandable>
</ParamField>

### Nickname

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/vehicleidentification-nickname`

Name personally assigned by the vehicle by the owner.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    ```json Example theme={null}
    {
      "value": "QueenLiz"
    }
    ```
  </Expandable>
</ParamField>

### Packages

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/vehicleidentification-packages`

Optional feature sets or bundle of accessories installed on the vehicle beyond the standard trim level.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="array" />

    ```json Example theme={null}
    {
      "values": [
        "Base",
        "MY2021"
      ]
    }
    ```
  </Expandable>
</ParamField>

### Trim

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/vehicleidentification-trim`

Trim level of the vehicle that indicates the specific variant within a model line.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    ```json Example theme={null}
    {
      "value": "100D"
    }
    ```
  </Expandable>
</ParamField>

### VIN

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/vehicleidentification-vin`

Vehicle Identification Number - A unique 17-character alphanumeric code assigned to each vehicle that serves as its identifier. Contains encoded information about the vehicle's manufacturer, model, features, and production details.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    ```json Example theme={null}
    {
      "value": "5YJSA1CN5DFP00101"
    }
    ```
  </Expandable>
</ParamField>


# VehicleUserAccount Signals
Source: https://smartcar.com/docs/api-reference/signals/vehicleuseraccount



### Permissions

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/vehicleuseraccount-permissions`

Permissions granted by the connecting account with the OEM. These may be different than your application's Smartcar permissions as they can be managed directly with the OEM.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="array">
      An array containing permissions granted by the connecting account with the OEM.
    </ParamField>

    ```json Example theme={null}
    {
      "values": [
        "vehicle_cmds",
        "vehicle_device_data"
      ]
    }
    ```
  </Expandable>
</ParamField>

### Role

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/vehicleuseraccount-role`

Indicates the access level to the vehicle for the connecting account as defined by the OEM. While the OEM representation may vary, these can be thought of as "secondary" and "primary" accounts where "secondary" accounts may have more limited access than an "primary" account. "secondary" accounts are granted access to vehicle by "primary" accounts.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    ```json Example theme={null}
    {
      "value": "Driver"
    }
    ```
  </Expandable>
</ParamField>


# Wheel Signals
Source: https://smartcar.com/docs/api-reference/signals/wheel



### Style

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/wheel-style`

Wheel style of the vehicle.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="string" />

    ```json Example theme={null}
    {
      "value": "Apollo"
    }
    ```
  </Expandable>
</ParamField>

### Tires

<Badge>GET</Badge> `/vehicles/{vehicleId}/signals/wheel-tires`

An array of objects, where each object represents a specific wheel on the vehicle.

<ParamField type="object">
  <Expandable title="body properties">
    <ParamField type="array">
      An array of objects containing information about the vehicle's wheels.
    </ParamField>

    <Expandable title="Array item properties">
      <ParamField type="number">
        Represents the row position of a specific wheel, front to back (0 to Wheels.rowCount-1).
      </ParamField>

      <ParamField type="number">
        Represents the column position of a specific wheel, left to right (0 to Wheels.columnCount-1).
      </ParamField>

      <ParamField type="number">
        Indicates the current tire pressure of the wheel.
      </ParamField>
    </Expandable>

    <ParamField type="number">
      Indicates the total number of wheel rows present in the vehicle. This signal, along with WheelColumnCount, provides information about the vehicle's wheel layout and the total number of wheels available.
    </ParamField>

    <ParamField type="number">
      Indicates the total number of wheel columns present in the vehicle. This signal, along with WheelRowCount, provides information about the vehicle's wheel layout and the total number of wheels available.
    </ParamField>

    <ParamField type="string" />

    ```json Example theme={null}
    {
      "rowCount": 2,
      "columnCount": 2,
      "values": [
        {
          "row": 0,
          "column": 0,
          "tirePressure": 32
        },
        {
          "row": 0,
          "column": 1,
          "tirePressure": 32
        },
        {
          "row": 1,
          "column": 0,
          "tirePressure": 35
        },
        {
          "row": 1,
          "column": 1,
          "tirePressure": 35
        }
      ],
      "unit": "kPa"
    }
    ```
  </Expandable>
</ParamField>


# Charge Port
Source: https://smartcar.com/docs/api-reference/tesla/control-charge-port

POST https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/charge_port_door
Open or close the vehicle's charge port door.

<Snippet />

## Permission

`control_charge`

## Request

**Path**

<Snippet />

**Body**

<ParamField type="string">
  Indicate whether to open or close the charge port door.
  Options: `OPEN` or `CLOSE`
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/charge_port_door" \
  -H "Authorization: Bearer {token}" \
  -X "POST" \
  -H "Content-Type: application/json" \
  -d '{"action" : "OPEN"}'
  ```

  ```python Python theme={null}
  charge_port = vehicle.request(
    "POST", 
    "{make}/charge/charge_port_door", 
    {"action" : "OPEN"}
  )
  ```

  ```js Node theme={null}
  const chargePort = vehicle.request(
    "POST", 
    "{make}/charge/charge_port_door", 
    {"action" : "OPEN"}
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("POST")
        .path("{make}/charge/charge_port_door")
        .addBodyParameter("action" : "OPEN")
        .build();
  VehicleResponse chargePort =  vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  charge_port =  vehicle.request(
    "POST", 
    "{make}/charge/charge_port_door", 
    {"action" : "OPEN"}
  )
  ```
</RequestExample>

## Response

<ResponseField name="status" type="string">
  If the request is successful, Smartcar will return “success”.
</ResponseField>

<ResponseField name="message" type="string">
  If the request is successful, Smartcar will return a message.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
      {
          "message": "Successfully sent request to vehicle",
          "status": "success"
      }   
  ```
</ResponseExample>


# Tesla: Battery Status
Source: https://smartcar.com/docs/api-reference/tesla/get-battery

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/battery
Returns all battery related data for a Tesla vehicle.

<Snippet />

<Warning>
  The following fields are not supported for streaming vehicles:

  * TeslaBatteryPercentRemainingUsable
  * TeslaBatteryMaxRangeChargeCounter
</Warning>

## Permission

`read_battery`

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/battery" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  battery =  vehicle.request(
        "GET", 
        "{make}/battery"
  )
  ```

  ```js Node theme={null}
  const battery =  await vehicle.request(
        "GET", 
        "{make}/battery"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/battery")
        .build();
  VehicleResponse battery = vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  battery =  vehicle.request(
        "GET", 
        "{make}/battery"
  )
  ```
</RequestExample>

## Request

**Path**

<Snippet />

## Response

<ResponseField name="percentRemaining" type="number | null">
  The EV’s state of charge as a percentage.
</ResponseField>

<ResponseField name="range" type="number | null">
  The distance the vehicle can travel powered by it’s high voltage battery.
</ResponseField>

<ResponseField name="heaterOn" type="bool | null">
  Indicates if the battery heater is on.
</ResponseField>

<ResponseField name="rangeEstimated" type="number | null">
  The estimated remaining distance the vehicle can travel powered by it’s high voltage battery as determined by Tesla.
</ResponseField>

<ResponseField name="rangeIdeal" type="number | null">
  The ideal remaining distance the vehicle can travel powered by it’s high voltage battery as determined by Tesla.
</ResponseField>

<ResponseField name="percentRemainingUsable" type="number | null">
  The EV’s useable state of charge as a percentage as reported by Tesla.
</ResponseField>

<ResponseField name="maxRangeChargeCounter" type="number | null">
  The number of times the vehicle has been charged to 100% as reported by Tesla.
</ResponseField>

<ResponseField name="notEnoughPowerToHeat" type="bool | null">
  Indicates if there is enough power to heat the battery.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
      "heaterOn": null,
      "maxRangeChargeCounter" : null,
      "notEnoughPowerToHeat" : true, 
      "percentRemaining": 0.3,
      "percentRemainingUsable" : 0.29,
      "range": 40.5,
      "rangeEstimated": 39.01,
      "rangeIdeal" : 40.5
  }
  ```
</ResponseExample>


# Cabin Climate
Source: https://smartcar.com/docs/api-reference/tesla/get-cabin

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/climate/cabin
Returns the current state and target temperature setting of a vehicle's cabin climate system.

<Snippet />

## Permission

`read_climate`

## Request

**Path**

<Snippet />

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/climate/cabin" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  cabin = vehicle.request(
        "GET", 
        "{make}/climate/cabin"
  )
  ```

  ```js Node theme={null}
  const chargeCompletion = await vehicle.request(
        "GET", 
        "{make}/climate/cabin"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/climate/cabin")
        .build();
  VehicleResponse chargeCompletion = vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  chargeCompletion = vehicle.request(
        "GET", 
        "{make}/climate/cabin"
  )
  ```
</RequestExample>

## Response

<ResponseField name="status" type="string">
  The current state of the climate cabin system.
</ResponseField>

<ResponseField name="temperature" type="number">
  The target temperature setting of the vehicle when the climate system is on (in Celsius by default or in Fahrenheit using the sc-unit-system).
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
  {
    "status": "ON",
    "temperature": 20
  }
  ```
</ResponseExample>


# Tesla: Charge Status
Source: https://smartcar.com/docs/api-reference/tesla/get-charge

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge
Returns all charging related data for a Tesla vehicle.

<Snippet />

<Warning>
  The following fields are not supported for streaming vehicles:

  * TeslaChargeRangeAddedRated
  * TeslaChargeRangeAddedIdeal
  * TeslaChargeChargeRate
  * TeslaChargeAmperageMaxCharger
  * TeslaChargeChargePortColor
</Warning>

## Permission

`read_charge`

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  charge =  vehicle.request(
        "GET", 
        "{make}/charge"
  )
  ```

  ```js Node theme={null}
  const charge =  await vehicle.request(
        "GET", 
        "{make}/charge"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/charge")
        .build();
  VehicleResponse charge =  vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  charge =  vehicle.request(
        "GET", 
        "{make}/charge"
  )
  ```
</RequestExample>

## Request

**Path**

<Snippet />

## Response

<ResponseField name="amperage" type="number | null">
  The rate that the vehicle is charging at (in amperes).
</ResponseField>

<ResponseField name="completionTime" type="string | null">
  An ISO8601 formatted datetime (YYYY-MM-DDTHH:mm:ss.SSSZ) for the time at which the vehicle expects to complete this charging session.
</ResponseField>

<ResponseField name="wattage" type="number | null">
  The instant power measured by the vehicle (in kilowatts).
</ResponseField>

<ResponseField name="isPluggedIn" type="bool | null">
  Indicates if the vehicle is plugged in
</ResponseField>

<ResponseField name="state" type="string | null">
  Indicates the charging status of the vehicle
</ResponseField>

<ResponseField name="socLimit" type="number | null">
  Indicates the level at which the vehicle will stop charging and be considered fully charged as a percentage.
</ResponseField>

<ResponseField name="amperageMaxVehicle" type="number | null">
  Indicates the max amperage the vehicle can request from the charger.
</ResponseField>

<ResponseField name="socLimitMax" type="number | null">
  Indicates the max SoC limit that can be set.
</ResponseField>

<ResponseField name="socLimitMin" type="number | null">
  Indicates the min SoC limit that can be set.
</ResponseField>

<ResponseField name="socLimitDefault" type="number | null">
  Indicates the default SoC limit of the vehicle.
</ResponseField>

<ResponseField name="amperageRequested" type="number | null">
  Indicates the amperage requested from the charger by the vehicle.
</ResponseField>

<ResponseField name="energyAdded" type="number | null">
  Energy added in the current charging session or most recent session if the vehicle is not charging (in kilowatts).
</ResponseField>

<ResponseField name="rangeAddedRated" type="number | null">
  The rated range as determined by Tesla added in the current charging session or most recent session if the vehicle is not charging (in kilometers added).
</ResponseField>

<ResponseField name="rangeAddedIdeal" type="number | null">
  The ideal range as determined by Tesla added in the current charging session or most recent session if the vehicle is not charging (in kilometers added).
</ResponseField>

<ResponseField name="chargeRate" type="number | null">
  The rate of range added in the charging session (in kilometers added / hour).
</ResponseField>

<ResponseField name="connector" type="string | null">
  Standard of the connector e.g. SAE
</ResponseField>

<ResponseField name="fastChargerPresent" type="bool | null">
  When charging, indicates if the vehicle connected to a fast charger.
</ResponseField>

<ResponseField name="fastChargerType" type="string | null">
  Indicates the type of fast charger.
</ResponseField>

<ResponseField name="fastChargerBrand" type="string | null">
  Indicates the brand of fast charger.
</ResponseField>

<ResponseField name="amperageMaxCharger" type="number | null">
  Indicates the max amperage supported by the charger.
</ResponseField>

<ResponseField name="chargePortColor" type="string | null">
  The indicator light color of the connector.
</ResponseField>

<ResponseField name="chargePortOpen" type="bool | null">
  Indicates if th charge port door is open.
</ResponseField>

<ResponseField name="chargePortLatch" type="string | null">
  Indicates if the charge port latch status.
</ResponseField>

<ResponseField name="chargerPhases" type="number | null">
  Indicates the charging phase.
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
      {
            "amperage": 0,
            "completionTime": null,
            "wattage": 0,
            "voltage": 1,
            "isPluggedIn": false,
            "state": "NOT_CHARGING",
            "socLimit": 0.8,
            "amperageMaxVehicle": 48,
            "socLimitMax": 1,
            "socLimitMin": 0.5,
            "socLimitDefault": 0.8,
            "amperageRequested": 48,
            "energyAdded": 11.52,
            "rangeAddedRated": 70.811,
            "rangeAddedIdeal": 70.811,
            "chargeRate": 0,
            "connector": "<invalid>",
            "fastChargerPresent": false,
            "fastChargerType": "<invalid>",
            "fastChargerBrand": "<invalid>",
            "amperageMaxCharger": 48,
            "chargePortColor": "<invalid>",
            "chargePortOpen": false,
            "chargePortLatch": "Engaged",
            "chargerPhases": null
      }
  ```
</ResponseExample>


# Amperage
Source: https://smartcar.com/docs/api-reference/tesla/get-charge-ammeter

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/ammeter
When the vehicle is charging, returns the charging amperage measured by the vehicle. When the vehicle is not charging, this endpoint results in a vehicle state error.

<Snippet />

## Permission

`read_charge`

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/ammeter" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  ammeter = vehicle.request(
        "GET", 
        "{make}/charge/ammeter"
  )
  ```

  ```js Node theme={null}
  const ammeter = await vehicle.request(
        "GET", 
        "{make}/charge/ammeter"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/charge/ammeter")
        .build();
  VehicleResponse ammeter = vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  ammeter = vehicle.request(
        "GET", 
        "{make}/charge/ammeter"
  )
  ```
</RequestExample>

## Request

**Path**

<Snippet />

## Response

<ResponseField name="amperage" type="number">
  The rate that the vehicle is charging at (in amperes).
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
    "amperage": 30
  }
  ```
</ResponseExample>


# Charge Completion Time
Source: https://smartcar.com/docs/api-reference/tesla/get-charge-completion-time

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/completion
When the vehicle is charging, returns the date and time when the vehicle is expected to reach its charge limit. When the vehicle is not charging, this endpoint results in a vehicle state error.

<Note>
  This endpoint is currently available for `tesla`.
</Note>

## Permission

`read_charge`

## Request

<ParamField type="string">
  `vehicle_id` of the vehicle you are making the request to.
</ParamField>

<ParamField type="string">
  The make to pass in the URL.
</ParamField>

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="time" type="string">
  An ISO8601 formatted datetime (`YYYY-MM-DDTHH:mm:ss.SSSZ`) for the time at which the vehicle expects to complete this charging session.
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
  {
    "time": "2022-01-13T22:52:55.358Z"
  }
  ```
</ResponseExample>


# Charge Billing Records
Source: https://smartcar.com/docs/api-reference/tesla/get-charge-records-billing

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/records/billing
Returns information about charging sessions for Tesla vehicles at public Tesla chargers including cost and charging site.

<Snippet />

## Permission

`read_charge_records`

## Request

**Path**

<Snippet />

**Query**

<ParamField>
  Date of the first record to return in YYYY-MM-DD format.
  Defaults to 30 days prior  or when the owner first granted your application access, whichever is shorter.
</ParamField>

<ParamField>
  Date of the final record to return in YYYY-MM-DD format. Defaults to the date of the request.
</ParamField>

<ParamField>
  The page number to fetch from Tesla where page 1 contains the most recent records.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/records/billing?page=12&startDate=2023-08-24" \
      -H "Authorization: Bearer {token}" \
      -X "GET" \
      -H "Content-Type: application/json" \
  ```

  ```python Python theme={null}
  billing = vehicle.request(
    "GET", 
    "{make}/charge/records/billing?startDate=2023-08-24&page=12"
  )
  ```

  ```js Node theme={null}
  const billing = vehicle.request(
    "GET", 
    "{make}/charge/records/billing?startDate=2023-08-24&page=12"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request =
      new SmartcarVehicleRequest.Builder()
          .method("GET")
          .path("ford/charge/schedule_by_location")
          .addQueryParameter("startDate", "2023-08-24")
          .addQueryParameter("page", "12")
          .build();

  VehicleResponse billing = vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  billing = vehicle.request(
    "GET", 
    "{make}/charge/records/billing?startDate=2023-08-24&page=12"
  )
  ```
</RequestExample>

## Response

<ResponseField name="records" type="[object]">
  An array of billing records for the vehicle associated with charging at public Tesla charging stations.

  Can be empty if the specified page does not contain any records for the vehicle.
  This **does not** mean that subsequent pages will also contain no records. Please check the `hasMoreData` field for confirmation instead.

  <Expandable>
    <ResponseField name="chargeStart" type="string">
      The date and time of charging session start, formatted in ISO 8601 standard.
    </ResponseField>

    <ResponseField name="chargeEnd" type="string">
      The date and time of charging session end, formatted in ISO 8601 standard.
    </ResponseField>

    <ResponseField name="energyConsumed" type="number">
      Energy consumed in the charging session.
    </ResponseField>

    <ResponseField name="cost" type="object">
      A cost breakout of the charging session.

      <Expandable>
        <ResponseField name="currency" type="string">
          The currency code for the fees.
        </ResponseField>

        <ResponseField name="energy" type="number">
          Fess associated with charging the vehicle.
        </ResponseField>

        <ResponseField name="other" type="number">
          Fees associated with the session other than charging the vehicle e.g. parking.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="location" type="string">
      The name of the charging site.
    </ResponseField>

    <ResponseField name="recordId" type="string">
      Tesla’s id for this charging session.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="hasMoreData" type="bool">
  Indicates if there are any more records to fetch from Tesla for this vehicle. **Does not** guarantee a non-empty list for the next page when `true`.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
    "records": [
        {
            "chargeEnd": "2022-07-10T16:20:00.000Z",
            "chargeStart": "2022-07-10T15:40:00.000Z",
            "energyConsumed": 44.10293884
            "cost": {
                "currency": "USD",
                "energy": "41",
                "other": "41"
            },
            "location": "Los Gatos, CA",
            "recordId": "GF220075000028-3-1682903685"
        }
    ],
    "hasMoreData" : false
  }
  ```
</ResponseExample>


# Charge Schedule
Source: https://smartcar.com/docs/api-reference/tesla/get-charge-schedule

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/schedule
Returns the charging schedule of a vehicle. The response contains the start time and departure time of the vehicle's charging schedule.

<Snippet />

## Permission

`read_charge`

## Request

**Path**

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="departureTime" type="object">
  The departure time configuration for the charging schedule.

  <Expandable title="departureTime">
    <ResponseField name="enabled" type="boolean">
      Indicates whether this schedule type is enabled or disabled.
      Only one of `departureTime` or `departureTime` can be enabled at a time.
    </ResponseField>

    <ResponseField name="time" type="string | null">
      When plugged in, the vehicle **may** delay starting a charging session as long as it can reach its
      [charge limit](/docs/api-reference/evs/get-charge-limit) by this time in HH:mm.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="startTime" type="object">
  The start time configuration for the charging schedule.

  <Expandable title="startTime">
    <ResponseField name="enabled" type="boolean">
      Indicates whether this schedule type is enabled or disabled.
      Only one of `departureTime` or `departureTime` can be enabled at a time.
    </ResponseField>

    <ResponseField name="time" type="string | null">
      When plugged in, the vehicle will delay starting a charging session until this time in HH:mm.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
    "departureTime": {
      "enabled": false,
      "time": null
    },
    "startTime": {
      "enabled": true,
      "time": "18:30"
    }
  }
  ```
</ResponseExample>


# Voltage
Source: https://smartcar.com/docs/api-reference/tesla/get-charge-voltmeter

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/voltmeter
When the vehicle is plugged in, returns the charging voltage measured by the vehicle. When the vehicle is not plugged in, this endpoint results in a vehicle state error.

<Note>
  This endpoint is currently available for `tesla`.
</Note>

## Permission

`read_charge`

## Request

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="voltage" type="number">
  The potential difference measured by the vehicle in volts (V).
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
  {
    "voltage": 240
  }
  ```
</ResponseExample>


# Wattage
Source: https://smartcar.com/docs/api-reference/tesla/get-charge-wattmeter

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/wattmeter
When the vehicle is charging, returns the instant charging wattage as measured by the vehicle. When the vehicle is not charging, this endpoint results in a vehicle state error.

<Snippet />

## Permission

`read_charge`

## Request

**Path**

<Snippet />

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/wattmeter" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  wattmeter = vehicle.request(
        "GET", 
        "{make}/charge/wattmeter"
  )
  ```

  ```js Node theme={null}
  const wattmeter = await vehicle.request(
        "GET", 
        "{make}/charge/wattmeter"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/charge/wattmeter")
        .build();
  VehicleResponse wattmeter = vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  wattmeter = vehicle.request(
        "GET", 
        "{make}/charge/wattmeter"
  )
  ```
</RequestExample>

## Response

<ResponseField name="wattage" type="number">
  The instant power measured by the vehicle (in kilowatts).
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
    "wattage": 3.5
  }
  ```
</ResponseExample>


# Defroster
Source: https://smartcar.com/docs/api-reference/tesla/get-defroster

GET https://api.smartcar.com/v2.0/vehicles/{is}/{make}/climate/defroster
Returns the current state of a vehicle's front and rear defroster.

<Snippet />

## Permission

`read_climate`

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/climate/defroster" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  defroster = vehicle.request(
        "GET", 
        "{make}/climate/defroster"
  )
  ```

  ```js Node theme={null}
  const defroster = await vehicle.request(
        "GET", 
        "{make}/climate/defroster"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/climate/defroster")
        .build();
  VehicleResponse defroster = vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  defroster = vehicle.request(
        "GET", 
        "{make}/climate/defroster"
  )
  ```
</RequestExample>

## Request

**Path**

<Snippet />

## Response

<ResponseField name="frontStatus" type="string">
  The current state of the front defroster.
</ResponseField>

<ResponseField name="rearStatus" type="string">
  The current state of the rear defroster.
</ResponseField>

<ResponseExample>
  ```json Example Response   theme={null}
  {
    "frontStatus": "ON",
    "rearStatus": "OFF"
  }
  ```
</ResponseExample>


# Extended Vehicle Info
Source: https://smartcar.com/docs/api-reference/tesla/get-ext-vehicle-info

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/attributes
Returns detailed configuration information for a vehicle.

<Snippet />

## Permission

`read_extended_vehicle_info`

## Request

**Path**

<Snippet />

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/attributes" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  attributes = vehicle.request(
        "GET", 
        "{make}/attributes"
  )
  ```

  ```js Node theme={null}
  const attributes = await vehicle.request(
        "GET", 
        "{make}/attributes"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/attributes")
        .build();
  VehicleResponse attributes = vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  attributes = vehicle.request(
        "GET", 
        "{make}/attributes"
  )
  ```
</RequestExample>

## Response

<ResponseField name="id" type="string">
  A vehicle ID (UUID v4).
</ResponseField>

<ResponseField name="make" type="string">
  The manufacturer of the vehicle.
</ResponseField>

<ResponseField name="model" type="string">
  The model of the vehicle.
</ResponseField>

<ResponseField name="year" type="integer">
  The model year.
</ResponseField>

<ResponseField name="firmwareVersion" type="string">
  Vehicle's current firmware.
</ResponseField>

<ResponseField name="trimBadging" type="string">
  Indicates the Tesla's trim.
</ResponseField>

<ResponseField name="efficiencyPackage" type="string">
  Efficiency package.
</ResponseField>

<ResponseField name="performancePackage" type="string">
  Performance package.
</ResponseField>

<ResponseField name="nickname" type="string">
  Vehicle's nickname.
</ResponseField>

<ResponseField name="driverAssistVersion" type="string">
  Driver Assist version.
</ResponseField>

<ResponseField name="atHome" type="bool">
  Indicates `true` if the vehicle is currently at the home address set in the vehicle. `False` indicates the vehicle is not at home or home location is not set. This value is `null` if `atHome` status could not be determined.
  This field comes back as `null` if the vehicle is not capable of supporting Tesla's Telemetry API (streaming).
</ResponseField>

<ResponseField name="sentryMode" type="object">
  Sentry Mode status and availability.

  <Expandable>
    <ResponseField name="available" type="bool">
      Does the vehicle support Sentry Mode.
    </ResponseField>

    <ResponseField name="enabled" type="bool">
      Is Sentry Mode currently enabled for a vehicle.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="style" type="object">
  Descriptors of the vehicle's interior and exterior.

  <Expandable>
    <ResponseField name="exteriorColor" type="string">
      Exterior color.
    </ResponseField>

    <ResponseField name="exteriorTrim" type="string">
      Exterior trim.
    </ResponseField>

    <ResponseField name="interiorTrim" type="string">
      Interior trim.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="wheel" type="object">
  Descriptors of the vehicle's wheel.

  <Expandable>
    <ResponseField name="style" type="string">
      Style of the wheel.
    </ResponseField>

    <ResponseField name="diameter" type="number">
      Diameter of the wheel.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="driveUnit" type="object">
  Details on the vehicle's drive unit(s).

  <Expandable>
    <ResponseField name="rear" type="string">
      Rear drive unit.
    </ResponseField>

    <ResponseField name="front" type="string">
      Front drive unit.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
  {
      "driveUnit": {
          "front": "PM216MOSFET",
          "rear": "NoneOrSmall"
      },
      "driverAssistVersion": "TeslaAP3",
      "efficiencyPackage": "MY2021",
      "firmwareVersion": "2022.8.10.12 0ce482dac45d",
      "id": "36ab27d0-fd9d-4455-823a-ce30af709ffc",
      "make": "TESLA",
      "model": "Model S",
      "nickname": "Tommy",
      "performancePackage": "Base",
      "sentryMode": {
          "available": false,
          "enabled": true
      },
      "style": {
          "exteriorColor": "SolidBlack",
          "exteriorTrim": "Black",
          "interiorTrim": "Black2"
      },
      "trimBadging": "74d",
      "wheel": {
          "diameter": 482.6,
          "style": "Apollo"
      },
      "year": 2022,
      "atHome": true
  }
  ```
</ResponseExample>


# Exterior Temperature
Source: https://smartcar.com/docs/api-reference/tesla/get-exterior-temperature

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/thermometer/exterior
Returns the vehicle’s last known exterior thermometer reading. See our [climate setting](/docs/api-reference/tesla/get-cabin) endpoints for managing a cabin temperature.

<Snippet />

## Permission

`read_thermometer`

## Request

**Path**

<Snippet />

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/thermometer/exterior" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  temperature = vehicle.request(
        "GET", 
        "{make}/thermometer/exterior"
  )
  ```

  ```js Node theme={null}
  const temperature = await vehicle.request(
        "GET", 
        "{make}/thermometer/exterior"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/thermometer/exterior")
        .build();
  VehicleResponse temperature = vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  temperature = vehicle.request(
        "GET", 
        "{make}/thermometer/exterior"
  )
  ```
</RequestExample>

## Response

<ResponseField name="temperature" type="number">
  The current exterior temperature of the vehicle.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
    "temperature": 33.42
  }
  ```
</ResponseExample>


# Interior Temperature
Source: https://smartcar.com/docs/api-reference/tesla/get-interior-temperature

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/thermometer/interior
Returns the vehicle’s last known interior thermometer reading. See our [climate setting](/docs/api-reference/tesla/get-cabin) endpoints for managing a cabin temperature.

<Snippet />

## Permission

`read_thermometer`

## Request

**Path**

<Snippet />

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/thermometer/interior" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  temperature = vehicle.request(
        "GET", 
        "{make}/thermometer/interior"
  )
  ```

  ```js Node theme={null}
  const temperature = await vehicle.request(
        "GET", 
        "{make}/thermometer/interior"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/thermometer/interior")
        .build();
  VehicleResponse temperature = vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  temperature = vehicle.request(
        "GET", 
        "{make}/thermometer/interior"
  )
  ```
</RequestExample>

## Response

<ResponseField name="temperature" type="number">
  The current interior temperature of the vehicle.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
    "temperature": 25.64
  }
  ```
</ResponseExample>


# Migration Status
Source: https://smartcar.com/docs/api-reference/tesla/get-migration-status

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/migration
Indicates if the vehicle needs to migrate to Tesla's new API. See [Tesla - What's New](https://smartcar.com/docs/help/oem-integrations/tesla/whats-new) for more details.

<Snippet />

## Permission

`read_vehicle_info`

## Request

**Path**

<Snippet />

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/migration" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  status = vehicle.request(
        "GET", 
        "{make}/migration"
  )
  ```

  ```js Node theme={null}
  const status = await vehicle.request(
        "GET", 
        "{make}/migration"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/migration")
        .build();
  VehicleResponse status = vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  status = vehicle.request(
        "GET", 
        "{make}/migration"
  )
  ```
</RequestExample>

## Response

<ResponseField name="requiresMigration" type="boolean">
  Set to `false` if the vehicle is connected to Smartcar via Tesla's new integration. See [Tesla - What's New](/docs/help/oem-integrations/tesla/whats-new) for more details.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
      "requiresMigration": false
  }
  ```
</ResponseExample>


# Speed
Source: https://smartcar.com/docs/api-reference/tesla/get-speedometer

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/speedometer
Returns the current speed of the vehicle.

<Snippet />

## Permission

`read_speedometer`

## Request

**Path**

<Snippet />

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/speedometer" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  speed = vehicle.request(
        "GET", 
        "{make}/speedometer"
  )
  ```

  ```js Node theme={null}
  const speed = await vehicle.request(
        "GET", 
        "{make}/speedometer"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/speedometer")
        .build();
  VehicleResponse speed = vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  speed = vehicle.request(
        "GET", 
        "{make}/speedometer"
  )
  ```
</RequestExample>

## Response

<ResponseField name="speed" type="number">
  The current speed of the vehicle.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
    "speed": 84.32
  }
  ```
</ResponseExample>


# Steering Heater
Source: https://smartcar.com/docs/api-reference/tesla/get-steering-heater

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/climate/steering_wheel
Returns the current state of a vehicle's steering wheel heater system.

<Snippet />

## Permission

`read_climate`

## Request

**Path**

<Snippet />

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/climate/steering_wheel" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  steering_wheel = vehicle.request(
        "GET", 
        "{make}/climate/steering_wheel"
  )
  ```

  ```js Node theme={null}
  const steeringWheel = await vehicle.request(
        "GET", 
        "{make}/climate/steering_wheel"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/climate/steering_wheel")
        .build();
  VehicleResponse steeringWheel = vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  steering_wheel = vehicle.request(
        "GET", 
        "{make}/climate/steering_wheel"
  )
  ```
</RequestExample>

## Response

<ResponseField name="status" type="enum">
  The current state of the steering wheel heater system. `UNAVAILABLE` indicates the vehicle is not equipped with a steering wheel heater.
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
  {
    "status": "ON",
  }
  ```
</ResponseExample>


# User Access
Source: https://smartcar.com/docs/api-reference/tesla/get-user-access

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/user/access
Returns the account type and permissions for the connected Tesla account.

<Snippet />

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/user/access" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  access = vehicle.request(
        "GET", 
        "{make}/user/access"
  )
  ```

  ```js Node theme={null}
  const access = await vehicle.request(
        "GET", 
        "{make}/user/access"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/user/access")
        .build();
  VehicleResponse access =vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  access = vehicle.request(
        "GET", 
        "{make}/user/access"
  )
  ```
</RequestExample>

## Request

**Path**

<Snippet />

## Response

<ResponseField name="accessType" type="string | null">
  Returns the type of Tesla account connected. Can be either `OWNER` or `DRIVER`. Please see our [Tesla FAQs](/docs/help/oem-integrations/tesla/faqs) for details on the differences between account types.
</ResponseField>

<ResponseField name="permissions" type="[string] | null">
  Returns a list of permissions granted by the user with their Tesla account. Please see [this page](/docs/help/oem-integrations/tesla/developers#permission-mappings) on the mapping from Smartcar permissions to Tesla's.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
    "accessType": "OWNER",
    "permissions" : ["vehicle_cmds", "vehicle_device_data"]
  }
  ```
</ResponseExample>

## Notes

* If you're receiving a [SERVER:INTERNAL](/docs/errors/api-errors/server-errors#internal) error please have the user reconnect their vehicle.


# Vehicle Status
Source: https://smartcar.com/docs/api-reference/tesla/get-vehicle-status

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/status
Returns the status for the vehicle.

<Snippet />

## Permission

`read_extended_vehicle_info`

## Request

**Path**

<Snippet />

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/status" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  status = vehicle.request(
        "GET", 
        "{make}/status"
  )
  ```

  ```js Node theme={null}
  const status = await vehicle.request(
        "GET", 
        "{make}/status"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/status")
        .build();
  VehicleResponse status = vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  status = vehicle.request(
        "GET", 
        "{make}/status"
  )
  ```
</RequestExample>

## Response

<ResponseField name="status" type="string">
  The current status of the vehicle. If the vehicle is asleep, this request will not wake the vehicle.
</ResponseField>

<ResponseField name="inService" type="bool">
  Indicates if the vehicle is in service mode.
</ResponseField>

<ResponseField name="gear" type="string">
  Indicates the current gear shift position.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
  "status": "ASLEEP",
  "inService": true,
  "gear": "DRIVE"
  }
  ```
</ResponseExample>


# Virtual Key Status
Source: https://smartcar.com/docs/api-reference/tesla/get-virtual-key-status

GET https://api.smartcar.com/v2.0/vehicles/{id}/{make}/virtual_key
Indicates if a vehicle has the appropriate virtual key installed. See [Tesla - What's New](https://smartcar.com/docs/help/oem-integrations/tesla/whats-new#if-your-application-issues-commands) for more details on Tesla's virtual key requirements.

<Snippet />

## Permission

`read_vehicle_info`

## Request

**Path**

<Snippet />

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/virtual_key" \
  -H "Authorization: Bearer {token}" \
  -X "GET"
  ```

  ```python Python theme={null}
  virtual_key = vehicle.request(
        "GET", 
        "{make}/virtual_key"
  )
  ```

  ```js Node theme={null}
  const virtualKey = await vehicle.request(
        "GET", 
        "{make}/virtual_key"
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("GET")
        .path("{make}/virtual_key")
        .build();
  VehicleResponse virtualKey = vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  virtual_key = vehicle.request(
        "GET", 
        "{make}/virtual_key"
  )
  ```
</RequestExample>

## Response

<ResponseField name="isPaired" type="boolean">
  Returns `true` if the vehicle has the appropriate Virtual Key installed. See [Tesla - What's New](/docs/help/oem-integrations/tesla/whats-new#if-your-application-issues-commands) for more details on Tesla's virtual key requirements.
</ResponseField>

<ResponseExample>
  ```json Example Response  theme={null}
  {
      "isPaired": true
  }
  ```
</ResponseExample>

## Notes

* This endpoint will throw a [COMPATIBILITY:PLATFORM\_NOT\_CAPABLE](/docs/errors/api-errors/compatibility-errors#platform-not-capable) error if a vehicle is connected to your application via Tesla's legacy integration.
* This endpoint will throw a [CONNECTED\_SERVICES\_ACCOUNT:VEHICLE\_MISSING](/docs/errors/api-errors/compatibility-errors#vehicle-missing) error if the Tesla account connected to Smartcar is **not** the Owner of the vehicle. See our [FAQs](/docs/help/oem-integrations/tesla/faqs#can-owner-and-driver-accounts-authorize-access-with-smartcar-through-connect) for more information on Owner and Driver account types.


# Charge Schedule
Source: https://smartcar.com/docs/api-reference/tesla/set-charge-schedule

POST https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/schedule
Sets the charging schedule for a vehicle.

<Snippet />

## Permission

`control_charge`

## Request

**Path**

<Snippet />

**Body**

<ParamField type="string">
  The type of schedule you want to set.

  <Expandable title="type">
    <ResponseField name="START_TIME">
      When plugged in, the vehicle will delay starting a charging session until this time in `HH:mm`.
    </ResponseField>

    <ResponseField name="DEPARTURE_TIME">
      When plugged in, the vehicle may delay starting a charging session as long as it can reach its
      [charge limit](/docs/api-reference/evs/get-charge-limit) by this time in `HH:mm`.
    </ResponseField>
  </Expandable>
</ParamField>

<ParamField type="boolean">
  Enables or disables the specified charging schedule.
</ParamField>

<ParamField type="string">
  The time for the provided schedule type in HH:mm.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.smartcar.com/v2.0/vehicles/{id}/{make}/charge/schedule" \
  -H "Authorization: Bearer {token}" \
  -X "POST" \
  -H "Content-Type: application/json" \
  -d '{"type": "START_TIME", "enable": true, "time": "23:30"}'
  ```

  ```python Python theme={null}
  chargeSchedule = vehicle.request(
    "POST", 
    "{make}/charge/schedule",
    {"type": "START_TIME", "enable": true, "time": "23:30"}
  )
  ```

  ```js Node theme={null}
  const chargeSchedule = vehicle.request(
    "POST", 
    "{make}/charge/schedule",
    {"type": "START_TIME", "enable": true, "time": "23:30"}
  );
  ```

  ```java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
        .method("POST")
        .path("{make}/charge/schedule")
        .addBodyParameter("type", "START_TIME")
        .addBodyParameter("enable", "true")
        .addBodyParameter("time", "23:30")
        .build();
  ChargeSchedule chargeSchedule = vehicle.request(request);
  ```

  ```ruby Ruby theme={null}
  chargeSchedule = vehicle.request(
    "POST", 
    "{make}/charge/schedule",
    {"type": "START_TIME", "enable": true, "time": "23:30"}
  )
  ```
</RequestExample>

## Response

<ResponseField name="departureTime" type="object">
  The departure time configuration for the charging schedule.

  <Expandable title="departureTime">
    <ResponseField name="enabled" type="boolean">
      Indicates whether this schedule type is enabled or disabled.
      Only one of `departureTime` or `departureTime` can be enabled at a time.
    </ResponseField>

    <ResponseField name="time" type="string | null">
      When plugged in, the vehicle **may** delay starting a charging session as long as it can reach its
      [charge limit](/docs/api-reference/evs/get-charge-limit) by this time in HH:mm.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="startTime" type="object">
  The start time configuration for the charging schedule.

  <Expandable title="startTime">
    <ResponseField name="enabled" type="boolean">
      Indicates whether this schedule type is enabled or disabled.
      Only one of `departureTime` or `departureTime` can be enabled at a time.
    </ResponseField>

    <ResponseField name="time" type="string | null">
      When plugged in, the vehicle will delay starting a charging session until this time in HH:mm.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
  {
    "departureTime": {
      "enabled": false,
      "time": null
    },
    "startTime": {
      "enabled": true,
      "time": "18:30"
    }
  }
  ```
</ResponseExample>


# User
Source: https://smartcar.com/docs/api-reference/user

GET https://api.smartcar.com/v2.0/user
Returns the ID of the vehicle owner who granted access to your application.

<Note>
  This endpoint is under a different path while we complete the transition to v3.0. You can safely continue using this endpoint, but please be aware that it may be deprecated in the future.
</Note>

This should be used as the static unique identifier for storing the access token and refresh token pair in your database.
Note: A single user can own multiple vehicles, and multiple users can own the same vehicle.

<Info>
  When using Single Select for Connect, a single user with multiple vehicles
  will have a 1:1 (`access_token`:`vehicle_id`) mapping.
</Info>

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="id" type="string">
  A user ID (UUID v4).
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
  {
      "id": "e0514ef4-5226-11e8-8c13-8f6e8f02e27e"
  }   
  ```
</ResponseExample>


# User Vehicles
Source: https://smartcar.com/docs/api-reference/user-vehicles

GET https://api.smartcar.com/v2.0/vehicles
Returns a paged list of all vehicles connected to the application for the current authorized `user`.

<Note>
  This endpoint is under a different path while we complete the transition to v3.0. You can safely continue using this endpoint, but please be aware that it may be deprecated in the future.
</Note>

## Request

**Query**

<ParamField type="integer">
  The number of vehicles to return per page. `Max: 50`
</ParamField>

<ParamField type="integer">
  The index to start the `vehicles` list at.
</ParamField>

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="paging" type="Object">
  Metadata about the current list of elements.

  <Expandable>
    <ResponseField name="count" type="integer">
      The total number of elements for the entire query (not just the given page).
    </ResponseField>

    <ResponseField name="offset" type="integer">
      The current start index of the returned list of elements.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="vehicles" type="[string]">
  An array of vehicle IDs.
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
  {
      "paging": {
          "count": 25,
          "offset": 10
      },
      "vehicles": [
          "36ab27d0-fd9d-4455-823a-ce30af709ffc"
      ]
  }
  ```
</ResponseExample>


# Vehicles API v2.0 Overview
Source: https://smartcar.com/docs/api-reference/v2-overview

Overview of the Smartcar Vehicles API v2.0 and deprecation notice.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

<Note>
  Remote commands are now available in [API v3](/docs/api-reference/commands/overview). We recommend using v3 for new command integrations. Commands remain available in v2.0 until it is deprecated.
</Note>

The Smartcar Vehicles API v2.0 is the previous version of our core API for accessing standardized vehicle data and sending remote commands. It allows developers to:

* Retrieve real-time vehicle signals (e.g., battery level, odometer, fuel, tire pressure)
* Send remote commands (lock/unlock, start/stop charging, etc.)

All requests to v2.0 require an OAuth2 access token, which is obtained by having the vehicle owner authorize your app via [Smartcar Connect](/docs/connect/what-is-connect).

## Base URL

```
https://api.smartcar.com/v2.0
```

For this API, the latency response times may vary per vehicle make and model. For more information, see [OEM Latency](/docs/help/oem-latency).


# Delivery Behavior
Source: https://smartcar.com/docs/api-reference/webhooks/delivery-behavior

HTTP delivery mechanics, retry policies, timeouts, and ordering guarantees

Understanding how Smartcar delivers webhook events helps you build a reliable integration. This page covers the technical details of webhook delivery, including HTTP semantics, retry behavior, and timing expectations.

## HTTP Request Format

### Request Method

All webhook deliveries use `HTTP POST` requests sent to your configured callback URI.

### Request Headers

Smartcar includes the following headers with every webhook delivery:

<ResponseField name="Content-Type" type="string">
  Always set to `application/json`. All webhook payloads are JSON-encoded.
</ResponseField>

<ResponseField name="SC-Signature" type="string">
  HMAC-SHA256 signature for payload verification. See [Payload Verification](/docs/integrations/webhooks/payload-verification) for details on how to validate this signature.
</ResponseField>

<ResponseField name="User-Agent" type="string">
  Identifies requests as coming from Smartcar. Format: `Smartcar/{version}`.
</ResponseField>

### Request Body

The request body contains a JSON payload matching one of the event types documented in [Event Reference](/docs/api-reference/webhooks/events/overview).

All requests include:

* Valid JSON formatting
* UTF-8 encoding
* Content-Length header matching the payload size

## Expected Response

### Success Response

Your webhook endpoint must return a **2xx status code** (200, 201, 202, 204, etc.) within the timeout window to acknowledge successful receipt. Any 2xx response is treated as success.

<CodeGroup>
  ```http HTTP Response theme={null}
  HTTP/1.1 200 OK
  Content-Type: application/json

  {}
  ```

  ```python Python theme={null}
  @app.post("/webhooks/smartcar")
  def handle_webhook(request):
      # Persist payload first
      save_to_queue(request.body)
      
      # Return 200 immediately
      return {"status": "received"}, 200
  ```

  ```javascript Node.js theme={null}
  app.post('/webhooks/smartcar', (req, res) => {
    // Persist payload first
    saveToQueue(req.body);
    
    // Return 200 immediately
    res.status(200).json({ status: 'received' });
  });
  ```

  ```java Java theme={null}
  @PostMapping("/webhooks/smartcar")
  public ResponseEntity<Map<String, String>> handleWebhook(@RequestBody String payload) {
      // Persist payload first
      saveToQueue(payload);
      
      // Return 200 immediately
      return ResponseEntity.ok(Map.of("status", "received"));
  }
  ```
</CodeGroup>

<Info>
  **Any 2xx status code is accepted.** You can return 200, 201, 202, 204, or any other 2xx response. Smartcar treats all 2xx codes as successful delivery.
</Info>

<Warning>
  **Response body is ignored.** Smartcar only checks the HTTP status code. You can return an empty body or a simple acknowledgment object.
</Warning>

### Response Timeout

**Your endpoint must respond within 15 seconds.** Requests that exceed this timeout are treated as delivery failures, even if your server eventually responds with a 200 status.

<Tip>
  **Decouple receiving from processing.** Persist the webhook payload to a queue or database immediately, return `200 OK`, then process the data asynchronously. This prevents timeouts from long-running business logic.
</Tip>

### Failed Responses

Any of the following are considered delivery failures and will trigger retries:

* Non-2xx HTTP status codes (including 3xx redirects, 4xx client errors, 5xx server errors)
* Connection timeouts (> 15 seconds)
* Connection refused or DNS resolution failures
* TLS/SSL handshake failures
* Network errors or connection resets

## Retry Behavior

### Retry Policy

When a delivery fails, Smartcar automatically retries up to **3 times** using an **exponential backoff** strategy with an initial delay of 25 seconds:

| Attempt       | Wait Time   | Total Elapsed        |
| ------------- | ----------- | -------------------- |
| 1st (initial) | 0s          | 0s                   |
| 2nd           | 25 seconds  | 25 seconds           |
| 3rd           | 50 seconds  | 1 minute 15 seconds  |
| 4th (final)   | 100 seconds | 2 minutes 55 seconds |

<Info>
  If all 4 delivery attempts fail, the payload is permanently dropped. Future events will still be attempted as long as the webhook remains active.
</Info>

### What Triggers Retries

Retries occur for:

* Non-2xx HTTP status codes (3xx, 4xx, 5xx)
* Request timeouts (> 15 seconds)
* Network errors (connection refused, DNS failures, etc.)
* TLS/SSL errors

### What Doesn't Trigger Retries

Once your endpoint returns any 2xx status code, Smartcar considers the delivery successful and will not retry, even if:

* Your processing logic fails later
* You detect the payload is invalid
* Your database write fails after responding

<Warning>
  **Always validate before responding.** If you return a 2xx status code and then discover the payload is invalid, you cannot trigger a retry. The delivery is considered complete.
</Warning>

### Retry Identification

Each delivery attempt receives a unique `deliveryId`, but the `eventId` remains the same across all retry attempts. Use the `eventId` to identify retries of the same event:

```json theme={null}
{
  "eventId": "f7c0f3e6-4c9d-4f0e-8e5d-6e7f8a9b0c1d",  // Same across all retries
  // ... event data ...
  "meta": {
    "deliveryId": "5d569643-3a47-4cd1-a3ec-db5fc1f6f03b",  // Different for each attempt
    "deliveredAt": 1678901234567
  }
}
```

If the first delivery fails and Smartcar retries, the payload will have:

* **Same `eventId`**: `f7c0f3e6-4c9d-4f0e-8e5d-6e7f8a9b0c1d`
* **New `deliveryId`**: `a1b2c3d4-e5f6-7890-abcd-ef1234567890`
* **Updated `deliveredAt`**: timestamp of the retry attempt

<Tip>
  Use `eventId` for deduplication, not `deliveryId`. The `eventId` uniquely identifies the webhook event, while `deliveryId` only identifies the specific delivery attempt.
</Tip>

See [Idempotency & Deduplication](/docs/integrations/webhooks/best-practices#implement-idempotency) for best practices on handling retries.

## Concurrent Deliveries

### Multiple Events for the Same Vehicle

Smartcar can deliver **multiple events for the same vehicle simultaneously**. This most commonly occurs when a vehicle is in a partial error state and triggers both:

* A `VEHICLE_STATE` event with signal data
* A `VEHICLE_ERROR` event with error details

Your webhook endpoint must handle concurrent requests for the same vehicle. Design your processing logic to be thread-safe and avoid race conditions.

<CodeGroup>
  ```python Python - Thread-Safe Processing theme={null}
  from threading import Lock

  vehicle_locks = {}

  @app.post("/webhooks/smartcar")
  def handle_webhook(request):
      payload = request.json
      vehicle_id = payload['data']['vehicle']['id']
      
      # Get or create a lock for this vehicle
      if vehicle_id not in vehicle_locks:
          vehicle_locks[vehicle_id] = Lock()
      
      # Process with vehicle-specific lock
      with vehicle_locks[vehicle_id]:
          process_payload(payload)
      
      return {"status": "received"}, 200
  ```

  ```javascript Node.js - Async Queue theme={null}
  const async = require('async');
  const vehicleQueues = {};

  app.post('/webhooks/smartcar', (req, res) => {
    const vehicleId = req.body.data.vehicle.id;
    
    // Create queue for this vehicle if it doesn't exist
    if (!vehicleQueues[vehicleId]) {
      vehicleQueues[vehicleId] = async.queue(processPayload, 1);
    }
    
    // Add to vehicle-specific queue
    vehicleQueues[vehicleId].push(req.body);
    
    // Return 200 immediately
    res.status(200).json({ status: 'received' });
  });
  ```
</CodeGroup>

### Cross-Vehicle Concurrency

Events for **different vehicles** can and will be delivered concurrently. If you have 1,000 vehicles subscribed to a webhook, you may receive events for multiple vehicles at the same time.

Your infrastructure should be able to handle concurrent requests proportional to your fleet size.

## Event Batching

### Single vs Multiple Deliveries

**One event per delivery.** Each webhook request contains a single event (either `VEHICLE_STATE` or `VEHICLE_ERROR`).

However, the number of deliveries depends on how the vehicle reports changes:

<AccordionGroup>
  <Accordion title="Scenario 1: Simultaneous Changes (1 delivery)">
    If a vehicle reports 3 signal changes at the same time (e.g., during a single vehicle data poll), Smartcar delivers **one `VEHICLE_STATE` event** containing all changed signals:

    ```json theme={null}
    {
      "eventType": "VEHICLE_STATE",
      "data": {
        "triggers": ["Charge.IsCharging", "TractionBattery.StateOfCharge", "TractionBattery.Range"],
        "signals": {
          "Charge.IsCharging": { "value": true, ... },
          "TractionBattery.StateOfCharge": { "value": 85, ... },
          "TractionBattery.Range": { "value": 250, ... }
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="Scenario 2: Sequential Changes (3 deliveries)">
    If a vehicle reports the same 3 signals as separate changes in quick succession, Smartcar delivers **three separate `VEHICLE_STATE` events**:

    **Delivery 1:**

    ```json theme={null}
    {
      "eventType": "VEHICLE_STATE",
      "data": {
        "triggers": ["Charge.IsCharging"],
        "signals": { "Charge.IsCharging": { "value": true, ... }, ... }
      }
    }
    ```

    **Delivery 2:**

    ```json theme={null}
    {
      "eventType": "VEHICLE_STATE",
      "data": {
        "triggers": ["TractionBattery.StateOfCharge"],
        "signals": { "TractionBattery.StateOfCharge": { "value": 85, ... }, ... }
      }
    }
    ```

    **Delivery 3:**

    ```json theme={null}
    {
      "eventType": "VEHICLE_STATE",
      "data": {
        "triggers": ["TractionBattery.Range"],
        "signals": { "TractionBattery.Range": { "value": 250, ... }, ... }
      }
    }
    ```
  </Accordion>
</AccordionGroup>

<Info>
  **The behavior depends on the vehicle manufacturer.** Some OEMs batch updates, while others stream individual changes. Your integration should handle both patterns.
</Info>

## Payload Size Limits

The maximum webhook payload size is **50 KB**. This limit applies to the entire JSON payload.

<Info>
  Most webhook payloads are well under this limit. A typical `VEHICLE_STATE` event with 10-20 signals usually under 5 KB, depending on the signals.
</Info>

If you're approaching this limit, consider:

* Reducing the number of signals in your webhook subscription
* Splitting data across multiple webhooks with different signal sets

## Delivery Logs & Monitoring

### Dashboard Logs

View delivery attempt history in the [Smartcar Dashboard](https://dashboard.smartcar.com) under the **Logs** tab. The logs show:

* **Successful deliveries**: Events that received a 2xx response
* **Failed deliveries**: Events that failed after all retry attempts
* **Individual retry attempts**: Each attempt with timestamp, status code, and response time
* **Signal names**: The signals that were included in the webhook payload

<Tip>
  Use the dashboard logs to:

  * Debug delivery failures
  * Monitor webhook health
  * Track which signals triggered events
  * Verify retry behavior
</Tip>

### Delivery Metrics

Track key metrics to ensure webhook reliability:

* **Success rate**: Percentage of events delivered successfully on first attempt
* **Retry rate**: Percentage of events requiring retries
* **Average response time**: How quickly your endpoint responds
* **Failure patterns**: Common error codes or failure reasons

<Warning>
  Set up monitoring alerts for:

  * Success rate drops below 95%
  * Average response time exceeds 5 seconds
  * Consecutive failures for the same vehicle
</Warning>

## Webhook Lifecycle

### Disabling Webhooks

When you disable a webhook in the Smartcar Dashboard:

* Smartcar **stops monitoring** subscribed vehicles for changes
* Smartcar **stops attempting deliveries** immediately
* No events are queued or stored while the webhook is disabled

### Re-enabling Webhooks

When you re-enable a webhook:

* Smartcar **resumes monitoring** subscribed vehicles for changes
* The next event will include a `FIRST_DELIVERY` trigger with current signal values
* **Not supported:** Events that occurred while disabled are not retroactively delivered

<Info>
  **No event history while disabled.** Smartcar does not queue events during the disabled period. When you re-enable, you'll receive current state, not historical changes.
</Info>

## Delivery Guarantees

### At-Least-Once Delivery

Smartcar guarantees **at-least-once delivery** for all webhook events. This means:

* **Guaranteed:** You will receive every event at least once (unless all retry attempts fail)
* **Expected:** You may receive the same event multiple times
* **Not guaranteed:** Events are not delivered in order (see below)

### Ordering

**Events are not guaranteed to be delivered in order.** Due to network conditions, retry behavior, and distributed systems, events may arrive out of sequence.

For example:

1. Vehicle's state of charge changes from 50% → 60% at 10:00 AM
2. Vehicle's state of charge changes from 60% → 70% at 10:05 AM
3. You might receive the 70% event before the 60% event

<Tip>
  **Use timestamps to establish order.** Each signal includes `meta.oemUpdatedAt` and `meta.fetchedAt` timestamps. Compare these values to determine the actual sequence of events:

  ```javascript theme={null}
  function isNewerThan(signalA, signalB) {
    return signalA.meta.oemUpdatedAt > signalB.meta.oemUpdatedAt;
  }
  ```
</Tip>

### Duplicate Prevention

While Smartcar delivers each event at least once, duplicates can occur due to:

* **Retry attempts**: If your endpoint doesn't return a 2xx response within 15 seconds, Smartcar will retry the same event, resulting in duplicate deliveries
* **Network issues**: Temporary connectivity problems may cause duplicate sends
* **Distributed systems**: Race conditions in distributed infrastructure

<Warning>
  **Most duplicates are caused by slow or failed responses.** If your endpoint takes longer than 15 seconds to respond or returns a non-2xx status code, Smartcar will retry the delivery. Always return a 2xx response quickly to minimize duplicates.
</Warning>

#### Rare Edge Case: Multiple Deliveries During Confirmation

In extremely rare circumstances, you may receive multiple deliveries for the same error **even when responding quickly**. This can occur when:

1. Smartcar detects a vehicle error (e.g., expired authorization)
2. A webhook delivery is initiated to your endpoint
3. **While confirming delivery**, the same error is detected again (e.g., another API request encounters the same expired authorization)
4. This triggers a second, independent delivery with a **different `eventId`**

**Key characteristics:**

* Happens during a narrow time window (typically milliseconds to seconds)
* Results in **different `eventId` values** for what is logically the same error condition
* Each delivery is a legitimate, distinct event from Smartcar's perspective
* Most common with `VEHICLE_ERROR` events when multiple operations encounter the same error state

**How to handle this:**

If your application is sensitive to duplicate error notifications (e.g., sending user alerts), implement additional deduplication. Use a combination of `userId`, `vehicleId`, error `code`, and a time window (2-5 minutes) in addition to standard `eventId` deduplication.

<Info>
  **This edge case is rare in practice.** Most applications won't need special handling beyond standard `eventId` deduplication.
</Info>

Always implement idempotent processing using the unique `eventId` for standard deduplication. See [Reliability Best Practices](/docs/integrations/webhooks/best-practices/reliability#implement-idempotency) for implementation patterns.

## Latency & Timing

### Understanding Webhook Latency

Webhook delivery latency consists of two components:

**1. Detection Latency** - Time for Smartcar to detect a vehicle data change

* Depends on the vehicle manufacturer's integration and data reporting frequency
* Varies significantly by OEM (from seconds to minutes)
* Outside of Smartcar's control

**2. Delivery Latency** - Time from detection to HTTP delivery

* Smartcar delivers webhooks within seconds of detecting a change
* Actual delivery time depends on network conditions and your endpoint's location

<Info>
  **Total end-to-end latency** = Detection latency (OEM-dependent) + Delivery latency (typically seconds)

  The detection latency varies by manufacturer and is the primary factor in total webhook latency. Once Smartcar detects a change, delivery occurs quickly.
</Info>

### Delivery Latency

Webhook deliveries typically occur within **seconds** of the triggering event. Latency depends on:

* **Vehicle OEM latency**: Time for the vehicle manufacturer to report data to Smartcar
* **Change detection**: Time for Smartcar to detect a signal value change
* **Network latency**: Time to deliver the HTTP request to your endpoint

<Info>
  Most deliveries complete within 1-5 seconds of Smartcar detecting a change, but OEM latency can vary significantly by manufacturer.
</Info>

### Event Freshness

Each signal includes two timestamps to help you understand data freshness:

* **`meta.oemUpdatedAt`**: When the vehicle manufacturer recorded the value (Unix timestamp in milliseconds)
* **`meta.fetchedAt`**: When Smartcar retrieved the value from the OEM (Unix timestamp in milliseconds)

The difference between these timestamps indicates how fresh the data is from the vehicle's perspective.

## Network Requirements

### HTTPS & SSL

All webhook endpoints must:

* Use HTTPS (not HTTP)
* Have a valid SSL/TLS certificate
* Support TLS 1.2 or higher

Self-signed certificates and internal corporate CAs are not supported.

### Public Internet Access

Your webhook endpoint must be accessible from the public internet. Smartcar cannot deliver to:

* `localhost` or `127.0.0.1`
* Private IP addresses (10.x.x.x, 192.168.x.x, 172.16-31.x.x)
* Internal corporate networks without public DNS

### IP Addresses

Smartcar sends webhook requests from **public IPv4 addresses** that may change over time. We do not publish a static list of IP addresses.

<Warning>
  **Avoid IP-based firewall rules.** Instead of allowlisting specific IP addresses, use signature verification to authenticate webhook requests. See [Payload Verification](/docs/integrations/webhooks/payload-verification).
</Warning>

### Firewall Configuration

If you must use firewall rules:

* Allow inbound HTTPS (port 443) from any IP
* Use signature verification for authentication
* Monitor for delivery failures that might indicate blocked IPs

## Error Handling

### Temporary vs Permanent Failures

**Temporary failures** (worth retrying):

* 500, 502, 503, 504 status codes
* Connection timeouts
* Temporary DNS failures
* Network blips

**Permanent failures** (not worth retrying):

* 400, 401, 403, 404, 405 status codes
* Invalid SSL certificates
* DNS resolution failures for non-existent domains

Smartcar retries both types, but you should fix permanent failures quickly to avoid dropped events.

### Monitoring Delivery Health

Monitor your webhook delivery success rate in the [Smartcar Dashboard](https://dashboard.smartcar.com) **Logs** tab. High failure rates may indicate:

* Your endpoint is down or unreachable
* Responses are too slow (> 15 seconds)
* Your endpoint is rejecting requests (4xx errors)
* SSL certificate issues

<Tip>
  Set up alerts for:

  * Delivery success rate drops below 95%
  * Average response time exceeds 5 seconds
  * Consecutive delivery failures (3+)
</Tip>

## Best Practices

To build a reliable webhook integration, follow these essential practices:

1. **Respond Quickly** - Return `200 OK` within 200ms. Queue the payload and process asynchronously to avoid timeouts.

2. **Validate Signatures** - Always verify the `SC-Signature` header before processing payloads to ensure authenticity.

3. **Handle Duplicates** - Use `eventId` to detect and skip duplicate deliveries due to retries or network issues.

4. **Use Timestamps** - Compare `meta.oemUpdatedAt` values to establish correct event ordering, as events may arrive out of sequence.

5. **Monitor Failures** - Track delivery success rates and set up alerts for anomalies or consecutive failures.

6. **Test Error Cases** - Verify your retry and error handling logic with test scenarios during development.

For detailed implementation guidance, see our comprehensive [Best Practices Guide](/docs/integrations/webhooks/best-practices/overview).

***

## Related Resources

<CardGroup>
  <Card title="Event Reference" icon="list" href="/api-reference/webhooks/events/overview">
    Complete reference for all webhook event types and payloads
  </Card>

  <Card title="Payload Verification" icon="signature" href="/integrations/webhooks/payload-verification">
    How to verify webhook signatures for security
  </Card>

  <Card title="Idempotency" icon="arrows-rotate" href="/integrations/webhooks/best-practices#implement-idempotency">
    Handle duplicate deliveries and ensure idempotent processing
  </Card>

  <Card title="Building a Receiver" icon="code" href="/integrations/webhooks/receiving-webhooks">
    Step-by-step guide to implementing a webhook endpoint
  </Card>
</CardGroup>


# Event Reference Overview
Source: https://smartcar.com/docs/api-reference/webhooks/events/overview

Understanding webhook event structure and types

Smartcar delivers webhook events to your configured endpoint. Each event notifies your application about changes to vehicle state, errors encountered during data retrieval, or verification challenges.

## Event Types

Smartcar webhooks deliver three types of events:

<CardGroup>
  <Card title="VERIFY" icon="shield-check" href="/api-reference/webhooks/events/verify">
    One-time challenge to verify your callback URL
  </Card>

  <Card title="VEHICLE_STATE" icon="car" href="/api-reference/webhooks/events/vehicle-state">
    Fired when any monitored signal changes value
  </Card>

  <Card title="VEHICLE_ERROR" icon="triangle-exclamation" href="/api-reference/webhooks/events/vehicle-error">
    Fired when signal retrieval fails or enters error state
  </Card>
</CardGroup>

***

## Event Envelope Structure

All webhook payloads follow this consistent structure:

```json Event Envelope theme={null}
{
  "eventId": "52f6e0bb-1369-45da-a61c-9e67d092d6db",
  "eventType": "VEHICLE_STATE",
  "vehicleId": "bc6ea99e-57d1-4e41-b129-27e7eb58713e",
  "data": {
    // Event-specific data (varies by eventType)
  },
  "meta": {
    "version": "4.0",
    "webhookId": "5a8e5e38-1e12-4011-a36d-56f120053f9e",
    "webhookName": "Battery Monitor",
    "deliveryId": "5d569643-3a47-4cd1-a3ec-db5fc1f6f03b",
    "deliveredAt": 1761896351529
  }
}
```

### Common Fields

All events include these fields:

<ResponseField name="eventId" type="string">
  Unique identifier for this event. Use this for deduplication to prevent processing the same event twice.

  **Important:** The `eventId` remains the same across delivery retries. Use this to implement idempotency.
</ResponseField>

<ResponseField name="eventType" type="string">
  The type of event: `VERIFY`, `VEHICLE_STATE`, or `VEHICLE_ERROR`.

  Use this field to route events to appropriate handlers in your application.
</ResponseField>

<ResponseField name="vehicleId" type="string">
  The Smartcar vehicle ID this event relates to.

  **Note:** Not present in `VERIFY` events, which are webhook-level (not vehicle-specific).
</ResponseField>

<ResponseField name="data" type="object">
  Event-specific data. The structure varies by `eventType`:

  * **VERIFY**: Contains a `challenge` string to hash and return
  * **VEHICLE\_STATE**: Contains **all** signals configured in your webhook subscription
  * **VEHICLE\_ERROR**: Contains error details and affected signals

  See individual event type pages for complete `data` schemas.
</ResponseField>

<ResponseField name="meta" type="object">
  Metadata about the webhook delivery.

  <Expandable title="meta object">
    <ResponseField name="version" type="string">
      Webhook API version (e.g., `"4.0"`)
    </ResponseField>

    <ResponseField name="webhookId" type="string">
      ID of the webhook subscription that triggered this event
    </ResponseField>

    <ResponseField name="webhookName" type="string">
      Name of the webhook subscription (user-defined in Dashboard)
    </ResponseField>

    <ResponseField name="deliveryId" type="string">
      Unique identifier for this delivery attempt. Different from `eventId` - each retry gets a new `deliveryId`.
    </ResponseField>

    <ResponseField name="deliveredAt" type="integer">
      Unix timestamp (milliseconds) when Smartcar sent this webhook
    </ResponseField>

    <ResponseField name="mode" type="string">
      Environment mode: `"LIVE"`
    </ResponseField>
  </Expandable>
</ResponseField>

## Event Delivery Guarantees

All webhook events follow these delivery characteristics:

<AccordionGroup>
  <Accordion title="At-Least-Once Delivery" icon="rotate">
    Events may be delivered more than once due to retries. Always use the `eventId` field for deduplication to ensure you process each unique event exactly once.

    **Why this happens:**

    * Network failures
    * Your endpoint returning non-2xx status codes
    * Timeout before your endpoint responds
  </Accordion>

  <Accordion title="No Ordering Guarantees" icon="arrows-up-down">
    Events are not guaranteed to arrive in chronological order. Concurrent deliveries or network delays can cause later events to arrive before earlier ones.

    **Best practice:** Always use timestamps to determine data freshness:

    * `meta.deliveredAt` - when Smartcar sent the webhook
    * `signals[].meta.oemUpdatedAt` - when the vehicle manufacturer updated the signal
    * `signals[].meta.fetchedAt` - when Smartcar retrieved the signal

    For `VEHICLE_STATE` events, use [`meta.sequence`](/docs/api-reference/webhooks/events/vehicle-state#payload-structure) to determine the order in which events were generated.
  </Accordion>

  <Accordion title="Idempotent Event IDs" icon="fingerprint">
    The `eventId` field remains constant across all retry attempts for the same event. The `deliveryId` changes with each retry.

    **Implementation:** Store processed `eventId` values for at least 7 days to handle late retries and reprocessing scenarios.
  </Accordion>

  <Accordion title="Retry Policy" icon="arrows-rotate">
    Failed deliveries are retried up to 3 times with exponential backoff:

    | Attempt       | Wait Time   | Total Elapsed        |
    | ------------- | ----------- | -------------------- |
    | 1st (initial) | 0s          | 0s                   |
    | 2nd           | 25 seconds  | 25 seconds           |
    | 3rd           | 50 seconds  | 1 minute 15 seconds  |
    | 4th (final)   | 100 seconds | 2 minutes 55 seconds |

    See [Delivery Behavior](/docs/api-reference/webhooks/delivery-behavior) for complete details.
  </Accordion>
</AccordionGroup>

***

## Event-Specific Documentation

<CardGroup>
  <Card title="VERIFY Event" icon="shield-check" href="/api-reference/webhooks/events/verify">
    Initial endpoint verification challenge
  </Card>

  <Card title="VEHICLE_STATE Event" icon="car" href="/api-reference/webhooks/events/vehicle-state">
    Signal data delivery when triggers fire
  </Card>

  <Card title="VEHICLE_ERROR Event" icon="triangle-exclamation" href="/api-reference/webhooks/events/vehicle-error">
    Error notifications and resolutions
  </Card>
</CardGroup>

***

## Next Steps

<CardGroup>
  <Card title="Delivery Behavior" icon="truck-fast" href="/api-reference/webhooks/delivery-behavior">
    Understand retry policies and timeouts
  </Card>

  <Card title="Receiving Webhooks" icon="code" href="/integrations/webhooks/receiving-webhooks">
    Build your webhook endpoint
  </Card>

  <Card title="Best Practices" icon="star" href="/integrations/webhooks/best-practices/reliability">
    Implement idempotency and ordering
  </Card>

  <Card title="Payload Verification" icon="shield-check" href="/integrations/webhooks/payload-verification">
    Verify webhook signatures
  </Card>
</CardGroup>


# VEHICLE_ERROR Event
Source: https://smartcar.com/docs/api-reference/webhooks/events/vehicle-error

Error notifications and resolution tracking for signal retrieval issues

Triggered when Smartcar encounters an error while attempting to retrieve signal data from a vehicle. This event helps you monitor data availability, understand missing or stale signal data and provide an event to trigger a user action to resolve the issue.

## When This Event Fires

The `VEHICLE_ERROR` event fires when:

* Smartcar detects an error while retrieving signal data
* The vehicle manufacturer's API returns an error
* The vehicle is offline or unreachable
* Authentication, permission, or compatibility errors occur

<Info>
  **Resolution notifications**: When an error condition is resolved (e.g., vehicle comes back online), Smartcar sends another `VEHICLE_ERROR` event with `state` set to `"RESOLVED"`. This enables automatic recovery workflows.
</Info>

***

## Error Categories

Errors are categorized by type and include specific error codes:

<AccordionGroup>
  <Accordion title="Connected Services Account Errors" icon="user-slash">
    Issues with the user's account with the vehicle manufacturer.

    | Type                         | Code                    | Description                                     |
    | ---------------------------- | ----------------------- | ----------------------------------------------- |
    | `CONNECTED_SERVICES_ACCOUNT` | `ACCOUNT_ISSUE`         | General account problem                         |
    | `CONNECTED_SERVICES_ACCOUNT` | `AUTHENTICATION_FAILED` | Authentication credentials are invalid          |
    | `CONNECTED_SERVICES_ACCOUNT` | `PERMISSION`            | User lacks necessary permissions                |
    | `CONNECTED_SERVICES_ACCOUNT` | `SUBSCRIPTION`          | Required subscription is inactive or expired    |
    | `CONNECTED_SERVICES_ACCOUNT` | `VIRTUAL_KEY_REQUIRED`  | Vehicle requires a virtual key to be configured |
  </Accordion>

  <Accordion title="Vehicle State Errors" icon="car-battery">
    Issues with the vehicle's connectivity or state.

    | Type            | Code                     | Description                              |
    | --------------- | ------------------------ | ---------------------------------------- |
    | `VEHICLE_STATE` | `REMOTE_ACCESS_DISABLED` | Remote access is disabled on the vehicle |
    | `VEHICLE_STATE` | `ASLEEP`                 | Vehicle is in sleep mode                 |
    | `VEHICLE_STATE` | `UNREACHABLE`            | Vehicle is not connected to the internet |
  </Accordion>

  <Accordion title="Compatibility Errors" icon="plug">
    Issues with signal availability for the specific vehicle.

    | Type            | Code                   | Description                                      |
    | --------------- | ---------------------- | ------------------------------------------------ |
    | `COMPATIBILITY` | `MAKE_NOT_COMPATIBLE`  | Vehicle manufacturer doesn't support this signal |
    | `COMPATIBILITY` | `SMARTCAR_NOT_CAPABLE` | Smartcar cannot retrieve this signal yet         |
    | `COMPATIBILITY` | `VEHICLE_NOT_CAPABLE`  | This specific vehicle doesn't support the signal |
  </Accordion>

  <Accordion title="Permission Errors" icon="lock">
    Issues with granted permissions.

    | Type         | Code   | Description                             |
    | ------------ | ------ | --------------------------------------- |
    | `PERMISSION` | `null` | Required permission not granted by user |
  </Accordion>
</AccordionGroup>

***

## Payload Structure

<ResponseField name="eventId" type="string">
  Unique identifier for this event. Use this for idempotency to prevent duplicate processing.
</ResponseField>

<ResponseField name="eventType" type="string">
  Always `"VEHICLE_ERROR"` for this event type.
</ResponseField>

<ResponseField name="vehicleId" type="string">
  Smartcar vehicle ID for the vehicle this event relates to.
</ResponseField>

<ResponseField name="data" type="object">
  Container for event data.

  <Expandable title="data object">
    <ResponseField name="user" type="object">
      Information about the user who connected the vehicle.

      <ResponseField name="id" type="string">
        Smartcar user ID
      </ResponseField>

      <ResponseField name="externalId" type="string">
        Your application's own identifier for the vehicle owner, if one was provided in the [Connect URL](/docs/connect/redirect-to-connect). `null` if none was set.
      </ResponseField>
    </ResponseField>

    <ResponseField name="vehicle" type="object">
      Vehicle information

      <ResponseField name="id" type="string">
        Smartcar vehicle ID
      </ResponseField>

      <ResponseField name="make" type="string">
        Vehicle manufacturer (e.g., `"TESLA"`, `"FORD"`, `"BMW"`)
      </ResponseField>

      <ResponseField name="model" type="string">
        Vehicle model (e.g., `"Model 3"`, `"Mustang Mach-E"`)
      </ResponseField>

      <ResponseField name="year" type="integer">
        Vehicle model year
      </ResponseField>

      <ResponseField name="mode" type="string">
        Vehicle mode (e.g., `"live"`)
      </ResponseField>

      <ResponseField name="powertrainType" type="string">
        Vehicle powertrain (e.g., `"BEV"`)
      </ResponseField>
    </ResponseField>

    <ResponseField name="errors" type="array">
      Array of error objects. Multiple errors may occur simultaneously.

      <ResponseField name="type" type="string">
        Error category: `CONNECTED_SERVICES_ACCOUNT`, `VEHICLE_STATE`, `COMPATIBILITY`, or `PERMISSION`
      </ResponseField>

      <ResponseField name="code" type="string">
        Specific error code (see error categories above)
      </ResponseField>

      <ResponseField name="state" type="string">
        Error state: `"ERROR"` when error is active, `"RESOLVED"` when the issue has been fixed
      </ResponseField>

      <ResponseField name="description" type="string">
        Technical description of the error for logging and debugging
      </ResponseField>

      <ResponseField name="suggestedUserMessage" type="string">
        User-friendly error message suitable for display to end users. Use this in your application UI.
      </ResponseField>

      <ResponseField name="docURL" type="string">
        Link to detailed error documentation. Useful for linking users to troubleshooting guides.
      </ResponseField>

      <ResponseField name="resolution" type="object">
        Suggested resolution steps

        <ResponseField name="type" type="string">
          Resolution category: `RETRY_LATER`, `CONTACT_SUPPORT`, `USER_ACTION_REQUIRED`, etc.
        </ResponseField>
      </ResponseField>

      <ResponseField name="signals" type="array">
        Array of signal objects that were affected by this error.

        <ResponseField name="code" type="string">
          Kebab-case signal identifier (e.g., `"location-preciselocation"`)
        </ResponseField>

        <ResponseField name="name" type="string">
          Human-readable signal name (e.g., `"PreciseLocation"`)
        </ResponseField>

        <ResponseField name="group" type="string">
          Signal category (e.g., `"Location"`, `"TractionBattery"`)
        </ResponseField>
      </ResponseField>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="meta" type="object">
  Webhook delivery metadata. See [Event Reference Overview](/docs/api-reference/webhooks/events/overview#common-fields) for complete `meta` object schema.
</ResponseField>

## Example Payloads

<Tabs>
  <Tab title="Error State">
    Delivered when an error occurs.

    ```json theme={null}
    {
      "eventId": "5a537912-9ad3-424b-ba33-65a1704567e9",
      "eventType": "VEHICLE_ERROR",
      "vehicleId": "123e4567-e89b-12d3-a456-426614174000",
      "data": {
        "user": {
          "id": "93b3ea96-ca37-43a9-9073-f4334719iok7",
          "externalId": "customer-user-abc123"
        },
        "vehicle": {
          "id": "123e4567-e89b-12d3-a456-426614174000",
          "make": "TESLA",
          "model": "Model 3",
          "year": 2020,
          "mode": "live",
          "powertrainType": "BEV"
        },
        "errors": [
          {
            "type": "COMPATIBILITY",
            "code": "VEHICLE_NOT_CAPABLE",
            "state": "ERROR",
            "description": "The vehicle is incapable of performing your request.",
            "suggestedUserMessage": "Your car is unable to perform this request.",
            "docURL": "https://smartcar.com/docs/errors/api-errors/compatibility-errors#vehicle-not-capable",
            "resolution": {
              "type": "CONTACT_SUPPORT"
            },
            "signals": [
              {
                "code": "location-preciselocation",
                "name": "PreciseLocation",
                "group": "Location"
              },
              {
                "code": "tractionbattery-stateofcharge",
                "name": "StateOfCharge",
                "group": "TractionBattery"
              }
            ]
          }
        ]
      },
      "meta": {
        "version": "4.0",
        "deliveryId": "48b25f8f-9fea-42e1-9085-81043682cbb8",
        "deliveredAt": 1761896351529,
        "webhookId": "123e4567-e89b-12d3-a456-426614174000",
        "webhookName": "Battery Monitoring",
        "mode": "LIVE"
      }
    }
    ```
  </Tab>

  <Tab title="Resolved State">
    Delivered when an error condition is resolved.

    ```json theme={null}
    {
      "eventId": "8d9e0f1a-2b3c-4d5e-6f7a-8b9c0d1e2f3a",
      "eventType": "VEHICLE_ERROR",
      "vehicleId": "123e4567-e89b-12d3-a456-426614174000",
      "data": {
        "user": {
          "id": "93b3ea96-ca37-43a9-9073-f4334719iok7",
          "externalId": "customer-user-abc123"
        },
        "vehicle": {
          "id": "123e4567-e89b-12d3-a456-426614174000",
          "make": "TESLA",
          "model": "Model 3",
          "year": 2020,
          "mode": "live",
          "powertrainType": "BEV"
        },
        "errors": [
          {
            "type": "VEHICLE_STATE",
            "code": "UNREACHABLE",
            "state": "RESOLVED",
            "description": "The vehicle is now reachable.",
            "signals": [
              {
                "code": "location-preciselocation",
                "name": "PreciseLocation",
                "group": "Location"
              }
            ]
          }
        ]
      },
      "meta": {
        "version": "4.0",
        "deliveryId": "9f8e7d6c-5b4a-3c2b-1d0e-9f8e7d6c5b4a",
        "deliveredAt": 1761898351529,
        "webhookId": "123e4567-e89b-12d3-a456-426614174000",
        "webhookName": "Battery Monitoring",
        "mode": "LIVE"
      }
    }
    ```
  </Tab>
</Tabs>

***

## Common Error Scenarios

| Scenario                                | Type                         | Code                  | Recommended Action                              |
| --------------------------------------- | ---------------------------- | --------------------- | ----------------------------------------------- |
| Vehicle offline                         | `VEHICLE_STATE`              | `UNREACHABLE`         | Retry later; notify user if persistent          |
| User revoked permissions                | `CONNECTED_SERVICES_ACCOUNT` | `PERMISSION`          | Prompt user to re-authenticate                  |
| Connected services subscription expired | `CONNECTED_SERVICES_ACCOUNT` | `SUBSCRIPTION`        | Direct user to renew manufacturer subscription  |
| Signal not supported                    | `COMPATIBILITY`              | `VEHICLE_NOT_CAPABLE` | Remove signal from webhook or handle gracefully |
| Vehicle asleep                          | `VEHICLE_STATE`              | `ASLEEP`              | Retry later; avoid waking vehicle unnecessarily |

***

## Processing VEHICLE\_ERROR Events

### Basic Handler

```javascript theme={null}
function handleVehicleError(payload) {
  const { vehicleId, data } = payload;
  const { errors } = data;
  
  errors.forEach(error => {
    if (error.state === 'ERROR') {
      // New error
      logError(vehicleId, error);
      notifyUser(vehicleId, error.suggestedUserMessage);
      
      // Take action based on error type
      if (error.resolution.type === 'RETRY_LATER') {
        scheduleRetry(vehicleId, error.signals);
      } else if (error.resolution.type === 'USER_ACTION_REQUIRED') {
        sendUserNotification(vehicleId, error);
      }
    } else if (error.state === 'RESOLVED') {
      // Error resolved
      logResolution(vehicleId, error);
      clearErrorState(vehicleId, error.code);
      notifyUser(vehicleId, 'Issue resolved, data is now available');
    }
  });
}
```

### Best Practices

<AccordionGroup>
  <Accordion title="Track error state changes" icon="chart-line">
    Monitor both `ERROR` and `RESOLVED` states to implement automatic recovery workflows.

    ```javascript theme={null}
    async function trackErrorState(payload) {
      const { vehicleId, data } = payload;
      
      for (const error of data.errors) {
        if (error.state === 'ERROR') {
          await db.errors.insert({
            vehicleId,
            errorType: error.type,
            errorCode: error.code,
            affectedSignals: error.signals.map(s => s.code),
            detectedAt: new Date()
          });
        } else if (error.state === 'RESOLVED') {
          await db.errors.update(
            { vehicleId, errorCode: error.code },
            { resolvedAt: new Date(), status: 'resolved' }
          );
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="Use suggestedUserMessage for notifications" icon="envelope">
    Display the user-friendly message to vehicle owners instead of technical error descriptions.

    ```javascript theme={null}
    function notifyVehicleOwner(error, userId) {
      const message = error.suggestedUserMessage || 
        'We encountered an issue retrieving data from your vehicle.';
      
      sendNotification(userId, {
        title: 'Vehicle Data Unavailable',
        body: message,
        link: error.docURL // Link to troubleshooting docs
      });
    }
    ```
  </Accordion>

  <Accordion title="Implement retry logic for transient errors" icon="rotate">
    Some errors (ASLEEP, UNREACHABLE) are transient. Implement exponential backoff retries.

    ```javascript theme={null}
    const TRANSIENT_ERROR_CODES = ['ASLEEP', 'UNREACHABLE'];

    function shouldRetry(error) {
      return TRANSIENT_ERROR_CODES.includes(error.code);
    }

    async function handleTransientError(vehicleId, error) {
      const retryDelays = [60000, 300000, 900000]; // 1m, 5m, 15m
      
      for (const delay of retryDelays) {
        await sleep(delay);
        
        try {
          // Attempt to fetch data again
          const data = await smartcar.fetchSignals(vehicleId, error.signals);
          return data; // Success
        } catch (err) {
          // Still failing, continue retrying
        }
      }
      
      // All retries failed
      notifyUser(vehicleId, 'Unable to reach vehicle after multiple attempts');
    }
    ```
  </Accordion>

  <Accordion title="Handle multiple simultaneous errors" icon="layer-group">
    A single `VEHICLE_ERROR` event can contain multiple errors affecting different signals.

    ```javascript theme={null}
    function categorizeErrors(errors) {
      const categorized = {
        transient: [],
        userAction: [],
        permanent: []
      };
      
      errors.forEach(error => {
        if (['ASLEEP', 'UNREACHABLE'].includes(error.code)) {
          categorized.transient.push(error);
        } else if (error.resolution.type === 'USER_ACTION_REQUIRED') {
          categorized.userAction.push(error);
        } else {
          categorized.permanent.push(error);
        }
      });
      
      return categorized;
    }
    ```
  </Accordion>

  <Accordion title="Degrade gracefully in your UI" icon="shield-halved">
    When errors occur, show stale data with a clear indication that it's not current.

    ```javascript theme={null}
    function displayVehicleData(vehicleId, hasActiveErrors) {
      const data = getLastKnownData(vehicleId);
      
      return {
        ...data,
        isStale: hasActiveErrors,
        staleSince: getLastSuccessfulFetch(vehicleId),
        errorMessage: 'Unable to retrieve current data. Showing last known values.'
      };
    }
    ```
  </Accordion>
</AccordionGroup>

***

## Error Resolution Tracking

When an error condition is resolved, Smartcar sends a `VEHICLE_ERROR` event with `state: "RESOLVED"`:

```javascript theme={null}
function handleErrorResolution(payload) {
  const { vehicleId, data } = payload;
  
  data.errors.forEach(error => {
    if (error.state === 'RESOLVED') {
      console.log(`Error resolved for ${vehicleId}: ${error.code}`);
      
      // Clear error flags
      clearVehicleError(vehicleId, error.code);
      
      // Resume data collection
      resumeDataCollection(vehicleId, error.signals);
      
      // Notify user
      notifyUser(vehicleId, 'Your vehicle is now connected and data is available');
    }
  });
}
```

<Tip>
  **Automatic recovery**: Use `state: "RESOLVED"` events to automatically resume normal operations without manual intervention.
</Tip>

***

## Next Steps

<CardGroup>
  <Card title="Error Reference" icon="circle-exclamation" href="/errors/api-errors">
    Complete error code documentation
  </Card>

  <Card title="VEHICLE_STATE Event" icon="car" href="/api-reference/webhooks/events/vehicle-state">
    Learn about successful signal deliveries
  </Card>

  <Card title="Reliability Best Practices" icon="shield" href="/integrations/webhooks/best-practices/reliability">
    Implement idempotency and retry handling
  </Card>

  <Card title="Delivery Behavior" icon="truck-fast" href="/api-reference/webhooks/delivery-behavior">
    Understand retry policies
  </Card>
</CardGroup>


# VEHICLE_STATE Event
Source: https://smartcar.com/docs/api-reference/webhooks/events/vehicle-state

Signal data delivery when trigger conditions are met

Triggered when one or more signals you've configured as triggers change their value. This event delivers the updated signal data for all subscribed signals in the payload.

<Note>
  **All Configured Signals Are Always Included**

  Every `VEHICLE_STATE` event contains **all** signals you configured in your webhook subscription, regardless of which signal(s) triggered the event. This ensures you always have complete vehicle state data.

  Example: If your webhook subscribes to 10 signals but only 1 trigger changes, you'll receive all 10 signals in the payload.
</Note>

## When This Event Fires

The `VEHICLE_STATE` event fires when Smartcar detects a signal value change for any trigger signal configured in your webhook.

### Trigger Configuration

You configure which signals should trigger this event through the Smartcar Dashboard when creating or editing a webhook. For example:

**Triggers:**

* `TractionBattery.StateOfCharge` (code: `tractionbattery-stateofcharge`)
* `Charge.IsCharging` (code: `charge-ischarging`)
* `Location.PreciseLocation` (code: `location-preciselocation`)

**Subscribed Signals:**

* `TractionBattery.StateOfCharge`
* `Charge.IsCharging`
* `Location.PreciseLocation`
* `Charge.Voltage`
* `Odometer.TraveledDistance`

If any of the trigger signals change, a `VEHICLE_STATE` event is delivered containing **all five subscribed signals**.

***

## Identifying Which Triggers Fired

The webhook payload includes a `triggers` field that specifies which trigger signal(s) changed to prompt this delivery. This helps you identify what caused the event without comparing all signal values.

### Trigger Types

<AccordionGroup>
  <Accordion title="Signal Change Triggers" icon="arrows-rotate">
    When a monitored trigger signal changes value, the `triggers` array contains the signal(s) that changed.

    ```json theme={null}
    {
      "triggers": [
        {
          "code": "tractionbattery-stateofcharge",
          "name": "StateOfCharge",
          "group": "TractionBattery"
        }
      ]
    }
    ```

    If multiple triggers change simultaneously, all will be included in the array.
  </Accordion>

  <Accordion title="First Delivery Trigger" icon="flag-checkered">
    When a webhook subscription is first created, a `FIRST_DELIVERY` trigger is sent to provide the initial state of the vehicle.

    ```json theme={null}
    {
      "triggers": [
        {
          "code": "FIRST_DELIVERY"
        }
      ]
    }
    ```

    This initial delivery:

    * Occurs after vehicle subscription to a webhook
    * Contains all subscribed signals at their current values
    * Does not indicate any signal value changes
    * Helps establish baseline state for your application

    **When FIRST\_DELIVERY is sent again:**

    * When a vehicle is unsubscribed and then resubscribed to your webhook
    * If your endpoint fails to respond with a 2xx status code, Smartcar will retry delivery with the same `FIRST_DELIVERY` trigger
  </Accordion>
</AccordionGroup>

<Tip>
  Use the `triggers` field to determine the delivery reason. Check for `"code": "FIRST_DELIVERY"` to identify initial state deliveries versus change-triggered deliveries.
</Tip>

***

## Payload Structure

<ResponseField name="eventId" type="string">
  Unique identifier for this event. Use this for idempotency to prevent duplicate processing.
</ResponseField>

<ResponseField name="eventType" type="string">
  Always `"VEHICLE_STATE"` for this event type.
</ResponseField>

<ResponseField name="vehicleId" type="string">
  Smartcar vehicle ID for the vehicle this event relates to.
</ResponseField>

<ResponseField name="data" type="object">
  Container for event data.

  <Expandable title="data object">
    <ResponseField name="user" type="object">
      Information about the user who connected the vehicle.

      <ResponseField name="id" type="string">
        Smartcar user ID
      </ResponseField>

      <ResponseField name="externalId" type="string">
        Your application's own identifier for the vehicle owner, if one was provided in the [Connect URL](/docs/connect/redirect-to-connect). `null` if none was set.
      </ResponseField>
    </ResponseField>

    <ResponseField name="vehicle" type="object">
      Vehicle information

      <ResponseField name="id" type="string">
        Smartcar vehicle ID
      </ResponseField>

      <ResponseField name="make" type="string">
        Vehicle manufacturer (e.g., `"TESLA"`, `"FORD"`, `"BMW"`)
      </ResponseField>

      <ResponseField name="model" type="string">
        Vehicle model (e.g., `"Model 3"`, `"Mustang Mach-E"`)
      </ResponseField>

      <ResponseField name="year" type="integer">
        Vehicle model year
      </ResponseField>

      <ResponseField name="mode" type="string">
        Vehicle mode (e.g., `"live"`)
      </ResponseField>

      <ResponseField name="powertrainType" type="string">
        Vehicle powertrain (e.g., `"BEV"`)
      </ResponseField>
    </ResponseField>

    <ResponseField name="triggers" type="array">
      Array of trigger signal objects that changed to prompt this delivery. Helps identify which configured triggers actually fired.

      <ResponseField name="code" type="string">
        Kebab-case signal identifier (e.g., `"tractionbattery-stateofcharge"`) or `"FIRST_DELIVERY"` for initial deliveries
      </ResponseField>

      <ResponseField name="name" type="string">
        Human-readable signal name (e.g., `"StateOfCharge"`)
      </ResponseField>

      <ResponseField name="group" type="string">
        Signal category (e.g., `"TractionBattery"`)
      </ResponseField>
    </ResponseField>

    <ResponseField name="signals" type="array">
      Array of signal objects containing data for **all** signals configured in your webhook subscription. This array always includes every subscribed signal, even if only one trigger changed to fire this event.

      <ResponseField name="code" type="string">
        Kebab-case signal identifier (e.g., `"tractionbattery-stateofcharge"`)
      </ResponseField>

      <ResponseField name="name" type="string">
        Human-readable signal name (e.g., `"StateOfCharge"`)
      </ResponseField>

      <ResponseField name="group" type="string">
        Signal category (e.g., `"TractionBattery"`, `"Charge"`, `"Location"`)
      </ResponseField>

      <ResponseField name="body" type="object">
        Signal-specific data structure. See [Signals Reference](/docs/api-reference/signals/schema) for complete schemas.

        Each signal type has a unique body structure. Common examples:

        * Battery state of charge: `{ "unit": "percent", "value": 78 }`
        * Charging status: `{ "value": true }`
        * Location: `{ "latitude": 37.4292, "longitude": -122.1381 }`
      </ResponseField>

      <ResponseField name="meta" type="object">
        Signal metadata with timestamp information

        <ResponseField name="oemUpdatedAt" type="integer">
          Unix timestamp (milliseconds) when the vehicle manufacturer last updated this signal
        </ResponseField>

        <ResponseField name="fetchedAt" type="integer">
          Unix timestamp (milliseconds) when Smartcar retrieved this signal from the vehicle manufacturer
        </ResponseField>
      </ResponseField>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="meta" type="object">
  Webhook delivery metadata. See [Event Reference Overview](/docs/api-reference/webhooks/events/overview#common-fields) for complete `meta` object schema.

  <Expandable title="meta object (VEHICLE_STATE-specific fields)">
    <ResponseField name="sequence" type="integer">
      Integer assigned when the event is generated; a later event never carries a lower value than an earlier one (events generated at the same time may share a value). Compare `sequence` values to order events for a vehicle, even when deliveries arrive out of order. Retries keep the original event's `sequence`, like `eventId`. Only present for `VEHICLE_STATE` events.
    </ResponseField>

    <ResponseField name="signalCount" type="integer">
      Number of signals included in this `VEHICLE_STATE` event. Only present for `VEHICLE_STATE` events.
    </ResponseField>
  </Expandable>
</ResponseField>

***

## Example Payloads

<Tabs>
  <Tab title="Signal Change Trigger">
    Delivered when a configured trigger signal changes value.

    ```json theme={null}
    {
      "eventId": "550e8400-e29b-41d4-a716-446655440000",
      "eventType": "VEHICLE_STATE",
      "vehicleId": "9af13248-3b73-4c9d-9a4b-d937ce6bc8e2",
      "data": {
        "user": {
          "id": "93b3ea96-ca37-43a9-9073-f4334719iok7",
          "externalId": "customer-user-abc123"
        },
        "vehicle": {
          "id": "9af13248-3b73-4c9d-9a4b-d937ce6bc8e2",
          "make": "TESLA",
          "model": "Model 3",
          "year": 2020,
          "mode": "live",
          "powertrainType": "BEV"
        },
        "triggers": [
          {
            "code": "tractionbattery-stateofcharge",
            "name": "StateOfCharge",
            "group": "TractionBattery"
          }
        ],
        "signals": [
          {
            "code": "tractionbattery-stateofcharge",
            "name": "StateOfCharge",
            "group": "TractionBattery",
            "body": {
              "unit": "percent",
              "value": 78
            },
            "meta": {
              "oemUpdatedAt": 1731940328000,
              "fetchedAt": 1731940330000
            }
          },
          {
            "code": "charge-ischarging",
            "name": "IsCharging",
            "group": "Charge",
            "body": {
              "value": true
            },
            "meta": {
              "oemUpdatedAt": 1731940328000,
              "fetchedAt": 1731940330000
            }
          },
          {
            "code": "charge-voltage",
            "name": "Voltage",
            "group": "Charge",
            "body": {
              "unit": "volts",
              "value": 240
            },
            "meta": {
              "oemUpdatedAt": 1731940328000,
              "fetchedAt": 1731940330000
            }
          }
        ]
      },
      "meta": {
        "version": "4.0",
        "deliveryId": "48b25f8f-9fea-42e1-9085-81043682cbb8",
        "deliveredAt": 1731940328000,
        "webhookId": "abde94ff-d57d-43b9-8d09-6020db2d977a",
        "webhookName": "Battery Monitoring",
        "sequence": 1731940327412,
        "signalCount": 3,
        "mode": "LIVE"
      }
    }
    ```
  </Tab>

  <Tab title="First Delivery">
    Delivered immediately after webhook subscription creation to provide initial vehicle state.

    ```json theme={null}
    {
      "eventId": "7c8d9e10-f2a3-4b5c-6d7e-8f9a0b1c2d3e",
      "eventType": "VEHICLE_STATE",
      "vehicleId": "9af13248-3b73-4c9d-9a4b-d937ce6bc8e2",
      "data": {
        "user": {
          "id": "93b3ea96-ca37-43a9-9073-f4334719iok7",
          "externalId": "customer-user-abc123"
        },
        "vehicle": {
          "id": "9af13248-3b73-4c9d-9a4b-d937ce6bc8e2",
          "make": "TESLA",
          "model": "Model 3",
          "year": 2020,
          "mode": "live",
          "powertrainType": "BEV"
        },
        "triggers": [
          {
            "code": "FIRST_DELIVERY"
          }
        ],
        "signals": [
          {
            "code": "tractionbattery-stateofcharge",
            "name": "StateOfCharge",
            "group": "TractionBattery",
            "body": {
              "unit": "percent",
              "value": 65
            },
            "meta": {
              "oemUpdatedAt": 1731926100000,
              "fetchedAt": 1731926102000
            }
          },
          {
            "code": "charge-ischarging",
            "name": "IsCharging",
            "group": "Charge",
            "body": {
              "value": false
            },
            "meta": {
              "oemUpdatedAt": 1731926100000,
              "fetchedAt": 1731926102000
            }
          },
          {
            "code": "charge-voltage",
            "name": "Voltage",
            "group": "Charge",
            "body": {
              "unit": "volts",
              "value": 0
            },
            "meta": {
              "oemUpdatedAt": 1731926100000,
              "fetchedAt": 1731926102000
            }
          }
        ]
      },
      "meta": {
        "version": "4.0",
        "deliveryId": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
        "deliveredAt": 1731926100000,
        "webhookId": "abde94ff-d57d-43b9-8d09-6020db2d977a",
        "webhookName": "Battery Monitoring",
        "sequence": 1731926099456,
        "signalCount": 3,
        "mode": "LIVE"
      }
    }
    ```
  </Tab>
</Tabs>

***

## Signal Reference

The `signals` array contains data structured according to the [Signals Schema Reference](/docs/api-reference/signals/schema). Each signal type has a specific shape:

<CardGroup>
  <Card title="Charge Signals" href="/api-reference/signals/charge">
    Battery charging status and metrics
  </Card>

  <Card title="Battery Signals" href="/api-reference/signals/tractionbattery">
    State of charge and battery health
  </Card>

  <Card title="Location Signals" href="/api-reference/signals/location">
    GPS coordinates and location data
  </Card>

  <Card title="Odometer" href="/api-reference/signals/odometer">
    Distance traveled
  </Card>

  <Card title="Fuel Tank" href="/api-reference/get-fuel-tank">
    Fuel level for ICE vehicles
  </Card>

  <Card title="All Signals" href="/api-reference/signals/schema">
    Complete signal catalog
  </Card>
</CardGroup>

***

## Signal-Level Errors

Individual signals within a `VEHICLE_STATE` payload can contain errors if the vehicle doesn't support that signal or if retrieval fails. When this occurs, the signal will have a `status` object with error details instead of a `body` with data:

```json Signal with Error theme={null}
{
  "code": "location-isathome",
  "name": "IsAtHome",
  "group": "Location",
  "status": {
    "error": {
      "code": "VEHICLE_NOT_CAPABLE",
      "type": "COMPATIBILITY"
    },
    "value": "ERROR"
  }
}
```

<Info>
  **Partial data delivery**: When some signals succeed and others fail, you'll receive a `VEHICLE_STATE` event with successful signals containing `body` data and failed signals containing `status` errors. This allows you to process available data even when some signals are unavailable.
</Info>

For complete error handling, see the [VEHICLE\_ERROR Event](/docs/api-reference/webhooks/events/vehicle-error) documentation.

***

## Processing VEHICLE\_STATE Events

### Basic Handler

```javascript theme={null}
function handleVehicleState(payload) {
  const { vehicleId, data } = payload;
  const { signals, triggers } = data;
  
  // Check if this is first delivery
  const isFirstDelivery = triggers.some(t => t.code === 'FIRST_DELIVERY');
  
  // Process each signal
  signals.forEach(signal => {
    if (signal.body) {
      // Signal has data
      console.log(`${signal.name}: ${JSON.stringify(signal.body)}`);
      updateDatabase(vehicleId, signal.code, signal.body);
    } else if (signal.status) {
      // Signal has error
      console.error(`${signal.name} error: ${signal.status.error.code}`);
      handleSignalError(vehicleId, signal);
    }
  });
}
```

### Best Practices

<AccordionGroup>
  <Accordion title="Use eventId for deduplication" icon="fingerprint">
    Always check if you've already processed an `eventId` before updating your database. Retries will have the same `eventId` but different `deliveryId`.

    ```javascript theme={null}
    async function processWebhook(payload) {
      const { eventId } = payload;
      
      // Check if already processed
      if (await isProcessed(eventId)) {
        console.log(`Already processed ${eventId}`);
        return;
      }
      
      // Process the event
      await handleVehicleState(payload);
      
      // Mark as processed
      await markProcessed(eventId);
    }
    ```
  </Accordion>

  <Accordion title="Check timestamp freshness" icon="clock">
    Use `signals[].meta.oemUpdatedAt` to determine if incoming data is newer than your stored state. Events can arrive out of order.

    ```javascript theme={null}
    function shouldUpdate(currentData, newSignal) {
      if (!currentData) return true;
      
      return newSignal.meta.oemUpdatedAt > currentData.timestamp;
    }
    ```
  </Accordion>

  <Accordion title="Handle partial failures gracefully" icon="shield-halved">
    Some signals may succeed while others fail. Process available data and log errors for unavailable signals.

    ```javascript theme={null}
    signals.forEach(signal => {
      if (signal.body) {
        updateVehicleData(signal);
      } else if (signal.status) {
        logSignalUnavailable(signal);
        // Don't block processing of other signals
      }
    });
    ```
  </Accordion>

  <Accordion title="Differentiate FIRST_DELIVERY from changes" icon="flag">
    Use the `triggers` field to identify initial state deliveries vs. actual signal changes.

    ```javascript theme={null}
    const isFirstDelivery = payload.data.triggers.some(
      t => t.code === 'FIRST_DELIVERY'
    );

    if (isFirstDelivery) {
      // Initialize vehicle state
      initializeVehicle(payload.data);
    } else {
      // Update changed signals
      updateVehicleState(payload.data);
    }
    ```
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup>
  <Card title="VEHICLE_ERROR Event" icon="triangle-exclamation" href="/api-reference/webhooks/events/vehicle-error">
    Handle error notifications
  </Card>

  <Card title="Signals Reference" icon="list" href="/api-reference/signals/schema">
    Complete signal schemas and data structures
  </Card>

  <Card title="Best Practices" icon="star" href="/integrations/webhooks/best-practices/reliability">
    Implement idempotency and ordering
  </Card>

  <Card title="Delivery Behavior" icon="truck-fast" href="/api-reference/webhooks/delivery-behavior">
    Understand retry policies
  </Card>
</CardGroup>


# VERIFY Event
Source: https://smartcar.com/docs/api-reference/webhooks/events/verify

One-time challenge to verify your webhook endpoint

A one-time event sent when you first create a webhook to verify that Smartcar can successfully deliver payloads to your callback URL.

<Warning>
  **Required Before Data Delivery**

  Your endpoint must successfully respond to the `VERIFY` event before Smartcar will deliver any `VEHICLE_STATE` or `VEHICLE_ERROR` events. This confirms your endpoint is configured correctly and ready to receive webhooks.
</Warning>

## When This Event Fires

The `VERIFY` event fires once when you:

* Create a new webhook in the Smartcar Dashboard
* Update the callback URL of an existing webhook
* Click "Verify this webhook" in the Dashboard

***

## Payload Structure

<CodeGroup>
  ```json Version 4.0 (Current) theme={null}
  {
    "eventId": "52f6e0bb-1369-45da-a61c-9e67d092d6db",
    "eventType": "VERIFY",
    "data": {
      "challenge": "3a5c8f72-e6d9-4b1a-9f2e-8c7d6a5b4e3f"
    },
    "meta": {
      "version": "4.0",
      "webhookId": "5a8e5e38-1e12-4011-a36d-56f120053f9e",
      "webhookName": "Example Webhook",
      "deliveryId": "5d569643-3a47-4cd1-a3ec-db5fc1f6f03b",
      "deliveredAt": 1761896351529
    }
  }
  ```

  ```json Version 2.0 (Legacy) theme={null}
  {
    "version": "2.0",
    "webhookId": "5a8e5e38-1e12-4011-a36d-56f120053f9e",
    "eventName": "verify",
    "payload": { 
      "challenge": "3a5c8f72-e6d9-4b1a-9f2e-8c7d6a5b4e3f"
    }
  }
  ```
</CodeGroup>

### Payload Fields

<ResponseField name="eventId" type="string">
  Unique identifier for this verification event.
</ResponseField>

<ResponseField name="eventType" type="string">
  Always `"VERIFY"` for this event type.
</ResponseField>

<ResponseField name="data" type="object">
  Container for the challenge.

  <Expandable title="data object">
    <ResponseField name="challenge" type="string">
      Random string that must be hashed with your Application Management Token and returned in your response.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="meta" type="object">
  Webhook delivery metadata. See [Event Reference Overview](/docs/api-reference/webhooks/events/overview#common-fields) for the complete `meta` object schema.
</ResponseField>

***

## Required Response

Your endpoint must respond with:

1. **Status code**: `200 OK`
2. **Content-Type header**: `application/json`
3. **Response body**: JSON object with the HMAC-SHA256 hash

```json Response Body theme={null}
{
  "challenge": "a3f5c8e9d2b4a1f6e8c7d9a5b3e1f2c4d6a8b9c1e3f5a7b9c2d4e6f8a1b3c5d7"
}
```

### Generate the HMAC

Create an HMAC-SHA256 hash of the `challenge` string using your **Application Management Token** as the secret key, then hex-encode the result:

<CodeGroup>
  ```python Python theme={null}
  import hmac
  import hashlib

  signature = hmac.new(
      application_management_token.encode(),
      challenge.encode(),
      hashlib.sha256,
  ).hexdigest()

  # Return in response body
  return {"challenge": signature}, 200
  ```

  ```javascript Node.js theme={null}
  const crypto = require('crypto');

  const hmac = crypto
    .createHmac('sha256', application_management_token)
    .update(challenge)
    .digest('hex');

  // Return in response body
  res.status(200).json({ challenge: hmac });
  ```

  ```java Java theme={null}
  import javax.crypto.Mac;
  import javax.crypto.spec.SecretKeySpec;
  import java.nio.charset.StandardCharsets;

  Mac mac = Mac.getInstance("HmacSHA256");
  mac.init(new SecretKeySpec(application_management_token.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
  byte[] raw = mac.doFinal(challenge.getBytes(StandardCharsets.UTF_8));
  StringBuilder sb = new StringBuilder();
  for (byte b : raw) {
      sb.append(String.format("%02x", b));
  }
  String hmac = sb.toString();

  // Return in response body
  return ResponseEntity.ok(Map.of("challenge", hmac));
  ```

  ```ruby Ruby theme={null}
  require 'openssl'

  hmac = OpenSSL::HMAC.hexdigest('SHA256', application_management_token, challenge)

  # Return in response body
  { challenge: hmac }
  ```
</CodeGroup>

***

## Complete Handler Example

Here's a complete webhook handler that responds to the `VERIFY` event:

<CodeGroup>
  ```javascript Node.js (Express) theme={null}
  const express = require('express');
  const crypto = require('crypto');

  const app = express();
  app.use(express.json());

  app.post('/webhooks/smartcar', (req, res) => {
    const { eventType, data } = req.body;
    
    if (eventType === 'VERIFY') {
      // Generate HMAC challenge response
      const hmac = crypto
        .createHmac('sha256', process.env.SMARTCAR_MANAGEMENT_TOKEN)
        .update(data.challenge)
        .digest('hex');
      
      return res.status(200).json({ challenge: hmac });
    }
    
    // Handle other event types...
    res.status(200).json({ status: 'received' });
  });
  ```

  ```python Python (Flask) theme={null}
  from flask import Flask, request, jsonify
  import hmac
  import hashlib
  import os

  app = Flask(__name__)

  @app.post('/webhooks/smartcar')
  def webhook_handler():
      payload = request.get_json()
      event_type = payload.get('eventType')
      
      if event_type == 'VERIFY':
          # Generate HMAC challenge response
          signature = hmac.new(
              os.environ['SMARTCAR_MANAGEMENT_TOKEN'].encode(),
              payload['data']['challenge'].encode(),
              hashlib.sha256,
          ).hexdigest()
          
          return jsonify({"challenge": signature}), 200
      
      # Handle other event types...
      return jsonify({"status": "received"}), 200
  ```

  ```java Java (Spring Boot) theme={null}
  @RestController
  public class WebhookController {
      
      @Value("${smartcar.management.token}")
      private String managementToken;
      
      @PostMapping("/webhooks/smartcar")
      public ResponseEntity<?> handleWebhook(@RequestBody Map<String, Object> payload) throws Exception {
          String eventType = (String) payload.get("eventType");
          
          if ("VERIFY".equals(eventType)) {
              // Generate HMAC challenge response
              Map<String, Object> data = (Map<String, Object>) payload.get("data");
              String challenge = (String) data.get("challenge");
              
              Mac mac = Mac.getInstance("HmacSHA256");
              mac.init(new SecretKeySpec(managementToken.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
              byte[] raw = mac.doFinal(challenge.getBytes(StandardCharsets.UTF_8));
              StringBuilder sb = new StringBuilder();
              for (byte b : raw) {
                  sb.append(String.format("%02x", b));
              }
              String hmac = sb.toString();
              
              return ResponseEntity.ok(Map.of("challenge", hmac));
          }
          
          // Handle other event types...
          return ResponseEntity.ok(Map.of("status", "received"));
      }
  }
  ```

  ```ruby Ruby (Sinatra) theme={null}
  require 'sinatra'
  require 'json'
  require 'openssl'

  post '/webhooks/smartcar' do
    payload = JSON.parse(request.body.read)
    event_type = payload['eventType']
    
    if event_type == 'VERIFY'
      # Generate HMAC challenge response
      hmac = OpenSSL::HMAC.hexdigest(
        'SHA256',
        ENV['SMARTCAR_MANAGEMENT_TOKEN'],
        payload['data']['challenge']
      )
      
      status 200
      content_type :json
      return { challenge: hmac }.to_json
    end
    
    # Handle other event types...
    status 200
    content_type :json
    { status: 'received' }.to_json
  end
  ```
</CodeGroup>

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Verification fails in Dashboard" icon="circle-xmark">
    **Common causes:**

    * Wrong Application Management Token used
    * HMAC not hex-encoded
    * Response body doesn't match `{ "challenge": "..." }` format
    * Endpoint returns non-200 status code
    * Response takes longer than 15 seconds

    **Solution:** Use the Dashboard's verification modal to see the expected challenge and response. Compare your implementation against the provided code snippets.
  </Accordion>

  <Accordion title="How do I test VERIFY locally?" icon="laptop">
    Use [ngrok](https://ngrok.com) or similar to expose your local server:

    ```bash theme={null}
    ngrok http 3000
    ```

    Then use the ngrok URL as your callback URI in the Dashboard. The Dashboard will send a real `VERIFY` event to your local endpoint.
  </Accordion>

  <Accordion title="Can I re-verify my webhook?" icon="rotate">
    Yes! You can click "Verify this webhook" in the Dashboard at any time to send a new `VERIFY` event to your endpoint.
  </Accordion>

  <Accordion title="Do I need to handle VERIFY in production?" icon="question">
    Yes, your production webhook endpoint should always handle the `VERIFY` event type, even after initial verification. This allows you to re-verify from the Dashboard if needed.
  </Accordion>
</AccordionGroup>

<Warning>
  **Timeout Requirement**

  Your endpoint must respond to the `VERIFY` event within **15 seconds**. If verification times out, Smartcar will not activate the webhook.
</Warning>

***

## Next Steps

After successfully responding to the `VERIFY` event, your webhook is activated and will begin receiving vehicle data.

<CardGroup>
  <Card title="VEHICLE_STATE Event" icon="car" href="/api-reference/webhooks/events/vehicle-state">
    Learn about signal data deliveries
  </Card>

  <Card title="VEHICLE_ERROR Event" icon="triangle-exclamation" href="/api-reference/webhooks/events/vehicle-error">
    Handle error notifications
  </Card>

  <Card title="Callback Verification Guide" icon="book" href="/integrations/webhooks/callback-verification">
    Complete step-by-step implementation
  </Card>

  <Card title="Receiving Webhooks" icon="code" href="/integrations/webhooks/receiving-webhooks">
    Build a complete webhook handler
  </Card>
</CardGroup>


# Subscribe
Source: https://smartcar.com/docs/api-reference/webhooks/subscribe-webhook

POST https://api.smartcar.com/v2.0/vehicles/{id}/webhooks/{webhook_id}
Subscribe a vehicle to a webhook.

## Request

**Path**

<Snippet />

<ParamField type="string">
  The webhook id you are subscribing the vehicle to. This can be found in Dashboard under Webhooks.
</ParamField>

<Snippet />

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="vehicleId" type="string">
  The [vehicle id](/docs/api-reference/all-vehicles) of the vehicle you are making a request to.
</ResponseField>

<ResponseField name="webhookId" type="string">
  The webhook id you are subscribing the vehicle to.
</ResponseField>

<ResponseExample>
  ```json ResponseExample theme={null}
  {
      "vehicleId": "dc6ea99e-57d1-4e41-b129-27e7eb58713e",
      "webhookId": "9b6ae692-60cc-4b3e-89d8-71e7549cf805"
  }   
  ```
</ResponseExample>


# Unsubscribe
Source: https://smartcar.com/docs/api-reference/webhooks/unsubscribe-webhook

DELETE https://api.smartcar.com/v2.0/vehicles/{id}/webhooks/{webhook_id}
Unsubscribe a vehicle from a webhook.

## Request

**Header**

<ParamField type="string">
  In the format `Bearer {application_management_token}`. You can find your `application_management_token` under
  your Application Configuration in Dashboard.
</ParamField>

**Path**

<Snippet />

<ParamField type="string">
  The [webhook id](/docs/api-reference/management/get-vehicle-connections) you are unsubscribing the vehicle from.
</ParamField>

<RequestExample>
  <Snippet />
</RequestExample>

## Response

<ResponseField name="status" type="string">
  Status of the request.
</ResponseField>

<ResponseExample>
  ```json Example Response theme={null}
  {
      "status": "success"
  }
  ```
</ResponseExample>


# 2022 Releases
Source: https://smartcar.com/docs/changelog/2022



## January 5, 2022

Smartcar is now compatible with Mercedes-Benz vehicles in the United States.

## February 23, 2022

The EV Battery and EV Charging status and control endpoints are now available for Lexus and Toyota vehicles in Canada and the United States.

## February 21, 2022

The Tire Pressure endpoint is now available for Lexus and Toyota vehicles in Canada and the United States.

## February 14, 2022

Smartcar is now compatible with Chrysler, Dodge, Jeep, and RAM vehicles in Canada.

## February 2, 2022

Brand-specific endpoints are now available for Cadillac, Chevrolet, and Tesla. A full list of the available endpoints is available in the API Reference.

<CodeGroup>
  ```Node Node theme={null}
  const amperage = vehicle.request('GET', 'tesla/charge/ammeter');
  ```

  ```Python Python theme={null}
  amperage = vehicle.request("GET", "tesla/charge/ammeter")
  ```

  ```Java Java theme={null}
  SmartcarVehicleRequest request = new SmartcarVehicleRequest.Builder()
    .method("GET")
    .path("tesla/charge/ammeter")
    .build();
  VehicleResponse amperage = vehicle.request(request);
  ```

  ```Ruby Ruby theme={null}
  amperage = vehicle.request("GET", "tesla/charge/ammeter")
  ```
</CodeGroup>

## March 7, 2022

Smartcar is now compatible with MINI vehicles in Canada, the United States, and our supported European countries.

## April 13, 2022

Smartcar's webhooks now have beta support for sending events in response to events that are generated by the vehicle itself. The initial release supports the following events on Ford, Tesla, and Toyota vehicles in Canada, the United States, and our supported European countries:

* `CHARGING_STARTED`
* `CHARGING_STOPPED`
* `CHARGING_COMPLETED`
  Webhook events sent in response to vehicle events can be distinguished from schedule events based on the `eventName` property of the POST body. For example, the POST body for event based webhooks will have the following structure:

```json theme={null}
{
  "version": "2.0",
  "webhookId": "uuid",
  "eventName": "eventBased",
  "mode": "test|live",
  "payload": {
    "eventId": "uuid",
    "vehicleId": "uuid",
    "eventType": "CHARGING_STARTED|CHARGING_STOPPED|CHARGING_COMPLETED",
    "eventTime": "ISO8601 Datetime"
  }
}
```

## May 9, 2022

Smartcar is now compatible with Kia vehicles in our supported European countries.

## May 5, 2022

The API now returns more detailed errors for the following:

`UPSTREAM:RATE_LIMIT` - a request fails due to a vehicle rate limit.
`VEHICLE_STATE:NOT_CHARGING` - a vehicle is not charging (only applies to endpoints that return details about a specific charging session e.g. Charging Completion Time).

## June 29, 2022

Smartcar is now compatible with Peugeot and Opel vehicles in our supported European countries.

## June 22, 2022

The Tire Pressure endpoint is now available for BMW, MINI, and Tesla vehicles in Canada, the United States, and our supported European countries.

## June 15, 2022

The API now returns a more detailed VEHICLE\_STATE error whenever a charge request fails due to charger issues or charging schedules. Click the following link to learn more:

VEHICLE\_STATE:CHARGE\_FAULT

## June 8, 2022

Smartcar is now compatible with Nissan vehicles in our supported European countries.

## July 20, 2022

Smartcar is now compatible with Citroën, DS, and Vauxhall vehicles in our supported European countries.

## July 6, 2022

The following brand-specific endpoints are now available for Tesla vehicles in Canada, the United States, and our supported European countries:

* GET `/tesla/compass`
* GET `/tesla/speedometer`

## August 24, 2022

Smartcar is now compatible with Rivian vehicles in the United States.

## August 3, 2022

Smartcar is now compatible with Škoda vehicles in our supported European countries.
The EV Charging control endpoint is now available for Hyundai vehicles in the United States.
The EV Battery Capacity endpoint is now available in our supported European countries.

## September 22, 2022

The following brand-specific endpoint is now available for Tesla vehicles in Canada, the United States, and our supported European countries:

* `POST /tesla/charge/ammeter`

## November 30, 2022

Smartcar is now compatible with Kia vehicles in Canada and the United States.

## December 29, 2022

The Location endpoint is now available for Volkswagen ID series vehicles in our supported European countries.


# 2023 Releases
Source: https://smartcar.com/docs/changelog/2023



## January 6, 2023

Smartcar API v1.0 has been sunset and is no longer supported. If you are currently using v1.0 for API requests, webhooks, errors, or compatibility, we recommend switching to v2.0 as soon as possible.

## March 16, 2023

The API now returns a new code for the RATE\_LIMIT error type if your application tries to make a request to a vehicle too frequently. Click the following link to learn more:

[RATE\_LIMIT:VEHICLE](https://smartcar.com/docs/errors/v2.0/rate-limit/#vehicle)

## March 14, 2023

Smartcar has revamped the Connect flow UI and backend to improve error handling and optimize user conversion rates. Our updates fall into 3 categories: improving brand selection, expanding login methods, and establishing new error codes specific to Connect. These include:

1. Allowing a user to search for:

a. Brand aliases in Brand Select such as VW for Volkswagen

b. Unavailable brands that we plan to introduce in the future, which will display a message highlighting future compatibility with the chosen brand.

2. Expanding login method coverage to include phone numbers for certain brands. We now allow users to log in using email or phone number for the Connect flow starting with Kia and Mercedes-Benz. Stay tuned to our changelog for more brand updates.
3. Providing clearer errors for the Connect flow:

a. no\_vehicles for when the user does not have any vehicles tied to their account and they click to go back to the application

b. configuration\_error for when exiting Connect back to your app through an error page (see below).

<Frame>
  <img />
</Frame>

c. server\_error which is thrown if there is not another Connect error specified.

More documentation on error handling can be found [here](https://smartcar.com/docs/integration-guide/test-your-integration/test-errors/#1-connect-errors).

## March 6, 2023

The disconnect endpoint now supports the use of management API token (MAT) for authorization purposes. Documentation can be found [here](https://smartcar.com/docs/api#delete-disconnect)

## May 10, 2023

Smartcar is now compatible with Infiniti vehicles in the United States.

## June 7, 2023

Smartcar is now compatible with Hyundai vehicles in Canada.

## June 5, 2023

Test mode supports the following email format with any password to generate an account with multiple vehicles:

`<number>-vehicles@smartcar.com`

## July 26, 2023

The following brand-specific endpoints are now available for Tesla vehicles in Canada, the United States, and our supported European countries:

* GET `/tesla/charge/records`
* GET `/tesla/charge/records/billing`

## July 19, 2023

Smartcar is now compatible with Mercedes-Benz vehicles in our supported European countries.

## July 12, 2023

The following brand-specific endpoints are now available for Tesla vehicles in Canada, the United States, and our supported European countries:

* GET `/tesla/charge/schedule`
* POST ` /tesla/charge/schedule`
* GET `/tesla/climate/cabin`
* POST ` /tesla/climate/cabin`
* GET `/tesla/climate/defroster`
* POST ` /tesla/climate/defroster`
* GET `/tesla/climate/steering_wheel`
* POST ` /tesla/climate/steering_wheel`

## August 22, 2023

The following brand-specific endpoints are now available for Nissan vehicles in the United States:

* GET /nissan/charge/schedule
* PUT /nissan/charge/schedule

## August 17, 2023

The following endpoints are now available to manage vehicle connections:

* GET Vehicle Connections
* DELETE Vehicle Connections

## August 9, 2023

<img />

The following brand-specific endpoints are now available for Ford and Lincoln vehicles in Canada, the United States, and our supported European countries:

* GET ford/charge/schedule\_by\_location
* PUT ford/charge/schedule\_by\_location
* GET lincoln/charge/schedule\_by\_location
* PUT lincoln/charge/schedule\_by\_location

## September 21, 2023

Introducing Vehicle Management! With this initial release you're able to see and manage
vehicles connected to your applications from within the [Smartcar Dashboard](https://dashboard.smartcar.com/login).

<Frame type="simple">
  <img />
</Frame>

<br />

<br />

<sub>
  <sup>
    Logos and brand names are for identification purposes only and do not
    indicate endorsement of or affiliation with Smartcar.
  </sup>
</sub>

## September 19, 2023

[Charge Records](/docs/api-reference/bmw/get-charge-records) is now available as a make specific endpoint for BMW and MINI in Canada, the United States, and our supported European countries.

## September 06, 2023

<img />

Lock Status is now available as a Core endpoint and supported by the following makes:

* Tesla (Global)
* Ford (Global)
* Kia (Global)
* Jaguar (Global)
* Land Rover (Global)
* BMW (Global)
* MINI (Global)
* Lincoln (US)
* Toyota (US)
* Lexus (US)

In addition to the lock status of the vehicle, Smartcar will also return the open status of doors, sunroof, windows, based on what the vehicle supports.

## October 19, 2023

<Frame type="simple">
  <img />
</Frame>

BMW and MINI EVs are now compatible with the following endpoints globally:

* [Get Charge Limit](/docs/api-reference/evs/get-charge-limit)
* [Set Charge Limit](/docs/api-reference/evs/set-charge-limit)

## October 5, 2023

<Frame type="simple">
  <img />
</Frame>

Smartcar is now compatible with Hyundai in supported European countries.

## October 3, 2023

<Frame type="simple">
  <img />
</Frame>

Smartcar is now compatible with Mazda and Porsche in supported European countries.

## November 15, 2023

<Frame type="simple">
  <img />
</Frame>

Smartcar is now compatible with CUPRA in supported European countries.


# 2024 Releases
Source: https://smartcar.com/docs/changelog/2024



<Update label="December 20, 2024">
  ## Fetched At Header

  A new [SC-Feched-At](https://smartcar.com/docs/api-reference/headers) header is now available. This new header highlights when Smartcar fetched the returned data from an OEM whereas `sc-data-age` indicates when the returned data was recorded by the vehicle.
</Update>

<Update label="December 20, 2024">
  ## Connect Playground

  <Frame type="simple">
    <img />
  </Frame>

  The [Connect Playground](https://smartcar.com/docs/getting-started/dashboard/playground) is available, making it easier than ever to create your Connect URL and start requesting vehicle consent.
</Update>

<Update label="December 18, 2024">
  ## Diagnostic Webhook

  A new [Diagnostic Webhook](https://smartcar.com/docs/getting-started/tutorials/webhooks-diagnostic) is available in beta. This webhook delivers either [Diagnostic Trouble Code](https://smartcar.com/docs/api-reference/get-dtcs) events or [System Status](https://smartcar.com/docs/api-reference/get-system-status) changes.
</Update>

<Update label="December 3, 2024">
  ## Diagnostic Trouble Codes

  A new [Diagnostic Trouble Code](https://smartcar.com/docs/api-reference/get-dtcs) endpoint is available in beta. This endpoint returns a list of active Diagnostic Trouble Codes (DTCs) and the timestamp they last became active.
</Update>

<Update label="November 5, 2024">
  ## Ford authentication update

  Ford's authentication process has been updated to require the use of SDKs. Our [Connect SDKs](https://smartcar.com/docs/connect/connect-sdks) have been updated to redirect to Ford's site to handle the authentication process when the user logs in.
</Update>

<Update label="November 1, 2024">
  ## System Status endpoint now in Beta

  A new [System Status](https://smartcar.com/docs/api-reference/get-system-status) endpoint is available in beta. This endpoint returns a list of vehicle components and their health state for FCA and GM makes.
</Update>

<Update label="October 10, 2024">
  ## Webhooks subscription status

  The Smartcar Dashboard now indicates which webhooks a vehicle is  subscribed to. From the Vehicles table, click into the three dot menu to view vehicle details. From here, navigate to the new Webhooks tab!
</Update>

<Update label="September 25, 2024">
  ## Dynamic Webhooks now in Beta

  [Dynamic Webhooks](/docs/getting-started/tutorials/webhooks-dynamic) are now in beta for Enterprise customers! Please request access from the Webhooks tab on the Smartcar Dashboard!
</Update>

<Update label="September 30, 2024">
  ## Multi-Factor Authentication in Dashboard

  [Multi-Factor Authentication](/docs/getting-started/dashboard/dashboard-mfa) is available to offer an additional layer of security for the Smartcar Dashboard.
</Update>

<Update label="August 19, 2024">
  ## Support for MG in Europe

  Support for the following endpoints are now available for the MG brand in Europe:

  * [VIN](/docs/api-reference/get-vin)
  * [Odometer](/docs/api-reference/get-odometer)
  * [Lock Status](/docs/api-reference/get-lock-status)
  * [Lock/Unlock](/docs/api-reference/control-lock-unlock)
  * [Tire Pressure](/docs/api-reference/get-tire-pressure)
  * [GET Charge Limit](/docs/api-reference/evs/get-charge-limit)
  * [POST Charge Limit](/docs/api-reference/evs/set-charge-limit)
  * [Battery Level](/docs/api-reference/evs/get-battery-level)
  * [Battery Capacity](/docs/api-reference/evs/get-battery-capacity)
</Update>

<Update label="August 9, 2024">
  ## Support for Honda, Subaru, Acura, and more!

  Smartcar is now compatible with the **Honda Prologue**, **Subaru Solterra** and the **Acura ZDX** in supported regions.

  ### Additional Releases

  The following brands now support [Control Charge](/docs/api-reference/evs/control-charge), [Battery Level](/docs/api-reference/evs/get-battery-level), [Battery Capacity](/docs/api-reference/evs/get-battery-capacity) and [Charge Status](/docs/api-reference/evs/get-charge-status):

  * Jeep, Fiat and Alfa Romeo (US, Canada and Europe)
  * Chevrolet, Cadillac and GMC (US and Canada)
  * RAM and Dodge (US and Canada)
  * Porsche (US and Europe)
  * Mazda (US and Europe)
  * Renault (Europe)
  * Nissan (Europe)
</Update>

<Update label="August 6, 2024">
  ## Smartcar is now compatible with Dacia in Europe.

  Support for the following endpoints are now available for the MG brand in Europe:

  * [Vehicle Info](/docs/api-reference/get-vehicle-info)
  * [Location](/docs/api-reference/get-location)
  * [Control Charge](/docs/api-reference/evs/control-charge)
  * [State of Charge](/docs/api-reference/evs/get-battery-level)
  * [Charging Status](/docs/api-reference/evs/get-charge-status)
</Update>

<Update label="July 31, 2024">
  ## Connect Insights is now available!

  <Frame type="simple">
    <img />
  </Frame>

  * Each Connect flow launched for the previous two weeks is available in the Smartcar Dashboard with a variety of ways to search for specific Connect launches.
  * Enterprise customers have access to funnel analysis so they can understand their conversion rates in the Connect flow.
</Update>

<Update label="July 30, 2024">
  ## Test & Simulated modes are now one

  Test and Simulated mode have been combined into a singular mode; Simulated.

  If a simulated vehicle is enabled, we will return data following the selected trip. If the simulated vehicle doesn't support the requested endpoint, randomized data will be returned.

  If no simulated vehicle is enabled for, we will return data as if a simulated vehicle with "Day Commute" was selected. If the simuday commute doesn't support the requested endpoint, randomized data will be returned.
</Update>

<Update label="July 25, 2024">
  ## Support for Google authentication in Dashboard

  The Smartcar Dashboard now supports Google authentication.
</Update>

<Update label="July 3, 2024">
  ## User information for Tesla

  The following endpoints are now available for Tesla:

  * [Get User Info](/docs/api-reference/tesla/get-user-info)
  * [Get User access](/docs/api-reference/tesla/get-user-access)
</Update>

<Update label="June 24, 2024">
  ## Customize brands in Connect

  <Frame type="simple">
    <img />
  </Frame>

  You can now customize which bands show up in Connect from the [Dashboard](https://dashboard.smartcar.com/). Easily manage which brands your users can connect to based on engine type or endpoint.
</Update>

<Update label="June 20, 2024">
  ## Get charge endpoint for Audi

  The following Brand Specific Endpoint is now available for Audi:

  * [Get Charge Status](/docs/api-reference/audi/get-charge)
</Update>

<Update label="June 5, 2024">
  ## Additional endpoints for Audi

  The following endpoints are now available for Audi:

  * [Get Charge Limit](/docs/api-reference/evs/get-charge-limit)
  * [Set Charge Limit](/docs/api-reference/evs/set-charge-limit)
  * [Control Charge](/docs/api-reference/evs/control-charge)
  * [Lock Status](/docs/api-reference/get-lock-status)
</Update>

<Update label="May 10, 2024">
  ## Service history

  The following endpoint is now available for Ford, Lincoln, Toyota, Lexus, Mazda and Volkswagen (US) vehicles:

  * [GET /service/history](/docs/api-reference/get-service-records)
</Update>

<Update label="May 8, 2024">
  ## Tesla alerts

  The following make specific endpoint is now available for Tesla across all supported regions:

  * [GET /tesla/alerts](/docs/api-reference/tesla/get-alerts)
</Update>

<Update label="April 25, 2024">
  ## Tesla charge battery and suggested user messages

  <Frame type="simple">
    <img />
  </Frame>

  The following make specific endpoints are now available for Tesla across all supported regions:

  * [GET /tesla/charge](/docs/api-reference/tesla/get-charge)
  * [GET /tesla/battery](/docs/api-reference/tesla/get-battery)

  ### Additional Releases

  Suggested user messages are now included as part of API error responses for you to easily surface resolution steps to vehicle owners. See our [error documentation](/docs/api-reference/api-errors) for more details.
</Update>

<Update label="April 9, 2024">
  ## Country management for Smartcar Connect

  <Frame type="simple">
    <img />
  </Frame>

  Country Management is now available for Connect! Easily manage what countries are enabled for your application on Dashboard.

  ### Additional Releases

  The `user` parameter is now available when [building the Connect URL](/docs/connect/redirect-to-connect) to pass a unique identifier for a vehicle owner to track and aggregate analytics across their Connect sessions for your application.
</Update>

<Update label="March 6, 2024">
  ## Organization access for teams

  <Frame type="simple">
    <img />
  </Frame>

  Organization access for Teams is now available on Dashboard. Check out our docs page on [Teams](/docs/getting-started/dashboard/teams) for details.

  ### Additional Releases

  The following endpoint is now available for Tesla vehicles globally:

  * [Virtual Key Status](/docs/api-reference/tesla/get-virtual-key-status)
</Update>

<Update label="February 14, 2024">
  ## Subaru US

  <Frame type="simple">
    <img />
  </Frame>

  Smartcar is now compatible with Subaru in the US.

  ### Additional Releases

  The following endpoints are now available for Tesla vehicles globally:

  * [Control Charge Port](/docs/api-reference/tesla/control-charge-port)
  * [Control Frunk](/docs/api-reference/tesla/control-frunk)
  * [Control Trunk](/docs/api-reference/tesla/control-trunk)
</Update>

<Update label="February 8, 2024">
  ## Fuel endpoint for European brands

  <Frame type="simple">
    <img />
  </Frame>

  The [GET /fuel](/docs/api-reference/get-fuel-tank) endpoint is now available for the following brands in supported European countries:

  | <div /> | <div />    | <div />       | <div />    |
  | ------- | ---------- | ------------- | ---------- |
  | Audi    | Hyundai    | Mercedes-Benz | Skoda      |
  | BMW     | Jaguar     | MINI          | Vauxhall   |
  | Citroen | Kia        | Opel          | Volkswagen |
  | DS      | Land Rover | Peugeot       | Volvo      |
  | Ford    | Mazda      | Renault       |            |
</Update>


# 2025 Releases
Source: https://smartcar.com/docs/changelog/2025



<Update label="December 15th, 2025">
  ## Mercedes-Benz Partner Integration Now Available in Europe!

  <Frame>
    <img alt="" />
  </Frame>

  We're excited to announce that Mercedes-Benz is now available on Smartcar! Connect Mercedes-Benz electric vehicles (BEV and PHEV) to access vehicle data and enable smart charging capabilities.

  **What's new:**

  * Mercedes-Benz BEV and PHEV vehicles can now connect through Smartcar
  * Enhanced connect flow with VIN verification for Mercedes vehicles
  * Support for key vehicle data signals including battery level, charge status, and location

  **Important notes:**

  * Currently, only Battery Electric Vehicles (BEV) and Plug-in Hybrid Electric Vehicles (PHEV) are supported with this integration.
  * Need support for other Mercedes vehicle types? [Contact us](https://smartcar.com/contact) to discuss your requirements.

  Check out the [Mercedes-Benz integration guide](/docs/help/oem-integrations/mercedes/whats-new) for more details.
</Update>

<Update label="December 5th, 2025">
  ## Vehicle data in Dashboard Coming Soon!

  <Frame>
    <img alt="" />
  </Frame>

  Vehicle data will be available in your Smartcar Dashboard. This feature is now rolling out to some customers and will be available to all customers over the next few weeks.

  If you are interested in this feature or have any questions, please reach out to your Smartcar account manager or contact our support team.
</Update>

<Update label="December 5th, 2025">
  ## Dashboard updates: API logs, timezone controls, and more!

  We've added more visibility into production usage in the Dashboard so you can monitor API requests and webhook delivery health in one place.

  **What's new:**

  * **API V3 call tracking**: See which API V3 endpoints are being called directly in the Dashboard to monitor migration progress
  * **Active vehicle counter**: Track how many vehicles are actively delivering webhooks successfully to spot delivery gaps faster
  * **Timezone customization**: Set your preferred timezone in the Dashboard so charts and tables align with your operations

  **Get started**: Check out these updates in the [Smartcar Dashboard](https://dashboard.smartcar.com/).
</Update>

<Update label="December 5th, 2025">
  ## BMW Charging API now live across Europe

  <Frame>
    <img alt="" />
  </Frame>

  We've partnered with BMW to bring their new Charging API to Europe, giving energy providers privacy-first access to BMW EVs for smart charging, grid optimization, and home energy management.

  This integration is now available in select European markets. Reach out to your Smartcar team to enable BMW Charging for your app or learn more in the [partnership announcement](https://smartcar.com/blog/smartcar-and-bmw-partnership).
</Update>

<Update label="November 19th, 2025">
  ## Improved Webhook Logs in Dashboard

  We've significantly improved the webhook logging experience in the Smartcar Dashboard, making it easier to monitor and debug webhook deliveries.

  **What's New:**

  * **Delivery-focused logging**: Each log row now represents a single webhook delivery, providing a clearer view of your webhook activity
  * **Detailed inspection**: Click "View logs" on any delivery to inspect the signal or endpoint items included in that delivery and their individual statuses
  * **Faster performance**: Reduced latency in both Webhook Logs and the webhook deliveries over time chart for a more responsive experience

  **Where to Find It:**
  You can view your webhook logs in two locations:

  * **Logs > Webhooks** in the main navigation
  * **Vehicles > \[Selected vehicle] > Webhooks** for vehicle-specific logs

  **Get started**: Head to the [Smartcar Dashboard](https://dashboard.smartcar.com/logs?tab=webhooks) to explore the improved webhook logs.
</Update>

<Update label="November 18th, 2025">
  ## Python SDK and Node SDK Updated to Support Version 3 of the Vehicles API

  The [Python SDK](https://github.com/smartcar/python-sdk) and [Node SDK](https://github.com/smartcar/node-sdk) have been updated to support [Version 3 of the Vehicles API](/docs/api-reference/intro).

  Both SDKs now include three new methods:

  * `get_vehicle` - Retrieve vehicle information
  * `get_signal` - Get a specific signal for a vehicle
  * `get_signals` - Get all available signals for a vehicle

  These new methods provide easier access to vehicle data through the latest API version, enabling developers to work with Smartcar's expanded signal catalog and improved data delivery capabilities.

  **Get started**: Update to the latest SDK version and explore the new methods in the [Python SDK](https://github.com/smartcar/python-sdk) and [Node SDK](https://github.com/smartcar/node-sdk) documentation.
</Update>

<Update label="November 12th, 2025">
  ## Polestar and BYD are now available on Smartcar!

  <Frame>
    <img alt="" />
  </Frame>

  We're excited to bring compatibility for Polestar and BYD, expanding the number of brands on the platform to 45!

  To enroll vehicles from these brands, make sure you have them enabled for your application in the [Dashboard](https://dashboard.smartcar.com/configuration?tab=oem-brands).

  Once enabled, you can direct vehicle owners to connect their Polestar and BYD vehicles through the Smartcar Connect flow.

  For a list of data points supported for these brands, see the [compatibility matrix](https://smartcar.com/product/compatible-vehicles).

  See important note about [BYD's login requirement](/docs/help/brand-quirks#byd).
</Update>

<Update label="November 12th, 2025">
  ## Upcoming Change to Webhook Payload Structure

  Webhook `VEHICLE_STATE` payloads are being updated to include a `status` value for all signals. Previously, a `status` value was only passed for signals with errors.

  Example Payload:

  ```json theme={null}
  {
    "code": "location-preciselocation",
    "name": "PreciseLocation",
    "group": "Location",
    "body": {
      "latitude": 37.386051,
      "longitude": -122.083855
    },
    "status": {
      "value": "SUCCESS"
    }
  },
  ```

  This change will go live on November 17, 2025, at 11:00AM Pacific Time. Please ensure your webhook receiver is prepared to handle deliveries in this format.
</Update>

<Update label="November 12th, 2025">
  ## Extended Expiration Times for Vehicle Refresh Tokens

  Starting November 12, 2025, Vehicle Refresh Tokens will expire 10 minutes after they are used to generate a new token set. This is an extension from the previous expiration time of 1 minute.

  For more information about access tokens, see [Refreshing Access Tokens](/docs/api-reference/authorization/refreshing-access-token)
</Update>

<Update label="November 10th, 2025">
  ## Verifying webhooks just got a lot easier!

  <Frame>
    <img alt="" />
  </Frame>

  When you verify a webhook, you'll see a guided modal with a sample challenge string, copy-ready SDK snippets (Python, Node, Java, Ruby), and inline instructions for hashing the `application_management_token` plus challenge.

  When your server responds with your webhook verification, you'll see the response that Smartcar received compared to the expected hash output.

  <Frame>
    <img alt="" />
  </Frame>

  If the verification fails, the new response tab surfaces the HTTP status, challenge string, expected hash output, and the payload Smartcar received so you can immediately compare and retry. This feedback loop removes trial-and-error, shortens onboarding for new teams, and ensures your webhook endpoint is producing the correct `SC-Signature` before you start ingesting production signals.

  **Get started**

  * Head to the [Smartcar Dashboard](https://dashboard.smartcar.com/integrations) and select your webhook integration to launch the verifier.
  * Follow the updated [Payload verification guide](/docs/integrations/webhooks/payload-verification) to reproduce the same HMAC calculation server-side.
  * After verification succeeds, wire up your [webhook receiver tutorial](/docs/getting-started/tutorials/webhook-receiver-recipe) or call the [webhook overview](/docs/integrations/webhooks/overview) docs for deployment best practices.
</Update>

<Update label="November 5th, 2025">
  ## TypeScript Webhook Recipe Now Available

  <Frame>
    <img alt="" />
  </Frame>

  Deploy production-ready webhook receivers in minutes with our new [TypeScript Webhook Recipe](https://github.com/smartcar/typescript-webhook-recipe)! This AWS serverless template provides everything you need to handle Smartcar webhooks at scale:

  * **Complete Infrastructure**: Lambda + API Gateway + SQS with AWS CDK
  * **Built-in Validation**: Automatic webhook verification and payload validation
  * **Error Handling**: Dead letter queues and retry logic for reliability
  * **Production Ready**: CloudWatch monitoring, IAM security, and auto-scaling
  * **Developer Friendly**: TypeScript types and comprehensive documentation

  The recipe eliminates the complexity of building webhook infrastructure from scratch, letting you focus on your business logic. Perfect for new webhook implementations or teams wanting to deploy quickly without infrastructure overhead.

  **Get started**: [Webhook Receiver Recipe Documentation](/docs/getting-started/tutorials/webhook-receiver-recipe) | [GitHub Repository](https://github.com/smartcar/typescript-webhook-recipe)
</Update>

<Update label="September 18th, 2025">
  ## Battery Capacity Selection in the Smartcar Connect Flow

  <Frame>
    <img alt="" />
  </Frame>

  When you request the `read_battery` permission and Smartcar detects multiple possible battery capacity matches for a vehicle, users will now be automatically prompted to select their battery capacity during the Connect flow.

  This streamlined experience eliminates the need for developers to prompt users or source the battery capacity selection from other sources. This step ensures that battery capacity data is available immediately after vehicle connection if Smartcar is not able to identify it.

  Read more about the [User Selected Battery Capacity](/docs/connect/user-selected-batcap).
</Update>

<Update label="September 15th, 2025">
  ## Smartcar Partners with Mercedes-Benz Connectivity Services GmbH!

  <Frame>
    <img alt="" />
  </Frame>

  We are excited to announce our partnership with Mercedes-Benz Connectivity Services GmbH, expanding seamless access to connected vehicle data for developers and businesses across Europe.

  This integration enables developers to build innovative applications using data from Mercedes-Benz vehicles, including popular models such as the A-Class, C-Class, E-Class, S-Class, GLA, GLC, and more.

  With this partnership, Smartcar customers can leverage secure, reliable, and real-time access to vehicle data for a wide range of use cases, from fleet management to mobility services.

  Read more about this partnership and its impact in our [blog post](https://smartcar.com/blog/smartcar-partners-with-mercedes-benz-connectivity-services-gmbh).
</Update>

<Update label="August 26th, 2025">
  ## Introducing the new Smartcar Platform!

  <Frame>
    <img alt="" />
  </Frame>

  We are excited to announce the launch of the new Smartcar Platform, designed to provide a more reliable and efficient way to access vehicle data. With our new [webhook integration](/docs/integrations/webhooks/overview) and [API](/docs/api-reference/intro), developers can now receive vehicle data at higher frequencies and with improved reliability.

  For all use cases, Smartcar can deliver data as it detects changes based on our new standardized Signal Schema while avoiding unnecessary polling. With over 80 signals available, developers can access a wide range of vehicle data to build innovative applications.

  Getting started with Smartcar is now even easier. [Configure](/docs/getting-started/configure-application) your app, [Connect](/docs/getting-started/connect-vehicles) vehicles, and start receiving data via [webhooks](/docs/integrations/webhooks/overview) in just a few minutes.

  To get started with the new webhooks, check out our [Getting Started guide](/docs/getting-started/introduction) and [Webhook integration overview](/docs/integrations/webhooks/overview).

  These new features are now available to all new customers. Existing customers can reach out to their account manager or contact our support team at [support@smartcar.com](mailto:support@smartcar.com)
</Update>

<Update label="August 6th, 2025">
  ## Smartcar Partners with Ford in Europe!

  <Frame>
    <img alt="" />
  </Frame>

  Smartcar is thrilled to announce our partnership with Ford in Europe, enabling developers to access vehicle data from millions of Ford vehicles across the continent.

  This upcoming integration will give developers seamless access to vehicle data from models including the Mustang Mach-E, E-Transit, Puma, Fiesta, and Kuga.

  Read more about this exciting partnership in our [blog post](https://smartcar.com/blog/smartcar-partners-with-ford-to-expand-access-to-connected-vehicle-apis?utm_source=docs\&utm_medium=changelog).
</Update>

<Update label="July 9, 2025">
  ## Rivian Commands Now Available!

  <Frame>
    <img alt="" />
  </Frame>

  You can now use the Smartcar API to send commands--such as lock, unlock, and start/stop charge--to Rivian vehicles!

  When requesting command permissions (like `control_security` or `control_charge`), Rivian owners will be prompted to pair their phone with their vehicle. After successful pairing, your application will be able to issue commands to the connected Rivian.

  For step-by-step instructions, see our [Rivian Bluetooth Pairing guide](/docs/connect/other-actions/rivian-bluetooth-pairing).

  > **Note:** Read data permissions (such as `read_location` or `read_charge`) do not require Bluetooth pairing.
  >
  > Smartcar mobile SDKs for iOS and Android are required for Bluetooth pairing.
</Update>

<Update label="June 23, 2025">
  ## Hyundai Lock and Unlock now available!

  <Frame>
    <img alt="" />
  </Frame>

  You can now lock and unlock Hyundai vehicles using the same standard Smartcar API. This new feature enables remote control of vehicle doors for supported Hyundai models, making it easier to build secure and convenient experiences for your users.

  For more details on how to use this capability, see our [API reference](/docs/api-reference/control-lock-unlock).

  ## Webhook Logs Now Available in Dashboard

  You can now view logs for your webhooks directly in the Smartcar Dashboard, alongside your API request logs. This update gives you greater visibility into webhook deliveries, making it easier to monitor, debug, and ensure successful integrations.

  To see your webhook logs in action, head over to the [Smartcar Dashboard](https://dashboard.smartcar.com/logs?tab=webhooks).
</Update>

<Update label="June 10, 2025">
  ## New Dashboard Overview Page

  <Frame>
    <img alt="" />
  </Frame>

  Our new Dashboard overview page offers a comprehensive snapshot of your application's performance at a glance. Now, you can quickly visualize:

  * Total vehicle connections
  * New connections in the last 7 days
  * Request trends over time
  * Conversion rates
  * Top five vehicle brands connected to your application

  This update is designed to help you monitor key metrics effortlessly.
</Update>

<Update label="May 20, 2025">
  ## Virtual Keys installation Is Now Supported in Connect

  Smartcar now provides detailed steps for adding and managing Virtual Keys during the connection flow. Virtual Keys are required for third-party applications to issue commands to Tesla vehicles and are the preferred method for accessing data.

  <Frame>
    <img alt="" />
  </Frame>

  For more details, visit the [Virtual Key documentation](/docs/help/oem-integrations/tesla/virtual-key-tesla).
</Update>

<Update label="May 9, 2025">
  ## atHome signal is now available!

  <Frame>
    <img alt="" />
  </Frame>

  Smartcar now supports a new vehicle signal `atHome` that returns true or false if a vehicle is at the configured home location. This signal is currently available for Tesla vehicles capable of streaming via [this endpoint](/docs/api-reference/tesla/get-ext-vehicle-info).
</Update>

<Update label="April 21, 2025">
  ## Our New Support Features Are Live!

  <Frame>
    <img alt="" />
  </Frame>

  We're excited to share that our new support experience is now available. These updates are designed to make it easier and faster to get the help you need through self-service tools, AI-powered assistance, and improved visibility into your support history.

  **Customer Support Portal** *(Available to paid customers via the Smartcar Dashboard)*

  Your new central hub for all support-related needs:

  * Browse the **Knowledge Base** for helpful articles, guides, and troubleshooting tips
  * Submit new support requests through a user-friendly form
  * View and update **open tickets**, track past communications, and receive timely updates
  * Get help fast with our **AI-powered chat agent**, available 24/7

  **Enhanced Slack Support** *(For eligible plans)*

  Our upgraded Slack support includes:

  * AI-powered answers to common questions directly in your Slack channel
  * Ability to create and track support tickets without leaving Slack
  * One-click access to the Customer Support Portal
  * Real-time updates and faster response workflows

  For more information about what's included in your current plan, please reach out to your account manager or contact us at [**support@smartcar.com**](mailto:support@smartcar.com).

  For step-by-step instructions on how to use the new features, check out our documentation [here](https://smartcar.com/docs/help/accessing-support-center).
</Update>

<Update label="March 26, 2025">
  ## Support for Single Sign-on (SSO)

  <Frame>
    <img alt="" />
  </Frame>

  Single Sign-On (SSO) is now available for teams on an Enterprise plan. To get started, reach out to your account manager to have it enabled. For implementation details and setup instructions, check out our [SSO documentation](/docs/getting-started/dashboard/single-sign-on).
</Update>

<Update label="February 26, 2025">
  ## User Selected Battery Capacity

  <Frame>
    <img alt="" />
  </Frame>

  <Frame>
    <img alt="" />
  </Frame>

  Developers can now redirect vehicle owners to a Smartcar Connect url where they can select the [battery capacity](/docs/api-reference/get-nominal-capacity) of their vehicle for cases where the battery capacity cannot be accurately determined. This can occur when vehicle owners purchase extension packs, or software upgrades specific to their vehicle. When a user selects an option, Smartcar will return this value with `USER_SELECTED` as the source.
</Update>

<Update label="February 14, 2025">
  ## Diagnostics Webhooks, DTSs, and System Status

  Smartcar now provides Diagnostic Webhooks, DTCs, and System Status vehicle data for an [initial set of brands](https://smartcar.com/product/compatible-vehicles) with more brands added in the future.
</Update>

<Update label="February 6, 2025">
  ## Support for Simplified Chinese

  <Frame>
    <img alt="" />
  </Frame>

  Vehicle owners can now select Simplified Chinese as they go through the Smartcar Connect flow to connect their cars.
</Update>

<Update label="January 30, 2025">
  ## Tesla Telemetry API

  Smartcar natively supports Tesla's Telemetry API as the default mechanism for retrieving data from Tesla vehicles out of the box and without any configuration from developers. Tesla's Telemetry API is the most efficient and effective way of gathering data from Tesla vehicles. It allows vehicles to stream data directly to Smartcar, eliminating the need to poll Tesla servers. This prevents unnecessary vehicle wakes and battery drain.
</Update>

<Update label="January 10, 2025">
  ## Smartcar MFA

  When a vehicle owner attempts to login to their OEM Connected Services Account and they do not have MFA enabled, Smartcar customers can enable this feature to enforce MFA verification for extra security. If you don't see this option in the Smartcar dashboard, contact [support@smartcar.com](mailto:support@smartcar.com) to get access to this feature.
</Update>

<Update label="January 6, 2025">
  ## New Billing page in Dashboard

  <Frame>
    <img alt="" />
  </Frame>

  This new page provides more visibility and the ability to update your billing information, view past invoices, and view your plan features and available upgrade options.
</Update>


# Latest Releases
Source: https://smartcar.com/docs/changelog/latest

Learn about Smartcar's latest product updates and improvements

[Subscribe to changelog updates](https://sta26.share.hsforms.com/2CCbdweFdSOeE5B58UvjVlw) and receive email notifications for new releases and updates.

<Update label="August 14th, 2026">
  ## Vehicles API v2.0 will be deprecated on December 1, 2026

  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. After that date it will no longer be supported.

  Migrate to the latest version, [v3](/docs/api-reference/intro), available since August 26, 2025. v3 covers vehicle data, commands, and connections with simpler application-level authentication. See the [v2.0 overview](/docs/api-reference/v2-overview) for the full deprecation notice.
</Update>

<Update label="July 30th, 2026">
  ## Bring your own identifier with external\_id

  <Frame>
    <img alt="external_id set on a connection and returned on the Connect response and in webhook payloads as user.externalId" />
  </Frame>

  You can now tag a Connect connection with your own identifier for the vehicle owner using `external_id`, and filter by this value when looking up connections.

  Set `external_id` when you launch Connect, in the Connect URL or with the JavaScript, iOS, Android, and Flutter SDKs. Smartcar stores it on the connection, echoes it back on the Connect response and in webhook payloads as `user.externalId`, and lets you filter the [`/connections`](/docs/api-reference/management/get-vehicle-connections) endpoint by it. In the Dashboard, you can filter connections by external\_id and see it on each vehicle's details.

  It is handy for machine-to-machine and application-token setups, where you can tie a connection back to your own records with an identifier you already use.

  See [Redirect to Connect](/docs/connect/redirect-to-connect) for setup.
</Update>

<Update label="July 29th, 2026">
  ## Test VIN/odometer verification and battery capacity selection in the Simulator

  The Vehicle Simulator now supports testing two additional Connect flows that prompt vehicle owners for additional input: the [VIN and odometer verification flow](/docs/help/oem-integrations/vw/whats-new) used by Audi, Cupra, Škoda, SEAT, and Volkswagen BEVs and PHEVs in Europe, and the [battery capacity selection flow](/docs/connect/user-selected-batcap) for EVs with an undetermined battery capacity.

  <Frame>
    <img alt="Testing the VIN/odometer and battery capacity Connect flows in the Vehicle Simulator" />
  </Frame>

  Learn how to test both flows in the [Vehicle Simulator documentation](/docs/getting-started/dashboard/simulator#test-additional-connect-flows).
</Update>

<Update label="July 28th, 2026">
  ## Legacy Tesla Model S and X require the data streaming toggle

  Owners of legacy Tesla Model S and X vehicles (model year 2020 and earlier) need to turn on **Allow Third-Party App Data Streaming** in the vehicle to keep a reliable connection. The setting is in the vehicle's **Safety** menu.

  <Frame>
    <img alt="Allow Third-Party App Data Streaming toggle in the vehicle's Safety menu" />
  </Frame>

  These vehicles don't support Virtual Keys. Tesla added third-party data streaming to them in firmware 2025.20 and later, and streaming is how Smartcar keeps an efficient connection for them going forward. When the toggle is off, the connection falls back to a reduced polling rate, so data may be delayed or intermittent.

  No code changes are required. Smartcar shows owners how to enable the toggle during Connect. For vehicles that are already connected, ask the owner to turn on Allow Third-Party App Data Streaming in the vehicle's Safety menu.
</Update>

<Update label="July 27th, 2026">
  ## Upcoming change: backend SDKs move to maintenance mode

  Our backend SDKs (Node.js, Python, Java, Ruby, and Go) are in maintenance mode as of today and are fully deprecated on December 1, 2026. Until then they receive security patches. After December 1, 2026 they will not be updated, including for security. The packages stay published and existing integrations keep working.

  For new integrations, call the API directly over HTTP with v3. The Connect SDKs (JavaScript, iOS, and Android) are unaffected and fully supported.

  Read more in [the announcement](https://smartcar.com/blog/a-simpler-way-to-build-with-smartcar).
</Update>

<Update label="July 16th, 2026">
  ## Webhook events now include a sequence number

  `VEHICLE_STATE` webhook events now include a `sequence` field in the `meta` object. It's an integer assigned when the event is generated, so a later event never carries a lower value than an earlier one.

  Deliveries aren't guaranteed to arrive in the order events were generated: retries and concurrent deliveries can put a later event ahead of an earlier one. If event order matters to your application, compare `sequence` values instead of relying on arrival order. Retried deliveries keep the original event's `sequence`, just like `eventId`.

  The field appears in all `VEHICLE_STATE` payloads automatically. No changes to your integration are needed.

  Learn more in the [`VEHICLE_STATE` event reference](/docs/api-reference/webhooks/events/vehicle-state#payload-structure).
</Update>

<Update label="July 16th, 2026">
  ## Compatibility matrix now shows four coverage states

  <Frame>
    <img alt="Compatibility matrix legend showing supported, not supported, not applicable, and not yet verified states" />
  </Frame>

  The compatibility matrix assesses Smartcar's signal and command level functionality across vehicle brands, based on real-world data from vehicles connected to the platform. It reflects which signals and commands have been successfully retrieved or executed against a given make, model, and year. This data updates continuously as vehicles connect and more signals and commands run. A vehicle's functional capabilities can vary with trim, optional packages, firmware version, and active subscriptions.

  Each cell in the [compatibility matrix](https://smartcar.com/product/compatible-vehicles) now shows one of four states:

  * **✓ Supported**: Indicates signals and commands that have been successfully retrieved or executed for this make, model, and year.
  * **✕ Not supported**: Smartcar has verified that this make, model, and year is not compatible with a given signal or command.
  * **N/A Not applicable**: Doesn't apply to this powertrain, such as charging signals on gas vehicles.
  * **– Not yet verified**: There isn't enough data on the platform yet to determine whether a signal or command is compatible with this make, model, and year. It might still work for these vehicles.
</Update>

<Update label="July 13th, 2026">
  ## Nominal capacity signal now supports Canadian vehicles

  Canadian vehicles are now supported by the [`TractionBattery.NominalCapacity`](/docs/api-reference/signals/tractionbattery#nominal-capacities) signal, so battery capacity for the US, Europe, and Canada is served through the same signal.

  If you integrate Canadian vehicles, you can use this signal now. The Canada-only [battery capacity endpoint](/docs/api-reference/evs/get-battery-capacity) will be deprecated alongside API v2.0.
</Update>

<Update label="July 13th, 2026">
  ## Updated Connect SDKs: pass external\_id and skip the code exchange

  New releases of our JavaScript, iOS, and Android SDKs let you set an `external_id` and launch Connect with `response_type=none`.

  **`external_id`**: your own identifier for the vehicle owner, passed in the [Connect URL](/docs/connect/redirect-to-connect). Smartcar stores it on the connection and returns it back to you, so you can tie a connection to a specific user in your system. We recommend setting it on every Connect session.

  **`response_type=none`**: pass this to complete the Connect flow without an authorization code to exchange. It also makes `redirect_uri` optional; without a redirect, the flow ends on a Smartcar-hosted completion page. This pairs with [application access tokens](/docs/api-reference/authorization/overview), Smartcar's recommended way to authenticate.

  We also recommend configuring permissions in [Vehicle Access](https://dashboard.smartcar.com/configuration?tab=vehicle-access) instead of passing `scope` in code. A Connect URL then needs only `application_id`, `external_id`, `redirect_uri`, and `response_type=none`, and Smartcar derives the requested permissions from your dashboard settings.

  Learn more in [Build the Connect URL](/docs/connect/redirect-to-connect).
</Update>

<Update label="June 22nd, 2026">
  ## Energy Added now available for the Volkswagen Group in Europe

  The [`Charge.EnergyAdded`](/docs/api-reference/signals/charge#energyadded) signal is now available for Volkswagen, Audi, ŠKODA, CUPRA, and SEAT vehicles in Europe, delivered through Volkswagen's official partner integration.

  `EnergyAdded` reports the cumulative electrical energy delivered to the vehicle during the current or most recent charging session, measured in kilowatt-hours (kWh). It's a core data point for managed charging use cases.

  If you already subscribe to this signal and have the required permissions, you'll start receiving it automatically with no changes to your code. To start consuming it, select it in [Vehicle Access](https://dashboard.smartcar.com/configuration?tab=vehicle-access).

  For data availability by make, model, year, and region, see the [compatibility matrix](https://smartcar.com/product/compatible-vehicles).
</Update>

<Update label="June 16th, 2026">
  ## The `required:` scope prefix change is now live

  The change to the `required:` scope prefix [announced on June 4th](#upcoming-change-a-clearer-more-reliable-required-scope-prefix) is now live. The `required:` prefix controls only whether a vehicle owner can uncheck a permission on the Connect grant screen, with consistent behavior across all supported regions.

  Existing applications are unaffected: every permission you currently request stays required, so the connection experience for your users does not change.

  To filter vehicle connections to specific powertrain types, use [Connection Filters](/docs/connect/advanced-config/connection-filters) instead of the `required:` prefix.

  Learn more in [Permissions](/docs/api-reference/permissions#required-permissions) and [Build the Connect URL](/docs/connect/redirect-to-connect).
</Update>

<Update label="June 4th, 2026">
  ## Charge Schedules now available for more makes

  You can now create charge schedules for **Nissan**, **Renault**, **Dacia**, **Chrysler**, **Dodge**, **Jeep**, **RAM**, **Fiat**, and **Alfa Romeo** vehicles, in addition to Volvo, Tesla, and Rivian. Charge schedules apply to BEV and PHEV vehicles and require the `control_charge` permission.

  Three schedule types are supported. Availability varies by make:

  * **Daily**: One charging window that applies every day.
  * **Workweek**: A weekday schedule and a separate weekend schedule.
  * **Weekly**: A different schedule for each day or specific days of the week.

  **Supported makes:**

  * **Nissan** (US & Canada): Daily, Workweek, and Weekly
  * **Nissan** (Europe): Daily and Workweek
  * **Renault and Dacia**: Daily, Workweek, and Weekly
  * **Chrysler, Dodge, Jeep, RAM, Fiat, and Alfa Romeo**: Daily, Workweek, and Weekly

  For the most up-to-date list of makes that support charge schedules, see the [compatibility matrix](https://smartcar.com/product/compatible-vehicles).

  **What's new:**

  * `POST /v3.0/vehicles/{id}/charge-schedules/daily`, `workweek`, and `weekly`
  * `DELETE /v3.0/vehicles/{id}/charge-schedules/{scheduleId}`

  After creating a schedule, read it back from the [`Charge.ChargeTimers`](/docs/api-reference/signals/charge#chargetimers) signal.

  **Get started**: Make sure your app has been granted `control_charge` permissions before issuing API requests. See the [Commands overview](/docs/api-reference/commands/overview) for endpoint details.
</Update>

<Update label="June 4th, 2026">
  ## Upcoming change: a clearer, more reliable `required:` scope prefix

  We're announcing an upcoming change to how the `required:` scope prefix works in Smartcar Connect, taking effect on June 16th, 2026. We're sharing it ahead of time so you can review it before it takes effect.

  Starting June 16th, the `required:` prefix will control only whether a vehicle owner can uncheck a permission on the Connect grant screen. This brings consistent behavior across all supported regions.

  **Filtering by powertrain**

  If you would like to filter vehicle connections to specific powertrain types (for example, an EV-only app), use [Connection Filters](/docs/connect/advanced-config/connection-filters). This filters vehicle connections more reliably across all regions.

  Existing applications are unaffected: every permission you currently request stays required, so the connection experience for your users does not change.

  Learn more in [Permissions](/docs/api-reference/permissions#required-permissions) and [Build the Connect URL](/docs/connect/redirect-to-connect).
</Update>

<Update label="May 26th, 2026">
  ## Volkswagen Group Partner Integration now available across Europe

  <Frame>
    <img alt="" />
  </Frame>

  Smartcar's partnership with the Volkswagen Group now extends to Europe, covering Volkswagen, Audi, ŠKODA, CUPRA, and SEAT Battery Electric and Plug-in Hybrid Electric vehicles.

  **What's new:**

  * Access charging, battery, and odometer data through Smartcar signals
  * Issue Charge Start and Charge Stop commands

  Learn more in the [Volkswagen integration updates](/docs/help/oem-integrations/vw/whats-new).
</Update>

<Update label="May 26th, 2026">
  ## SEAT now available on Smartcar in Europe

  <Frame>
    <img alt="" />
  </Frame>

  Smartcar is now compatible with SEAT in supported European countries. At this time, support is limited to Battery Electric Vehicles (BEV) and Plug-in Hybrid Electric Vehicles (PHEV).
</Update>

<Update label="May 26th, 2026">
  ## Tesla Business Fleet Enrollment Now Available

  <Frame>
    <img alt="" />
  </Frame>

  Smartcar now supports enrollment of Tesla vehicles purchased through Tesla's Business-to-Business (B2B) program. Once enrolled, Business Fleet vehicles appear alongside your other Smartcar-connected Tesla vehicles and use your existing integration.

  **What's new:**

  * Seamless consent flow for all vehicles
  * Manage your Tesla Business Fleet vehicle permissions and Virtual Key pairing seamlessly
  * Keeps your fleet in sync as vehicles are added or removed

  **Get started**: To enroll your Tesla Business Fleet vehicles, contact Smartcar support. See the [Tesla Business Fleet enrollment](/docs/help/oem-integrations/tesla/business-fleet-onboarding) page for full details.
</Update>

<Update label="May 21st, 2026">
  ## Charge Schedules Now Available for Rivian

  You can now create and delete charge schedules for Rivian vehicles through Smartcar's API. Rivian supports all three schedule types: Daily, Weekly, and Workweek.

  **What's new:**

  * Rivian BEV vehicles support all three charge schedule types
  * No additional preconditions beyond standard `control_charge` permission

  **Get started**: Make sure your app has been granted `control_charge` permissions before issuing API requests. See the [Commands overview](/docs/api-reference/commands/overview) for endpoint details.
</Update>

<Update label="May 18th, 2026">
  ## Charge Schedules Now Available

  <Frame>
    <img alt="" />
  </Frame>

  The latest version of Smartcar's API (V3) now includes the ability to create and delete charge schedules for Volvo and Tesla.  Support for additional makes coming soon! Charge schedules apply to BEV and PHEV vehicles.

  Three schedule types are supported:

  * **Daily**: One charging window that applies every day.
  * **Workweek**: A weekday schedule and a separate weekend schedule.
  * **Weekly**: A different schedule for each day or specific days of the week.

  **Supported makes:**

  * **Tesla**: Daily, Weekly, and Workweek schedules
  * **Volvo**: Daily schedules only. [Brand quirks apply](/docs/help/brand-quirks#charge-schedules), review before integrating.

  For the most up-to-date list of makes that support charge schedules, see the [compatibility matrix](https://smartcar.com/product/compatible-vehicles).

  **What's new:**

  * `POST /v3.0/vehicles/{id}/charge-schedules/daily`, `workweek`, and `weekly`
  * `DELETE /v3.0/vehicles/{id}/charge-schedules/{scheduleId}`

  Learn more about these endpoints [here](/docs/api-reference/commands/overview)
  You can retrieve existing charge schedules via Webhooks or by issuing a GET request to the API for the [`Charge.ChargeTimers`](/docs/api-reference/signals/charge#charge-timers) signal.

  **Get started**: Make sure your app has been granted `control_charge` permissions before issuing API requests.
</Update>

<Update label="April 30th, 2026">
  ## Vehicle Location is now available for Volvo US

  The Location signal is now available for Volvo vehicles connected in the US. Applications subscribed to Location can read latitude and longitude for these vehicles without any code changes.

  **What's new:**

  * Location data flows for US Volvo vehicles through the existing [Location](/docs/api-reference/signals/location) signal
  * No new permissions, fields, or migration required for apps already subscribed to Location

  **Get started**: If your application already requests the Location signal, no action is needed. To add it, update your permissions in the [Smartcar Dashboard](https://dashboard.smartcar.com) and review the [Location](/docs/api-reference/signals/location) signal reference.
</Update>

<Update label="April 23rd, 2026">
  ## Filter vehicle connections by powertrain type

  You can now restrict which vehicles can connect to your application based on powertrain type. The new **Connection Filters** tab in your application's Configuration page on the Smartcar Dashboard lets you allow or block connections from `ICE`, `BEV`, and `PHEV` vehicles.

  **What's new:**

  * Select which powertrain types are allowed to connect — unselected types are blocked from completing the Connect flow
  * Optionally block vehicles whose powertrain type cannot be verified at connection time (affects roughly 1% of connections)
  * If no types are selected, the filter is not applied and all types are allowed

  **Get started**: Open the **Connection Filters** tab in your application's [Configuration page](https://dashboard.smartcar.com) and publish your filter settings. See the [Connection Filters](/docs/connect/advanced-config/connection-filters) docs for details.

  <Info>Connection Filters are available on the Custom plan.</Info>
</Update>

<Update label="April 16th, 2026">
  ## New API version and authentication now available

  The Smartcar API has a new version (V3) and a simpler way to authenticate. Your backend exchanges a Client ID and Client Secret for an access token that works across all your connected vehicles. No per-vehicle tokens, no refresh logic.

  **What's new:**

  * New V3 API endpoints for vehicle data, commands, and connections
  * Generate API credentials from the **API Credentials** tab in your Dashboard
  * One access token valid for 1 hour, no refresh tokens to manage
  * `sc-user-id` header to scope requests to a specific user
  * Webhook payloads include `user.id` for user-level routing

  Existing per-vehicle tokens continue to work. Migration is optional for existing customers.  For new customers, we recommend using the simpler authentication approach.

  **Get started:**

  * [API Authentication Setup](/docs/getting-started/how-to/api-authentication) — Step-by-step setup and code examples
  * [Overview](/docs/api-reference/authorization/overview) — How it works, key concepts, and security
  * [Migration Guide](/docs/getting-started/how-to/m2m/migration-guide) — Transition from per-vehicle tokens
  * [FAQ](/docs/getting-started/how-to/m2m/faq) — Common questions and answers
</Update>

<Update label="April 8th, 2026">
  ## Introducing the new Compatible Vehicles dataset: redesigned interface and new API

  The data behind Smartcar's Compatible Vehicles has been reworked. You can browse signal-level compatibility by make, model, year, region, and powertrain type through a redesigned interface and a dedicated API endpoint.

  The dataset updates daily from actual platform activity. Every vehicle listed has connected to Smartcar, delivered compatible signals, and run commands successfully. If a make or model isn't listed, we haven't seen it on the platform yet. Once connected, it will show up in the dataset.

  **What's new:**

  * See which signals and commands are available for each vehicle, broken out by category: battery, charging, location, odometer, and more
  * Filter by powertrain type (BEV, PHEV, ICE, HEV) to scope results to your use case
  * Filter by region (US, Canada, Europe) and manufacturer
  * New `GET https://compatibility.api.smartcar.com/v3/compatible-vehicles` endpoint
  * Compatibility data comes from verified vehicle test results and OEM partner integrations, with better model matching and powertrain classification

  **Get started**: Browse the [Compatible Vehicles](/docs/api-reference/compatible-vehicles) page in the API Reference.
</Update>

<Update label="March 13th, 2026">
  ## Polish Language Support in Smartcar Connect

  <Frame>
    <img alt="Smartcar Connect preamble screen displayed in Polish" />
  </Frame>

  Smartcar Connect now supports Polish, making it easier for Polish-speaking vehicle owners to understand and complete the vehicle linking process.

  When a user's browser language is set to Polish, or when they manually select "Polski" from the language dropdown, all Connect screens including the preamble, permissions, and OEM login will be displayed in Polish.

  **Get started**: Polish is automatically available to all applications using Smartcar Connect. No configuration changes are needed. Learn more about [country and language settings](/docs/connect/advanced-config/country-flag) in Connect.
</Update>

<Update label="March 11th, 2026">
  ## Vehicle Simulator now supports Smartcar Connect simulation

  You can now test simulated vehicle connection flows in the [Vehicle Simulator](/docs/getting-started/dashboard/simulator), including experiences that mirror how vehicle owners connect through [Smartcar Connect](/docs/connect/what-is-connect).

  **What's new:**

  * **Connection-state testing** — Create simulated vehicles in a disconnected state, then connect them later to test connection and reconnection behavior.
  * **Two connection options** — Connect simulated vehicles automatically, or run a full Smartcar Connect simulation flow with simulated credentials.
  * **Brand simulation in Connect flow** — Vehicles connected through simulated Connect reflect the selected brand in Dashboard views, webhook payloads, and API responses (`vehicle.make`).
  * **Permissions parity for simulation** — Simulator connection flows use the configured `VehicleUserAccount.Permissions` signal, which overrides app-level permissions.
  * **Disconnect and resubscribe workflows** — Disconnect simulated vehicles from Dashboard tables or via API, while preserving the simulated vehicle for future reconnection tests.

  **Get started**: Create a simulated vehicle in the Dashboard to test automatic connection, Connect simulation, and disconnection scenarios in [Vehicle Simulator](/docs/getting-started/dashboard/simulator).
</Update>

<Update label="March 10th, 2026">
  ## Powertrain Type Now Available in Webhook and API V3 Responses

  The `vehicle` object in `VEHICLE_STATE` webhook payloads and API V3 responses now includes a `powertrainType` field. This field indicates the vehicle's powertrain and returns one of the following values: `BEV` (Battery Electric Vehicle), `PHEV` (Plug-in Hybrid Electric Vehicle), `ICE` (Internal Combustion Engine), or `HEV` (Hybrid Electric Vehicle).

  **Example webhook payload:**

  ```json theme={null}
  {
    "vehicle": {
      "id": "9af13248-3b73-4c9d-9a4b-d937ce6bc8e2",
      "make": "TESLA",
      "model": "Model 3",
      "year": 2020,
      "powertrainType": "BEV"
    }
  }
  ```

  Developers can use this value to filter data and tailor different customer experiences based on powertrain type. For example, you can show battery level for BEV vehicles, fuel level for ICE vehicles, or both for PHEV vehicles.

  **Get started**: The `powertrainType` field is automatically included in all `VEHICLE_STATE` webhook deliveries and API V3 vehicle responses — no configuration changes are needed. See the [VEHICLE\_STATE webhook reference](/docs/api-reference/webhooks/events/vehicle-state) for the full payload structure.
</Update>

<Update label="February 18th, 2026">
  ## Tesla Virtual Key Pairing flow improvements

  We've improved the Tesla Virtual Key Pairing experience to make recovery from first-attempt failures clearer and faster.

  <Frame>
    <div>
      <img alt="Tesla virtual key relaunch prompt screen" />

      <img alt="Tesla virtual key warning and retry screen" />
    </div>
  </Frame>

  **What's new:**

  * **Clearer retry guidance** — If the "Add virtual key" prompt does not appear in the Tesla app, users are now prompted to try again since the second attempt often succeeds.
  * **New "Relaunch Tesla" action** — Vehicle owners can immediately relaunch the Tesla app from the pairing flow and retry without returning to the vehicle list.
</Update>

<Update label="February 17th, 2026">
  ## All-New Vehicle Simulator

  <Frame>
    <img alt="Smartcar Vehicle Simulator V2" />
  </Frame>

  We've rebuilt the [Vehicle Simulator](/docs/getting-started/dashboard/simulator) from the ground up. The new simulator gives you full control over your simulated vehicle's state and lets you test your Smartcar integration end-to-end — including webhooks — without needing a real vehicle.

  **What's new:**

  * **Configuration-based testing** — Directly configure your simulated vehicle's state and see changes reflected immediately in API responses and webhook deliveries. No more waiting for trips to play out.
  * **Webhook testing** — Subscribe simulated vehicles to your existing [webhook integrations](/docs/integrations/webhooks/overview) and trigger deliveries by publishing vehicle state changes. Test your full webhook pipeline without a live vehicle.
  * **Full signal configuration** — Configure all available signals organized by signal group, with default values provided for every signal. The signal groups match the same structure you see when setting up [vehicle permissions](/docs/api-reference/permissions) for your application.
  * **Permission simulation** — Toggle individual permissions on or off to test how your application handles partial permission grants and permission errors.
  * **Vehicle commands** — Test lock/unlock, start/stop charge, set charge limit, and send destination. Commands trigger realistic state changes on the simulated vehicle.
  * **Error state testing** — Recreate error scenarios like permission denials or in-motion lock attempts to validate your application's error handling.

  The previous simulator remains available as [Vehicle Simulator (Legacy)](/docs/getting-started/dashboard/simulator-legacy).

  **Get started**: Open the [Simulator](/docs/getting-started/dashboard/simulator) in your Smartcar Dashboard and create your first simulated vehicle.
</Update>

<Update label="January 28th, 2026">
  ## Charging signal CONNECTOR replaced with CHARGING\_TYPE is now live

  The charging signal change [announced on January 12th](#upcoming-change-charging-signal-connector-to-charging_type) is now live. The `CONNECTOR` type has been replaced with `CHARGING_TYPE` in the following signals:

  * Charge.ChargeLimits
  * Charge.ChargeRecords
  * Charge.ChargeTimers

  These signals now return the charging current type (`AC` or `DC`) instead of a connector hardware type. If your integration parses any of these signals and still references the `CONNECTOR` type, update your code to use `CHARGING_TYPE` and parse the `chargingType` field.

  For full details on the change, see the [original announcement](#upcoming-change-charging-signal-connector-to-charging_type) below.
</Update>

<Update label="January 20th, 2026">
  ## Send Destination now available for Volkswagen

  You can now use the Smartcar API to send destinations to Volkswagen vehicles in the United States.

  With the Send Destination command, your application can route a destination directly to a driver's built-in navigation screen. This unlocks new workflows:

  * Fleet management: Route drivers to their next pickup, delivery, or service location
  * Car sharing and rentals: Send return location addresses when a rental period is ending
  * Repair and maintenance: Direct customers to your nearest service center when maintenance is needed
  * Charging networks: Guide EV drivers to available chargers when battery is low

  **Get started**: Request the `control_navigation` permission during the Smartcar Connect flow and call [Send Destination](/docs/api-reference/send-destination-to-vehicle).
</Update>

<Update label="January 16th, 2026">
  ## Ruby SDK and Java SDK Updated to Support Version 3 of the Vehicles API

  The [Ruby SDK](https://github.com/smartcar/ruby-sdk) and [Java SDK](https://github.com/smartcar/java-sdk) have been updated to support [Version 3 of the Vehicles API](/docs/api-reference/intro).

  Both SDKs now include three new methods:

  * `get_vehicle` - Retrieve vehicle information
  * `get_signal` - Get a specific signal for a vehicle
  * `get_signals` - Get all available signals for a vehicle

  These new methods provide easier access to vehicle data through the latest API version, enabling developers to work with Smartcar's expanded signal catalog and improved data delivery capabilities.

  **Get started**: Update to the latest SDK version and explore the new methods in the [Ruby SDK](https://github.com/smartcar/ruby-sdk) and [Java SDK](https://github.com/smartcar/java-sdk) documentation.
</Update>

<Update label="January 14th, 2026">
  ## Volvo Cars Partner Integration now available!

  <Frame>
    <img alt="" />
  </Frame>

  Smartcar is excited to announce a partnership with Volvo Cars, providing access to vehicles across the United States and Europe.

  **What's new:**

  * Access charging, battery, location, and odometer data through Smartcar signals
  * Use the updated consent flow through Volvo's official portal

  Learn more in the [Volvo integration updates](/docs/help/oem-integrations/volvo/whats-new).
</Update>

<Update label="January 12th, 2026">
  ## Upcoming change: Charging signal `CONNECTOR` to `CHARGING_TYPE`

  On January 28th, 2026, we're updating three charging-related signals. This is a breaking change that may require updates to your integration.

  **Affected signals:**

  * `Charge.ChargeLimits`
  * `Charge.ChargeRecords`
  * `Charge.ChargeTimers`

  **What's changing:**
  In all three signals, the `CONNECTOR` type is being replaced with `CHARGING_TYPE`. Instead of returning a connector hardware type (e.g., `J1772`), these signals will now return the charging current type (`AC` or `DC`).

  **Before (current format):**

  ```json theme={null}
  {
    "type": "CONNECTOR",
    "condition": {
      "connectorType": "J1772"
    }
  }
  ```

  **After (new format):**

  ```json theme={null}
  {
    "type": "CHARGING_TYPE",
    "condition": {
      "chargingType": "AC"
    }
  }
  ```

  Other types such as `GLOBAL` and `LOCATION` remain unchanged.

  **Why we're making this change:**
  OEMs report connector hardware types inconsistently--some return proprietary strings, others return nothing at all. In contrast, AC vs. DC charging type is more widely provided across manufacturers.

  This change gives you more consistent, actionable data. Rather than maintaining a mapping of connector type strings, you can rely on a simple AC or DC value to determine whether the vehicle is on Level 1/2 charging or DC fast charging.

  **What you need to do:**
  If your integration parses any of these signals and handles the `CONNECTOR` type, update your code to:

  * Expect `CHARGING_TYPE` instead of `CONNECTOR`
  * Parse `chargingType` (values: `AC` or `DC`) instead of `connectorType`

  **Timeline:**

  * Now -> January 27th, 2026: Current format remains in place
  * January 28th, 2026: New format goes live

  **Questions?**
  Reach out to your Smartcar account manager or [contact support](https://smartcar.com/contact).
</Update>


# Connect Options
Source: https://smartcar.com/docs/connect/advanced-config/connect-options

Configure which OEM brands and countries are available for your users to select from in Smartcar Connect.

From the **Connect Options** tab in your application's Configuration page, you can control which vehicle brands appear in the brand selector and which countries are available in the country selector on the Connect launch screen.

<Info>Connect Options are available on the Custom plan.</Info>

## OEM Brands

By default, all brands supported by Smartcar are available in Connect's brand selector. You can restrict this to a specific subset of brands — for example, if your application is only designed to work with a particular manufacturer.

<Info>
  At least one brand must be selected. If you configure only one brand, the brand selector will still appear but with just that one option listed. To skip the brand selector entirely and send users directly to a brand's login page, use Brand Select mode. See [Connect Flows](/docs/connect/advanced-config/flows) for more details.
</Info>

Changes take effect after you click **Publish** in the dashboard.

## Countries

By default, all countries supported by Smartcar are available in Connect's country selector. You can restrict this to a specific subset of countries on the **Countries** sub-tab.

<Info>
  This setting controls which countries your users can choose from in the country selector — it does not set a default country. To set a default country for your Connect sessions, use the `flags=country:{country_code}` parameter in your Connect URL. See [Country Selection](/docs/connect/advanced-config/country-flag) for details.
</Info>

Changes take effect after you click **Publish** in the dashboard.


# Connection Filters
Source: https://smartcar.com/docs/connect/advanced-config/connection-filters

Restrict which vehicles can connect to your application based on powertrain type.

Connection Filters let you restrict connections to specific powertrain types. By default, all powertrain types are allowed. Vehicles that don't match your selection will be blocked from completing the Connect flow.

Configure this in the **Connection Filters** tab in your application's Configuration page on the [Smartcar Dashboard](https://dashboard.smartcar.com).

<Info>Connection Filters are available on the Custom plan.</Info>

## Powertrain Filter

You can allow or block connections based on the following powertrain types:

| Type   | Description                                                                                              |
| ------ | -------------------------------------------------------------------------------------------------------- |
| `ICE`  | Internal Combustion Engine — includes traditional combustion engines and hybrid electric vehicles (HEVs) |
| `BEV`  | Battery Electric Vehicle                                                                                 |
| `PHEV` | Plug-in Hybrid Electric Vehicle                                                                          |

All three types are allowed by default. Uncheck any type to block vehicles of that type from connecting to your application.

<Info>
  If no powertrain types are selected, the filter is not applied and all types are allowed to connect.
</Info>

Changes take effect after you click **Publish** in the dashboard.

## Block Unknown Powertrains

When you restrict connections to a subset of powertrain types, an additional checkbox appears: **Allow connections when powertrain is 'UNKNOWN'**.

When this checkbox is checked, vehicles whose powertrain type cannot be determined at connection time are allowed to connect. When unchecked, those vehicles are blocked.

<Info>
  When a vehicle's powertrain cannot be verified at connection time, it is classified as 'UNKNOWN'. This affects roughly 1% of connections due to manufacturer data limitations.
</Info>


# Country Selection
Source: https://smartcar.com/docs/connect/advanced-config/country-flag

By default Connect will launch based on the devices location impacting the brands that are available to the user e.g. Renault is only available in Europe.

You can override this behavior by passing a country feature flag in your Connect URL in the form `country:{country_code}`.

Your feature flag should contain the [two-character ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)
of the country that your user is located in.

<Tip>
  Our SDKs provide ways for you to add this as part of the various `authUrlBuilder` or `getAuthUrl` methods.
</Tip>

```plaintext Connect URL w/ country feature flag theme={null}
https://connect.smartcar.com/oauth/authorize?
response_type=code
&application_id=8229df9f-91a0-4ff0-a1ae-a1f38ee24d07
&scope=read_odometer read_vehicle_info
&redirect_uri=https://example.com/home
&flags=country:GB
```

Alternatively, your users can manually change their country and language on Connect's preamble screen:

<Frame type="simple">
  <img />
</Frame>


# Connect Flows
Source: https://smartcar.com/docs/connect/advanced-config/flows

Connect can be launched with three different workflows (default, single select, and single select with VIN). Depending on your use case and what information you  have about the vehicle ahead of a launching Connect, you may be able to leverage one of these flows for a more streamlined Connect experience.

<Tabs>
  <Tab title="Default">
    When you launch Connect, users will be able to select the brand of their vehicle from a list before they enter their credentials and grant access to your application.

    <Frame>
      <img />
    </Frame>
  </Tab>

  <Tab title="Authorizing a Single Vehicle">
    In some cases you may only want to connect to a single vehicle, even if there are more than one on your user's connected services account. Smartcar provides two ways for you to do this:

    * Single Select
    * Single Select with VIN

    ### Single Select

    Limits the user's selection on the permissions screen to a single car if there are multiple vehicles on their connected services account. Notice that check-boxes turn into radio buttons, and the call to action wording changes slightly.

    <Frame>
      <img />
    </Frame>

    To enable Single Select, you can pass `single_select=true` as URL parameter when launching Smartcar Connect.

    ### Single Select with VIN

    In addition, if you know the user’s VIN ahead of time you can pass this over to us in the connect URL. In doing so:

    1. Smartcar  decodes the VIN to get the brand and send the user to the appropriate login form directly
    2. If the owner has more than one vehicle on their connected services account, we’ll only show the VIN that was passed to us on the permission grant screen.

    <Frame>
      <img />
    </Frame>

    To enable Single Select with VIN, you can pass `single_select=true` and `single_select_vin=:vin` as URL parameters when launching Smartcar Connect.
  </Tab>

  <Tab title="Bypassing the Brand Selection Screen">
    ### Brand Select

    Instead of having users go through the brand selector screen, you can pass us a brand in the Connect URL and send the user to the appropriate login form directly.

    <Frame>
      <img />
    </Frame>

    To enable Brand Select, you can pass `make` as URL parameter when launching Connect. For example, `make=TESLA`
  </Tab>
</Tabs>


# Modes
Source: https://smartcar.com/docs/connect/advanced-config/modes

Connect can be launched in different modes depending on whether you want to interact with real vehicles or test your integration.

<Tip>
  If no mode is specified, Connect will launch in `live` mode by default.
</Tip>

| Mode      | Description                                                                                                           |
| --------- | --------------------------------------------------------------------------------------------------------------------- |
| live      | Launches Connect in live mode allowing a user to log in with a real connected services account.                       |
| simulated | Launches Connect in simulated mode allowing developers to connect to vehicles created on Dashboard via the Simulator. |


# SDKs for Connect
Source: https://smartcar.com/docs/connect/connect-sdks

Our SDKs make integrating Smartcar fast and easy in different languages and frameworks.

For mobile or single page web apps, you can use one of our frontend SDKs. Please note that our frontend SDKs only handle
integrating Connect into your application. You will still need to use a [backend SDK](/docs/api-reference/api-sdks) to manage tokens and make API requests to vehicles.

<Snippet />

<Note>**Note:** In addition to using a frontend SDK to integrate with Smartcar Connect, a backend SDK is strongly recommended to securely manage tokens, receive data from Smartcar, and make API requests to issue commands to vehicles. The backend SDK facilitates authentication, token exchange, and all communication with Smartcar’s APIs.</Note>

For server-side rendered applications, you can use one of our backend SDKs:

<Snippet />

<br />

<Tip>
  Don't see an SDK for your language? No problem!
  As long as you can build a URL and handle HTTP requests, you're good to go.
</Tip>


# Dashboard Configuration
Source: https://smartcar.com/docs/connect/dashboard-config



## Registration

To get started, register your application with Smartcar by navigating to our [dashboard](https://dashboard.smartcar.com/login).

After registration, your application will be assigned a `CLIENT_ID` and a `CLIENT_SECRET`. The `CLIENT_SECRET` must be kept safe and used only in exchanges between your application’s server and Smartcar’s <Tooltip>authorization server</Tooltip>.

## Redirect URIs

A redirect URI is required only for the Authorization Code flow (`response_type=code`). If your application uses application access tokens, registering one is optional: without it, the Connect flow ends on a Smartcar-hosted completion page, and you can look up new connections (by user\_id or your own `external_id`) on the [/connections endpoint](/docs/api-reference/list-connections).

For the Authorization Code flow, you’ll need to provide one or more redirect URIs. The user will be redirected to the specified URI upon completing the Connect flow. On redirect, the URI will contain a `user_id`, `external_id`, and `state` as query parameters. Store the `user_id` to use as the `sc-user-id` header when making API requests on behalf of this user.

The first redirect URI you add to your application is automatically set as the default. If you do not specify a `redirect_uri` in your Connect URL, Smartcar will use this default URI. You can add multiple URIs and set any of them as the default in the Smartcar Dashboard.

The redirect URIs must match one of the following formats:

| Protocol       | Format                                                                                   | Example                                                                        |
| -------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| HTTP           | a localhost URI with protocol `http://`                                                  | `http://localhost:8000`                                                        |
| HTTPS          | a URI with protocol `https://`                                                           | `https://myapplication.com`                                                    |
| JavaScript SDK | `https://javascript-sdk.smartcar.com/v2/redirect?app_origin={localhost-or-HTTPS-origin}` | `https://javascript-sdk.smartcar.com/v2/redirect?app_origin=https://myapp.com` |
| Custom-scheme  | `sc{clientId}://{hostname-with-optional-path-component-or-TLD}`                          | `sc4a1b01e5-0497-417c-a30e-6df6ba33ba46://callback`                            |

<Note>HTTP is allowed only for testing purposes on localhost</Note>

### Javascript SDK

The JavaScript SDK redirect is used along with the JavaScript SDK library. For more details and examples on the redirect usage, see the [SDK documentation](https://github.com/smartcar/javascript-sdk).

### Custom-scheme

Custom-scheme URIs are used for mobile applications. They must begin with `sc{clientId}` and can have an optional path or TLD. See the OAuth reference on redirect URIs.


# Handle the Response
Source: https://smartcar.com/docs/connect/handle-the-response

Upon successfully accepting the permissions, Smartcar will redirect the user back to your application using the specified `REDIRECT_URI`, along with a `user_id` as a query parameter. In the case of an error, we'll provide an error and description as parameters instead.

<Note>
  This page applies to Connect flows that end in a redirect. If you launch Connect with `response_type=none` and no `redirect_uri`, there is no response to handle: the flow ends on a Smartcar-hosted completion page, and you can look up the new connection on the [/connections endpoint](/docs/api-reference/list-connections).
</Note>

## Success

<ResponseField name="user_id" type="string">
  A Smartcar-generated UUID that identifies this user. Store this ID alongside your internal user identifier — you will use it as the `sc-user-id` header when making API requests on behalf of this user.
</ResponseField>

<ResponseField name="external_id" type="string">
  The [`external_id`](/docs/connect/redirect-to-connect) you passed in the Connect URL, echoed back so you can match this connection to your records. Only present if you set one.
</ResponseField>

<Snippet />

```http Success theme={null}
HTTP/1.1 302 Found
Location: https://example.com/home?
user_id=725146a3-69f4-46c8-965d-54b3b6f81eb7
&external_id=customer-user-abc123
&state=0facda3319
```

## Error

For a detailed description of these errors, please see our [errors page](/docs/api-reference/api-errors).

<ResponseField name="error">
  The type of error
</ResponseField>

<ResponseField name="error_description">
  A detailed description of what caused the error
</ResponseField>

<Snippet />

```http Error theme={null}
HTTP/1.1 302 Found
Location: https://example.com/home?
error=access_denied
&error_description=User+denied+access+to+application.
&state=0facda3319
```

<Info>
  In addition to the error code and description, Smartcar will return the following parameters when a
  user tries to authorize an incompatible vehicle in Connect.
</Info>

<ResponseField name="vin">
  Can be returned for errors where the vehicle is incompatible.
</ResponseField>

<ResponseField name="make">
  The manufacturer of the vehicle.
</ResponseField>

<ResponseField name="model">
  The model of the vehicle.
</ResponseField>

<ResponseField name="year">
  The year of production of the vehicle.
</ResponseField>

## What's Next

Now that you have a `user_id`, here's what you can do with it:

* [API Authentication](/docs/getting-started/how-to/api-authentication) — Get an application access token to make API requests
* [API Overview](/docs/api-reference/intro) — See what data and commands you can access
* [Vehicle Data](/docs/api-reference/list-signals) — Read signals like battery level, odometer, and location
* [Vehicle Commands](/docs/api-reference/commands/overview) — Lock, unlock, start/stop charging, set destination, and more
* [Connections](/docs/api-reference/list-connections) — List and manage this user's vehicle connections

Pass the `user_id` as the `sc-user-id` header on any request to scope it to this user.


# Rivian Bluetooth Pairing
Source: https://smartcar.com/docs/connect/other-actions/rivian-bluetooth-pairing

To support vehicle commands such as lock/unlock or start/stop charge, Rivian requires a mobile device to be paired via Bluetooth with the vehicle.

If permissions for commands are requested in your Connect URL (i.e. `control_security`, `control_charge`), Rivian owners will be prompted to pair their phone to the vehicle to complete the connection. After successful login, users will see a list of vehicles within their Rivian account to pair to. It is important that the mobile phone has Bluetooth enabled at this time.

<Frame>
  <img />
</Frame>

After selecting the vehicle, the user will be prompted to tap “Set up now” on the Rivian vehicle’s display and follow any on-screen prompts to connect.

<Frame>
  <img />
</Frame>

Once setup is complete, the application will be able to issue commands to the Rivian vehicle.

<Frame>
  <img />
</Frame>

Should Bluetooth be disabled or the Rivian display prompts not followed, the Bluetooth connection will not be established and the vehicle will not be connected to your application.

<Frame>
  <img />
</Frame>

## Notes

* Rivian vehicles must be paired via Bluetooth to support commands. Data permissions (i.e. `read_location`, `read_charge`) do not require Bluetooth pairing.
* The following commands are supported for Rivian vehicles: lock/unlock, start/stop charge, and set charge limit.
* If a user has multiple Rivian vehicles, they will be prompted to pair each vehicle that they wish to connect to your application.
* At least one vehicle must be paired via Bluetooth to complete the pairing process before the user can continue with the Connect flow and connect their Rivian to your application.
* If there are multiple drivers associated with a Rivian account and both drivers want to connect to your application, each driver must pair their mobile device to the vehicle via Bluetooth.
* There is a limit of four devices that can be paired to a Rivian vehicle at one time. If a user has already paired four devices to their Rivian, they will need to unpair one of the existing devices from the vehicle before they can pair their mobile device and complete the connection to your application.
* Smartcar mobile SDKs for iOS and Android are required to pair the vehicle via Bluetooth.


# Tesla Virtual Keys
Source: https://smartcar.com/docs/connect/other-actions/tesla-virtual-key

To support vehicle commands such as lock/unlock or start/stop charge, and benefit from faster data frequencies, Tesla requires a Virtual Key to be added to the vehicle.

For more information about Virtual Keys, please visit the [Virtual Key page](/docs/help/oem-integrations/tesla/virtual-key-tesla).

### Vehicle Owners adding a Virtual Key

Smartcar Connect will present Tesla vehicle owners a prompt to install the Tesla Virtual Key after granting access and prior to redirecting them back to your application.

<Frame>
  <img />
</Frame>

When users open the virtual key link, depending on their device, they will be redirected to the Tesla app or prompted to scan a QR code.

<Tabs>
  <Tab title="Mobile Device">
    On mobile devices, they will be redirected to the Tesla app and prompted to add the Virtual Key

    <Frame>
      <img />
    </Frame>
  </Tab>

  <Tab title="Desktop">
    On Desktop, they will be prompted to scan the QR code which in turn opens up the Tesla app and prompts them to add a Virtual Key

    <Frame>
      <img />
    </Frame>
  </Tab>
</Tabs>

Virtual Key status can be checked at any time from the Tesla infotainment screen under Settings > Locks.

<Frame>
  <img />
</Frame>

Smartcar will automatically determine which Tesla vehicles require a Virtual Key and prompt users to add it only for those vehicles. If a user has multiple Tesla vehicles, they will be prompted to add a Virtual Key for each vehicle that requires it. At least one vehicle must complete the pairing process before the user can continue with the Connect flow and connect their Tesla to your application.

### 2020 and Earlier Model S/X with Streaming Support

For 2020 and earlier Model S and X vehicles that support streaming (via a software update), Smartcar Connect handles this differently:

* These vehicles **do not require Virtual Key installation**
* During the Connect flow, users are prompted about enabling streaming via an in-vehicle toggle
* Users can request email instructions on how to enable the streaming setting in their vehicle's infotainment screen
* Once the streaming toggle is enabled in the vehicle, data will be refreshed more frequently
* Without streaming enabled, data is refreshed every 5 minutes while the vehicle is awake


# Handle the Response
Source: https://smartcar.com/docs/connect/re-auth/handle-response

If the re-auth is successful, the redirect to your application will contain a vehicle ID. In the case of an error, we'll provide an error and description as parameters instead.

## Success

<ResponseField name="vehicle_id">
  Unique identifier for a vehicle on Smartcar’s platform.
</ResponseField>

<Snippet />

```http Success theme={null}
HTTP/1.1 302 Found
Location: https://example.com/home?
vehicle_id=sc4a1b01e5-0497-417c-a30e-6df6ba33ba46
&state=0facda3319
```

## Error

For a detailed description of these errors, please see our [errors page](/docs/api-reference/api-errors).

<ResponseField name="error">
  The type of error
</ResponseField>

<ResponseField name="error_description">
  A detailed description of what caused the error
</ResponseField>

<Snippet />

```http Error theme={null}
HTTP/1.1 302 Found
Location: https://example.com/home?
error=access_denied
&error_description=User+denied+access+to+application.
&state=0facda3319
```


# OEM Migrations and Re-authentication
Source: https://smartcar.com/docs/connect/re-auth/oem-migrations

Understanding when and why vehicle owners need to re-authenticate due to OEM infrastructure changes and migrations.

## Overview

As automakers evolve their connected services infrastructure, Smartcar occasionally needs to migrate integrations to newer OEM APIs or authentication systems. These migrations ensure your application maintains access to the latest features, improved reliability, and continued compatibility with OEM platforms. Smartcar does this work on your behalf to minimize disruption.

**Important**: Some OEM migrations will require vehicle owners to re-authenticate through Smartcar Connect. This is a necessary step to maintain secure access to vehicle data.

<Warning>
  Re-authentication requirements are an inevitable part of working with automotive APIs. Ensuring your application can gracefully manage [re-atuthentication](/docs/connect/re-auth/redirect-to-connect) will help minimize disruption to your users.
</Warning>

## When Re-authentication Is Required

Vehicle owners may need to re-authenticate in several scenarios:

### Common Scenarios

Re-authentication may be required when:

* Vehicle owners change their OEM account credentials
* Connected services subscriptions are renewed or modified
* Vehicle owners revoke and re-grant access through OEM portals

### OEM Infrastructure Changes

When an automaker upgrades their API infrastructure or releases a new connected services platform, existing connections may need to be re-established. Examples include:

* **New APIs**: When OEMs annouce a new API platform for third-parties requiring all connected vehicles to re-authenticate
* **OEM Platform Updates**: When OEMs periodically update their authentication systems invalidating existing tokens forcing re-authentication
* **OEM Migrations**: When accounts or platforms are migrated between regions or systems deprecating legacy platforms

## Migration Communication

When a migration requiring re-authentication is necessary, Smartcar will:

1. **Notify you in advance** via email and your dedicated Slack channel
2. **Provide migration timelines** so you can plan communications with your users
3. **Offer technical support** throughout the migration process
4. **Provide documentation** outlining required actions (if any)

## Implementation Best Practices

### Plan for Re-authentication

Build your application with the expectation that re-authentication will be needed:

```javascript theme={null}
// Example: Handle authentication errors gracefully
try {
  const response = await vehicle.odometer();
} catch (error) {
  if (error.type === 'AUTHENTICATION' || 
      error.statusCode === 'CONNECTED_SERVICES_ACCOUNT:AUTHENTICATION_FAILED') {
    // Prompt user to re-authenticate
    const reauthUrl = error.resolution?.url;
    redirectToReauth(reauthUrl);
  }
}
```

### Monitor for Authentication Errors

Watch for authentication-related errors in your API responses:

* `AUTHENTICATION_FAILED`: Indicates credentials are invalid or expired
* `PERMISSION` errors: May require permission updates through re-authentication
* API errors with `resolution.url`: Often include a pre-built re-authentication URL

See our [error documentation](/docs/errors/api-errors/connected-services-account-errors) for complete details.

### Use Webhooks for Proactive Detection

Subscribe to [webhooks](/docs/integrations/webhooks/overview) to detect authentication issues before users report them:

```json theme={null}
{
  "eventId": "5a537912-9ad3-424b-ba33-65a1704567e9",
  "eventType": "VEHICLE_ERROR",
  "vehicleId": "123e4567-e89b-12d3-a456-426614174000",
  "data": {
    "user": {
      "id": "93b3ea96-ca37-43a9-9073-f4334719iok7"
    },
    "vehicle": {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "make": "TESLA",
      "model": "Model 3",
      "year": 2020,
      "mode": "live",
      "powertrainType": "BEV"
    },
    "errors": [
      {
        "type": "CONNECTED_SERVICES_ACCOUNT",
        "code": "AUTHENTICATION_FAILED",
        "description": "Smartcar was unable to authenticate with the user’s connected services account. Please prompt the user to re-authenticate using Smartcar Connect.",
        "docURL": "https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#authentication-failed",
        "statusCode": 400,
        "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
        "resolution": {
          "type": "REAUTHENTICATE",
          "url": "https://connect.smartcar.com/oauth/reauthenticate?response_type=vehicle_id&client_id=8229df9f-91a0-4ff0-a1ae-a1f38ee24d07&vehicle_id=sc4a1b01e5-0497-417c-a30e-6df6ba33ba46"
        },
        "suggestedUserMessage": "Your car got disconnected from <app name>. Please use this link to re-connect your car: <link to Smartcar Connect>."
      }
    ]
  },
  "meta": {
    "version": "4.0",
    "deliveryId": "48b25f8f-9fea-42e1-9085-81043682cbb8",
    "deliveredAt": 1761896351529,
    "webhookId": "123e4567-e89b-12d3-a456-426614174000",
    "webhookName": "Your Webhook's Name",
    "mode": "LIVE"
  }
}
```

### Implement Streamlined Re-authentication

Use Smartcar's [re-authentication flow](/docs/connect/re-auth/redirect-to-connect) to make the process seamless:

* Pre-populate the vehicle ID to skip vehicle selection
* Use the error's `resolution.url` field when available
* Provide clear messaging about why re-authentication is needed

### Communicate Proactively

When a migration is announced:

1. **Email users ahead of time** explaining the need and benefits
2. **Show in-app notifications** with clear calls-to-action
3. **Provide support resources** for users who have questions
4. **Track re-authentication completion** to follow up with users who haven't completed the process

### Example User Communication

<Accordion title="Sample email template">
  **Subject**: Action Required: Reconnect Your \[Vehicle Make] to \[Your App Name]

  Hi \[User Name],

  \[Your App Name] lost connection to your \[Vehicle Make]. Your action is needed to continue receiving \[Your app's benefits].

  **Why is this needed?**
  Connections to \[Vehicle Make] may expire from time to time. To maintain secure access to your vehicle data, you need to reconnect your vehicle.

  **What you need to do:**

  1. Click the button below to reconnect your vehicle
  2. Log in with your \[Vehicle Make] account credentials
  3. Approve the connection

  \[Reconnect My Vehicle Button]

  This process takes less than a minute. Your vehicle data and preferences will not be affected.

  If you have questions, reply to this email or contact our support team.

  Thank you,
  The \[Your App Name] Team
</Accordion>

## Frequently Asked Questions

<AccordionGroup>
  <Accordion title="Will all OEM migrations require re-authentication?">
    No. Smartcar handles many OEM updates transparently without requiring user action. Re-authentication is only required when the changes are not compatible with the current integration. Smartcar does its best to minimize re-authentication related to OEM platform changes.
  </Accordion>

  <Accordion title="How much notice will we receive for migrations?">
    Smartcar provides advance notice for planned migrations, typically several weeks to months depending on the scope. In rare cases where OEMs make unexpected changes, we'll communicate as soon as possible.
  </Accordion>

  <Accordion title="What happens if users don't re-authenticate?">
    API requests will continue to fail with authentication errors until re-authentication is completed. The vehicle connection will remain in your system, but no data can be retrieved.
  </Accordion>

  <Accordion title="Can we force re-authentication for all users at once?">
    Yes. The sooner re-authentication occurs, the sooner you and your users can leverage new features or resolve downtime.
  </Accordion>

  <Accordion title="Will access tokens and refresh tokens change?">
    This depends on the migration. In some cases, existing connections will remain valid. In other cases, existing tokens will expire and re-authentication is required to resolve re-establish a connection. Smartcar will specify this in migration communication.
  </Accordion>
</AccordionGroup>

## Need Help?

If you have questions about an upcoming migration or need assistance implementing re-authentication flows:

* Contact [support@smartcar.com](mailto:support@smartcar.com)
* Visit our [Support Center](/docs/help/accessing-support-center)
* Check the [Changelog](/docs/changelog/latest) for migration announcements

<Note>
  For enterprise customers, coordinate Tesla tenant setup and other OEM-specific configurations with your Solutions Architect before going live with customer-facing vehicles.
</Note>


# Redirect to Connect
Source: https://smartcar.com/docs/connect/re-auth/redirect-to-connect



There will be times when a user updates credentials to their connected services account. When this happens, the user will need to go through Connect
again to update your authorization through Smartcar.

You can do this with a streamlined Connect flow using a special re-auth URL with the parameters below.

<Info>
  Re-authentication is also required when OEMs migrate to new API platforms. See [OEM Migrations and Re-authentication](/docs/connect/re-auth/oem-migrations) to understand when and why these migrations occur, and how to prepare your implementation.
</Info>

<Tip>
  The [`AUTHENTICATION_FAILED`](/docs/errors/api-errors/connected-services-account-errors#authentication-failed) API error contains a partially constructed re-authentication URL in the `resolution.url` field.
</Tip>

<br />

<ParamField type="string">
  The application’s unique identifier.
</ParamField>

<ParamField type="string">
  The URI a user will be redirected to after authorization. This value **must** match one of the redirect URIs set in the credentials tab of the dashboard.

  Required if `response_type` is set to `vehicle_id`. If `response_type` is set to `none`, this parameter is optional: if you do not set a redirect URI, the flow ends on a Smartcar-hosted completion page.

  The first redirect URI you add to your application is automatically set as the default. If you do not specify a `redirect_uri` in your Connect URL, Smartcar will use this default URI. You can add multiple URIs and set any of them as the default in the Smartcar Dashboard.
</ParamField>

<ParamField type="string">
  This value must be set to `vehicle_id` or `none`. In both cases, the `vehicle_id` and `external_id` (if provided and is valid) are returned as query parameters in the redirect back to your application.

  * `vehicle_id`: `redirect_uri` is required.
  * `none`: `redirect_uri` is optional; if you do not set one, the flow ends on a Smartcar-hosted completion page.
</ParamField>

<ParamField type="string">
  The id of the vehicle you are reauthenticating.
</ParamField>

<ParamField type="string">
  An optional value included as a query parameter in the redirect\_uri back to your application. This value is often used to identify a user and/or prevent cross-site request forgery
</ParamField>

<ParamField type="string">
  Your application's own identifier for the vehicle owner. See the [Connect URL reference](/docs/connect/redirect-to-connect) for validation rules and where the value is surfaced.

  This parameter is optional, but we strongly recommend setting it on every Connect session, including re-authentication. The stored value is replaced by the `external_id` of the new session; re-authenticating with `external_id=null` clears it.
</ParamField>

<RequestExample>
  ```http Connect URL Example theme={null}
  HTTP/1.1 302 Found
  Location: https://connect.smartcar.com/oauth/reauthenticate?
    response_type=vehicle_id
    &application_id=8229df9f-91a0-4ff0-a1ae-a1f38ee24d07
    &vehicle_id=sc4a1b01e5-0497-417c-a30e-6df6ba33ba46
    &redirect_uri=https://example.com/home
    &state=0facda3319
    &external_id=customer-user-abc123
  ```
</RequestExample>


# Build the Connect URL
Source: https://smartcar.com/docs/connect/redirect-to-connect

Learn how to construct the Smartcar Connect URL to redirect users through the vehicle authorization flow.

<Tip>
  For mobile or single-page web applications you can use one of our [frontend SDKs](/docs/connect/connect-sdks), or for server-side rendered applications you can use one of
  our [backend SDKs](/docs/connect/connect-sdks). Using our SDKs makes it much easier to generate the Connect URL with the proper parameters.
</Tip>

You can configure default permissions for your application in the "Vehicle Access" tab of your application's Configuration page in the [Smartcar Dashboard](https://dashboard.smartcar.com). These settings will determine what permissions are requested during the Connect flow. Any `scope` parameters you specify in the Connect URL will override these dashboard settings.

<Frame>
  <img alt="Smartcar Dashboard Configuration Page For Vehicle Access" />
</Frame>

<Tip>
  **Recommended setup:** configure your permissions in [Vehicle Access](https://dashboard.smartcar.com/configuration?tab=vehicle-access), then launch Connect with just `application_id`, `external_id`, `redirect_uri`, and `response_type=none`. Scopes are derived from your Vehicle Access settings, so there's no `scope` list to maintain in code. Any `scope` you pass in the URL overrides those settings.
</Tip>

Once you have configured your application, you can get a pre-built Connect URL by clicking the "Share Connect Link" button at the top right in the Smartcar Dashboard.

<Frame>
  <img alt="Getting the Connect URL" />
</Frame>

To build the Connect URL manually by overriding your dashboard settings, pass the following parameters:

<Warning>
  Any parameters you specify in the Connect URL will override your dashboard settings.
</Warning>

<Tip>
  Use the `required:` prefix on a permission in the `scope` parameter to lock it on the grant screen so the vehicle owner cannot uncheck it. Learn more in [Required permissions](/docs/api-reference/permissions#required-permissions).
</Tip>

<ParamField type="string">
  The application’s unique identifier. To find this value in the dashboard, navigate to the configuration page, then the application details tab.
</ParamField>

<ParamField type="string">
  The URI a user will be redirected to after authorization. This value must match one of the redirect URIs set in the credentials tab of the dashboard.

  The redirect is optional for `response_type=none`: if you set one, the user is redirected to it after authorization as usual; if you do not, the flow ends on a Smartcar-hosted completion page that tells the vehicle owner the connection succeeded.

  The first redirect URI you add to your application is automatically set as the default. If you do not specify a `redirect_uri` in your Connect URL, Smartcar will use this default URI. You can add multiple URIs and set any of them as the default in the Smartcar Dashboard.
</ParamField>

<ParamField type="string">
  Determines how the Connect flow completes.

  * `code` — the OAuth2 Authorization Code flow. Smartcar redirects the user to your `redirect_uri` with an authorization code your application exchanges for an access token. A `redirect_uri` is required.
  * `none` — the flow completes without returning an authorization code. Use this if your application authenticates with [application access tokens](/docs/api-reference/authorization/overview), which don't require a code exchange. A `redirect_uri` is optional.

  To reauthenticate a user after they have already connected a vehicle, you can set this value to the `vehicle_id` of a previously connected vehicle.
</ParamField>

<ParamField type="[permissions]">
  A space-separated list of permissions that your application is requesting access to. The valid permission names can be found in the [permissions](/docs/api-reference/permissions) section.

  A permission is optional by default: it appears checked on the grant screen and the vehicle owner can uncheck it before connecting. Add the `required:` prefix to a permission name (e.g. `required:read_odometer`) to lock it on the grant screen so the owner cannot uncheck it. At least one permission must remain selected for the owner to complete the connection.

  Only add the `required:` prefix to permissions that are absolutely necessary for your application to function. Avoid marking permissions as required if they are not necessary for your application to provide services to drivers.

  <Info>
    The `required:` prefix controls only whether the owner can uncheck a permission. It does not filter which vehicles can connect, and it behaves the same in all regions. If a vehicle does not support a permission you requested, you receive a [VEHICLE\_NOT\_CAPABLE](/docs/errors/api-errors/compatibility-errors#vehicle-not-capable) error when you call that endpoint, not during Connect. To restrict connections by powertrain type, use [Connection Filters](/docs/connect/advanced-config/connection-filters).
  </Info>

  If you don't specify a `scope` parameter, Smartcar will use the permissions configured in the "Vehicle Access" tab of your application's Configuration page in the Dashboard. Any `scope` parameters passed in the Connect URL will override those dashboard settings.
</ParamField>

<ParamField type="string">
  An optional value included as a query parameter in the `REDIRECT_URI` back to your application. This value is often used to identify a user and/or prevent cross-site request forgery
</ParamField>

<ParamField type="string">
  An optional value that sets the behavior of the approval dialog displayed to the user.
  Defaults to `auto` and will only display the approval dialog if the user has not previously approved the scope.
  Set this to `force` to ensure the approval dialog is always shown to the user even if they have previously approved the same scope.
</ParamField>

<ParamField type="ENUM">
  <Expandable title="modes">
    <ResponseField name="simulated" type="string">
      Simulated mode lets you make requests to a vehicle created using the Vehicle Simulator to receive realistic responses from specific makes, models, years, and various states of the vehicle.

      Should the selected simulator not support the desired endpoint randomized data will be returned instead.
    </ResponseField>

    <ResponseField name="live" type="string">
      Live mode should be used when connecting to a real vehicle.
    </ResponseField>
  </Expandable>
</ParamField>

<ParamField type="string">
  Allows users to bypass the Brand Selector screen. Valid `makes` can be found in the [makes](/docs/api-reference/makes) section on API reference.
  The `single_select_vin` parameter takes precedence over this parameter.
</ParamField>

<ParamField type="bool">
  Sets the vehicle selection behavior of the grant dialog. If set to true, then the user is only allowed to select a single vehicle. Please refer to the Single Select section for more information.

  This parameter is only available in the Custom Plan.
</ParamField>

<ParamField type="string">
  Sets the behavior of the permissions screen in Smartcar Connect.
  When using `single_select_vin`, you need to pass in the VIN (Vehicle Identification Number) of a specific vehicle into the `single_select_vin` parameter.
  Additionally, you need to set the `single_select` parameter to `true`.
  Smartcar Connect will then let the user authorize **only the vehicle with that specific VIN**.
  The `single_select_vin` parameter takes precedence over the `make` parameter.
  Please refer to the Single Select section for more information.

  This parameter is only available in the Custom Plan.
</ParamField>

<ParamField type="[flags]">
  A space separated list of feature flags in the form `{flag}:{value}`.

  <Expandable title="flags">
    <ResponseField name="country" type="ENUM">
      The two-character ISO country code of the country that your user is located in. You can set the default country for Connect on Dashboard

      If no flag is passed or set as default on Dashboard, Smartcar will use the devices IP to set an appropriate country.

      This flag determines what brands are listed on the Brand Selector screen in Connect e.g. Renault is available in Europe, but not the US.
    </ResponseField>
  </Expandable>
</ParamField>

<ParamField type="string">
  Your application's own identifier for the vehicle owner, stored on the connection so you can match it to your records. It is returned as `externalId` by the [/connections endpoint](/docs/api-reference/list-connections), which also accepts it as a filter, and included in webhook payloads as `user.externalId`. Dashboard uses it to aggregate Connect analytics for each vehicle owner.

  This parameter is optional, but we strongly recommend setting it on every Connect session, whichever `response_type` you use. It is the simplest way to tie a connection back to a specific user in your system.

  The value must be 100 characters or fewer and may contain only letters, numbers, periods, underscores, and hyphens (`^[a-zA-Z0-9._-]+$`). A value that doesn't meet these requirements is not stored.

  When a vehicle owner reconnects, the stored value is replaced by the `external_id` of the new Connect session, but only if it is provided. Reconnecting with `external_id=null` clears the stored value.
</ParamField>

<RequestExample>
  ```http Example Connect URL theme={null}
  HTTP/1.1 302 Found
  Location: https://connect.smartcar.com/oauth/authorize?
  application_id=8229df9f-91a0-4ff0-a1ae-a1f38ee24d07
  &external_id=customer-user-abc123
  &response_type=none
  ```

  ```http Authorization Code flow theme={null}
  HTTP/1.1 302 Found
  Location: https://connect.smartcar.com/oauth/authorize?
  response_type=code
  &application_id=8229df9f-91a0-4ff0-a1ae-a1f38ee24d07
  &redirect_uri=https://example.com/home
  &external_id=customer-user-abc123
  ```
</RequestExample>


# User Selected Battery Capacity
Source: https://smartcar.com/docs/connect/user-selected-batcap

This flow can be launched using the URL provided by the [battery capacity](/docs/api-reference/get-nominal-capacity) endpoint.

## Automatic Battery Capacity Selection

When you request the `read_battery` permission, users will automatically be prompted to select their vehicle's battery capacity during the Smartcar Connect flow if we cannot determine the specific capacity for their vehicle(s). This ensures accurate battery information for your application is readily available.

<Frame>
  <img />
</Frame>

For users that skip the selection prompt or were connected prior to September 18th, 2025, you can still launch the battery capacity selection flow manually using the URL provided by the [GET /battery/nominal\_capacity](/docs/api-reference/get-nominal-capacity) endpoint.

### Append your redirect URI

Smartcar will provide a URL with the following parameters from the [GET
/battery/nominal\_capacity](/docs/api-reference/get-nominal-capacity) endpoint:

```http theme={null}
https://connect.smartcar.com/battery-capacity
?vehicle_id=36ab27d0-fd9d-4455-823a-ce30af709ffc
&client_id=8229df9f-91a0-4ff0-a1ae-a1f38ee24d07
&token=90abecb6-e7ab-4b85-864a-e1c8bf67f2ad
&response_type=vehicle_id
&redirect_uri=
```

<ParamField type="string">
  The Smartcar vehicle Id.
</ParamField>

<ParamField type="string">
  The `client_id` from the Smartcar Dashboard for your application.
</ParamField>

<ParamField type="string">
  Must be set to `vehicle_id`.
</ParamField>

<ParamField type="string">
  The URI you would like the response sent to after a user exits the
  flow.

  **NOTE:** this is the only parameter that will **not** be prepopulated as
  part of the API response. You **must** append it in order to launch the
  flow successfully and receive confirmation the user has exited the flow.
</ParamField>

<ParamField type="string">
  A token to validate that the URL was provided from a [battery capacity](/docs/api-reference/get-nominal-capacity)
  response for your application. The token is valid for 30 days. If a token is not provided or is no longer valid,
  the user will be directed to re-auth prior to selecting their capacity.
</ParamField>

## Response

### Success

After the user selects a capacity and completes the flow, Smartcar will send
the following to your redirect URI:

```http Success theme={null}
https://example.com/home
?vehicle_id=36ab27d0-fd9d-4455-823a-ce30af709ffc
&selected_capacity=80.9
&reason=battery_capacity
```

Upon receiving a success response, you can access the `selected_capacity` by calling the GET
[/battery/nominal\_capacity](/docs/api-reference/get-nominal-capacity) endpoint to
view the selection in the `capacity.nominal` field.

### Error

When you redirect the user to select a battery capacity and they select "I don't know the battery capacity", Smartcar will send the
following to your redirect URI:

```http Error theme={null}
https://example.com/home
?error=battery_capacity_no_selection
&error_description=user did not know battery capacity
&vehicle_id=36ab27d0-fd9d-4455-823a-ce30af709ffc
```

## Flow Example

<Frame>
  <img />
</Frame>


# What is Connect?
Source: https://smartcar.com/docs/connect/what-is-connect



Smartcar Connect is the fastest and most transparent way to collect user consent. Before you can make API requests to a car, your customer needs to link the vehicle to your app. It’s a simple process for your users to enroll their vehicles:

1. Select the car brand
2. Sign in
3. Give consent

<Frame>
  <img />
</Frame>

From your app, you'll [redirect your users to Connect](/docs/connect/redirect-to-connect), and [handle the response](/docs/connect/handle-the-response) once the user completes or exits the Connect flow. You'll receive a `user_id` that identifies this user's vehicle connection, which you'll store and use as the `sc-user-id` header when making API requests.

We have designed Connect in compliance with the OAuth2 authorization protocol, safely handling all user information.

Connect comes with robust configurations to fit your needs and frontend [SDKs](/docs/connect/connect-sdks) for faster integration.


# Authentication Errors
Source: https://smartcar.com/docs/errors/api-errors/authentication-errors

Thrown when there is an issue with your authorization header.

# `NULL`

The authorization header is missing or malformed, or it contains invalid or expired authentication credentials (e.g. access token, client ID, client secret). Please check for missing parameters, spelling and casing mistakes, and other syntax issues.

```json theme={null}
{
  "type": "AUTHENTICATION",
  "code": null,
  "description": "The authorization header is missing or malformed, or it contains invalid or expired authentication credentials. Please check for missing parameters, spelling and casing mistakes, and other syntax issues.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/authentication-errors",
  "statusCode": 401,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null } 
}
```

### Suggested Resolution

You can resolve this error by referring to our API reference and ensuring that you pass all the parameters as specified. If you are certain that your request is well-formed, please try refreshing your access token.

### Troubleshooting Steps

Refer to our API reference and ensure that you use the correct authentication mechanism for your request

* Check constants like Bearer and Basic for spelling mistakes.
* If you make a request to a vehicle endpoint, verify that your access token grants you access to the correct vehicle. You can do so by making a request to the /vehicles endpoint and ensuring that the correct vehicle ID is included in the returned response.
* If you have refreshed your access token, make sure that it persists and that you use your new token to make your request.


# Billing Errors
Source: https://smartcar.com/docs/errors/api-errors/billing-errors

Thrown when limits have been reached based on your plan, or if the feature is not available.

# `VEHICLE_LIMIT`

You’ve reached the limit of vehicles in your plan. Please upgrade to unlock access to more vehicles.

```json VEHICLE_LIMIT theme={null}
{
  "type": "BILLING",
  "code": "VEHICLE_LIMIT",
  "description": "You’ve reached the limit of vehicles in your plan. Please upgrade to unlock access to more vehicles.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/billing-errors#vehicle-limit",
  "statusCode": 430,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "CONTACT_SUPPORT" }
}
```

### Troubleshooting Steps

To resolve this error, please [contact us](mailto:support@smartcar.com) to upgrade your plan and increase your vehicle limit.
Please note that you won’t be able to make requests to additional vehicles until the end of the current billing period or until you have upgraded your plan.

# `INVALID_PLAN`

The feature you are trying to use is not included in your current pricing plan. Please visit our pricing page to learn more about our plans and features.

```json INVALID_PLAN theme={null}
{
  "type": "BILLING",
  "code": "INVALID_PLAN",
  "description": "The feature you are trying to use is not included in your current pricing plan. Please visit our pricing page to learn more about our plans and features.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/billing-errors#invalid-plan",
  "statusCode": 430,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "CONTACT_SUPPORT" } 
}
```

### Troubleshooting Steps

If you have checked our pricing page and believe that the feature you are trying to use is included in your plan,
please [contact us](mailto:support@smartcar.com) and we’ll be happy to assist you.

# `VEHICLE_REQUEST_LIMIT`

You have exceeded the number of API requests that are allowed for **this** vehicle in the current billing period.
Please log in to the [Smartcar dashboard](https://dashboard.smartcar.com/login) and visit the Billing tab to learn more.

```json VEHICLE_REQUEST_LIMIT theme={null}
{
  "type": "BILLING",
  "code": "VEHICLE_REQUEST_LIMIT",
  "description": "You have exceeded the number of API requests that are allowed for this vehicle in the current billing period. Please log into the Smartcar dashboard and visit the Billing tab to learn more.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/billing-errors#vehicle-request-limit",
  "statusCode": 430,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "CONTACT_SUPPORT" } 
}
```

### Troubleshooting Steps

To resolve this error, please [contact us](mailto:support@smartcar.com) to upgrade your plan and increase your vehicle limit.
Please note that you won’t be able to make additional requests to this vehicle until the end of the current billing period or until you have upgraded your plan.

# `ACCOUNT_SUSPENDED`

Your Smartcar account is past due and has been suspended.
Please reach out to our finance team to resolve this issue.

```json ACCOUNT_SUSPENDED theme={null}
{
  "type": "BILLING",
  "code": "ACCOUNT_SUSPENDED",
  "description": "Your Smartcar account is past due and has been suspended. Please reach out to our finance team to resolve this issue.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/billing-errors#account-suspended",
  "statusCode": 430,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20882a",
  "resolution": { "type": "FINANCE" } 
}
```

### Troubleshooting Steps

To resolve this error, please [contact us](mailto:finance@smartcar.com) to pay past due invoices.
Please note that you won’t be able to make any requests until you have resolved this issue.


# Compatibility Errors
Source: https://smartcar.com/docs/errors/api-errors/compatibility-errors

Thrown when Smartcar does not support a make, or feature for a vehicle.

# `MAKE_NOT_COMPATIBLE`

Smartcar is not yet compatible with this vehicle’s make in the country you specified.

```json theme={null}
{
  "type": "COMPATIBILITY",
  "code": "MAKE_NOT_COMPATIBLE",
  "description": "Smartcar is not yet compatible with this vehicle’s make in the country you specified.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/compatibility-errors#make-not-compatible",
  "statusCode": 501,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null } 
}
```

**Suggested User Messaging**<br />
`<your app name>` is not yet able to connect to your car brand.

<br />

# `PLATFORM_NOT_CAPABLE`

You're connected to the vehicle using an OEM integration that does not support this endpoint. This can be a result of the OEM migrating to a newer API or requiring vehicle owners to migrate to a new application they have released.

```json theme={null}
{
  "type": "COMPATIBILITY",
  "code": "PLATFORM_NOT_CAPABLE",
  "description": "You're connected to the vehicle using an OEM integration that does not support this endpoint.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/compatibility-errors#platform-not-capable",
  "statusCode": 501,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "REAUTHENTICATE" } 
}
```

**Troubleshooting Steps**<br />
For Tesla vehicles please have the owner re-authenticate using the latest Tesla authorization flow.

<br />

# `SMARTCAR_NOT_CAPABLE`

Smartcar does not yet support this feature for this vehicle.

```json theme={null}
{
  "type": "COMPATIBILITY",
  "code": "SMARTCAR_NOT_CAPABLE",
  "description": "Smartcar does not yet support this feature for this vehicle.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/compatibility-errors#smartcar-not-capable",
  "statusCode": 501,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null } 
}
```

**Troubleshooting Steps**<br />
Please check that the vehicles make and engine type support the feature you are trying to use.

Please contact us to learn when this feature will become available.
If you have a vehicle that supports this feature and would like to help out, check out Smartcar’s Research Fleet.

<br />

# `VEHICLE_NOT_CAPABLE`

This error occurs when a physical limitation makes the vehicle incapable of performing your request
(e.g. battery electric vehicles are incapable of responding to read fuel requests).

```json theme={null}
{
  "type": "COMPATIBILITY",
  "code": "VEHICLE_NOT_CAPABLE",
  "description": "The vehicle is incapable of performing your request.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/compatibility-errors#vehicle-not-capable",
  "statusCode": 501,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null } 
}
```

**Suggested User Messaging**<br />
Your car is unable to perform this request.

<br />


# Connected Services Account Errors
Source: https://smartcar.com/docs/errors/api-errors/connected-services-account-errors

Thrown when there are issues with the user's connected service account.

# `ACCOUNT_ISSUE`

Action needed in the user’s connected services account. The user needs to log in and complete an outstanding task in their connected services account.

Examples:

* The user needs to accept the connected services app’s Terms of Service.
* The user has created but not yet fully activated their connected services account.
* If you've received this error while testing with Vehicle Simulator, it likely means a simulation has not been started for the vehicle. Visit the Simulator tab in the Smartcar Dashboard to start a simulation for the vehicle.

```json theme={null}
{
  "type": "CONNECTED_SERVICES_ACCOUNT",
  "code": "ACCOUNT_ISSUE",
  "description": "Action needed in the user’s connected services account. Please prompt the user to log into their connected services account and complete any outstanding tasks.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#account-issue",
  "statusCode": 400,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Action required in your connected services account. Please log into your connected services app or web portal and complete any outstanding tasks (e.g. finish activating your account or accept the Terms of Service)." 
}
```

### Suggested resolution

The user can resolve this error by logging into their connected services account and completing any outstanding tasks.

### Troubleshooting steps

* Prompt the user to log into their connected services account using the app or web portal.
* Prompt the user to try triggering an action on their car, e.g. locking the doors or flashing the lights.
* At this point, the app should prompt the user to complete their outstanding task.

### Suggested user message

> Action required in your connected services account. Please log into your connected services app or web portal and complete any outstanding tasks (e.g. finish activating your account or accept the Terms of Service).

***

# `AUTHENTICATION_FAILED`

Smartcar was unable to authenticate with the user’s connected services account. This error usually occurs when the user has updated their connected
services account credentials and not yet re-authenticated in Smartcar Connect. The user should re-authenticate using Smartcar Connect.

```json theme={null}
{
  "type": "CONNECTED_SERVICES_ACCOUNT",
  "code": "AUTHENTICATION_FAILED",
  "description": "Smartcar was unable to authenticate with the user’s connected services account. Please prompt the user to re-authenticate using Smartcar Connect.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#authentication-failed",
  "statusCode": 400,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": {
    "type": "REAUTHENTICATE",
    "url": "https://connect.smartcar.com/oauth/reauthenticate?response_type=vehicle_id&client_id=8229df9f-91a0-4ff0-a1ae-a1f38ee24d07&vehicle_id=sc4a1b01e5-0497-417c-a30e-6df6ba33ba46"
  },
  "suggestedUserMessage": "Your car got disconnected from <app name>. Please use this link to re-connect your car: <link to Smartcar Connect>."
}
```

### Suggested resolution

Please provide the user with a link to Smartcar Connect Re-authentication and prompt them to re-connect their vehicle.
The resolution field contains a partially constructed URL for Smartcar Connect Re-authentication, please see the API reference for more detail.

### Suggested user message

> Your car got disconnected from \<app name>. Please use this link to re-connect your car: \<link to Smartcar Connect>.

***

# `NO_VEHICLES`

No vehicles found in the user’s connected services account. The user might not yet have added their vehicle to their account, or they might not yet have activated connected services for the vehicle.

```json theme={null}
{
  "type": "CONNECTED_SERVICES_ACCOUNT",
  "code": "NO_VEHICLES",
  "description": "No vehicles found in the user’s connected services account. Please prompt the user to add their vehicle to their connected services account and re-authenticate using Smartcar Connect.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#no-vehicles",
  "statusCode": 400,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null }, 
  "suggestedUserMessage": "Your car got disconnected from <app name>. Please use this link to re-connect your car: <link to Smartcar Connect>."
}
```

### Suggested resolution

Please provide the user with a link to Smartcar Connect Re-authentication and prompt them to re-connect their vehicle.
The resolution field contains a partially constructed URL for Smartcar Connect Re-authentication, please see the API reference for more detail.

### Troubleshooting Steps

* Prompt the user to log into their connected services account using the app or web portal.
* Prompt the user to check whether there are any vehicles listed in their account.
* If there are no vehicles listed, prompt the user to add their vehicle.
* If there are one or more vehicles listed, this means that none of the vehicles have had their connected services activated. Prompt the user to activate connected services for at least one vehicle.
* Provide the user with a link to Smartcar Connect and prompt them to re-connect their vehicle.

### Suggested user message

> Your car got disconnected from \<app name>. Please use this link to re-connect your car: \<link to Smartcar Connect>.

***

# `PERMISSION`

This error occurs when a vehicle owner had initially granted Smartcar access to their OEM account, but has since revoked it via the OEM's management portal.

```json theme={null}
{
  "type": "CONNECTED_SERVICES_ACCOUNT",
  "code": "PERMISSION",
  "description": "The vehicle owner has revoked Smartcar’s access to their OEM account.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#permission",
  "statusCode": 400,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": {
	  "type" : "REAUTHENTICATE"
  }
}
```

### Suggested resolution

For Tesla Owners:

* Prompt the vehicle owner to go through the Connect flow again or use our [reauthentication flow](/docs/help/oem-integrations/tesla/developers#stand-alone-flow) to streamline the process.

***

# `SUBSCRIPTION`

The vehicle’s connected services subscription is inactive or does not support the requested API endpoint.

```json theme={null}
{
  "type": "CONNECTED_SERVICES_ACCOUNT",
  "code": "SUBSCRIPTION",
  "description": "The vehicle’s connected services subscription is inactive or does not support the requested API endpoint.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#subscription",
  "statusCode": 400,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your car’s connected services subscription has either expired or it doesn’t support the necessary features to connect to <app name>. Please activate your subscription or contact us to upgrade your subscription."
}
```

### Suggested resolution

The user can resolve this error by logging into their connected services account and either (re-)activating their subscription or purchasing the required subscription package.

### Troubleshooting Steps

If you don’t know which subscription package the user needs to purchase, please contact our team for help.

### Suggested user message

> Your car’s connected services subscription has either expired or it doesn’t support the necessary features to connect to \<app name>. Please activate your subscription or contact us to upgrade your subscription.

***

# `VEHICLE_MISSING`

This vehicle is no longer associated with the user’s connected services account. The user might have removed it from their account.
The user needs to log into their connected services account and either re-add the vehicle or re-activate its subscription.

If you've received this error while testing with Vehicle Simulator, it likely means the simulated vehicle has not been found in your application. Visit the Simulator tab in the Smartcar Dashboard to create a simulated vehicle to test with.

```json theme={null}
{
  "type": "CONNECTED_SERVICES_ACCOUNT",
  "code": "VEHICLE_MISSING",
  "description": "This vehicle is no longer associated with the user’s connected services account. Please prompt the user to re-add the vehicle to their account.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#vehicle-missing",
  "statusCode": 400,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your car’s connected services subscription has either expired or it doesn’t support the necessary features to connect to <app name>. Please activate your subscription or contact us to upgrade your subscription."
}
```

### Suggested resolution

The user can resolve this issue by logging into their connected services account and either re-adding the vehicle or re-activating its subscription.

If the user wishes to disconnect their vehicle from your app, please make a request to our Disconnect endpoint and refrain from making API requests to this vehicle in the future.

### Troubleshooting Steps

* Prompt the user to log into their connected services account using the app or web portal.
* Prompt the user to check whether the vehicle is listed under their account.
* If the vehicle is not listed, prompt the user to add the vehicle to their account.
* If the vehicle is listed, prompt the user to activate the vehicle’s connected services subscription.

### Suggested user message

> This car is no longer associated with your connected services account. Please log into your account and re-add this car.

***

# `VIRTUAL_KEY_REQUIRED`

The vehicle owner has granted your application access to the vehicle through Smartcar. However, additional steps are needed on the owners part in order to perform this specific request.

```json theme={null}
{
  "type": "CONNECTED_SERVICES_ACCOUNT",
  "code": "VIRTUAL_KEY_REQUIRED",
  "description": "The vehicle owner needs to grant additional access to Smartcar in order to perform this request.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#virtual-key-required",
  "statusCode": 400,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": {
	  "type" : "ACTION_REQUIRED",
	  "url" : "https://www.tesla.com/_ak/smartcar.com"
  }
  "suggestedUserMessage": "In order to perform this request you’ll need to add a Third-Party Virtual key to your vehicle. Please open this link on the phone with your Tesla App to complete this step."
}
```

### Suggested resolution

For Tesla Owners:

* The vehicle owner needs to add Smartcar’s Third-Party Virtual Key. As of late 2023, Tesla is starting to require virtual keys for Third-Party applications to perform commands.
* In order to issue commands, please prompt the vehicle owner to add Smartcar’s Third-Party virtual key: [https://www.tesla.com/\_ak/smartcar.com](https://www.tesla.com/_ak/smartcar.com)

### Troubleshooting steps

* Please direct the vehicle owner to add Smartcar’s [Third-Party Virtual Key (tesla.com)](https://www.tesla.com/_ak/smartcar.com) in order to allow your application to issue commands to the vehicle.

### Suggested user message

> In order to perform this request you’ll need to add a Third-Party Virtual key to your vehicle. Please open [this](https://www.tesla.com/_ak/smartcar.com) link on the phone with your Tesla App to complete this step.


# Permission Errors
Source: https://smartcar.com/docs/errors/api-errors/permission-errors

Thrown when Smartcar does not support a make or feature for a vehicle.

# `NULL`

Your application has insufficient permissions to access the requested resource. Please prompt the user to re-authenticate using Smartcar Connect.

If you receive this error while testing with Vehicle Simulator, it is likely because the simulated vehicle has not yet been connected to your application, or your application doesn't have access to the requested permission.
Visit the Simulator documentation to learn how to connect the vehicle to your application.

```json theme={null}
{
  "type": "PERMISSION",
  "code": null,
  "description": "Your application has insufficient permissions to access the requested resource. Please prompt the user to re-authenticate using Smartcar Connect.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/permission-errors#null",
  "statusCode": 403,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "REAUTHENTICATE" }  
}
```

### Suggested Resolution

You can resolve this error by ensuring that the scope parameter contains all the permissions that your application requires and prompting the user to re-authenticate using Smartcar Connect.

### Troubleshooting Steps

* Ensure that the scope parameter contains all the permissions that your application requires.
* Ensure that you spell all permission names in the scope parameter correctly.
* Prompt the user to re-authenticate using Smartcar Connect.


# Rate Limit Errors
Source: https://smartcar.com/docs/errors/api-errors/rate-limit-errors

Thrown when there is an issue with the frequency of your requests.

# `SMARTCAR_API`

Your application has exceeded its rate limit. Please retry your request in a few minutes.

```json theme={null}
{
  "type": "RATE_LIMIT",
  "code": "SMARTCAR_API",
  "description": "Your application has exceeded its rate limit. Please retry your request in a few minutes.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/rate-limit-errors#smartcar-api",
  "statusCode": 429,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "RETRY_LATER" },
  "suggestedUserMessage": "Your vehicle is temporarily unable to connect to <app name>. Please be patient while we’re working to resolve this issue."
}
```

### Suggested resolution

You can resolve this error by refraining from making API requests for a certain period of time.
If your application automatically retries requests for certain errors, please disable automatic retries or implement a backoff period to retry certain requests less frequently.

### Troubleshooting steps

If you believe that you received this error by mistake and your application didn’t actually exceed its rate limit, please contact us and we’ll be happy to assist you.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `VEHICLE`

You have reached the throttling rate limit for this vehicle. Please see the `retry-after` header (seconds) for when to retry the request.

This limit is in place to prevent excessive vehicle requests that could:

* Lead to 12v battery drain.
* Trigger UPSTREAM:RATE\_LIMIT errors that prevent you from making requests for a longer period of time.

```json theme={null}
{
  "type": "RATE_LIMIT",
  "code": "VEHICLE",
  "description": "You have reached the throttling rate limit for this vehicle. Please see the retry-after header for when to retry the request.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/rate-limit-errors#vehicle",
  "statusCode": 429,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "RETRY_LATER" },
  "suggestedUserMessage": "Your vehicle is temporarily unable to connect to <app name>. Please be patient while we’re working to resolve this issue."
 
}
```

### Suggested resolution

You can resolve this error by refraining from making API requests. Please see the retry-after header for when to try again. If your application automatically retries requests for certain errors, please disable them for this one.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***


# Resource Not Found
Source: https://smartcar.com/docs/errors/api-errors/resource-not-found-errors

Thrown when the incorrect API version is used or when the endpoint URL is incorrect.

# `PATH`

The requested resource does not exist. Please check the URL and try again.

```json theme={null}
{
  "type": "RESOURCE_NOT_FOUND",
  "code": "PATH",
  "description": "The requested resource does not exist. Please check the URL and try again.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/resource-errors#pathh",
  "statusCode": 404,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your vehicle is temporarily unable to connect to <app name>. Please be patient while we’re working to resolve this issue."
}
```

### Suggested Resolution

You can resolve this error by referring to our API reference and ensuring that you use the correct URL for your request.

### Troubleshooting Steps

* Ensure that you spell all static parts of the URL correctly.
* Ensure that you use the correct URL path parameters (e.g. vehicle ID).
* Ensure that you use the correct HTTP method.

***

# `VERSION`

The requested resource does not exist. Your request either does not specify a version number or it specifies a version number that is not supported by this resource.

```json theme={null}
{
  "type": "RESOURCE_NOT_FOUND",
  "code": "VERSION",
  "description": "The requested resource does not exist. Please check your specified version number and try again.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/resource-errors#version",
  "statusCode": 404,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your vehicle is temporarily unable to connect to <app name>. Please be patient while we’re working to resolve this issue."
}
```

### Suggested Resolution

You can resolve this error by referring to our API reference and ensuring that you specify v2.0 in the URL path (e.g. `https://api.smartcar.com/v2.0/vehicles`). Version 1 has been sunset and is no longer supported.


# Server Errors
Source: https://smartcar.com/docs/errors/api-errors/server-errors

Thrown when Smartcar runs into an unexpected issue and was unable to process the request.

# `INTERNAL`

An internal Smartcar error has occurred. Our team has been notified and is working to resolve this issue.

```json theme={null}
{
  "type": "SERVER",
  "code": "INTERNAL",
  "description": "An internal Smartcar error has occurred. Our team has been notified and is working to resolve this issue.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/server-errors#internal",
  "statusCode": 500,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "RETRY_LATER" },
  "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we’re working to resolve this issue." 
}
```

### Suggested Resolution

Please contact us to learn more about the error and our steps to resolve it.

### Suggested User Message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `RECORD_NOT_FOUND`

Smartcar is unable to locate a battery capacity record for this vehicle. Depending on the make of the vehicle, battery capacity may depend on upstream sources to fulfil a request if it is not directly provided by the OEM.

If you’re seeing this error then the OEM doesn’t provide all the data we aim to provide in our response and we were unable to locate this information from other sources.

```json theme={null}
{
  "type": "SERVER",
  "code": "RECORD_NOT_FOUND",
  "description": "Smartcar was unable to locate a battery capacity record for this vehicle.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/server-errors#record-not-found",
  "statusCode": 500,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "CONTACT_SUPPORT" },
  "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we’re working to resolve this issue." 
}
```

### Suggested Resolution

Please reach out to support to see if we are able to update capacity data for the vehicle.

### Suggested User Message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `MULTIPLE_RECORDS_FOUND`

Smartcar is unable to locate a battery capacity record for this vehicle. Depending on the make of the vehicle, battery capacity may depend on upstream sources to fulfil a request if it is not directly provided by the OEM.

If you’re seeing this error then the OEM doesn’t provide all the data we aim to provide in our response and we were unable to find a specific match. Please see the error response `detail` field for possible matches.

```json theme={null}
{
	"statusCode": 500,
	"type": "SERVER",
	"code": "MULTIPLE_RECORDS_FOUND",
	"description": "Smartcar found multiple battery capacity records for this vehicle.",
	"docURL": "https://smartcar.com/docs/errors/api-errors/server-errors#multiple-records-found",
	"resolution": {
		"type": "CONTACT_SUPPORT"
	},
	"suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we’re working to resolve this issue.",
	"detail": [
		{
			"capacities": [83.9, 83.9, 70.2]
		}
	],
	"requestId": "9c8dd6fa-f9d7-4d18-9fdd-2255f6cd8613"
}
```

### Suggested Resolution

For battery capacity errors please check the detail field of the error response for a list of possible options and reach out support if you need us to update the capacity value for a specific vehicle.

### Suggested User Message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.


# Upstream Errors
Source: https://smartcar.com/docs/errors/api-errors/upstream-errors

Thrown when the OEM servers or vehicle failed to process the request.

<Info>
  <b>Check Smartcar Reliability & Status</b><br />
  For upt-to-date information on Smartcar's platform and brand reliability, visit our:

  <ul>
    <li><a href="https://brandreliability.smartcar.com/">Brand Reliability page</a></li>
    <li><a href="https://status.smartcar.com/">Platform Status page</a></li>
  </ul>
</Info>

# `INVALID_DATA`

One of Smartcar’s upstream sources provided data that is malformed, invalid, or logically invalid (e.g. 65535 psi for tire pressure).

```json theme={null}
{
  "type": "UPSTREAM",
  "code": "INVALID_DATA",
  "description": "Smartcar received invalid data from an upstream source. Please retry your request at a later time.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/upstream-errors#invalid-data",
  "statusCode": 502,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "RETRY_LATER" },
  "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we’re working to resolve this issue." 
}
```

### Suggested resolution

You can resolve this error by retrying your request at a later time.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `KNOWN_ISSUE`

Smartcar received an error from an upstream source. This error usually occurs when an upstream source experiences an error that we have previously investigated and categorized as a known issue.

```json theme={null}
{
  "type": "UPSTREAM",
  "code": "KNOWN_ISSUE",
  "description": "Smartcar received an error from an upstream source. Please retry your request at a later time.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/upstream-errors#known-issue",
  "statusCode": 502,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "RETRY_LATER" },
  "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we’re working to resolve this issue." 
}
```

### Suggested resolution

You can resolve this error by retrying your request at a later time.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `NO_RESPONSE`

One of Smartcar’s upstream sources failed to respond. This error usually occurs when one of Smartcar’s upstream sources is experiencing issues and is currently unavailable.
This error can also occur when a specific vehicle in located in an area with weak cellular reception and fails to respond to your request in a timely manner.

```json theme={null}
{
  "type": "UPSTREAM",
  "code": "NO_RESPONSE",
  "description": "One of Smartcar’s upstream sources failed to respond. Please retry your request at a later time.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/upstream-errors#no-response",
  "statusCode": 502,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "RETRY_LATER" },
  "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we’re working to resolve this issue."
}
```

### Suggested resolution

You can resolve this error by retrying your request at a later time.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `RATE_LIMIT`

Your application’s requests have exceeded this vehicle’s rate limit.

```json theme={null}
{
  "type": "UPSTREAM",
  "code": "NO_RESPONSE",
  "description": "One of Smartcar’s upstream sources failed to respond. Please retry your request at a later time.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/upstream-errors#rate-limit",
  "statusCode": 502,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "RETRY_LATER" },
  "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we’re working to resolve this issue."
}
```

### Suggested resolution

You can resolve this error by refraining from making API requests to this specific vehicle for a period of time.
If your application automatically retries requests, please disable automatic retries or implement a backoff period to retry less frequently.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `UNKNOWN_ISSUE`

Smartcar received an unknown error from an upstream source. This error usually occurs when one of Smartcar’s upstream sources experiences an error that we have not yet investigated or mitigated.

There are several reasons why we might not have investigated this error yet:

* The feature or vehicle make is still in beta.
* This error does not occur very frequently.
* This is the first time we have received this error.

```json theme={null}
{
  "type": "UPSTREAM",
  "code": "UNKNOWN_ISSUE",
  "description": "Smartcar received an unknown error from an upstream source. Please retry your request at a later time and contact us if the issue persists.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/upstream-errors#unknown-issue",
  "statusCode": 502,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "RETRY_LATER" },
  "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we’re working to resolve this issue."
}
```

### Suggested resolution

Given the broad range of situations that can cause this error, you might or might not be able to resolve this error by retrying your request at a later time.
If you retry your request and the issue persists, please contact us to help you mitigate this error.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***


# Authentication Errors
Source: https://smartcar.com/docs/errors/api-errors/v3/authentication-errors

Thrown when there is an issue with your authorization header.

# `UNAUTHORIZED`

The authorization header is missing or malformed, or it contains invalid or expired authentication credentials (e.g. access token, client ID, client secret). Please check for missing parameters, spelling and casing mistakes, and other syntax issues.

```json UNAUTHORIZED theme={null}
{
      "errors": [
        {
            "links": {
                "about": "https://smartcar.com/docs/errors/api-errors/authentication-errors#null"
            },
            "status": "401",
            "type": "AUTHENTICATION",
            "code": "UNAUTHORIZED",
            "title": "Unauthorized",
            "detail": "The Authorization token is missing or invalid."
        }
    ]
}
```

### Suggested Resolution

Ensure your Authentication header is present in the `Bearer {token}` format.
Use the token endpoint to get a new access token.

### Troubleshooting Steps

Refer to our API reference and ensure that you use the correct authentication mechanism for your request

* Check constants like Bearer for spelling mistakes.
* Use the [oauth2/token](/docs/api-reference/authorization/request-access-token) endpoint to get a new access token. Access tokens over an hour old have likely expired.

# `ACCESS_DENIED`

The provided token does not have access to the request resource or path

```json ACCESS_DENIED theme={null}
{
    "errors": [
        {
            "status": "403",
            "type": "AUTHENTICATION",
            "code": "ACCESS_DENIED",
            "title": "Access Denied",
            "detail": "The given token does not provide access to the requested resource."
        }
    ]
}
```

### Suggested Resolution

Ensure you are requesting valid resources for the application associated with the given access token. Ensure your request path is valid.


# Billing Errors
Source: https://smartcar.com/docs/errors/api-errors/v3/billing-errors

Thrown when limits have been reached based on your plan, or if the feature is not available.

# `VEHICLE_LIMIT`

You’ve reached the limit of vehicles in your plan. Please upgrade to unlock access to more vehicles.

```json VEHICLE_LIMIT theme={null}
{
  "errors": [
    {
      "status": "430",
      "type": "BILLING",
      "code": "VEHICLE_LIMIT",
      "title": "Vehicle Limit Reached",
      "detail": "You’ve reached the limit of vehicles in your plan. Please upgrade to unlock access to more vehicles.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/billing-errors#vehicle-limit",
      },
      "resolution": { "type": "CONTACT_SUPPORT" },
    },
  ]
}
```

### Troubleshooting Steps

To resolve this error, please [contact us](mailto:support@smartcar.com) to upgrade your plan and increase your vehicle limit.
Please note that you won’t be able to make requests to additional vehicles until the end of the current billing period or until you have upgraded your plan.

# `INVALID_PLAN`

The feature you are trying to use is not included in your current pricing plan. Please visit our pricing page to learn more about our plans and features.

```json INVALID_PLAN theme={null}
{
  "errors": [
    {
      "status": "430",
      "type": "BILLING",
      "code": "INVALID_PLAN",
      "title": "Invalid Plan",
      "detail": "The feature you are trying to use is not included in your current pricing plan. Please visit our pricing page to learn more about our plans and features.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/billing-errors#invalid-plan",
      },
      "resolution": { "type": "CONTACT_SUPPORT" },
    },
  ]
}
```

### Troubleshooting Steps

If you have checked our pricing page and believe that the feature you are trying to use is included in your plan,
please [contact us](mailto:support@smartcar.com) and we’ll be happy to assist you.

# `VEHICLE_REQUEST_LIMIT`

You have exceeded the number of API requests that are allowed for **this** vehicle in the current billing period.
Please log in to the [Smartcar dashboard](https://dashboard.smartcar.com/login) and visit the Billing tab to learn more.

```json VEHICLE_REQUEST_LIMIT theme={null}
{
  "errors": [
    {
      "status": "430",
      "type": "BILLING",
      "code": "VEHICLE_REQUEST_LIMIT",
      "title": "Vehicle Request Limit Exceeded",
      "detail": "You have exceeded the number of API requests that are allowed for this vehicle in the current billing period. Please log into the Smartcar dashboard and visit the Billing tab to learn more.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/billing-errors#vehicle-request-limit",
      },
      "resolution": { "type": "CONTACT_SUPPORT" },
    },
  ]
}
```

### Troubleshooting Steps

To resolve this error, please [contact us](mailto:support@smartcar.com) to upgrade your plan and increase your vehicle limit.
Please note that you won’t be able to make additional requests to this vehicle until the end of the current billing period or until you have upgraded your plan.

# `ACCOUNT_SUSPENDED`

Your Smartcar account is past due and has been suspended.
Please reach out to our finance team to resolve this issue.

```json ACCOUNT_SUSPENDED theme={null}
{
  "errors": [
    {
      "status": "430",
      "type": "BILLING",
      "code": "ACCOUNT_SUSPENDED",
      "title": "Account Suspended",
      "detail": "Your Smartcar account is past due and has been suspended. Please reach out to our finance team to resolve this issue.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/billing-errors#account-suspended",
      },
      "resolution": { "type": "FINANCE" },
    },
  ]
}
```

### Troubleshooting Steps

To resolve this error, please [contact us](mailto:finance@smartcar.com) to pay past due invoices.
Please note that you won’t be able to make any requests until you have resolved this issue.


# Compatibility Errors
Source: https://smartcar.com/docs/errors/api-errors/v3/compatibility-errors

Thrown when Smartcar does not support a make, or feature for a vehicle.

# `MAKE_NOT_COMPATIBLE`

Smartcar is not yet compatible with this vehicle’s make in the country you specified.

```json MAKE_NOT_COMPATIBLE theme={null}
{
  "errors": [
    {
      "status": "501",
      "type": "COMPATIBILITY",
      "code": "MAKE_NOT_COMPATIBLE",
      "title": "Make Not Compatible",
      "detail": "Smartcar is not yet compatible with this vehicle’s make in the country you specified.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/compatibility-errors#make-not-compatible",
      },
      "resolution": { "type": null },
    },
  ]
}
```

**Suggested User Messaging**<br />
`<your app name>` is not yet able to connect to your car brand.

<br />

# `PLATFORM_NOT_CAPABLE`

You're connected to the vehicle using an OEM integration that does not support this endpoint. This can be a result of the OEM migrating to a newer API or requiring vehicle owners to migrate to a new application they have released.

```json PLATFORM_NOT_CAPABLE theme={null}
{
  "errors": [
    {
      "status": "501",
      "type": "COMPATIBILITY",
      "code": "PLATFORM_NOT_CAPABLE",
      "title": "Platform Not Capable",
      "detail": "You're connected to the vehicle using an OEM integration that does not support this endpoint.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/compatibility-errors#platform-not-capable",
      },
      "resolution": { "type": "REAUTHENTICATE" },
    },
  ]
}
```

**Troubleshooting Steps**<br />
For Tesla vehicles please have the owner re-authenticate using the latest Tesla authorization flow.

<br />

# `SMARTCAR_NOT_CAPABLE`

Smartcar does not yet support this feature for this vehicle.

```json SMARTCAR_NOT_CAPABLE theme={null}
{
  "errors": [
    {
      "status": "501",
      "type": "COMPATIBILITY",
      "code": "SMARTCAR_NOT_CAPABLE",
      "title": "Smartcar Not Capable",
      "detail": "Smartcar does not yet support this feature for this vehicle.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/compatibility-errors#smartcar-not-capable",
      },
      "resolution": { "type": null },
    },
  ]
}
```

**Troubleshooting Steps**<br />
Please check that the vehicles make and engine type support the feature you are trying to use.

Please contact us to learn when this feature will become available.
If you have a vehicle that supports this feature and would like to help out, check out Smartcar’s Research Fleet.

<br />

# `VEHICLE_NOT_CAPABLE`

This error occurs when a physical limitation makes the vehicle incapable of performing your request
(e.g. battery electric vehicles are incapable of responding to read fuel requests).

```json VEHICLE_NOT_CAPABLE theme={null}
{
  "errors": [
    {
      "status": "501",
      "type": "COMPATIBILITY",
      "code": "VEHICLE_NOT_CAPABLE",
      "title": "Vehicle Not Capable",
      "detail": "The vehicle is incapable of performing your request.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/compatibility-errors#vehicle-not-capable",
      },
      "resolution": { "type": null },
    },
  ]
}
```

**Suggested User Messaging**<br />
Your car is unable to perform this request.

<br />


# Connected Services Account Errors
Source: https://smartcar.com/docs/errors/api-errors/v3/connected-services-account-errors

Thrown when there are issues with the user's connected service account.

# `ACCOUNT_ISSUE`

Action needed in the user’s connected services account. The user needs to log in and complete an outstanding task in their connected services account.

Examples:

* The user needs to accept the connected services app’s Terms of Service.
* The user has created but not yet fully activated their connected services account.
* If you've received this error while testing with Vehicle Simulator, it likely means a simulation has not been started for the vehicle. Visit the Simulator tab in the Smartcar Dashboard to start a simulation for the vehicle.

```json ACCOUNT_ISSUE theme={null}
{
  "errors": [
    {
      "status": "400",
      "type": "CONNECTED_SERVICES_ACCOUNT",
      "code": "ACCOUNT_ISSUE",
      "title": "Account Issue",
      "detail": "Action needed in the user’s connected services account. Please prompt the user to log into their connected services account and complete any outstanding tasks.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#account-issue",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Action required in your connected services account. Please log into your connected services app or web portal and complete any outstanding tasks (e.g. finish activating your account or accept the Terms of Service).",
    },
  ]
}
```

### Suggested resolution

The user can resolve this error by logging into their connected services account and completing any outstanding tasks.

### Troubleshooting steps

* Prompt the user to log into their connected services account using the app or web portal.
* Prompt the user to try triggering an action on their car, e.g. locking the doors or flashing the lights.
* At this point, the app should prompt the user to complete their outstanding task.

### Suggested user message

> Action required in your connected services account. Please log into your connected services app or web portal and complete any outstanding tasks (e.g. finish activating your account or accept the Terms of Service).

***

# `AUTHENTICATION_FAILED`

Smartcar was unable to authenticate with the user’s connected services account. This error usually occurs when the user has updated their connected
services account credentials and not yet re-authenticated in Smartcar Connect. The user should re-authenticate using Smartcar Connect.

```json AUTHENTICATION_FAILED theme={null}
{
  "errors": [
    {
      "status": "400",
      "type": "CONNECTED_SERVICES_ACCOUNT",
      "code": "AUTHENTICATION_FAILED",
      "title": "Authentication Failed",
      "detail": "Smartcar was unable to authenticate with the user’s connected services account. Please prompt the user to re-authenticate using Smartcar Connect.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#authentication-failed",
      },
      "resolution": { "type": "REAUTHENTICATE", "url": "https://connect.smartcar.com/oauth/reauthenticate?response_type=vehicle_id&client_id=8229df9f-91a0-4ff0-a1ae-a1f38ee24d07&vehicle_id=sc4a1b01e5-0497-417c-a30e-6df6ba33ba46" },
      "suggestedUserMessage": "Your car got disconnected from <app name>. Please use this link to re-connect your car: <link to Smartcar Connect>.",
    },
  ]
}
```

### Suggested resolution

Please provide the user with a link to Smartcar Connect Re-authentication and prompt them to re-connect their vehicle.
The resolution field contains a partially constructed URL for Smartcar Connect Re-authentication, please see the API reference for more detail.

### Suggested user message

> Your car got disconnected from \<app name>. Please use this link to re-connect your car: \<link to Smartcar Connect>.

***

# `NO_VEHICLES`

No vehicles found in the user’s connected services account. The user might not yet have added their vehicle to their account, or they might not yet have activated connected services for the vehicle.

```json NO_VEHICLES theme={null}
{
  "errors": [
    {
      "status": "400",
      "type": "CONNECTED_SERVICES_ACCOUNT",
      "code": "NO_VEHICLES",
      "title": "No Vehicles Found",
      "detail": "No vehicles found in the user’s connected services account. Please prompt the user to add their vehicle to their connected services account and re-authenticate using Smartcar Connect.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#no-vehicles",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your car got disconnected from <app name>. Please use this link to re-connect your car: <link to Smartcar Connect>.",
    },
  ]
}
```

### Suggested resolution

Please provide the user with a link to Smartcar Connect Re-authentication and prompt them to re-connect their vehicle.
The resolution field contains a partially constructed URL for Smartcar Connect Re-authentication, please see the API reference for more detail.

### Troubleshooting Steps

* Prompt the user to log into their connected services account using the app or web portal.
* Prompt the user to check whether there are any vehicles listed in their account.
* If there are no vehicles listed, prompt the user to add their vehicle.
* If there are one or more vehicles listed, this means that none of the vehicles have had their connected services activated. Prompt the user to activate connected services for at least one vehicle.
* Provide the user with a link to Smartcar Connect and prompt them to re-connect their vehicle.

### Suggested user message

> Your car got disconnected from \<app name>. Please use this link to re-connect your car: \<link to Smartcar Connect>.

***

# `PERMISSION`

This error occurs when a vehicle owner had initially granted Smartcar access to their OEM account, but has since revoked it via the OEM's management portal.

```json PERMISSION theme={null}
{
  "errors": [
    {
      "status": "400",
      "type": "CONNECTED_SERVICES_ACCOUNT",
      "code": "PERMISSION",
      "title": "Permission Revoked",
      "detail": "The vehicle owner has revoked Smartcar’s access to their OEM account.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#permission",
      },
      "resolution": { "type": "REAUTHENTICATE" },
    },
  ]
}
```

### Suggested resolution

For Tesla Owners:

* Prompt the vehicle owner to go through the Connect flow again or use our [reauthentication flow](/docs/help/oem-integrations/tesla/developers#stand-alone-flow) to streamline the process.

***

# `SUBSCRIPTION`

The vehicle’s connected services subscription is inactive or does not support the requested API endpoint.

```json SUBSCRIPTION theme={null}
{
  "errors": [
    {
      "status": "400",
      "type": "CONNECTED_SERVICES_ACCOUNT",
      "code": "SUBSCRIPTION",
      "title": "subscription",
      "detail": "The vehicle’s connected services subscription is inactive or does not support the requested API endpoint.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#subscription",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your car's connected services subscription has either expired or it doesn't support the necessary features to connect to <app name>. Please activate your subscription or contact us to upgrade your subscription.",
    },
  ]
}
```

### Suggested resolution

The user can resolve this error by logging into their connected services account and either (re-)activating their subscription or purchasing the required subscription package.

### Troubleshooting Steps

If you don’t know which subscription package the user needs to purchase, please contact our team for help.

### Suggested user message

> Your car’s connected services subscription has either expired or it doesn’t support the necessary features to connect to \<app name>. Please activate your subscription or contact us to upgrade your subscription.

***

# `VEHICLE_MISSING`

This vehicle is no longer associated with the user’s connected services account. The user might have removed it from their account.
The user needs to log into their connected services account and either re-add the vehicle or re-activate its subscription.

If you've received this error while testing with Vehicle Simulator, it likely means the simulated vehicle has not been found in your application. Visit the Simulator tab in the Smartcar Dashboard to create a simulated vehicle to test with.

```json VEHICLE_MISSING theme={null}
{
  "errors": [
    {
      "status": "400",
      "type": "CONNECTED_SERVICES_ACCOUNT",
      "code": "VEHICLE_MISSING",
      "title": "Vehicle Missing",
      "detail": "This vehicle is no longer associated with the user’s connected services account. Please prompt the user to re-add the vehicle to their account.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#vehicle-missing",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your car's connected services subscription has either expired or it doesn't support the necessary features to connect to <app name>. Please activate your subscription or contact us to upgrade your subscription.",
    },
  ]
}
```

### Suggested resolution

The user can resolve this issue by logging into their connected services account and either re-adding the vehicle or re-activating its subscription.

If the user wishes to disconnect their vehicle from your app, please make a request to our Disconnect endpoint and refrain from making API requests to this vehicle in the future.

### Troubleshooting Steps

* Prompt the user to log into their connected services account using the app or web portal.
* Prompt the user to check whether the vehicle is listed under their account.
* If the vehicle is not listed, prompt the user to add the vehicle to their account.
* If the vehicle is listed, prompt the user to activate the vehicle’s connected services subscription.

### Suggested user message

> This car is no longer associated with your connected services account. Please log into your account and re-add this car.

***

# `VIRTUAL_KEY_REQUIRED`

The vehicle owner has granted your application access to the vehicle through Smartcar. However, additional steps are needed on the owners part in order to perform this specific request.

```json VIRTUAL_KEY_REQUIRED theme={null}
{
  "errors": [
    {
      "status": "400",
      "type": "CONNECTED_SERVICES_ACCOUNT",
      "code": "VIRTUAL_KEY_REQUIRED",
      "title": "Virtual Key Required",
      "detail": "The vehicle owner needs to grant additional access to Smartcar in order to perform this request.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#virtual-key-required",
      },
      "resolution": { "type": "ACTION_REQUIRED", "url": "https://www.tesla.com/_ak/smartcar.com" },
      "suggestedUserMessage": "In order to perform this request you'll need to add a Third-Party Virtual key to your vehicle. Please open this link on the phone with your Tesla App to complete this step.",
    },
  ]
}
```

### Suggested resolution

For Tesla Owners:

* The vehicle owner needs to add Smartcar’s Third-Party Virtual Key. As of late 2023, Tesla is starting to require virtual keys for Third-Party applications to perform commands.
* In order to issue commands, please prompt the vehicle owner to add Smartcar’s Third-Party virtual key: [https://www.tesla.com/\_ak/smartcar.com](https://www.tesla.com/_ak/smartcar.com)

### Troubleshooting steps

* Please direct the vehicle owner to add Smartcar’s [Third-Party Virtual Key (tesla.com)](https://www.tesla.com/_ak/smartcar.com) in order to allow your application to issue commands to the vehicle.

### Suggested user message

> In order to perform this request you’ll need to add a Third-Party Virtual key to your vehicle. Please open [this](https://www.tesla.com/_ak/smartcar.com) link on the phone with your Tesla App to complete this step.


# Rate Limit Errors
Source: https://smartcar.com/docs/errors/api-errors/v3/rate-limit-errors

Thrown when there is an issue with the frequency of your requests.

# `SMARTCAR_API`

Your application has exceeded its rate limit. Please retry your request in a few minutes.

```json SMARTCAR_API theme={null}
{
  "errors": [
    {
      "status": "429",
      "type": "RATE_LIMIT",
      "code": "SMARTCAR_API",
      "title": "Too Many Requests",
      "detail": "Your application has exceeded its rate limit. Please retry your request in a few minutes.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/rate-limit-errors#smartcar-api",
      },
      "resolution": { "type": "RETRY_LATER" },
      "suggestedUserMessage": "Your vehicle is temporarily unable to connect to <app name>. Please be patient while we're working to resolve this issue.",
    },
  ]
}
```

### Suggested resolution

You can resolve this error by refraining from making API requests for a certain period of time.
If your application automatically retries requests for certain errors, please disable automatic retries or implement a backoff period to retry certain requests less frequently.

### Troubleshooting steps

If you believe that you received this error by mistake and your application didn’t actually exceed its rate limit, please contact us and we’ll be happy to assist you.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `VEHICLE`

You have reached the throttling rate limit for this vehicle. Please see the `retry-after` header (seconds) for when to retry the request.

This limit is in place to prevent excessive vehicle requests that could:

* Lead to 12v battery drain.
* Trigger UPSTREAM:RATE\_LIMIT errors that prevent you from making requests for a longer period of time.

```json VEHICLE theme={null}
{
  "errors": [
    {
      "status": "429",
      "type": "RATE_LIMIT",
      "code": "VEHICLE",
      "title": "Too Many Requests",
      "detail": "You have reached the throttling rate limit for this vehicle. Please see the retry-after header for when to retry the request.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/rate-limit-errors#vehicle",
      },
      "resolution": { "type": "RETRY_LATER" },
      "suggestedUserMessage": "Your vehicle is temporarily unable to connect to <app name>. Please be patient while we're working to resolve this issue.",
    },
  ]
}
```

### Suggested resolution

You can resolve this error by refraining from making API requests. Please see the retry-after header for when to try again. If your application automatically retries requests for certain errors, please disable them for this one.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***


# Resource Not Found
Source: https://smartcar.com/docs/errors/api-errors/v3/resource-not-found-errors

Thrown when the incorrect API version is used, the endpoint URL is incorrect, or the provided identifier does not match an existing entity

# `RESOURCE_NOT_FOUND`

The requested resource does not exist. Check the identifier provided.

```json PATH theme={null}
{
  "errors": [
    {
      "status": "404",
      "type": "RESOURCE_NOT_FOUND",
      "code": "{RESOURCE}_NOT_FOUND",
      "title": "Not Found",
      "detail": "Item not found for {identifier}.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/resource-errors#path",
      }
    },
  ]
}
```

### Suggested Resolution

You can resolve this error by checking that the identifier provided for a specific resource is correct

### Troubleshooting Steps

* Use an endpoint to list resources, check correctness of the provided identifier against returned values
* Ensure proper casing for signal codes

***

# `PATH`

The requested resource does not exist. Please check the URL and try again.

```json PATH theme={null}
{
  "errors": [
    {
      "status": "404",
      "type": "RESOURCE_NOT_FOUND",
      "code": "PATH",
      "title": "Not Found",
      "detail": "The requested resource does not exist. Please check the URL and try again.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/resource-errors#path",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your vehicle is temporarily unable to connect to <app name>. Please be patient while we're working to resolve this issue.",
    },
  ]
}
```

### Suggested Resolution

You can resolve this error by referring to our API reference and ensuring that you use the correct URL for your request.

### Troubleshooting Steps

* Ensure that you spell all static parts of the URL correctly.
* Ensure that you use the correct URL path parameters (e.g. vehicle ID).
* Ensure that you use the correct HTTP method.

***

# `VERSION`

The requested resource does not exist. Your request either does not specify a version number or it specifies a version number that is not supported by this resource.

```json VERSION theme={null}
{
  "errors": [
    {
      "status": "404",
      "type": "RESOURCE_NOT_FOUND",
      "code": "VERSION",
      "title": "Not Found",
      "detail": "The requested resource does not exist. Please check your specified version number and try again.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/resource-errors#version",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your vehicle is temporarily unable to connect to <app name>. Please be patient while we're working to resolve this issue.",
    },
  ]
}
```

### Suggested Resolution

You can resolve this error by referring to our API reference and ensuring that you specify v3 in the URL path (e.g. `https://vehicle.api.smartcar.com/v3/vehicles`). Version 1 has been sunset and is no longer supported. Version 2.0 is deprecated and will be sunset on December 1, 2026.


# Server Errors
Source: https://smartcar.com/docs/errors/api-errors/v3/server-errors

Thrown when Smartcar runs into an unexpected issue and was unable to process the request.

# `INTERNAL`

An internal Smartcar error has occurred. Our team has been notified and is working to resolve this issue.

```json INTERNAL theme={null}
{
  "errors": [
    {
      "status": "500",
      "type": "SERVER",
      "code": "INTERNAL",
      "title": "Internal Server Error",
      "detail": "An internal Smartcar error has occurred. Our team has been notified and is working to resolve this issue.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/server-errors#internal",
      },
      "resolution": { "type": "RETRY_LATER" },
      "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we're working to resolve this issue.",
    },
  ]
}
```

### Suggested Resolution

Please contact us to learn more about the error and our steps to resolve it.

### Suggested User Message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `RECORD_NOT_FOUND`

Smartcar is unable to locate a battery capacity record for this vehicle. Depending on the make of the vehicle, battery capacity may depend on upstream sources to fulfil a request if it is not directly provided by the OEM.

If you’re seeing this error then the OEM doesn’t provide all the data we aim to provide in our response and we were unable to locate this information from other sources.

```json RECORD_NOT_FOUND theme={null}
{
  "errors": [
    {
      "status": "500",
      "type": "SERVER",
      "code": "RECORD_NOT_FOUND",
      "title": "Record Not Found",
      "detail": "Smartcar was unable to locate a battery capacity record for this vehicle.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/server-errors#record-not-found",
      },
      "resolution": { "type": "CONTACT_SUPPORT" },
      "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we're working to resolve this issue.",
    },
  ]
}
```

### Suggested Resolution

Please reach out to support to see if we are able to update capacity data for the vehicle.

### Suggested User Message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `MULTIPLE_RECORDS_FOUND`

Smartcar is unable to locate a battery capacity record for this vehicle. Depending on the make of the vehicle, battery capacity may depend on upstream sources to fulfil a request if it is not directly provided by the OEM.

If you’re seeing this error then the OEM doesn’t provide all the data we aim to provide in our response and we were unable to find a specific match. Please see the error response `detail` field for possible matches.

```json MULTIPLE_RECORDS_FOUND theme={null}
{
  "errors": [
    {
      "status": "500",
      "type": "SERVER",
      "code": "MULTIPLE_RECORDS_FOUND",
      "title": "Multiple Records Found",
      "detail": "Smartcar found multiple battery capacity records for this vehicle.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/server-errors#multiple-records-found",
      },
      "meta": {
        "capacities": [83.9, 83.9, 70.2],
      },
      "resolution": { "type": "CONTACT_SUPPORT" },
      "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we're working to resolve this issue.",
    },
  ]
}
```

### Suggested Resolution

For battery capacity errors please check the detail field of the error response for a list of possible options and reach out support if you need us to update the capacity value for a specific vehicle.

### Suggested User Message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.


# Upstream Errors
Source: https://smartcar.com/docs/errors/api-errors/v3/upstream-errors

Thrown when the OEM servers or vehicle failed to process the request.

<Info>
  <b>Check Smartcar Reliability & Status</b><br />
  For up-to-date information on Smartcar's platform and brand reliability, visit our:

  <ul>
    <li><a href="https://brandreliability.smartcar.com/">Brand Reliability page</a></li>
    <li><a href="https://status.smartcar.com/">Platform Status page</a></li>
  </ul>
</Info>

# `INVALID_DATA`

One of Smartcar’s upstream sources provided data that is malformed, invalid, or logically invalid (e.g. 65535 psi for tire pressure).

```json INVALID_DATA theme={null}
{
  "errors": [
    {
      "status": "502",
      "type": "UPSTREAM",
      "code": "INVALID_DATA",
      "title": "Bad Gateway",
      "detail": "Smartcar received invalid data from an upstream source. Please retry your request at a later time.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/upstream-errors#invalid-data",
      },
      "resolution": { "type": "RETRY_LATER" },
      "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we're working to resolve this issue.",
    },
  ]
}
```

### Suggested resolution

You can resolve this error by retrying your request at a later time.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `KNOWN_ISSUE`

Smartcar received an error from an upstream source. This error usually occurs when an upstream source experiences an error that we have previously investigated and categorized as a known issue.

```json KNOWN_ISSUE theme={null}
{
  "errors": [
    {
      "status": "502",
      "type": "UPSTREAM",
      "code": "KNOWN_ISSUE",
      "title": "Bad Gateway",
      "detail": "Smartcar received an error from an upstream source. Please retry your request at a later time.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/upstream-errors#known-issue",
      },
      "resolution": { "type": "RETRY_LATER" },
      "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we're working to resolve this issue.",
    },
  ]
}
```

### Suggested resolution

You can resolve this error by retrying your request at a later time.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `NO_RESPONSE`

One of Smartcar’s upstream sources failed to respond. This error usually occurs when one of Smartcar’s upstream sources is experiencing issues and is currently unavailable.
This error can also occur when a specific vehicle in located in an area with weak cellular reception and fails to respond to your request in a timely manner.

```json NO_RESPONSE theme={null}
{
  "errors": [
    {
      "status": "502",
      "type": "UPSTREAM",
      "code": "NO_RESPONSE",
      "title": "Bad Gateway",
      "detail": "One of Smartcar’s upstream sources failed to respond. Please retry your request at a later time.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/upstream-errors#no-response",
      },
      "resolution": { "type": "RETRY_LATER" },
      "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we're working to resolve this issue.",
    },
  ]
}
```

### Suggested resolution

You can resolve this error by retrying your request at a later time.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `RATE_LIMIT`

Your application’s requests have exceeded this vehicle’s rate limit.

```json RATE_LIMIT theme={null}
{
  "errors": [
    {
      "status": "502",
      "type": "UPSTREAM",
      "code": "RATE_LIMIT",
      "title": "Bad Gateway",
      "detail": "Your application’s requests have exceeded this vehicle’s upstream rate limit. Please retry your request at a later time.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/upstream-errors#rate-limit",
      },
      "resolution": { "type": "RETRY_LATER" },
      "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we're working to resolve this issue.",
    },
  ]
}
```

### Suggested resolution

You can resolve this error by refraining from making API requests to this specific vehicle for a period of time.
If your application automatically retries requests, please disable automatic retries or implement a backoff period to retry less frequently.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `UNKNOWN_ISSUE`

Smartcar received an unknown error from an upstream source. This error usually occurs when one of Smartcar’s upstream sources experiences an error that we have not yet investigated or mitigated.

There are several reasons why we might not have investigated this error yet:

* The feature or vehicle make is still in beta.
* This error does not occur very frequently.
* This is the first time we have received this error.

```json UNKNOWN_ISSUE theme={null}
{
  "errors": [
    {
      "status": "502",
      "type": "UPSTREAM",
      "code": "UNKNOWN_ISSUE",
      "title": "Bad Gateway",
      "detail": "Smartcar received an unknown error from an upstream source. Please retry your request at a later time and contact us if the issue persists.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/upstream-errors#unknown-issue",
      },
      "resolution": { "type": "RETRY_LATER" },
      "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we're working to resolve this issue.",
    },
  ]
}
```

### Suggested resolution

Given the broad range of situations that can cause this error, you might or might not be able to resolve this error by retrying your request at a later time.
If you retry your request and the issue persists, please contact us to help you mitigate this error.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***


# Validation Errors
Source: https://smartcar.com/docs/errors/api-errors/v3/validation-errors

Thrown if there is an issue with the format of the request or body.

# `INVALID_INPUT_FORMAT`

Request invalid or malformed. Please check for missing parameters, spelling and casing mistakes, and other syntax issues.

```json INVALID_INPUT_FORMAT theme={null}
{
    "errors": [
              {
            "links": {
                "about": "https://smartcar.com/docs/errors/api-errors/validation-errors"
            },
            "status": "400",
            "type": "VALIDATION",
            "code": "INVALID_INPUT_FORMAT",
            "title": "Bad Request",
            "detail": "Invalid latitude. Latitude must be a number between -90 and 90."
        },
        {
            "links": {
                "about": "https://smartcar.com/docs/errors/api-errors/validation-errors"
            },
            "status": "400",
            "type": "VALIDATION",
            "code": "INVALID_INPUT_FORMAT",
            "title": "Bad Request",
            "detail": "Invalid longitude. Longitude must be a number between -180 and 180."
        }
    ]
}
```

### Suggested resolution

You can resolve this error by referring to our API reference and ensuring that you pass all the parameters as specified.

### Troubleshooting Steps

* Ensure that you spell and case all parameters correctly.
* Ensure that your request has the correct content-type (i.e. application/json).
* Ensure that your request has the correct URL and HTTP method.

For Ford or Lincoln vehicles:

* Please check the coordinates provided for setting a charge schedule are associated with a saved charging location for this vehicle.


# Vehicle State Errors
Source: https://smartcar.com/docs/errors/api-errors/v3/vehicle-state-errors

Thrown when a request fails due to the state of a vehicle or logically cannot be completed e.g. you can't start a vehicle charging if it's not plugged in.

# `ASLEEP`

The vehicle is in a sleep state and temporarily unable to perform your request. Either the vehicle has been inactive for a certain period of time (time periods vary between makes and models) or the user has manually triggered the vehicle’s sleep state.

```json theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "ASLEEP",
      "title": "Vehicle Asleep",
      "detail": "The vehicle is in a sleep state and temporarily unable to perform your request.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#asleep",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your vehicle is in a sleep state. This request was not sent to preserve battery life.",
    },
  ]
}
```

### Suggested resolution

The vehicle is in a sleep state and temporarily unable to perform your request.

### Troubleshooting Steps

* Prompt the user to start the vehicle’s engine (required) and to drive the vehicle for a short distance (optional).
* Wait for a few minutes and retry your request.
* Ensure that the vehicle’s 12-volt battery is sufficiently charged.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. To re-establish the connection, please start your car and take it for a short drive.

***

# `CHARGING_IN_PROGRESS`

The vehicle is currently charging and unable to perform your request. This error usually occurs when you make a request to the start charge endpoint while the vehicle is already charging.

```json theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "CHARGING_IN_PROGRESS",
      "title": "Charging In Progress",
      "detail": "The vehicle is currently charging and unable to perform your request.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#charging-in-progress",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your vehicle is already charging.",
    },
  ]
}
```

### Suggested resolution

You usually don’t need to resolve this error. If you believe that this error should not have occurred, please follow the troubleshooting steps below.

### Troubleshooting Steps

* Prompt the user to stop charging their vehicle and/or unplug the charger.
* Wait for a few minutes and retry your request.

### Suggested user message

> Your car is already charging.

***

# `CHARGING_PLUG_CONNECTED`

The vehicle is connected to an EV charger and unable to perform your request.

```json theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "CHARGING_PLUG_CONNECTED",
      "title": "Charging Plug Connected",
      "detail": "The vehicle is connected to an EV charger and unable to perform your request.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#charging-plug-connected",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "We're unable to issue the command because the vehicle is currently plugged in.",
    },
  ]
}
```

### Suggested resolution

The user can resolve this error by unplugging the vehicle.

### Suggested user message

> We're unable to issue the command because the vehicle is currently plugged in. Please ensure that you have unplugged the vehicle from an EV charger.

***

# `CHARGING_PLUG_NOT_CONNECTED`

The vehicle is not connected to an EV charger and unable to perform your request. This error usually occurs when you make a request to the start charge endpoint
but the vehicle’s charge port does not have an EV charger plugged into it.

If testing an electric vehicle with Vehicle Simulator, you will receive this error when attempting a start or stop charge request while the vehicle is in a parked
or driving state (not charging).

```json theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "CHARGING_PLUG_NOT_CONNECTED",
      "title": "Charging Plug Not Connected",
      "detail": "The vehicle is not connected to an EV charger and unable to perform your request.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#charging-plug-not-connected",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your vehicle is not plugged in.",
    },
  ]
}
```

### Suggested resolution

The user can resolve this error by plugging an EV charger into the vehicle’s charge port.

### Troubleshooting Steps

* Prompt the user to plug an EV charger into the vehicle’s charge port.
* If this doesn’t resolve the issue, prompt the user to ensure that the EV charger is connected to a working power source, that it isn’t faulty, and that it is compatible with the user’s vehicle. For example, prompt the user to try out other EV chargers and to check the vehicle’s owner manual for a list of compatible chargers.

### Suggested user message

> Your car isn’t able to start charging. Please ensure that you have plugged an EV charger into your car’s charge port.

***

# `DOOR_OPEN`

The vehicle could not perform your request because one or more of its doors are open. This error usually occurs when you make a request to the lock endpoint while one or more of the vehicle’s doors stand open.

```json theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "DOOR_OPEN",
      "title": "Door Open",
      "detail": "The vehicle could not perform your request because one or more of its doors are open.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#door-open",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your vehicle was unable to lock. Please ensure that all doors and the trunk are fully closed.",
    },
  ]
}
```

### Suggested resolution

The user can resolve this error by fully closing all of the vehicle’s doors and the trunk.

### Troubleshooting Steps

* Prompt the user to ensure that there is nothing preventing the doors from fully closing and/or locking properly.
* Prompt the user to ensure that the vehicle’s trunk is fully closed.

### Suggested user message

> Your car was unable to lock. Please ensure that all doors and the trunk are fully closed.

***

# `FULLY_CHARGED`

The vehicle is unable to perform your request because its EV battery is fully charged. This error usually occurs when you make a request to the start charge endpoint while the vehicle is already fully charged.

```json theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "FULLY_CHARGED",
      "title": "Fully Charged",
      "detail": "The vehicle is unable to perform your request because its EV battery is fully charged.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#fully-charged",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your vehicle is already fully charged.",
    },
  ]
}
```

### Suggested user message

> Your car is already fully charged.

***

# `NOT_CHARGING`

The vehicle is unable to perform your request because it is not currently charging. This error usually occurs when you request information about a vehicle’s charge session while the battery is not charging.

```json theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "NOT_CHARGING",
      "title": "Not Charging",
      "detail": "The vehicle is unable to perform your request because it is not currently charging.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#not-charging",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Please ensure that you have plugged an EV charger into your car's charge port and the vehicle is charging.",
    },
  ]
}
```

### Suggested resolution

You can resolve this error by having the user start a charge session or by sending a start charge request if the vehicle supports that capability.

### Troubleshooting Steps

* Prompt the user to start charging their vehicle.
* Wait for a few minutes and retry your request.

### Suggested user message

> Please ensure that you have plugged an EV charger into your car’s charge port and the vehicle is charging.

***

# `CHARGE_FAULT`

The vehicle is connected to an EV charger but cannot perform the request because:

* the charger is not providing any current
* there is a conflict with another charging schedule

```json theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "CHARGE_FAULT",
      "title": "Charge Fault",
      "detail": "The vehicle is connected to an EV charger but cannot perform the request because 1) the charger is not providing any current, or 2) there is a conflict with another charging schedule.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#charge-fault",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your vehicle is unable to start or stop charging because of a conflict with the vehicle's charging schedule.",
    },
  ]
}
```

### Suggested resolution

The user can resolve this error by:

* Disabling any schedules that control when the charger can supply current and charge the vehicle.
* Ensuring that the charging cable is securely connected to the vehicle.
* Disabling any charge schedules on the vehicle’s infotainment system or connected service application.
* Disabling any departure timers on the vehicle’s infotainment system or connected service application.
* Removing the vehicle from other charge scheduling services.

### Troubleshooting Steps

* Prompt the user to start charging their vehicle.
* Wait for a few minutes and retry your request.

### Suggested user message

> Your car is unable to start or stop charging because of a conflict with your vehicle’s charging schedule. Please check that:
>
> * You have disabled any schedules that control when your charger is able to supply current to and charge the vehicle.
> * The charging cable is securely connected to your vehicle.
> * You have disabled any charge schedules on your vehicle’s infotainment system or connected service application.
> * You have disabled any departure timers on your vehicle’s infotainment system or connected service application.
> * Your vehicle is not connected to any other charge scheduling services.

***

# `OEM_BUSINESS_RULE_NOT_MET`

The OEM is rejecting this request because the vehicle does not meet the business rules set by the OEM. For example, the vehicle is outside of a required geofence, the vehicle must be plugged in, etc.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "OEM_BUSINESS_RULE_NOT_MET",
  "description": "The OEM is rejecting this request because the vehicle does not meet the business rules set by the OEM. For example, the vehicle is outside of a required geofence, the vehicle must be plugged in, etc.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#oem-business-rule-not-met",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": {
    "type": "ACTION_REQUIRED",
    "message": "Vehicle is not at the specified charging location"
  },
  "suggestedUserMessage": "Your vehicle is unable to perform this request because one or more OEM conditions were not met."
}
```

### Suggested resolution

The vehicle must be in a state that satisfies the OEM's requirements before retrying the request. Check the `resolution.message` field for the specific reason the request was rejected.

### Troubleshooting Steps

* Check the `resolution.message` field.
* If you haven't, you can set up webhooks to monitor relevant vehicle state changes and try again when the condition is met (e.g. the vehicle plugged in status has changed).
* Retry your request once the required conditions are met.

### Suggested user message

> Your vehicle is unable to perform this request because one or more OEM conditions were not met.

***

# `HOOD_OPEN`

The vehicle is unable to perform your request because its hood is open. This error usually occurs when you make a request to the lock endpoint while the vehicle’s hood stands open.

```json HOOD_OPEN theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "HOOD_OPEN",
      "title": "Hood Open",
      "detail": "The vehicle is unable to perform your request because its hood is open.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#hood-open",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your vehicle was unable to lock. Please ensure that the vehicle's hood is fully closed.",
    },
  ]
}
```

### Suggested resolution

The user can resolve this error by ensuring that the vehicle’s hood is fully closed.

### Suggested user message

> Your car was unable to lock. Please ensure that your car’s hood is fully closed.

***

# `IGNITION_ON`

The vehicle was unable to perform your request because its engine is running. Depending on the vehicle’s make and model, this error can occur for a variety of API endpoints.

```json IGNITION_ON theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "IGNITION_ON",
      "title": "Ignition On",
      "detail": "The vehicle was unable to perform your request because its engine is running.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#ignition-on",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your vehicle is currently running.",
    },
  ]
}
```

### Suggested resolution

The user can resolve this error by turning off their vehicle. You can also resolve this error by retrying your request at a later time.

### Suggested user message

> Your car is temporarily unable to connect to \<app name> because its engine is running. To re-establish the connection, please turn off your car’s engine.

***

# `IN_MOTION`

The vehicle is currently in motion and unable to perform your request. Depending on the vehicle’s make and model, this error can occur for a variety of API endpoints. The lock/unlock endpoint is a common example.

If testing with Vehicle Simulator, you will receive this error when attempting a lock/unlock request while the vehicle is in a driving state along the simulation.

```json IN_MOTION theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "IN_MOTION",
      "title": "In Motion",
      "detail": "The vehicle is currently in motion and unable to perform your request.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#in-motion",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your vehicle is unable to perform the request while in motion.",
    },
  ]
}
```

### Suggested resolution

The user can resolve this error by parking their car and turning off the engine. You can also resolve this error by retrying your request at a later time.

### Suggested user message

> Your car is in motion and temporarily unable to connect to \<app name>. To re-establish the connection, please park your car and turn off its engine.

***

# `REMOTE_ACCESS_DISABLED`

The vehicle is unable to perform your request because the user has disabled remote access for connected services.

```json REMOTE_ACCESS_DISABLED theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "REMOTE_ACCESS_DISABLED",
      "title": "Remote Access Disabled",
      "detail": "The vehicle is unable to perform your request because the user has disabled remote access for connected services.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#remote-access-disabled",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your vehicle is unable to perform the request as remote access is disabled or unavailable.",
    },
  ]
}
```

### Suggested resolution

The user can resolve this error by re-enabling remote access inside their vehicle. If the user is unsure how to enable remote access for connected services, prompt them to refer to their vehicle’s owner manual for more details.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. To re-establish the connection, please make sure that remote access for connected services is enabled inside your car. Please refer to your car’s owner manual for more details.

***

# `TRUNK_OPEN`

The vehicle is unable to perform your request because its trunk is open. This error usually occurs when you make a request to the lock endpoint while the vehicle’s trunk and/or front trunk are open.

```json TRUNK_OPEN theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "TRUNK_OPEN",
      "title": "Trunk Open",
      "detail": "The vehicle is unable to perform your request because its trunk is open.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#trunk-open",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your vehicle was unable to open the trunk because it is already open.",
    },
  ]
}
```

### Suggested resolution

The user can resolve this error by closing the vehicle’s trunk and/or front trunk.

### Suggested user message

> Your car was unable to lock. Please ensure that your car’s trunk (and front trunk) is closed.

***

# `UNKNOWN`

The vehicle was unable to perform your request due to an unknown issue. This error occurs when the vehicle is in a state that makes it unable to perform your request, and we are unable to determine which state the vehicle is in.

If testing an electric vehicle with Vehicle Simulator, you will receive this error when attempting a stop charge request while the vehicle is in a charging state.

```json UNKNOWN theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "UNKNOWN",
      "title": "Unknown Vehicle State",
      "detail": "The vehicle was unable to perform your request due to an unknown issue.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#unknown",
      },
      "resolution": { "type": "RETRY_LATER" },
      "suggestedUserMessage": "Your vehicle is temporarily unable to connect due to an unknown issue. Please be patient while we're working to resolve this issue.",
    },
  ]
}
```

### Suggested resolution

Please retry your request at a later time.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `UNREACHABLE`

The vehicle was unable to perform your request because it is currently unreachable. This error usually occurs when the vehicle is in a location with poor cellular reception (e.g. a parking garage or underground parking).

If testing with Vehicle Simulator, you will receive this error when attempting a lock/unlock or start/stop charge request while the simulation is paused or completed.

```json UNREACHABLE theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "UNREACHABLE",
      "title": "Vehicle Unreachable",
      "detail": "The vehicle was unable to perform your request because it is currently unreachable.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#unreachable",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your vehicle is currently unreachable. Ensure the vehicle has adequate mobile coverage.",
    },
  ]
}
```

### Suggested resolution

The user can resolve this error by moving the vehicle to a location with better cellular reception. You can also resolve this error by retrying your request at a later time.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. To re-establish the connection, please move your car to a location with a better cell phone signal.

***

# `VEHICLE_OFFLINE_FOR_SERVICE`

The vehicle was unable to perform your request because it is currently in service mode. Service mode temporarily limits or disables the vehicle’s remote capabilities.

```json VEHICLE_OFFLINE_FOR_SERVICE theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "VEHICLE_OFFLINE_FOR_SERVICE",
      "title": "Vehicle Offline For Service",
      "detail": "The vehicle was unable to perform your request because it is currently in service mode.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#vehicle-offline-for-service",
      },
      "resolution": { "type": null },
      "suggestedUserMessage": "Your vehicle is in service mode and temporarily unable to perform this task.",
    },
  ]
}
```

### Suggested resolution

Please retry your request at a later time.

### Suggested user message

> Your car is in service mode and temporarily unable to connect to \<app name>. Please try again later.

***

# `LOW_BATTERY`

The vehicle was unable to perform your request because the 12v or high voltage battery is too low.

```json LOW_BATTERY theme={null}
{
  "errors": [
    {
      "status": "409",
      "type": "VEHICLE_STATE",
      "code": "LOW_BATTERY",
      "title": "Low Battery",
      "detail": "The vehicle was unable to perform your request because the 12v or high voltage battery is too low.",
      "links": {
        "about": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#low-battery",
      },
      "resolution": { "type": "RETRY_LATER" },
      "suggestedUserMessage": "Your vehicle battery is too low to perform this task.",
    },
  ]
}
```

### Suggested resolution

Please retry your request at a later time.

* For EVs ensure that the battery is topped up to at least 60% SoC.
* Ensure that the vehicle’s 12-volt battery is sufficiently charged. Taking the vehicle on a short drive can help.

### Suggested user message

> \<app name> was unable to connect to your car because its battery is too low. Please ensure the battery is charged and try again later.

***


# Validation Errors
Source: https://smartcar.com/docs/errors/api-errors/validation-errors

Thrown if there is an issue with the format of the request or body.

# `NULL`

Request invalid or malformed. Please check for missing parameters, spelling and casing mistakes, and other syntax issues.

```json theme={null}
{
  "type": "VALIDATION",
  "code": null,
  "description": "Request invalid or malformed. Please check for missing parameters, spelling and casing mistakes, and other syntax issues.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/validation-errors#null",
  "statusCode": 400,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we’re working to resolve this issue."
}
```

### Suggested resolution

You can resolve this error by referring to our API reference and ensuring that you pass all the parameters as specified.

### Troubleshooting Steps

* Ensure that you spell and case all parameters correctly.
* Ensure that your request has the correct content-type (i.e. application/json or application/x-www-form-urlencoded).
* Ensure that your request has the correct URL and HTTP method.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.

***

# `PARAMETER`

Your request is formatted correctly, but one or more of the provided parameters is incorrect.

```json theme={null}
{
  "type": "VALIDATION",
  "code": null,
  "description": "Your request is formatted correctly, but one or more of the provided parameters is incorrect.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/validation-errors#parameter",
  "statusCode": 400,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your car is temporarily unable to connect to <app name>. Please be patient while we’re working to resolve this issue." 
}
```

### Suggested resolution

You can resolve this error by referring to our API reference and ensuring that you pass all the parameters as specified.

For Ford or Lincoln vehicles:

* Please check the coordinates provided for setting a charge schedule are associated with a saved charging location for this vehicle.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we’re working to resolve this issue.


# Vehicle State Errors
Source: https://smartcar.com/docs/errors/api-errors/vehicle-state-errors

Thrown when a request fails due to the state of a vehicle or logically cannot be completed e.g. you can't start a vehicle charging if it's not plugged in.

# `ASLEEP`

The vehicle is in a sleep state and temporarily unable to perform your request. Either the vehicle has been inactive for a certain period of time (time periods vary between makes and models) or the user has manually triggered the vehicle's sleep state.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "ASLEEP",
  "description": "The vehicle is in a sleep state and temporarily unable to perform your request.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#asleep",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your vehicle is in a sleep state. This request was not sent to preserve battery life. "
}
```

### Suggested resolution

The vehicle is in a sleep state and temporarily unable to perform your request.

### Troubleshooting Steps

* Prompt the user to start the vehicle's engine (required) and to drive the vehicle for a short distance (optional).
* Wait for a few minutes and retry your request.
* Ensure that the vehicle's 12-volt battery is sufficiently charged.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. To re-establish the connection, please start your car and take it for a short drive.

***

# `CHARGE_FAULT`

The vehicle is connected to an EV charger but cannot perform the request because:

* the charger is not providing any current
* there is a conflict with another charging schedule

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "CHARGE_FAULT",
  "description": "The vehicle is connected to an EV charger but cannot perform the request because 1) the charger is not providing any current, or 2) there is a conflict with another charging schedule.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#charge-fault",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your vehicle is unable to start or stop charging because of a conflict with the vehicle's charging schedule."
}
```

### Suggested resolution

The user can resolve this error by:

* Disabling any schedules that control when the charger can supply current and charge the vehicle.
* Ensuring that the charging cable is securely connected to the vehicle.
* Disabling any charge schedules on the vehicle's infotainment system or connected service application.
* Disabling any departure timers on the vehicle's infotainment system or connected service application.
* Removing the vehicle from other charge scheduling services.

### Troubleshooting Steps

* Prompt the user to start charging their vehicle.
* Wait for a few minutes and retry your request.

### Suggested user message

> Your car is unable to start or stop charging because of a conflict with your vehicle's charging schedule. Please check that:
>
> * You have disabled any schedules that control when your charger is able to supply current to and charge the vehicle.
> * The charging cable is securely connected to your vehicle.
> * You have disabled any charge schedules on your vehicle's infotainment system or connected service application.
> * You have disabled any departure timers on your vehicle's infotainment system or connected service application.
> * Your vehicle is not connected to any other charge scheduling services.

***

# `CHARGING_IN_PROGRESS`

The vehicle is currently charging and unable to perform your request. This error usually occurs when you make a request to the start charge endpoint while the vehicle is already charging.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "CHARGING_IN_PROGRESS",
  "description": "The vehicle is currently charging and unable to perform your request.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#charging-in-progress",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your vehicle is already charging."
}
```

### Suggested resolution

You usually don't need to resolve this error. If you believe that this error should not have occurred, please follow the troubleshooting steps below.

### Troubleshooting Steps

* Prompt the user to stop charging their vehicle and/or unplug the charger.
* Wait for a few minutes and retry your request.

### Suggested user message

> Your car is already charging.

***

# `CHARGING_PLUG_CONNECTED`

The vehicle is connected to an EV charger and unable to perform your request.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "CHARGING_PLUG_CONNECTED",
  "description": "The vehicle is connected to an EV charger and unable to perform your request.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#charging-plug-connected",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "We’re unable to issue the command because the vehicle is currently plugged in."
}
```

### Suggested resolution

The user can resolve this error by unplugging the vehicle.

### Suggested user message

> We're unable to issue the command because the vehicle is currently plugged in. Please ensure that you have unplugged the vehicle from an EV charger.

***

# `CHARGING_PLUG_NOT_CONNECTED`

The vehicle is not connected to an EV charger and unable to perform your request. This error usually occurs when you make a request to the start charge endpoint
but the vehicle's charge port does not have an EV charger plugged into it.

If testing an electric vehicle with Vehicle Simulator, you will receive this error when attempting a start or stop charge request while the vehicle is in a parked
or driving state (not charging).

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "CHARGING_PLUG_NOT_CONNECTED",
  "description": "The vehicle is not connected to an EV charger and unable to perform your request.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#charging-plug-not-connected",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your vehicle is not plugged in."
}
```

### Suggested resolution

The user can resolve this error by plugging an EV charger into the vehicle's charge port.

### Troubleshooting Steps

* Prompt the user to plug an EV charger into the vehicle's charge port.
* If this doesn't resolve the issue, prompt the user to ensure that the EV charger is connected to a working power source, that it isn't faulty, and that it is compatible with the user's vehicle. For example, prompt the user to try out other EV chargers and to check the vehicle's owner manual for a list of compatible chargers.

### Suggested user message

> Your car isn't able to start charging. Please ensure that you have plugged an EV charger into your car's charge port.

***

# `DOOR_OPEN`

The vehicle could not perform your request because one or more of its doors are open. This error usually occurs when you make a request to the lock endpoint while one or more of the vehicle's doors stand open.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "DOOR_OPEN",
  "description": "The vehicle could not perform your request because one or more of its doors are open.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#door-open",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your vehicle was unable to lock. Please ensure that all doors and the trunk are fully closed."
}
```

### Suggested resolution

The user can resolve this error by fully closing all of the vehicle's doors and the trunk.

### Troubleshooting Steps

* Prompt the user to ensure that there is nothing preventing the doors from fully closing and/or locking properly.
* Prompt the user to ensure that the vehicle's trunk is fully closed.

### Suggested user message

> Your car was unable to lock. Please ensure that all doors and the trunk are fully closed.

***

# `FULLY_CHARGED`

The vehicle is unable to perform your request because its EV battery is fully charged. This error usually occurs when you make a request to the start charge endpoint while the vehicle is already fully charged.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "FULLY_CHARGED",
  "description": "The vehicle is unable to perform your request because its EV battery is fully charged.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#fully-charged",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your vehicle is already fully charged."
}
```

### Suggested user message

> Your car is already fully charged.

***

# `HOOD_OPEN`

The vehicle is unable to perform your request because its hood is open. This error usually occurs when you make a request to the lock endpoint while the vehicle's hood stands open.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "HOOD_OPEN",
  "description": "The vehicle is unable to perform your request because its hood is open.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#hood-open",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your vehicle was unable to lock. Please ensure that the vehicle's hood is fully closed."
}
```

### Suggested resolution

The user can resolve this error by ensuring that the vehicle's hood is fully closed.

### Suggested user message

> Your car was unable to lock. Please ensure that your car's hood is fully closed.

***

# `IGNITION_ON`

The vehicle was unable to perform your request because its engine is running. Depending on the vehicle's make and model, this error can occur for a variety of API endpoints.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "IGNITION_ON",
  "description": "The vehicle was unable to perform your request because its engine is running.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#ignition-on",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your vehicle is currently running."
}
```

### Suggested resolution

The user can resolve this error by turning off their vehicle. You can also resolve this error by retrying your request at a later time.

### Suggested user message

> Your car is temporarily unable to connect to \<app name> because its engine is running. To re-establish the connection, please turn off your car's engine.

***

# `IN_MOTION`

The vehicle is currently in motion and unable to perform your request. Depending on the vehicle's make and model, this error can occur for a variety of API endpoints. The lock/unlock endpoint is a common example.

If testing with Vehicle Simulator, you will receive this error when attempting a lock/unlock request while the vehicle is in a driving state along the simulation.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "IN_MOTION",
  "description": "The vehicle is currently in motion and unable to perform your request.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#in-motion",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your vehicle is unable to perform the request while in motion."
}
```

### Suggested resolution

The user can resolve this error by parking their car and turning off the engine. You can also resolve this error by retrying your request at a later time.

### Suggested user message

> Your car is in motion and temporarily unable to connect to \<app name>. To re-establish the connection, please park your car and turn off its engine.

***

# `LOW_BATTERY`

The vehicle was unable to perform your request because the 12v or high voltage battery is too low.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "LOW_BATTERY",
  "description": "The vehicle was unable to perform your request because the 12v or high voltage battery is too low.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#low-battery",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "RETRY_LATER" },
  "suggestedUserMessage": "Your vehicle battery is too low to perform this task."
}
```

### Suggested resolution

Please retry your request at a later time.

* For EVs ensure that the battery is topped up to at least 60% SoC.
* Ensure that the vehicle's 12-volt battery is sufficiently charged. Taking the vehicle on a short drive can help.

### Suggested user message

> \<app name> was unable to connect to your car because its battery is too low. Please ensure the battery is charged and try again later.

***

# `NOT_CHARGING`

The vehicle is unable to perform your request because it is not currently charging. This error usually occurs when you request information about a vehicle's charge session while the battery is not charging.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "NOT_CHARGING",
  "description": "The vehicle is unable to perform your request because it is not currently charging.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#not-charging",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Please ensure that you have plugged an EV charger into your car’s charge port and the vehicle is charging."
}
```

### Suggested resolution

You can resolve this error by having the user start a charge session or by sending a start charge request if the vehicle supports that capability.

### Troubleshooting Steps

* Prompt the user to start charging their vehicle.
* Wait for a few minutes and retry your request.

### Suggested user message

> Please ensure that you have plugged an EV charger into your car's charge port and the vehicle is charging.

***

# `OEM_BUSINESS_RULE_NOT_MET`

The OEM is rejecting this request because the vehicle does not meet the business rules set by the OEM. For example, the vehicle is outside of a required geofence, the vehicle must be plugged in, etc.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "OEM_BUSINESS_RULE_NOT_MET",
  "description": "The OEM is rejecting this request because the vehicle does not meet the business rules set by the OEM. For example, the vehicle is outside of a required geofence, the vehicle must be plugged in, etc.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#oem-business-rule-not-met",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": {
    "type": "ACTION_REQUIRED",
    "message": "Vehicle is not at the specified charging location"
  },
  "suggestedUserMessage": "Your vehicle is unable to perform this request because one or more OEM conditions were not met."
}
```

### Suggested resolution

The vehicle must be in a state that satisfies the OEM's requirements before retrying the request. Check the `resolution.message` field for the specific reason the request was rejected.

### Troubleshooting Steps

* Check the `resolution.message` field.
* If you haven't, you can set up webhooks to monitor relevant vehicle state changes and try again when the condition is met (e.g. the vehicle plugged in status has changed).
* Retry your request once the required conditions are met.

### Suggested user message

> Your vehicle is unable to perform this request because one or more OEM conditions were not met.

***

# `REMOTE_ACCESS_DISABLED`

The vehicle is unable to perform your request because the user has disabled remote access for connected services.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "REMOTE_ACCESS_DISABLED",
  "description": "The vehicle is unable to perform your request because the user has disabled remote access for connected services.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#remote-access-disabled",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your vehicle is unable to perform the request as remote access is disabled or unavailable."
}
```

### Suggested resolution

The user can resolve this error by re-enabling remote access inside their vehicle. If the user is unsure how to enable remote access for connected services, prompt them to refer to their vehicle's owner manual for more details.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. To re-establish the connection, please make sure that remote access for connected services is enabled inside your car. Please refer to your car's owner manual for more details.

***

# `TRUNK_OPEN`

The vehicle is unable to perform your request because its trunk is open. This error usually occurs when you make a request to the lock endpoint while the vehicle's trunk and/or front trunk are open.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "TRUNK_OPEN",
  "description": "The vehicle is unable to perform your request because its trunk is open.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#trunk-open",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your vehicle was unable to open the trunk because it is already open."
}
```

### Suggested resolution

The user can resolve this error by closing the vehicle's trunk and/or front trunk.

### Suggested user message

> Your car was unable to lock. Please ensure that your car's trunk (and front trunk) is closed.

***

# `UNKNOWN`

The vehicle was unable to perform your request due to an unknown issue. This error occurs when the vehicle is in a state that makes it unable to perform your request, and we are unable to determine which state the vehicle is in.

If testing an electric vehicle with Vehicle Simulator, you will receive this error when attempting a stop charge request while the vehicle is in a charging state.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "UNKNOWN",
  "description": "The vehicle was unable to perform your request due to an unknown issue.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#unknown",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": "RETRY_LATER" },
  "suggestedUserMessage": "Your vehicle is temporarily unable to connect due to an unknown issue. Please be patient while we’re working to resolve this issue."
}
```

### Suggested resolution

Please retry your request at a later time.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. Please be patient while we're working to resolve this issue.

***

# `UNREACHABLE`

The vehicle was unable to perform your request because it is currently unreachable. This error usually occurs when the vehicle is in a location with poor cellular reception (e.g. a parking garage or underground parking).

If testing with Vehicle Simulator, you will receive this error when attempting a lock/unlock or start/stop charge request while the simulation is paused or completed.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "UNREACHABLE",
  "description": "The vehicle was unable to perform your request because it is currently unreachable.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#unreachable",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your vehicle is currently unreachable. Ensure the vehicle has adequate mobile coverage."
}
```

### Suggested resolution

The user can resolve this error by moving the vehicle to a location with better cellular reception. You can also resolve this error by retrying your request at a later time.

### Suggested user message

> Your car is temporarily unable to connect to \<app name>. To re-establish the connection, please move your car to a location with a better cell phone signal.

***

# `VEHICLE_OFFLINE_FOR_SERVICE`

The vehicle was unable to perform your request because it is currently in service mode. Service mode temporarily limits or disables the vehicle's remote capabilities.

```json theme={null}
{
  "type": "VEHICLE_STATE",
  "code": "VEHICLE_OFFLINE_FOR_SERVICE",
  "description": "The vehicle was unable to perform your request because it is currently in service mode.",
  "docURL": "https://smartcar.com/docs/errors/api-errors/vehicle-state-errors#vehicle-offline-for-service",
  "statusCode": 409,
  "requestId": "5dea93a1-3f79-4246-90c5-89610a20471b",
  "resolution": { "type": null },
  "suggestedUserMessage": "Your vehicle is in service mode and temporarily unable to perform this task."
}
```

### Suggested resolution

Please retry your request at a later time.

### Suggested user message

> Your car is in service mode and temporarily unable to connect to \<app name>. Please try again later.

***


# Access Denied
Source: https://smartcar.com/docs/errors/connect-errors/access-denied

This error occurs when a user denies your application access to the requested scope of permissions.

| Parameter           | Required | Description                        |
| ------------------- | -------- | ---------------------------------- |
| `error`             | `true`   | `access_denied`                    |
| `error_description` | `true`   | User denied access to application. |

```http Example redirect uri theme={null}
HTTP/1.1 302 Found
Location: https://example.com/home
?error=access_denied
&error_description=User+denied+access+to+application
```

## Testing

To test this error, launch Smartcar Connect in test mode and select “Deny access” on the permissions screen.

<Frame>
  <img />
</Frame>

We recommend handling this error by re-prompting the user to authorize their vehicle and adding a message like in the example below.

<Frame>
  <img />
</Frame>


# Configuration
Source: https://smartcar.com/docs/errors/connect-errors/configuration-error

This error occurs when the user has encountered an Error page in Connect and has chosen to return to your application.

| Parameter           | Required | Description                                                       |
| ------------------- | -------- | ----------------------------------------------------------------- |
| `error`             | `true`   | `configuration_error`                                             |
| `error_description` | `true`   | There has been an error in the configuration of your application. |
| `status_code`       | `true`   | The status code of the error encountered in Connect               |
| `error_message`     | `true`   | The error message seen by the user                                |

```http Example redirect uri theme={null}
HTTP/1.1 302 Found
Location: https://example.com/callback
?error=configuration_error
&error_description=There%20has%20been%20an%20error%20in%20the%20configuration%20of%20your%20application.&status_code=400
&error_message=You%20have%20entered%20a%20test%20mode%20VIN.%20Please%20enter%20a%20VIN%20that%20belongs%20to%20a%20real%20vehicle.
```

On redirect, Connect will return the status code and message of the error that they encountered. This will be triggered if:

* A user tried to directly navigate to a page that is past their current step in Connect (i.e. going directly from the Preamble screen to the Permission Grants screen by directly going to connect.smartcar.com/grant).
* A user is trying to use Single Select in live mode with a test mode VIN or with a simulated VIN in a non-simulated mode.
* A user is trying to use Single Select with an invalid mock VIN.
* A validation error occurs when trying to check compatibility by VIN.

These cases will trigger the following error and give the user the ability to “Exit” Connect.

<Frame>
  <img />
</Frame>


# Invalid Subscription
Source: https://smartcar.com/docs/errors/connect-errors/invalid-subscription

This error occurs when a user’s vehicle is compatible but their connected services subscription is inactive because either it has expired or it has never been activated.

| Parameter          | Required | Description                                                  |   |
| ------------------ | -------- | ------------------------------------------------------------ | - |
| error              | true     | invalid\_subscription                                        |   |
| error\_description | true     | User does not have an active connected vehicle subscription. |   |

```http Example redirect uri theme={null}
HTTP/1.1 302 Found
Location: https://example.com/callback
?error=invalid_subscription
&error_description=User%20does%20not%20have%20an%20active%20connected%20vehicle%20subscription
```

Smartcar will direct the user to the connected services website to (re-)activate their subscription. However, a user may choose to return back to your application instead, like in the example below.

<Frame>
  <img />
</Frame>

## Testing

To test this error, launch Smartcar Connect in test mode and log in with the email [smartcar@invalid-subscription.com](mailto:smartcar@invalid-subscription.com) and any password. If you use Single Select, please see the table below for a simulated VIN.

| Email                                                                         | VIN               |
| ----------------------------------------------------------------------------- | ----------------- |
| [smartcar@invalid-subscription.com](mailto:smartcar@invalid-subscription.com) | 0SCAUDI0155C49A95 |

In the event of an `AUTHENTICATION_FAILED`, the user will need to be prompted to re-connect their vehicle. Smartcar Connect Re-authentication makes the process of re-authenticating a user much more seamless. In addition, the `AUTHENTICATION_FAILED` error provides a partially constructed URL for the re-authentication flow inside the resolution object.


# No Vehicles
Source: https://smartcar.com/docs/errors/connect-errors/no-vehicles

This error occurs when a vehicle owner has a connected services account, but there are no vehicles associated with the account.

| Parameter          | Required | Description                                                  |   |
| ------------------ | -------- | ------------------------------------------------------------ | - |
| error              | true     | no\_vehicles                                                 |   |
| error\_description | true     | User does not have an active connected vehicle subscription. |   |

```http Example redirect uri theme={null}
HTTP/1.1 302 Found
Location: https://example.com/callback
?error=no_vehicles&error_description=No%20vehicles%20found.%20Please%20add%20vehicles%20to%20your%20account%20and%20try%20again.
```

The error is triggered when a user logs into their connected services account and is shown to have no vehicles listed like in the example below for BMW.

<Frame>
  <img />
</Frame>

The user has the option to add vehicles or return to your application.


# OEM Login Cancelled
Source: https://smartcar.com/docs/errors/connect-errors/oem-login-cancelled

This error occurs when a user went to authorize directly with the OEM but exited the flow for some reason.

| Parameter           | Required | Description                                          |
| ------------------- | -------- | ---------------------------------------------------- |
| `error`             | `true`   | `oem_cancelled_login`                                |
| `error_description` | `true`   | The user did not complete authorization with the OEM |

```http Example redirect uri theme={null}
HTTP/1.1 302 Found
Location: https://example.com/callback
?error=oem_cancelled_login
&the%20user%20did%20not%20complete%20authorization%20with%20the%20OEM
```

<Frame>
  <img />
</Frame>


# User returned to application
Source: https://smartcar.com/docs/errors/connect-errors/returned-to-application

This error occurs when a user leaves the Connect flow after hitting **Back to application** before granting your application access to their vehicle.

| Parameter           | Required | Description                                                     |
| ------------------- | -------- | --------------------------------------------------------------- |
| `error`             | `true`   | `user_manually_returned_to_application`                         |
| `error_description` | `true`   | The user exited Connect before granting your application access |

There are cases where a user may wish to exit Connect before granting your application access to their vehicle. In these cases, if the user hits **Back to application** instead of closing out the window, Smartcar will return this error to your callback URI. Below are places in the Connect flow users can return to your application.

<Tabs>
  <Tab title="Missing Permissions">
    <Frame>
      <img />
    </Frame>
  </Tab>

  <Tab title="MFA Entry">
    <Frame>
      <img />
    </Frame>
  </Tab>

  <Tab title="PIN Entry">
    <Frame>
      <img />
    </Frame>
  </Tab>
</Tabs>


# Server
Source: https://smartcar.com/docs/errors/connect-errors/server-error

If there is a server error, the user will return to your application.

| Parameter          | Required | Description                                |
| ------------------ | -------- | ------------------------------------------ |
| error              | true     | server\_error                              |
| error\_description | true     | Unexpected server error. Please try again. |

```http Example redirect uri theme={null}
HTTP/1.1 302 Found
Location: https://example.com/callback
?error=configuration_error
&error_description=There%20has%20been%20an%20error%20in%20the%20configuration%20of%20your%20application.&status_code=400
&error_message=You%20have%20entered%20a%20test%20mode%20VIN.%20Please%20enter%20a%20VIN%20that%20belongs%20to%20a%20real%20vehicle.
```

<Note>
  We only show the “Exit” button if a redirect URI is available. If there is a failure before the validation of the redirect URI,  we are unable to include the “Exit” button on the Error page. In those cases, we would not be able to report the `status_code` and `error_message` back to the developer, but they will still be available on screen in the Error page.
</Note>

<Frame>
  <img />
</Frame>


# Vehicle Incompatible
Source: https://smartcar.com/docs/errors/connect-errors/vehicle-incompatible

This error occurs when a user tries to authorize an incompatible vehicle in Smartcar Connect.

| Parameter           | Required | Description                           |
| ------------------- | -------- | ------------------------------------- |
| `error`             | `true`   | `vehicle_incompatible`                |
| `error_description` | `true`   | The user’s vehicle is not compatible. |
| `make`              | `false`  | The manufacturer of the vehicle.      |
| `vin`               | `false`  | The VIN of the vehicle.               |

In order to be compatible, a vehicle must:

* Have the hardware required for internet connectivity
* Belong to the makes and models Smartcar is compatible with
* Be capable of the required permissions that your application is requesting access to
* If the user’s vehicle is incompatible, Smartcar will let the user know and offer them to share their vehicle’s VIN, make, model, and year with your application.

This error is triggered when a user selects an unsupported make, or selects "I don't see my brand..." and then hits "Back to application"

<Frame>
  <img />
</Frame>

We recommend that your application provides a flow for incompatible vehicles like in the example below.

<Frame>
  <img />
</Frame>

<br />

<Info>
  Note: This error will never occur if your application uses the Compatibility API. The Compatibility API verifies the compatibility of a vehicle before the user enters Smartcar Connect.
</Info>

To test this error, launch Smartcar Connect in test mode and log in with the email [smartcar@vehicle-incompatible.com](mailto:smartcar@vehicle-incompatible.com) and any password.

If you use Single Select, please see the table below for a simulated VIN.

| Email                                                                         | VIN               |
| ----------------------------------------------------------------------------- | ----------------- |
| [smartcar@vehicle-incompatible.com](mailto:smartcar@vehicle-incompatible.com) | 0SCAUDI012FE3B132 |


# Testing Errors
Source: https://smartcar.com/docs/errors/testing-errors

By launching Connect in [simulated mode](/docs/connect/advanced-config/modes), you're able to test your application against certain errors.

## Testing Connect Errors

You can use the following emails to test a subset of Connect errors:

| Error                  | Email                                                                         | VIN               |
| ---------------------- | ----------------------------------------------------------------------------- | ----------------- |
| `invalid_subscription` | [smartcar@invalid-subscription.com](mailto:smartcar@invalid-subscription.com) | 0SCAUDI0155C49A95 |
| `vehicle_incompatible` | [smartcar@vehicle-incompatible.com](mailto:smartcar@vehicle-incompatible.com) | 0SCAUDI012FE3B132 |

Visit the [Connect Errors](/docs/api-reference/api-errors#connect-errors) page for more details.

## Testing API Errors

You can use use the following emails to test these API error types:

* `COMPATIBILITY`
* `CONNECTED_SERVICES_ACCOUNT`
* `UPSTREAM`
* `VEHICLE_STATE`

| Type                         | Code                          | Email                                                                                                                                    | VIN               |
| ---------------------------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
| `COMPATIBILITY`              | `MAKE_NOT_COMPATIBLE`         | [COMPATIBILITY.MAKE\_NOT\_COMPATIBLE@smartcar.com](mailto:COMPATIBILITY.MAKE_NOT_COMPATIBLE@smartcar.com)                                | 0SCLR000270BE6600 |
| `COMPATIBILITY`              | `SMARTCAR_NOT_CAPABLE`        | [COMPATIBILITY.SMARTCAR\_NOT\_CAPABLE@smartcar.com](mailto:COMPATIBILITY.SMARTCAR_NOT_CAPABLE@smartcar.com)                              | 0SCLR0002DC18F57F |
| `COMPATIBILITY`              | `VEHICLE_NOT_CAPABLE`         | [COMPATIBILITY.VEHICLE\_NOT\_CAPABLE@smartcar.com](mailto:COMPATIBILITY.VEHICLE_NOT_CAPABLE@smartcar.com)                                | 0SCLR00024C7CDF7A |
| `CONNECTED_SERVICES_ACCOUNT` | `ACCOUNT_ISSUE`               | [CONNECTED\_SERVICES\_ACCOUNT.ACCOUNT\_ISSUE@smartcar.com](mailto:CONNECTED_SERVICES_ACCOUNT.ACCOUNT_ISSUE@smartcar.com)                 | 0SCLR00026BAAA136 |
| `CONNECTED_SERVICES_ACCOUNT` | `AUTHENTICATION_FAILED`       | [CONNECTED\_SERVICES\_ACCOUNT.AUTHENTICATION\_FAILED@smartcar.com](mailto:CONNECTED_SERVICES_ACCOUNT.AUTHENTICATION_FAILED@smartcar.com) | 0SCLR00021D803C7B |
| `CONNECTED_SERVICES_ACCOUNT` | `NO_VEHICLES`                 | [CONNECTED\_SERVICES\_ACCOUNT.NO\_VEHICLES@smartcar.com](mailto:CONNECTED_SERVICES_ACCOUNT.NO_VEHICLES@smartcar.com)                     | 0SCLR00027671837B |
| `CONNECTED_SERVICES_ACCOUNT` | `SUBSCRIPTION`                | [CONNECTED\_SERVICES\_ACCOUNT.SUBSCRIPTION@smartcar.com](mailto:CONNECTED_SERVICES_ACCOUNT.SUBSCRIPTION@smartcar.com)                    | 0SCLR0002B9BAF29F |
| `CONNECTED_SERVICES_ACCOUNT` | `VEHICLE_MISSING`             | [CONNECTED\_SERVICES\_ACCOUNT.VEHICLE\_MISSING@smartcar.com](mailto:CONNECTED_SERVICES_ACCOUNT.VEHICLE_MISSING@smartcar.com)             | 0SCLR00024E29EEBD |
| `UPSTREAM`                   | `INVALID_DATA`                | [UPSTREAM.INVALID\_DATA@smartcar.com](mailto:UPSTREAM.INVALID_DATA@smartcar.com)                                                         | 0SCLR000298A0A649 |
| `UPSTREAM`                   | `KNOWN_ISSUE`                 | [UPSTREAM.KNOWN\_ISSUE@smartcar.com](mailto:UPSTREAM.KNOWN_ISSUE@smartcar.com)                                                           | 0SCLR0002A8760B72 |
| `UPSTREAM`                   | `NO_RESPONSE`                 | [UPSTREAM.NO\_RESPONSE@smartcar.com](mailto:UPSTREAM.NO_RESPONSE@smartcar.com)                                                           | 0SCLR0002C23E43AB |
| `UPSTREAM`                   | `UNKNOWN_ISSUE`               | [UPSTREAM.UNKNOWN\_ISSUE@smartcar.com](mailto:UPSTREAM.UNKNOWN_ISSUE@smartcar.com)                                                       | 0SCLR0002D4878901 |
| `VEHICLE_STATE`              | `ASLEEP`                      | [VEHICLE\_STATE.ASLEEP@smartcar.com](mailto:VEHICLE_STATE.ASLEEP@smartcar.com)                                                           | 0SCLR0002E8896323 |
| `VEHICLE_STATE`              | `CHARGING_IN_PROGRESS`        | [VEHICLE\_STATE.CHARGING\_IN\_PROGRESS@smartcar.com](mailto:VEHICLE_STATE.CHARGING_IN_PROGRESS@smartcar.com)                             | 0SCLR000221F1E672 |
| `VEHICLE_STATE`              | `CHARGING_PLUG_NOT_CONNECTED` | [VEHICLE\_STATE.CHARGING\_PLUG\_NOT\_CONNECTED@smartcar.com](mailto:VEHICLE_STATE.CHARGING_PLUG_NOT_CONNECTED@smartcar.com)              | 0SCLR0002CBFC7C21 |
| `VEHICLE_STATE`              | `DOOR_OPEN`                   | [VEHICLE\_STATE.DOOR\_OPEN@smartcar.com](mailto:VEHICLE_STATE.DOOR_OPEN@smartcar.com)                                                    | 0SCLR0002F8BD90B8 |
| `VEHICLE_STATE`              | `FULLY_CHARGED`               | [VEHICLE\_STATE.FULLY\_CHARGED@smartcar.com](mailto:VEHICLE_STATE.FULLY_CHARGED@smartcar.com)                                            | 0SCLR00029CD9D894 |
| `VEHICLE_STATE`              | `HOOD_OPEN`                   | [VEHICLE\_STATE.HOOD\_OPEN@smartcar.com](mailto:VEHICLE_STATE.HOOD_OPEN@smartcar.com)                                                    | 0SCLR000219CD4A2C |
| `VEHICLE_STATE`              | `IGNITION_ON`                 | [VEHICLE\_STATE.IGNITION\_ON@smartcar.com](mailto:VEHICLE_STATE.IGNITION_ON@smartcar.com)                                                | 0SCLR00021D49E58A |
| `VEHICLE_STATE`              | `IN_MOTION`                   | [VEHICLE\_STATE.IN\_MOTION@smartcar.com](mailto:VEHICLE_STATE.IN_MOTION@smartcar.com)                                                    | 0SCLR00024F6EE640 |
| `VEHICLE_STATE`              | `REMOTE_ACCESS_DISABLED`      | [VEHICLE\_STATE.REMOTE\_ACCESS\_DISABLED@smartcar.com](mailto:VEHICLE_STATE.REMOTE_ACCESS_DISABLED@smartcar.com)                         | 0SCLR0002588A5CC1 |
| `VEHICLE_STATE`              | `TRUNK_OPEN`                  | [VEHICLE\_STATE.TRUNK\_OPEN@smartcar.com](mailto:VEHICLE_STATE.TRUNK_OPEN@smartcar.com)                                                  | 0SCLR00023C607FDB |
| `VEHICLE_STATE`              | `UNKNOWN`                     | [VEHICLE\_STATE.UNKNOWN@smartcar.com](mailto:VEHICLE_STATE.UNKNOWN@smartcar.com)                                                         | 0SCLR0002E6CC0314 |
| `VEHICLE_STATE`              | `UNREACHABLE`                 | [VEHICLE\_STATE.UNREACHABLE@smartcar.com](mailto:VEHICLE_STATE.UNREACHABLE@smartcar.com)                                                 | 0SCLR000247EBF067 |
| `VEHICLE_STATE`              | `VEHICLE_OFFLINE_FOR_SERVICE` | [VEHICLE\_STATE.VEHICLE\_OFFLINE\_FOR\_SERVICE@smartcar.com](mailto:VEHICLE_STATE.VEHICLE_OFFLINE_FOR_SERVICE@smartcar.com)              | 0SCLR0002AF1D71A1 |


# Implementation Checklist
Source: https://smartcar.com/docs/getting-started/Implementation-Checklist

Use this guide to track your progress through the Smartcar integration process, from initial setup to production launch.

## Phase 0: Pre-Kickoff

* **Tech Stack:** Identify technology stack for implementation. Use the [Connect SDKs](https://smartcar.com/docs/connect/connect-sdks) for the vehicle connection flow, and call the API directly over HTTP for data and commands (see [Making API Requests](https://smartcar.com/docs/getting-started/how-to/making-api-requests)). Review the [getting started resources](https://smartcar.com/docs/getting-started/introduction).
* **Tesla Tenanting:** (*Enterprise Only*) Check in with your Solution Architect to ensure you have your Tesla Tenant set up enabling your org to have a [Virtual Key with your own brand name](https://smartcar.com/docs/help/oem-integrations/tesla/virtual-key-tesla#enterprise-plan).
* **Slack Channel**: (*Enterprise Only*) Smartcar will set up a [dedicated Slack channel](https://smartcar.com/docs/help/assist-ai-slack) for technical communications - ensure the relevant stakeholders are added.

## Phase 1: Application Setup & Security Foundation

* **Team Access:** [Invite relevant team members](https://smartcar.com/docs/getting-started/dashboard/teams#members) to your Smartcar Dashboard account.
* **Subscribe to Updates:** Ensure your team subscribes to [status.smartcar.com](https://status.smartcar.com), [brandreliability.smartcar.com](https://brandreliability.smartcar.com) and [product changelogs](https://smartcar.com/docs/changelog/latest) to stay informed on platform health and updates.
* **Environment Setup:** Create distinct **Test** and **Production** applications in the dashboard with clear naming conventions.
* **Credentials:** Capture and securely store your `Client ID` and `Client Secret`.
* **Secret Management:** Integrate your `Client Secret` into an enterprise secrets management system (e.g. AWS Secrets Manager, Vault). **Never commit secrets to version control.**
* **Connect Configuration:** Set each application’s Privacy Policy URL and Logo.
* **Redirect URIs:** Configure the Redirect URI for each application (ensure they are externally accessible). Required if you use the Authorization Code flow (`response_type=code`).
* **Scope Definition:** [Define your Vehicle Access Configuration](https://smartcar.com/docs/getting-started/how-to/configure-permissions#how-to-configure-permissions-for-vehicle-data-collection) (OAuth scopes) based on the specific signals and commands your application requires.
* **Scope Minimization:** Strictly enforce **Scope Minimization** by requesting only the minimum necessary data permissions from the user.
* **Brand Select:** Confirm and specify which OEM Brands will be displayed to the user and if you want to automatically add any new brands as they become available.
* **Compatibility Check:** *(Enterprise Only)* Validate target vehicle compatibility using the [Region and Make Compatibility API](https://smartcar.com/docs/api-reference/compatibility/by-region-and-make).

## Phase 2: Connect Flow & Conversion Optimization

* **User Journey:** Determine how your application will funnel users into the Smartcar Connect flow.
* **Frontend Implementation:** Implement the frontend Connect flow to generate the authorization URL (using `link.getAuthUrl()`).
* **First Connection:** Onboard your first test vehicle and review its data in the Smartcar Dashboard.
* **Brand Select:** Assess and implement [**Brand Select**](https://smartcar.com/docs/connect/advanced-config/flows#bypassing-the-brand-selection-screen) functionality (if applicable) to skip the brand selection screen and accelerate the user flow.
* **Error Simulation:** Validate your application’s error handling by testing with [simulated error VINs ](https://smartcar.com/docs/errors/testing-errors#testing-errors)(e.g., using the `invalid_subscription` trigger).

## Phase 3: Core Implementation & Token Resilience

* **Architecture**: Design the backend architecture.
* **Webhook Endpoint:** Implement a [backend endpoint to receive webhook data](https://smartcar.com/docs/integrations/webhooks/receiving-webhooks) and error payloads.
* **Callback Endpoint:** Implement a backend endpoint to receive the `user_id` and `state` at your [Redirect URI](https://smartcar.com/docs/connect/handle-the-response) when a user completes the Connect flow.
* **Application Access Token:** Implement the logic to [request an application-level access token](https://smartcar.com/docs/api-reference/authorization/request-access-token) using the OAuth 2.0 Client Credentials flow (`grant_type=client_credentials`). The access token is valid for **1 hour**. There is no refresh token.
* **Secure Storage:** Securely store your `Client Secret` using an enterprise secrets management system (e.g. AWS Secrets Manager, Vault). The access token can be cached in memory or a secure cache for its 1-hour lifetime. Tokens must never be stored client-side.
* **Proactive Renewal:** Implement logic to request a new access token before the 1-hour expiration window closes. A simple timer or check before each API call is sufficient.
* **Support Protocol:** Establish internal support protocols to handle questions from your vehicle owners (ensure your team acts as Tier 1 support before escalating to Smartcar).

## Phase 4: Operational Scale & Error Handling

* **Webhooks-First:** *(If migrating)* Shift data ingestion models from polling to a **Webhooks-First** architecture for real-time scalability.
* **Webhook Configuration:** Configure Webhook integrations in the Smartcar Dashboard (select triggers, set callback URI).
* **Payload Verification:** Implement the mandatory callback URI verification logic (responding to the `VERIFY` event with the challenge hash).
* **User Error Handling:** Map Connect errors (e.g. `no_vehicles`) to clear, actionable messages for your users.
* **Vehicle Error Handling:** Handle `VEHICLE_ERROR` events and trigger user notifications when specific vehicle owner actions are required to resolve the issue.
* **Re-authentication:** Implement resolution logic for `ACCOUNT_ISSUE` errors by prompting the user to re-authenticate via Smartcar Connect.
* **Rate Limiting:** Implement **Exponential Backoff** strategies for retrying API errors (429) and adhere to `Retry-After` headers.

## Phase 5: Production Readiness Review

* **Access Control:** Ensure all service-specific IAM roles adhere to the principle of least privilege.
* **Secret Management:** Verify all secrets are stored and accessed via a dedicated secrets manager.
* **Encryption:** Ensure data is encrypted at rest and in transit.
* **Vulnerability Scanning:** Confirm that dependency and vulnerability scans pass with zero critical/high issues.
* **Network Security:** Configure firewalls/security groups to block unauthorized ports and apply WAF rules where appropriate.
* **Logging:** Ensure structured logs are successfully ingested for staging and production environments, with configurable log levels.
* **Observability:** Configure a dashboard to capture essential metrics (Latency, Error Rate, Traffic).
* **Alerting:** Configure critical alerts to route to your on-call channels.
* **CI/CD:** Ensure a fully automated build and deployment pipeline is in place for all environments.
* **Infrastructure as Code (IaC)**: The service infrastructure is managed using IaC (e.g., Terraform, CDK).
* **Architecture Review Complete:** The service architecture has passed the formal review.
* **Service Runbook:** A complete runbook exists detailing: service owners, quick start, deployment, scaling, and incident response.
* **Tagging:** Tagging policy is applied to infrastructure.
* **Support Review:** Review the vehicle owner support approach again and ensure VO's are not channeled to Smartcar support directly and that Smartcar support is used as Tier 3


# Configure Your Application
Source: https://smartcar.com/docs/getting-started/configure-application

Learn how to configure your Smartcar application, including setting up permissions and redirect URIs.

Once you have registered your application in the [Smartcar Dashboard](https://dashboard.smartcar.com), you can configure it to suit your business needs.

## Application Configuration Overview

Your application configuration includes several key components:

* **Application Name & Description**: A clear name and description help users understand what your application does.
* **Redirect URI**: The URL to which users will be redirected after they authorize your application. This must match the redirect URI you use in your OAuth flow. A redirect URI is required if you use the Authorization Code flow (`response_type=code`); applications using application access tokens can skip it.
* **Privacy Policy URL**: A link to your application's privacy policy that will be presented to users during the authorization process.
* **Vehicle Data**: Select the specific vehicle data signals your application will request access to. This determines the permissions your application will need from users.

<Frame type="simple">
  <img alt="Application Configuration in Smartcar Dashboard" />
</Frame>

#### What’s Next?

* [Connect your first vehicle](/docs/getting-started/connect-vehicles).
* [Build your first integration](/docs/getting-started/integration-overview).


# Connect Vehicles
Source: https://smartcar.com/docs/getting-started/connect-vehicles

Learn how to connect vehicles to your Smartcar application using Smartcar Connect.

Smartcar Connect is the starting point for connecting vehicles to your application. It uses Smartcar's patented and secure [OAuth 2.0](https://oauth.net/2/) flow to let vehicle owners grant your app access to their car data and control features.

### Prerequisites

Before you begin, make sure you have [configured](/docs/getting-started/configure-application) your Smartcar application in the [Smartcar Dashboard](https://dashboard.smartcar.com/configuration). You will need:

* Your application's `Client ID` and `Client Secret`
* A valid `redirect_uri` for your application, if you use the Authorization Code flow (`response_type=code`)
* The vehicle data you want to access (e.g., odometer, location, etc.)

<Steps>
  <Step title="Step 1: Launch Smartcar Connect">
    Direct your users to the Smartcar Connect URL. This can be done using the Smartcar SDK for your platform (web, iOS, or Android) or copying the URL from the [Smartcar Dashboard](https://dashboard.smartcar.com/configuration). The user will:

    * Select their vehicle brand
    * Log in with their connected services account
    * Review and approve the requested permissions
  </Step>

  <Step title="Step 2: Handle the Connect Response">
    After the user authorizes access, Smartcar will redirect them back to your application using the default `redirect_uri` you provided in your app configuration. The `user_id` query parameter will be needed for vehicle api requests. Read more about Connect redirect URL parameters [here](/docs/connect/handle-the-response).

    The authorization code applies to the Authorization Code flow (`response_type=code`). If you launched Connect with `response_type=none`, no code is returned. You can still set a `redirect_uri` to bring the user back to your application; if you don't, the flow ends on a Smartcar-hosted completion page. You can look up the new connection with the `user_id` returned in the redirect or the `external_id` you provided at the [/connections endpoint](/docs/api-reference/list-connections).
  </Step>
</Steps>

<Info>
  Vehicle owners may occasionally need to re-authenticate due to OEM platform migrations, credential changes, or permission updates. Build your integration to handle these scenarios gracefully. See [Handle Re-authentication](/docs/connect/re-auth/oem-migrations) for implementation guidance.
</Info>

## What’s Next

* [Build your first integration](/docs/getting-started/integration-overview).
* [See more about Smartcar Connect](/docs/connect/what-is-connect)
* [Explore available API endpoints](/docs/api-reference)
* [Learn about permissions and scopes](/docs/api-reference/permissions)


# Connect Insights
Source: https://smartcar.com/docs/getting-started/dashboard/connect-insights

Connect Insights allows you to visualize your Connect conversion rate and identify where individual users are running into issues during onboarding.

## Conversion Rate

For Enterprise customers, the **Conversion Rate** gives you high-level insight into how users are progressing through the Connect Flow over the last two weeks.

<Frame type="glass">
  <img />
</Frame>

## Session Details

Clicking into an event in the **Sessions Feed** will pull up more detailed
information for that specific user's session, allowing you to see where they
dropped off and highlighting issues they may have run into.

If you need to dial into a specific time frame or individual user, you can use
filters such as Date, VIN, User or Session ID to do so.

<Frame type="glass">
  <img />
</Frame>


# Dashboard Multi-Factor Authentication (MFA)
Source: https://smartcar.com/docs/getting-started/dashboard/dashboard-mfa



## Configuring Multi-Factor Authentication

From the settings gear, you can access User Security, which supports Multi-Factor Authentication (MFA). Enable MFA and scan with your preferred authenticator app such as Google Authenticator or 1Password.

Once enabled, each following login will require the use of your authenticator app to provide a unique code for login.

MFA can be disabled for your user at any time, though the authenticator app will be required to disable MFA.

<Frame type="glass">
  <img />
</Frame>


# Dashboard Overview
Source: https://smartcar.com/docs/getting-started/dashboard/overview

All you need to know about the Smartcar Dashboard

You can sign up for a Smartcar account [here](https://dashboard.smartcar.com/signup).
The Smartcar Dashboard allows you to manage your application configurations, connected vehicles, billing settings, team members, simulated vehicles, and webhooks.

<Frame type="glass">
  <img />
</Frame>


# Vehicle Simulator
Source: https://smartcar.com/docs/getting-started/dashboard/simulator



Before launching your integration, we recommend using Smartcar's Vehicle Simulator to test your application on a simulated vehicle. With the Simulator, you can choose the vehicle's powertrain type and then configure its state to simulate any real-world situation you would like to test. Subscribe the vehicle to a webhook integration to rapidly test realistic vehicle state change events in your application.

<Note>
  This is an all-new version of Vehicle Simulator that introduces full Webhook support for simulated vehicles, continued access to these vehicles via the Vehicle API, including vehicle commands, as well as granular control over nearly every vehicle signal available through the Smartcar platform. For legacy simulator documentation, [click here](/docs/getting-started/dashboard/simulator-legacy).
</Note>

<Frame type="glass">
  <img alt="Smartcar Vehicle Simulator" />
</Frame>

## 1. Create a simulated vehicle

#### Choose a powertrain type

Select from BEV, ICE, HEV, or PHEV. The available vehicle data signals you can configure will vary based on the powertrain type you choose.

#### Give it a name

The name you provide will also be reflected in the vehicle's state within the `VehicleIdentification.Nickname` signal.

#### Optional: create without connection

Optionally create the simulated vehicle in a disconnected state. [Learn more about simulated vehicle connections](#6-test-simulated-vehicle-connections).

<Frame type="glass">
  <img alt="Vehicle simulator create modal" />
</Frame>

#### Your simulated vehicle is now connected

Once created, the vehicle is fully connected to your Smartcar application. You can immediately begin making API requests and commands to the vehicle, or continue on to subscribing the vehicle to an integration. See [Accessing a simulated vehicle](#accessing-a-simulated-vehicle) for how to authenticate your requests.

* All compatible permissions are granted by default
* You can edit granted permissions later in the vehicle configuration
* Simulated vehicles will appear in your connections and logs with `Simulated` as the make and the chosen powertrain type as the model, eg: `2023 Simulated BEV`.

#### Accessing a simulated vehicle

Simulated vehicles are accessed through the Smartcar API exactly like live vehicles.

* **Application-level (M2M) tokens (recommended):** Query and send commands to your simulated vehicles using your application's access tokens, the same way you access live vehicles. See [API Authentication Setup](/docs/getting-started/how-to/api-authentication) to get started.
* **Per-vehicle (opaque) tokens:** If your integration uses the OAuth 2.0 authorization code flow, connect the simulated vehicle with `response_type=code` and a configured redirect URI to receive an authorization code you can exchange for a per-vehicle access token. See [How to Get an API Access Token](/docs/getting-started/how-to/get-an-access-token).

<Note>
  Connecting a simulated vehicle does not issue a per-vehicle access token automatically. Access it with your application-level (M2M) tokens, or use the authorization code flow above if your integration specifically needs per-vehicle tokens.
</Note>

## 2. Subscribe the vehicle to a webhook

#### Choose a webhook

Subscribe the simulated vehicle to one of your existing webhook integrations. If you don't have a webhook integration yet, [create your first integration](/docs/integrations/webhooks/overview).

<Note>
  Simulated vehicles are not included in the webhook auto-subscription feature. You must manually subscribe simulated vehicles through the Simulator dashboard, even if auto-subscription is enabled for one or more of your integrations.
</Note>

#### Receive the first delivery

After subscribing the vehicle to a verified and enabled webhook integration, you will receive your first payload within a few minutes.

## 3. Configure the vehicle state

You control the current state of each vehicle data signal. Simulated vehicle state changes are entirely user-driven. All powertrain-type compatible signals are enabled for configuration by default.

<Note>
  The Simulator is designed for logic testing with simulated vehicle data. Actual signal compatibility for a specific OEM brand can be found in the [Compatibility Matrix](https://compatibility.smartcar.com).
</Note>

#### Vehicle signals

Control the state of each vehicle data signal in the simulated vehicle's configuration tab. You can edit one or many signals at a time. Click **Publish** to store the vehicle's updated state. This state will be used in subsequent webhook payloads or API requests.

If the published changes include a signal that is set as a trigger in your webhook integration, a new vehicle state or error event will be delivered to your application.

#### Vehicle commands

Simulated vehicles support the following API commands:

* [Set charge limit](/docs/api-reference/evs/set-charge-limit)
* [Start and stop charge](/docs/api-reference/evs/control-charge)
* [Lock and unlock](/docs/api-reference/control-lock-unlock)
* [Send destination](/docs/api-reference/send-destination-to-vehicle)

You can control access to these commands by editing the vehicle's permissions. If you are testing commands while monitoring the vehicle's state in the Simulator dashboard, click **Refresh** to view the vehicle's updated state after the command request.

#### Permissions

Simulated vehicles are granted all compatible permissions by default based on the chosen powertrain type. You can edit granted permissions under the `VehicleUserAccount.Permissions` signal in the Vehicle State panel.

<Frame type="glass">
  <img alt="Control simulated vehicle permissions" />
</Frame>

To test permission errors in your webhooks, uncheck certain permissions while still requesting those signals in your webhook vehicle state payload. [Learn more about permissions](/docs/api-reference/permissions).

## 4. Test you webhook integrations

Test your webhook integrations by configuring and publishing the vehicle state in different scenarios. Each set of published changes that includes a webhook trigger signal will deliver a webhook payload to your integration.

<Note>
  You can view logs for simulated webhook payloads and API requests in the Dashboard Logs with the tables filtered to `simulated` mode.
</Note>

## 5. Test error states

You can configure your simulated vehicle's state to recreate error scenarios for testing. Examples:

* Uncheck a permission in `VehicleUserAccount.Permissions` before triggering a webhook payload to receive a `PERMISSIONS` error
* Set the simulated vehicle's `Transmission.GearState` to `DRIVE` before making a `POST /security` lock request to receive a `VEHICLE_STATE:IN_MOTION` error

<Note>
  Simulated vehicles do not have rate limits or API command latencies to enable a faster and smoother testing experience. Live vehicles can expect to have rate limits and latencies.
</Note>

## 6. Test simulated vehicle connections

Use the Simulator to test vehicle connection and disconnection scenarios. By default, simulated vehicles are fully connected to your application upon creation. However, you can opt to create a simulated vehicle in a disconnected state and connect it later.

#### Connect a simulated vehicle

When connecting a simulated vehicle, you have two options depending on your testing needs; connecting automatically or simulating the vehicle owner experience using [Smartcar Connect](/docs/connect/what-is-connect).

<Note>
  Both options use the permissions configured in the simulated vehicle's state under the signal VehicleUserAccount.Permissions, which will override any application-level permissions.
</Note>

**Option 1: Connect automatically**

Instantly connect the simulated vehicle to your application. Once connected, access it with your application-level (M2M) tokens — see [Accessing a simulated vehicle](#accessing-a-simulated-vehicle).

**Option 2: Connect via Smartcar Connect simulation**

Test the vehicle owner's connection flow by simulating the Smartcar Connect authorization process. You'll receive a Connect URL with the mode parameter set to "simulated" and authentication credentials to use in the Connect flow. This simulated flow uses `response_type=none`, so it does not issue a per-vehicle access token; access the connected vehicle with your application-level (M2M) tokens. If you specifically need per-vehicle tokens, use `response_type=code` with a configured redirect URI.

After connecting through Smartcar Connect, the vehicle will display the selected brand in the dashboard and in all webhook payloads and API responses (in the vehicle.make field).

<Note>
  You can select any brand from the Connect flow brand select screen to authenticate the simulated vehicle with. The selected brand is only used for the Connect simulation and will not impact the simulated vehicle’s compatibility or simulation data.
</Note>

<Frame type="glass">
  <img alt="Connect a simulated vehicle using Smartcar Connect" />
</Frame>

<Frame type="glass">
  <img alt="Smartcar Connect in simulated mode" />
</Frame>

#### Disconnect a simulated vehicle

You can disconnect a simulated vehicle from any of these locations:

1. In the Vehicle Connections table
2. In the Simulated Vehicles table
3. Via the delete vehicle connection endpoint

Disconnecting removes the vehicle connection but preserves the simulated vehicle. Any active webhook subscriptions will be removed and must be reconfigured if you reconnect the vehicle.

#### Managing simulated vehicle connections

Manage simulated vehicle connections in the Vehicle Connections dashboard alongside live vehicles. Filter the table by mode to show simulated vehicles only. Vehicles from the legacy Simulator are marked with a 'Legacy' chip.

<Note>
  **Why was my simulated vehicle disconnected?**

  If you didn't disconnect the vehicle manually, a team member may have, or it may have been created in a disconnected state. Simulated vehicles can be disconnected via the API or Vehicle Connections dashboard, just like live vehicles.
</Note>

## Test additional Connect flows

Depending on your use case, some vehicles prompt the user for additional input during the Smartcar Connect authorization flow. Use the Simulator to test these scenarios.

#### Test the VIN and odometer verification flow

In parts of Europe, some Volkswagen Group vehicle owners authenticate using their VIN and current odometer reading as an alternate to signing in with their connected services account.

1. Create a BEV or PHEV simulated vehicle and disable **Connect automatically** (or disconnect the vehicle once it's been created).
2. Open the Connect modal for the vehicle and select **Connect manually via Smartcar Connect**.
3. Launch the Connect flow.
4. In the Connect flow, select a European country.
5. On the brand select screen, select one of the following brands: Audi, Cupra, Škoda, SEAT, or Volkswagen.
6. Enter the VIN and odometer reading from the simulated vehicle's Configuration screen in the dashboard.

<Frame type="glass">
  <img alt="Smartcar Connect VIN and odometer verification screen" />
</Frame>

7. Finish connecting the vehicle.

<Note>
  The VIN and odometer verification flow currently only applies to BEV and PHEV models for the following brands in the EU: Audi, Cupra, Škoda, SEAT, and Volkswagen.
</Note>

[Learn more about the VIN and odometer verification flow in Smartcar Connect →](/docs/help/oem-integrations/vw/whats-new)

#### Test the user-selected battery capacity flow

Some EVs report an undetermined battery capacity, prompting the vehicle owner to select their capacity during Connect.

1. Create a BEV simulated vehicle and disable **Connect automatically** (or disconnect the vehicle once it's been created).
2. In the simulated vehicle's Configuration screen, open the `TractionBattery.NominalCapacity` signal's edit modal.
3. Toggle on the prompt for battery capacity selection in Connect.

<Frame type="glass">
  <img alt="Toggle to prompt for battery capacity selection in Connect" />
</Frame>

4. Click **Done**, then publish the simulated vehicle's modified signal configuration.
5. Double check the vehicle is in a disconnected state, then launch the Connect flow.
6. Complete the battery capacity selection flow, which is presented after the permissions grant screen in Connect.

[Learn more about the battery capacity selection flow in Smartcar Connect →](/docs/connect/user-selected-batcap)


# Single Sign-on (SSO)
Source: https://smartcar.com/docs/getting-started/dashboard/single-sign-on

Smartcar offers SSO through your identity provider (IdP) for Enterprise customers.

## About SSO with Smartcar

Our Dashboard supports SSO integrations with popular identity providers
including:

* Okta
* Microsoft Azure AD
* Google Workspace
* OneLogin
* Ping Identity
* ADFS
* Custom SAML 2.0 providers

To set up SSO for your organization's Dashboard accounts, you'll need to:

1. Be an Owner for an existing Team on an Enterprise plan
2. Verify your domain
3. Configure your identity provider

The following section will guide you through each step of this process.

## Setting up SSO

On Dashboard navigate to **Team settings > Security** and select **Enable SSO**

<Frame>
  <img alt="" />
</Frame>

You’ll be redirected to start the SSO configuration process.

<Frame>
  <img alt="" />
</Frame>

Depending on your DNS provider, you'll receive instructions on how to verify your domain.

<Frame>
  <img alt="" />
</Frame>

Once your domain is verified, you’ll be able to select your Identity Provider
(IdP).

<Frame>
  <img alt="" />
</Frame>

You'll be provided a guide on how to get set up based on your IdP.

<Frame>
  <img alt="" />
</Frame>

Once you’ve got everything configured, you’ll be prompted to test SSO.

<Frame>
  <img alt="" />
</Frame>

<br />

<Tip>
  If you exit the flow at any time before finalizing your configuration, you
  can jump back in from Dashboard.
</Tip>

<Frame>
  <img alt="" />
</Frame>

## Disabling SSO

If you have SSO configured, the Team Owner can disable it from **Team
settings > Security**.

<Warning>
  Disabling SSO will require you to go through the whole setup process
  again.
</Warning>

## Inviting team members with SSO enabled

Once enabled, you’ll need to add members to your team through your identity
provider. Invites via the Dashboard will be disabled while SSO is enabled.

<Frame>
  <img alt="" />
</Frame>

When a newly added member has signed in via SSO, they will have the Viewer role
by default. Other team members with the appropriate role can promote these
members as needed.

<Note>
  If a user creates a Dashboard account with their email prior to being added
  to your IdP, they will be added to their own Team initially. When they are
  added to your IdP they will be able to switch Teams in Dashboard.
</Note>

## A note on aliased emails

If members of your team have Dashboard accounts using email aliases prior to
enabling SSO e.g. [rover+thebest@dog.com](mailto:rover+thebest@dog.com), once SSO is enabled for your Team and
they’re added to your IdP, their login will be tied to their non-aliased email
address e.g. [rover@dog.com](mailto:rover@dog.com).

SSO is only available on the **Enterprise** plan, please reach out to your Account Manager for more details.


# Team Settings
Source: https://smartcar.com/docs/getting-started/dashboard/teams

Your Smartcar Team is the central hub for managing your applications, vehicles, members, security settings, and billing information.

Your Smartcar Team allows you to collaborate with other members and manage your applications in one place.

## Members

You can add team members to your Smartcar account on any plan for free.
Team members can be added to your Smartcar account by navigating to the **Settings** tab in the Dashboard and selecting **Members** under the **Team** section.

<Frame type="glass">
  <img />
</Frame>

## Roles and Permissions

Team members can be added on any plan. Specific roles are available on our [Enterprise plan](https://smartcar.com/pricing).

| <div />              | Owner <div /> | Admin <div /> | Editor <div /> | Viewer <div /> |
| -------------------- | ------------- | ------------- | -------------- | -------------- |
| Manage billing       | ✅             |               |                |                |
| View billing         | ✅             |               |                |                |
| Delete applications  | ✅             |               |                |                |
| Modify team settings | ✅             |               |                |                |
| Remove team members  | ✅             | ✅             |                |                |
| Modify team members  | ✅             | ✅             |                |                |
| Create applications  | ✅             | ✅             |                |                |
| Modify applications  | ✅             | ✅             | ✅              |                |
| View applications    | ✅             | ✅             | ✅              | ✅              |
| View team members    | ✅             | ✅             | ✅              | ✅              |

<Tip>
  Editors and Viewers can be limited to specific applications.
</Tip>

## Roles

### Owner

Owners have full control and access to the team. They're able to add and remove members, create and modify applications, edit billing information and more.

A team **can** have multiple Owners, but **must** have at least one.

### Admin

Admins have similar access to Owners but can't edit or view billing information.

### Editor

Editors have similar access to Admins but are limited to specific applications. They're unable to manage team members, view the team's billing information, create applications, or delete applications they're allowed to access.

### Viewer

Viewers have similar permissions to Editors but only have read-only access to applications they've been invited to.


# API Authentication Setup
Source: https://smartcar.com/docs/getting-started/how-to/api-authentication

Set up API Authentication to access the Smartcar API using application-level tokens.

API Authentication uses the OAuth 2.0 Client Credentials flow to obtain an application-level access token. Use this token to make API requests on behalf of your users.

## Prerequisites

API Authentication is available for applications using Smartcar's webhooks offering and the v3 REST API. If your application was created before June 1st, 2025, you may need to upgrade to the v3 API in your Dashboard settings.

***

## Step 1: Generate Your API Credentials

<Steps>
  <Step title="Navigate to API Credentials">
    In your [Smartcar Dashboard](https://dashboard.smartcar.com), go to your application and select the **API Credentials** tab.
  </Step>

  <Step title="Create an API Secret">
    Click **Create Secret** in the API Credentials section. Your client ID will be displayed, and a new client secret will be generated.

    <Warning>
      The client secret is only shown once. Copy and store it securely in your backend environment. Never expose API credentials in client-side code.
    </Warning>
  </Step>

  <Step title="Store Credentials Securely">
    Store your API credentials in a secure secrets manager or environment variables. These credentials grant access to all vehicles connected to your application.
  </Step>
</Steps>

***

## Step 2: Capture the User ID from Connect

When a user completes the Smartcar Connect flow, the redirect URL now includes a `user_id` parameter alongside the authorization code. Read more about Connect redirect url parameters [here](/docs/connect/handle-the-response).

***

## Step 3: Obtain an Access Token

Exchange your API credentials for an access token using the client credentials grant:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://iam.smartcar.com/oauth2/token" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "grant_type=client_credentials" \
    -d "client_id=YOUR_CLIENT_ID" \
    -d "client_secret=YOUR_CLIENT_SECRET"
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://iam.smartcar.com/oauth2/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: new URLSearchParams({
      grant_type: 'client_credentials',
      client_id: process.env.SMARTCAR_CLIENT_ID,
      client_secret: process.env.SMARTCAR_CLIENT_SECRET,
    }),
  });

  const { access_token, expires_in } = await response.json();
  ```

  ```python Python theme={null}
  import requests
  import os

  response = requests.post(
      'https://iam.smartcar.com/oauth2/token',
      data={
          'grant_type': 'client_credentials',
          'client_id': os.environ['SMARTCAR_CLIENT_ID'],
          'client_secret': os.environ['SMARTCAR_CLIENT_SECRET'],
      }
  )

  token_data = response.json()
  access_token = token_data['access_token']
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "access_token": "{access_token}",
  "token_type": "Bearer",
  "expires_in": 3600
}
```

<Info>
  Access tokens are valid for **1 hour**. There is no refresh token — simply request a new token when the current one expires.
</Info>

***

## Step 4: Make API Requests

Include the access token in the `Authorization` header:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://vehicle.api.smartcar.com/v3/vehicles/{vehicleId}" \
    -H "Authorization: Bearer {access_token}"
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
    `https://vehicle.api.smartcar.com/v3/vehicles/${vehicleId}`,
    {
      headers: {
        'Authorization': `Bearer ${accessToken}`,
      },
    }
  );
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      f'https://vehicle.api.smartcar.com/v3/vehicles/{vehicle_id}',
      headers={
          'Authorization': f'Bearer {access_token}',
      }
  )
  ```
</CodeGroup>

<Note>
  When accessing vehicle signals or issuing commands, also include the `sc-user-id` header set to the user's ID obtained from the Connect redirect. See [Step 2](#step-2-capture-the-user-id-from-connect) above.
</Note>

***

## Step 5: List User Connections

Use the Connections API to retrieve all vehicles connected by a specific user:

```bash theme={null}
curl -X GET "https://vehicle.api.smartcar.com/v3/connections?filter[user_id]={userId}" \
  -H "Authorization: Bearer {access_token}"
```

**Response:**

```json theme={null}
{
  "connections": [
    {
      "id": "conn-uuid-1",
      "userId": "a4c82e9f-7b31-4d56-8e0a-3f6d91c5b2e7",
      "vehicleId": "vehicle-uuid-1",
      "connectedAt": "2025-01-15T10:30:00Z"
    },
    {
      "id": "conn-uuid-2",
      "userId": "a4c82e9f-7b31-4d56-8e0a-3f6d91c5b2e7",
      "vehicleId": "vehicle-uuid-2",
      "connectedAt": "2025-01-20T14:45:00Z"
    }
  ],
  "paging": {
    "cursor": null
  }
}
```

***

## Security Best Practices

<Warning>
  API credentials provide access to **all vehicles** connected to your application. Handle them with the same care as database credentials or encryption keys.
</Warning>

* **Never expose API credentials in client-side code** (mobile apps, browser JavaScript, etc.)
* **Rotate secrets periodically** using the Dashboard
* **Use environment variables** or a secrets manager for credential storage
* **Implement audit logging** for access token usage
* **Limit access** to API credentials within your organization

***

## Webhooks with API Authentication

When using API Authentication, webhook payloads include the `user.id` field nested inside the `data` object. Both Vehicle Connection Status and Vehicle State events contain the `userId` alongside the `vehicleId`, allowing you to identify which user's vehicle triggered the event:

```json theme={null}
{
  "eventId": "event-uuid",
  "eventType": "VEHICLE_STATE",
  "data": {
    "vehicle": {
      "id": "vehicle-uuid",
      "make": "Tesla",
      "model": "Model S",
      "year": 2020,
      "vin": "5YJSA1E26FFP12345"
    },
    "signals": [...],
    "user": {
      "id": "a4c82e9f-7b31-4d56-8e0a-3f6d91c5b2e7"
    }
  },
  "triggers": [...],
  "meta": {...}
}
```

***

## What's Next

* [Overview](/docs/api-reference/authorization/overview) — Understand when and why to use API Authentication
* [Migration Guide](/docs/getting-started/how-to/m2m/migration-guide) — Transition from per-vehicle tokens
* [FAQ](/docs/getting-started/how-to/m2m/faq) — Common questions and answers
* [Connections API Reference](/docs/api-reference/list-connections) — List and manage connections
* [Webhooks Overview](/docs/integrations/webhooks/overview) — Set up event-driven updates


# How to Configure Permissions for Vehicle Data Collection
Source: https://smartcar.com/docs/getting-started/how-to/configure-permissions

Step-by-step guide to selecting signals, commands, and attributes in the Smartcar Dashboard and requesting the right permissions from vehicle owners.

To retrieve vehicle data through Smartcar, you must configure your application to request the correct permissions from vehicle owners. This guide walks you through the process using the Smartcar Dashboard.

<Steps>
  <Step title="Open the Configuration Page in the Dashboard">
    Go to the [Smartcar Dashboard](https://dashboard.smartcar.com/configuration) and select your application. Navigate to the <b>Configuration</b> section and choose the <b>Vehicle access</b> tab.
  </Step>

  <Step title="Select Signals, Commands, and Attributes">
    Under the <b>Signals</b>, <b>Commands</b>, and <b>Attributes</b> tabs, select the specific vehicle data points and actions your application needs. Each selection corresponds to a permission that the vehicle owner must approve.

    <Frame type="simple">
      <img alt="Smartcar Dashboard configuration page showing signal selection and Connect Preview." />
    </Frame>

    <ul>
      <li><b>Signals:</b> Dynamic vehicle data (e.g., battery level, odometer, location).</li>
      <li><b>Commands:</b> Actions your app can perform (e.g., lock/unlock, start charging).</li>
      <li><b>Attributes:</b> Static vehicle info (e.g., make, model, year).</li>
    </ul>

    <Note>
      Only select the permissions your application truly needs. This improves user trust and increases the likelihood of successful connections.
    </Note>
  </Step>

  <Step title="Preview the Owner Experience">
    As you select signals, commands, and attributes, the <b>Connect Preview</b> on the right updates to show what the vehicle owner will see when connecting their vehicle. This preview lists the permissions your app is requesting and the vehicles that will be connected.
  </Step>

  <Step title="Publish Your Configuration">
    Once you are satisfied with your selections, click <b>Publish</b> to save your configuration. Your application will now request these permissions from vehicle owners during the Smartcar Connect flow.
  </Step>
</Steps>

## Dynamic Permissions

If your application needs to access different permissions based on user actions or vehicle types, you can leverage the `scope` parameter in the Smartcar Connect URL to dynamically request permissions at runtime. This allows you to tailor the permissions based on the specific vehicle or user context.
Keep in mind that any permissions you pass via the `scope` parameter will override the permissions configured in the Smartcar Dashboard for that specific connection.

### Notes

* If you need to change permissions later, you can return to this configuration page and update your selections. Vehicle owners will need to reauthorize your application to grant any new permissions.
* The permissions you select here will determine the data and actions available to your application. Make sure to choose only what is necessary for your use case.

## Mark Permissions as Required or Optional

In the **Vehicle Access** tab, each signal has a **Required** toggle that controls how its permission appears to vehicle owners on the Connect grant screen.

* **Required** (toggle on): the permission appears checked and locked. The vehicle owner cannot uncheck it.
* **Optional** (toggle off): the permission appears checked by default, and the vehicle owner can uncheck it before connecting.

<Frame type="simple">
  <img alt="Smartcar Dashboard Vehicle Access tab with the Required toggle on for Amperage and Amperage Max and off for other Charge signals." />
</Frame>

At least one permission must remain selected for the owner to complete the connection.

Only mark a permission as required if it is absolutely necessary for your application to function. Leaving non-essential permissions optional gives vehicle owners more control and can improve your connection rate.

<Note>
  Marking a permission as required signals that your application needs it. It does not guarantee the vehicle supports it. To restrict which vehicles can connect by powertrain type, use [Connection Filters](/docs/connect/advanced-config/connection-filters).
</Note>

***

## What’s Next

* [How to Connect Vehicles](/docs/getting-started/connect-vehicles)
* [API Authentication Setup](/docs/getting-started/how-to/api-authentication)
* [API Reference: Permissions](/docs/api-reference/permissions)


# How to Detect and Process Charging Sessions with Webhooks
Source: https://smartcar.com/docs/getting-started/how-to/detect-charging-session

Learn how to use Smartcar webhooks to detect when a vehicle starts and ends charging, and how to process charging session data.

Smartcar webhooks make it easy to detect and process vehicle charging sessions in real time. This guide explains how to configure your webhook, handle charging events, and process charging session data in your backend.

<Steps>
  <Step title="Configure Your Webhook for Charging Events">
    In the [Smartcar Dashboard](https://dashboard.smartcar.com/integrations), create or edit a webhook integration. Under <b>Triggers</b>, select the following events:

    <ul>
      <li>Charge.IsCharging</li>
      <li>Charge.IsChargingCableConnected</li>
    </ul>

    These signals will act as triggers for detecting when a vehicle starts and stops charging and when it is plugged in or unplugged. Whenever these signals change, Smartcar will send a webhook event to your configured endpoint.
    Next, you'll configure your **data**. This is the information you want to receive in your webhook payload every time you receive a webhook event. Triggers are included by default, but you can also add additional signals to the data payload, such as:

    <ul>
      <li>Charge.StateOfCharge (included as a trigger)</li>
      <li>Charge.ChargingCurrent (included as a trigger)</li>
      <li>Charge.ActiveLimit</li>
      <li>Charge.Amperage</li>
      <li>Charge.Voltage</li>
      <li>Charge.Wattage</li>
      <li>Charge.EnergyAdded</li>
      <li>Charge.TimeToComplete</li>
      <li>TractionBattery.Range</li>
      <li>TractionBattery.NominalCapacity</li>
      <li>Location.PreciseLocation</li>
    </ul>

    These data signals will be delivered for every webhook event, allowing you to track the state of charge and other relevant metrics while the vehicle is charging.
    Next, provide your webhook URL where Smartcar will send the events. Make sure your endpoint is publicly accessible and can handle POST requests. You can choose to auto enroll all your vehicles to this webhook or manually subscribe vehicles later (you can do this from the Dashboard). For this guide, select "don't subscribe any vehicles".
    Now it is time to save and verify your webhook.
  </Step>

  <Step title="Validate Webhook Events">
    Smartcar will send a verification request to your endpoint, which you must respond to with a 200 OK status code to complete the setup (see [Webhook Verification guide](/docs/integrations/webhooks/callback-verification)).
    Once verified, you will start to receive vehicle data for the vehicles you have subscribed to this webhook. For this guide, we chose not to auto subscribe vehicles, so let's head over to the [Smartcar Dashboard](https://dashboard.smartcar.com/vehicles) to manually subscribe a vehicle to your webhook.
    Select a vehicle from your list of connected vehicles and click on the three dots action menu to the right of the row and click subscribe. Select your newly created webhook from the options and click subscribe.

    <Frame type="simple">
      <img alt="Smartcar Dashboard showing how to subscribe a vehicle to a webhook." />
    </Frame>
  </Step>
</Steps>

At this point, your webhook is fully configured to receive charging events from the subscribed vehicle. Now let's handle the incoming webhook events in your backend.

Every webhook will include an `eventId` and an `eventType` field. The `eventType` will indicate the type of event that occurred, such as `VEHICLE_STATE` or `VEHICLE_ERROR`.
Your handler should gracefully handle both event types. For `VEHICLE_STATE` events, you will receive the updated vehicle data. For `VEHICLE_ERROR` events, you may want to log the error.
For `VEHICLE_STATE` events, you will receive the data in a `data` property of the payload. There will also be an array of signals under a `triggers` property that caused the event to be sent. Lastly, you will also receive a `meta` property with additional context about the event, such as the webhook ID, name, delivery ID, delivery timestamp, etc.

### How to track charging sessions

When a vehicle starts charging, you will receive a webhook event with the `eventType` of `VEHICLE_STATE` and the `Charge.IsCharging` signal set to `true`. When the vehicle stops charging, you will receive another event with `Charge.IsCharging` set to `false`. You can use these events to track the start and end of each charging session.

Example event payload:

```json theme={null}
{
  "eventId": "a7738a15-7ee2-40b3-9815-823d146230cd",
  "eventType": "VEHICLE_STATE",
  "data": {
    "user": {
      "id": "deee49b6-d638-4be4-82dc-121ea613eed9"
    },
    "vehicle": {
      "id": "829e30ab-5a13-40b5-9f8a-8538af86ed95",
      "make": "Tesla",
      "model": "Model 3",
      "year": 2020,
      "mode": "live",
      "powertrainType": "BEV"
    },
    "signals": [
      {
        "code": "charge-ischarging",
        "name": "IsCharging",
        "group": "Charge",
        "body": {
          "value": true
        },
        "status": {
          "value": "SUCCESS"
        },
        "meta": {
          "oemUpdatedAt": 1754365413366,
          "retrievedAt": 1754365413366
        }
      }
    ],
    "triggers": [
      {
        "type": "SIGNAL_UPDATED",
        "signal": {
          "code": "charge-ischarging",
          "name": "IsCharging",
          "group": "Charge"
        }
      }
    ],
    "meta": {
      "webhookId": "f1c2d3e4-5678-90ab-cdef-1234567890ab",
      "webhookName": "My Charging Webhook",
      "deliveryId": "b1c2d3e4-5678-90ab-cdef-1234567890ab",
      "deliveryTimestamp": "2024-08-04T17:00:00Z",
      "mode": "LIVE",
      "signalCount": 1
    }
  }
}
```

Tip: Always validate the webhook signature to ensure the request is from Smartcar.

***

## What’s Next

* [How to Configure Permissions](/docs/getting-started/how-to/configure-permissions)
* [API Authentication Setup](/docs/getting-started/how-to/api-authentication)
* [API Reference: Webhooks](/docs/api-reference/webhooks/subscribe-webhook)


# API Authentication FAQ
Source: https://smartcar.com/docs/getting-started/how-to/m2m/faq

Frequently asked questions about API Authentication and API credentials.

<AccordionGroup>
  ## General

  <Accordion title="What is API Authentication?">
    API Authentication is an authentication method that uses the OAuth 2.0 Client Credentials flow. You exchange your API credentials for a short-lived access token and include the `sc-user-id` header in each request to specify which user's vehicles you are accessing.
  </Accordion>

  <Accordion title="How is API Authentication different from per-vehicle access tokens?">
    API Authentication is scoped to your application rather than to an individual vehicle. A single access token, combined with the `sc-user-id` header, lets you access any user's vehicles connected to your application.
  </Accordion>

  <Accordion title="Who can use API Authentication?">
    API Authentication is available for applications using Smartcar's webhooks offering and the v3 REST API. If your application has not yet adopted the v3 API, you must upgrade first. Refer to the migration guide for steps.
  </Accordion>

  <Accordion title="Do I have to migrate to API Authentication?">
    No. There is no forced migration. Your existing opaque tokens continue to work indefinitely. You can adopt API Authentication at your own pace.
  </Accordion>

  ## Setup & Configuration

  <Accordion title="How do I create API credentials?">
    You create API credentials through the Smartcar Dashboard. Navigate to the **API Credentials** tab in your application settings and click **Create Secret**. The dashboard will provide you with a client ID and client secret.

    <Info>
      Store these credentials securely immediately after generation. The secret will not be displayed again.
    </Info>
  </Accordion>

  <Accordion title="Where do I find my client ID and secret?">
    Your API credentials are available in the Smartcar Dashboard under the **API Credentials** tab. The client ID is always visible, but the client secret is only shown once at creation. If you lose the secret, you must generate a new one.
  </Accordion>

  <Accordion title="Can I have multiple API secrets?">
    Yes. You can generate up to 3 client secrets for the same application. This is useful for credential rotation, allowing you to generate a new secret and retire the old one without downtime. Manage all secrets through the **API Credentials** tab in the Smartcar Dashboard.

    <Tip>
      Use multiple secrets to support zero-downtime secret rotation. Generate a new secret, update your application to use it, then delete the old secret.
    </Tip>
  </Accordion>

  ## Authentication & Usage

  <Accordion title="How do I obtain an access token?">
    Send a POST request to the Smartcar token endpoint with your API credentials:

    ```bash theme={null}
    curl -X POST https://iam.smartcar.com/oauth2/token \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET"
    ```

    The response includes an `access_token` that you use in subsequent API requests.
  </Accordion>

  <Accordion title="How long are access tokens valid?">
    Access tokens are valid for 1 hour (3600 seconds). After expiration, you must request a new token using your API credentials.
  </Accordion>

  <Accordion title="Do access tokens have refresh tokens?">
    No. Access tokens do not include refresh tokens. To obtain a new access token after expiration, simply make another request to the token endpoint with your API credentials. This ensures you always use fresh, short-lived tokens.
  </Accordion>

  <Accordion title="What is the sc-user-id header?">
    The `sc-user-id` header identifies which user's vehicles you want to access. Since API credentials grant access to all vehicles connected to your application, this header scopes the request to a particular user. Include it in your API requests to ensure you only access the intended user's vehicle data.

    Example:

    ```bash theme={null}
    curl https://vehicle.api.smartcar.com/v3/vehicles \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "sc-user-id: USER_ID"
    ```
  </Accordion>

  <Accordion title="How do I get a user's userId?">
    The `userId` is returned in the Smartcar Connect flow after a user authorizes your application. You also receive it in webhook payloads under the `user.id` field. Store this identifier to use in the `sc-user-id` header for subsequent API requests on behalf of that user.
  </Accordion>

  ## Migration

  <Accordion title="Can I use both API Authentication and opaque tokens at the same time?">
    Yes. You can use application-level access tokens and opaque tokens simultaneously during your migration. This allows you to gradually transition your application without requiring all changes at once.
  </Accordion>

  <Accordion title="What happens to my existing opaque tokens if I enable API Authentication?">
    Your existing opaque tokens continue to work indefinitely. Enabling API Authentication does not affect or invalidate your current per-vehicle tokens. You can use both authentication methods concurrently.
  </Accordion>

  <Accordion title="Do I need to change my Connect flow?">
    No changes to your Connect flow are required. The Connect authorization flow remains the same. API credentials are generated separately through the dashboard and operate independently of the Connect flow.
  </Accordion>

  <Accordion title="How do webhooks work with API Authentication?">
    Webhooks continue to function as before. Webhook payloads now include the `user.id` field nested inside the `data` object. Both Vehicle Connection Status and Vehicle State events contain the `userId` alongside the `vehicleId`. You can use this to identify which user's vehicle triggered the event and use that `userId` in subsequent API requests with the `sc-user-id` header.
  </Accordion>

  ## Security

  <Accordion title="How should I store API credentials?">
    <Warning>
      Never store your client secret in public clients (frontend JavaScript, mobile apps) or in plain text files. Always store credentials securely on your backend server using environment variables or a secure secrets management system.
    </Warning>

    Best practices:

    * Store credentials in environment variables or a secrets vault
    * Use infrastructure-level security (IAM roles, key management services)
    * Never commit credentials to version control
    * Rotate secrets regularly according to your security policy
  </Accordion>

  <Accordion title="What happens if my client secret is compromised?">
    If you suspect your client secret has been compromised:

    1. Generate a new API credential immediately through the Smartcar Dashboard
    2. Update your application to use the new secret
    3. Delete the compromised secret
    4. Review your audit trail for any unauthorized access

    All token requests are logged, so you can check your audit trail to identify any suspicious activity.
  </Accordion>

  <Accordion title="Can an access token access any user's vehicles?">
    Access tokens grant access to all vehicles connected to your application. However, you control which user's vehicles you access by specifying the `sc-user-id` header in each request. Only vehicles connected to that specific user are accessible. Always verify you're using the correct `userId` to prevent unauthorized access to other users' data.
  </Accordion>

  ## Still Have Questions?

  If you need additional help with API Authentication, reach out to the Smartcar support team. Our team is here to help you implement it securely and efficiently.
</AccordionGroup>


# Migrating from V2 to V3 APIs
Source: https://smartcar.com/docs/getting-started/how-to/m2m/migration-guide

A step-by-step guide for transitioning your integration from per-vehicle user tokens to application-level access tokens.

## Overview

This guide walks through transitioning your existing integration from per-vehicle user tokens to application-level access tokens using API Authentication.

**Important:** This migration is required to use API v3.0, which only supports application-level (M2M) access tokens. Per-vehicle user tokens are a v2.0 concept and cannot be used with v3.0.

<Warning>
  The Vehicles API v2.0 will be deprecated on **December 1, 2026**. The latest version, [v3](/docs/api-reference/intro), was introduced on August 26, 2025. We recommend migrating as soon as possible to ensure continued support and access to new features.
</Warning>

## Before You Begin

Ensure you have the following:

* Active Smartcar developer account with dashboard access
* Existing integration using per-vehicle user tokens and Smartcar Connect
* Ability to update your backend database schema
* Development and staging environments ready for testing
* Team familiarity with your current token storage approach

## Migration Overview

The transition follows four steps. You control the pace.

1. **Create API credentials** — Generate your Client ID and Secret in the Dashboard
2. **Capture `user_id` from Connect** — Store the `user_id` returned in the Connect redirect URL
3. **Backfill existing connections** — Use the Connections endpoint to retrieve user IDs for existing connections
4. **Switch to application tokens** — Replace per-vehicle user tokens with your application access token + `sc-user-id` header

## Phase 1: Enable API Authentication (Parallel Operation)

<Steps>
  <Step title="Create API credentials in Dashboard">
    1. Log in to your [Smartcar Dashboard](https://dashboard.smartcar.com)
    2. Navigate to **API Credentials** in your application settings
    3. Click **Create Secret**
    4. Copy the `client_id` and `client_secret` and store them securely

    <Warning>
      Store these credentials as environment variables. Never commit them to version control.
    </Warning>
  </Step>

  <Step title="Continue using per-vehicle user tokens">
    Keep your existing token refresh and storage logic unchanged. You'll phase this out in Phase 3.
  </Step>

  <Step title="Test API Authentication">
    Exchange your credentials for an access token:

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST https://iam.smartcar.com/oauth2/token \
        -H "Content-Type: application/x-www-form-urlencoded" \
        -d "grant_type=client_credentials" \
        -d "client_id=YOUR_CLIENT_ID" \
        -d "client_secret=YOUR_CLIENT_SECRET"
      ```

      ```javascript Node.js theme={null}
      const axios = require('axios');

      async function getAppToken() {
        const response = await axios.post('https://iam.smartcar.com/oauth2/token', {
          grant_type: 'client_credentials',
          client_id: process.env.SMARTCAR_CLIENT_ID,
          client_secret: process.env.SMARTCAR_CLIENT_SECRET
        }, {
          headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
        });

        return response.data.access_token;
      }

      getAppToken().then(token => console.log('Access Token:', token));
      ```

      ```python Python theme={null}
      import os
      import requests

      def get_app_token():
          url = "https://iam.smartcar.com/oauth2/token"
          data = {
              "grant_type": "client_credentials",
              "client_id": os.getenv("SMARTCAR_CLIENT_ID"),
              "client_secret": os.getenv("SMARTCAR_CLIENT_SECRET")
          }
          response = requests.post(url, data=data)
          return response.json()["access_token"]

      token = get_app_token()
      print(f"Access Token: {token}")
      ```
    </CodeGroup>

    <Note>
      Access tokens are valid for 1 hour. Cache them and refresh when expired. Build a token refresh loop in Phase 2.
    </Note>
  </Step>

  <Step title="Run Phase 1 in staging">
    Deploy your API credentials to your staging environment. Make test API calls using the access token. Verify responses match your per-vehicle user token calls.
  </Step>
</Steps>

## Phase 2: Update Integration

<Steps>
  <Step title="Capture userId from Connect redirect">
    When users complete Smartcar Connect, the redirect now includes a `userId` parameter:

    ```
    https://example.com/callback?code=CODE&userId=a4c82e9f-...&state=STATE
    ```

    Update your callback handler to extract and store this userId:

    <CodeGroup>
      ```javascript Node.js theme={null}
      app.get('/callback', (req, res) => {
        const { code, userId, state } = req.query;

        // Verify state token (CSRF protection)
        if (state !== req.session.state) {
          return res.status(400).send('Invalid state');
        }

        // Store userId for later
        req.session.smartcarUserId = userId;

        // Exchange code for per-vehicle user token (Phase 1 & 2)
        const tokenData = await exchangeCodeForToken(code);

        // Store both for now (Phase 1 & 2)
        req.user.smartcarUserId = userId;
        req.user.smartcarToken = tokenData.access_token;
        await req.user.save();

        res.redirect('/dashboard');
      });
      ```

      ```python Python theme={null}
      from flask import request, session
      from urllib.parse import parse_qs

      @app.route('/callback')
      def callback():
          code = request.args.get('code')
          user_id = request.args.get('userId')
          state = request.args.get('state')

          # Verify state token (CSRF protection)
          if state != session.get('state'):
              return 'Invalid state', 400

          # Store userId
          session['smartcar_user_id'] = user_id

          # Exchange code for per-vehicle user token
          token_data = exchange_code_for_token(code)

          # Store both
          current_user.smartcar_user_id = user_id
          current_user.smartcar_token = token_data['access_token']
          db.session.commit()

          return redirect('/dashboard')
      ```
    </CodeGroup>
  </Step>

  <Step title="Store userId ↔ user ID mappings">
    Create a new database column to store the Smartcar userId alongside your internal user ID. See the schema changes section below.
  </Step>

  <Step title="Query connections by userId">
    Start querying the connections endpoint with the userId filter:

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X GET "https://vehicle.api.smartcar.com/v3/connections?filter[user_id]=a4c82e9f-..." \
        -H "Authorization: Bearer {access_token}" \
        -H "sc-user-id: a4c82e9f-..."
      ```

      ```javascript Node.js theme={null}
      const axios = require('axios');

      async function getUserConnections(appToken, userId) {
        const response = await axios.get(
          `https://vehicle.api.smartcar.com/v3/connections?filter[user_id]=${userId}`,
          {
            headers: {
              'Authorization': `Bearer ${appToken}`,
              'sc-user-id': userId
            }
          }
        );
        return response.data;
      }
      ```

      ```python Python theme={null}
      import requests

      def get_user_connections(app_token, user_id):
          url = f"https://vehicle.api.smartcar.com/v3/connections?filter[user_id]={user_id}"
          headers = {
              "Authorization": f"Bearer {app_token}",
              "sc-user-id": user_id
          }
          response = requests.get(url, headers=headers)
          return response.json()
      ```
    </CodeGroup>

    <Tip>
      The `sc-user-id` header tells Smartcar which user's connections you're accessing. Always include it.
    </Tip>
  </Step>

  <Step title="Handle webhooks with user.id">
    Smartcar webhooks now include `user.id` in the payload. Use this to route events to the correct user:

    ```json theme={null}
    {
      "eventId": "b9e4d2a6-5f18-43c7-a0b3-8d1f6e9c7a54",
      "eventType": "VEHICLE_STATE",
      "data": {
        "vehicle": {
          "id": "vehicle123",
          "make": "Tesla",
          "model": "Model S",
          "year": 2020,
          "vin": "5YJSA1E26FFP12345"
        },
        "signals": [],
        "user": {
          "id": "a4c82e9f-..."
        }
      },
      "triggers": [],
      "meta": {}
    }
    ```

    Update your webhook handler to extract and use the user ID:

    <CodeGroup>
      ```javascript Node.js theme={null}
      app.post('/webhooks/smartcar', (req, res) => {
        const { data, eventType } = req.body;
        const userId = data.user.id;
        const vehicle = data.vehicle;

        // Route to correct user
        const userRecord = User.findBySmartcarId(userId);

        if (eventType === 'VEHICLE_STATE') {
          handleVehicleStateChange(userRecord, vehicle);
        }

        res.status(200).send('OK');
      });
      ```

      ```python Python theme={null}
      @app.route('/webhooks/smartcar', methods=['POST'])
      def handle_webhook():
          payload = request.json
          data = payload['data']
          user_id = data['user']['id']
          event_type = payload['eventType']
          vehicle = data['vehicle']

          # Route to correct user
          user_record = User.query.filter_by(smartcar_user_id=user_id).first()

          if event_type == 'VEHICLE_STATE':
              handle_vehicle_state_change(user_record, vehicle)

          return 'OK', 200
      ```
    </CodeGroup>
  </Step>
</Steps>

## Phase 3: Full Migration

<Steps>
  <Step title="Switch to API Authentication">
    Update all API calls to use the access token and `sc-user-id` header:

    <CodeGroup>
      ```javascript Node.js theme={null}
      // Before (per-vehicle user token per vehicle)
      async function getVehicleInfo(vehicleId, vehicleToken) {
        const response = await axios.get(
          `https://api.smartcar.com/v2.0/vehicles/${vehicleId}/info`,
          {
            headers: {
              'Authorization': `Bearer ${vehicleToken}`
            }
          }
        );
        return response.data;
      }

      // After (application access token + userId)
      async function getVehicleInfo(vehicleId, appToken, userId) {
        const response = await axios.get(
          `https://vehicle.api.smartcar.com/v3/vehicles/${vehicleId}`,
          {
            headers: {
              'Authorization': `Bearer ${appToken}`,
              'sc-user-id': userId
            }
          }
        );
        return response.data;
      }
      ```

      ```python Python theme={null}
      # Before (per-vehicle user token per vehicle)
      def get_vehicle_info(vehicle_id, vehicle_token):
          headers = {'Authorization': f'Bearer {vehicle_token}'}
          response = requests.get(
              f'https://api.smartcar.com/v2.0/vehicles/{vehicle_id}/info',
              headers=headers
          )
          return response.json()

      # After (application access token + userId)
      def get_vehicle_info(vehicle_id, app_token, user_id):
          headers = {
              'Authorization': f'Bearer {app_token}',
              'sc-user-id': user_id
          }
          response = requests.get(
              f'https://vehicle.api.smartcar.com/v3/vehicles/{vehicle_id}',
              headers=headers
          )
          return response.json()
      ```
    </CodeGroup>
  </Step>

  <Step title="Remove per-vehicle user token refresh logic">
    Delete the code that refreshes per-vehicle user tokens. Application access tokens are re-requested from the token endpoint when expired.

    <Warning>
      Ensure your access token cache and refresh loop are working before removing per-vehicle user token logic.
    </Warning>
  </Step>

  <Step title="Decommission token storage">
    Once all API calls use API Authentication, remove the `vehicle_access_token` column from your database. You only need to store the `smartcar_user_id` per user.
  </Step>
</Steps>

## Database Schema Changes

### Before (Per-Vehicle User Tokens)

```sql theme={null}
CREATE TABLE users (
  id INT PRIMARY KEY,
  email VARCHAR(255),
  name VARCHAR(255),
  created_at TIMESTAMP
);

CREATE TABLE vehicles (
  id INT PRIMARY KEY,
  user_id INT,
  vin VARCHAR(17),
  vehicle_access_token VARCHAR(255),
  token_created_at TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id)
);
```

### After (API Authentication with userId Mapping)

```sql theme={null}
CREATE TABLE users (
  id INT PRIMARY KEY,
  email VARCHAR(255),
  name VARCHAR(255),
  smartcar_user_id VARCHAR(36),
  created_at TIMESTAMP
);

CREATE TABLE vehicles (
  id INT PRIMARY KEY,
  user_id INT,
  vin VARCHAR(17),
  smartcar_vehicle_id VARCHAR(36),
  FOREIGN KEY (user_id) REFERENCES users(id)
);
```

<Info>
  You can keep the `smartcar_vehicle_id` for reference, but you no longer need token storage.
</Info>

## Code Changes: Before & After

<CodeGroup>
  ```javascript Before theme={null}
  // Old approach: Store and refresh per-vehicle tokens
  async function getVehicleData(user) {
    const vehicle = await Vehicle.findOne({ userId: user.id });

    // Check token expiration
    if (isTokenExpired(vehicle.tokenCreatedAt)) {
      const newToken = await refreshVehicleToken(vehicle.refreshToken);
      vehicle.vehicleAccessToken = newToken;
      await vehicle.save();
    }

    // Make API call with vehicle token
    const response = await axios.get(
      `https://vehicle.api.smartcar.com/v3/vehicles/${vehicle.id}/signals`,
      {
        headers: {
          'Authorization': `Bearer ${vehicle.vehicleAccessToken}`
        }
      }
    );

    return response.data;
  }
  ```

  ```javascript After theme={null}
  // New approach: Use application access token + user ID header
  async function getVehicleData(user) {
    const vehicle = await Vehicle.findOne({ userId: user.id });
    const appToken = await getAppToken(); // Cached and refreshed automatically

    // Make API call with application access token
    const response = await axios.get(
      `https://vehicle.api.smartcar.com/v3/vehicles/${vehicle.id}/signals`,
      {
        headers: {
          'Authorization': `Bearer ${appToken}`,
          'sc-user-id': user.smartcarUserId
        }
      }
    );

    return response.data;
  }
  ```
</CodeGroup>

## Testing Your Migration

Use this checklist to validate each phase:

**Phase 1 Validation:**

* [ ] API credentials created and stored securely
* [ ] Access token obtained successfully
* [ ] Staging environment receives access token
* [ ] Test API call with access token returns same data as per-vehicle user token call
* [ ] Both opaque and access token calls work in parallel without conflicts

**Phase 2 Validation:**

* [ ] `userId` captured from Connect redirect
* [ ] `smartcar_user_id` stored in user database
* [ ] Connections query with `userId` filter returns results
* [ ] Webhook handler routes events correctly using `user.id`
* [ ] Old per-vehicle user token calls still work for existing connections

**Phase 3 Validation:**

* [ ] All API calls updated to use access token + `sc-user-id` header
* [ ] Token refresh loop running and caching access tokens
* [ ] Opaque token refresh code removed from codebase
* [ ] Database migration completed (`vehicle_access_token` removed)
* [ ] Production traffic flows through API Authentication
* [ ] No errors in error logs for authentication failures

## Rollback Plan

If you encounter issues, rolling back is simple:

1. **Phase 1 Rollback:** Delete API credentials from the Dashboard. No code changes needed.

2. **Phase 2 Rollback:** Stop consuming `userId` from Connect redirect. Revert webhook handler to previous version. Per-vehicle user tokens still work.

3. **Phase 3 Rollback:** Restore per-vehicle user token refresh logic from version control. Redeploy previous code. Vehicles remain connected.

<Note>
  Because per-vehicle user tokens continue to work until the Vehicles API v2.0 is deprecated, you can roll back at any phase before then without losing access to vehicles.
</Note>

## What's Next

* [Making API Requests](/docs/getting-started/how-to/making-api-requests) — Per-language examples for tokens, data, commands, and webhook verification
* [Setup Guide](/docs/getting-started/how-to/api-authentication) — Complete implementation steps
* [FAQ](/docs/getting-started/how-to/m2m/faq) — Common questions and answers
* [Webhooks Overview](/docs/integrations/webhooks/overview) — Set up event-driven updates
* [Connections API](/docs/api-reference/list-connections) — Manage vehicle connections


# Making API Requests
Source: https://smartcar.com/docs/getting-started/how-to/making-api-requests

Making a request to the Smartcar v3 API is a simple HTTP call. Examples for tokens, data, commands, and webhook verification in Node.js, Python, Ruby, Go, and Java.

Making a request to the Smartcar API is simple. Each endpoint is a standard HTTP call, so you can read data, send commands, and verify webhooks straight from your server in any language, without a backend SDK. This page shows each common task with examples in Node.js, Python, Ruby, Go, and Java.

To receive vehicle data, use [event-driven webhooks](/docs/integrations/webhooks/overview) rather than polling: Smartcar pushes updates to your server as they arrive. Use the requests below for on-demand reads and to send commands.

You need two things:

* An **access token**, obtained with the OAuth 2.0 Client Credentials flow. Tokens are valid for one hour and there is no refresh token. Request a new one when it expires. See [API Authentication](/docs/getting-started/how-to/api-authentication).
* A **user ID** (`sc-user-id`), captured from the Connect redirect. Signal reads and commands require it.

Webhook signature verification uses your **Application Management Token**, not the access token.

<Info>
  Moving an existing v2 integration off per-vehicle tokens? See the [Migration Guide](/docs/getting-started/how-to/m2m/migration-guide) for the phased rollout, database schema changes, and rollback plan.
</Info>

## Get an access token

<CodeGroup>
  ```javascript Node.js theme={null}
  const res = await fetch('https://iam.smartcar.com/oauth2/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      grant_type: 'client_credentials',
      client_id: process.env.SMARTCAR_CLIENT_ID,
      client_secret: process.env.SMARTCAR_CLIENT_SECRET,
    }),
  });
  const { access_token } = await res.json();
  ```

  ```python Python theme={null}
  import os, requests

  res = requests.post('https://iam.smartcar.com/oauth2/token', data={
      'grant_type': 'client_credentials',
      'client_id': os.environ['SMARTCAR_CLIENT_ID'],
      'client_secret': os.environ['SMARTCAR_CLIENT_SECRET'],
  })
  access_token = res.json()['access_token']
  ```

  ```ruby Ruby theme={null}
  require 'net/http'
  require 'json'

  res = Net::HTTP.post_form(URI('https://iam.smartcar.com/oauth2/token'), {
    'grant_type' => 'client_credentials',
    'client_id' => ENV['SMARTCAR_CLIENT_ID'],
    'client_secret' => ENV['SMARTCAR_CLIENT_SECRET'],
  })
  access_token = JSON.parse(res.body)['access_token']
  ```

  ```go Go theme={null}
  form := url.Values{}
  form.Set("grant_type", "client_credentials")
  form.Set("client_id", os.Getenv("SMARTCAR_CLIENT_ID"))
  form.Set("client_secret", os.Getenv("SMARTCAR_CLIENT_SECRET"))

  res, err := http.PostForm("https://iam.smartcar.com/oauth2/token", form)
  if err != nil {
      return err
  }
  defer res.Body.Close()

  var body struct {
      AccessToken string `json:"access_token"`
  }
  json.NewDecoder(res.Body).Decode(&body)
  accessToken := body.AccessToken
  ```

  ```java Java theme={null}
  String form = "grant_type=client_credentials"
      + "&client_id=" + System.getenv("SMARTCAR_CLIENT_ID")
      + "&client_secret=" + System.getenv("SMARTCAR_CLIENT_SECRET");

  HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://iam.smartcar.com/oauth2/token"))
      .header("Content-Type", "application/x-www-form-urlencoded")
      .POST(HttpRequest.BodyPublishers.ofString(form))
      .build();

  HttpResponse<String> response = HttpClient.newHttpClient()
      .send(request, HttpResponse.BodyHandlers.ofString());
  // Parse response.body() for "access_token" with your JSON library.
  ```
</CodeGroup>

## Retrieve vehicle data

Read all signals for a vehicle with `GET /vehicles/{vehicleId}/signals`. For a single signal, use `GET /vehicles/{vehicleId}/signals/{signalCode}`.

<CodeGroup>
  ```javascript Node.js theme={null}
  const res = await fetch(
    `https://vehicle.api.smartcar.com/v3/vehicles/${vehicleId}/signals`,
    { headers: { Authorization: `Bearer ${accessToken}`, 'sc-user-id': userId } }
  );
  const signals = await res.json();
  ```

  ```python Python theme={null}
  res = requests.get(
      f'https://vehicle.api.smartcar.com/v3/vehicles/{vehicle_id}/signals',
      headers={'Authorization': f'Bearer {access_token}', 'sc-user-id': user_id},
  )
  signals = res.json()
  ```

  ```ruby Ruby theme={null}
  uri = URI("https://vehicle.api.smartcar.com/v3/vehicles/#{vehicle_id}/signals")
  req = Net::HTTP::Get.new(uri)
  req['Authorization'] = "Bearer #{access_token}"
  req['sc-user-id'] = user_id

  res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
  signals = JSON.parse(res.body)
  ```

  ```go Go theme={null}
  url := "https://vehicle.api.smartcar.com/v3/vehicles/" + vehicleID + "/signals"
  req, _ := http.NewRequest("GET", url, nil)
  req.Header.Set("Authorization", "Bearer "+accessToken)
  req.Header.Set("sc-user-id", userID)

  res, err := http.DefaultClient.Do(req)
  if err != nil {
      return err
  }
  defer res.Body.Close()
  ```

  ```java Java theme={null}
  HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://vehicle.api.smartcar.com/v3/vehicles/" + vehicleId + "/signals"))
      .header("Authorization", "Bearer " + accessToken)
      .header("sc-user-id", userId)
      .GET()
      .build();

  HttpResponse<String> response = HttpClient.newHttpClient()
      .send(request, HttpResponse.BodyHandlers.ofString());
  ```
</CodeGroup>

## Issue a command

Commands are `POST /vehicles/{vehicleId}/commands/...`, for example `security/lock`, `security/unlock`, `charge/start`, `charge/stop`, `charge/set-limit`, and `navigation/set-destination`. Commands that take parameters send them as a JSON body. Locking a vehicle takes no body.

<CodeGroup>
  ```javascript Node.js theme={null}
  const res = await fetch(
    `https://vehicle.api.smartcar.com/v3/vehicles/${vehicleId}/commands/security/lock`,
    { method: 'POST', headers: { Authorization: `Bearer ${accessToken}`, 'sc-user-id': userId } }
  );
  const result = await res.json();
  ```

  ```python Python theme={null}
  res = requests.post(
      f'https://vehicle.api.smartcar.com/v3/vehicles/{vehicle_id}/commands/security/lock',
      headers={'Authorization': f'Bearer {access_token}', 'sc-user-id': user_id},
  )
  result = res.json()
  ```

  ```ruby Ruby theme={null}
  uri = URI("https://vehicle.api.smartcar.com/v3/vehicles/#{vehicle_id}/commands/security/lock")
  req = Net::HTTP::Post.new(uri)
  req['Authorization'] = "Bearer #{access_token}"
  req['sc-user-id'] = user_id

  res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
  result = JSON.parse(res.body)
  ```

  ```go Go theme={null}
  url := "https://vehicle.api.smartcar.com/v3/vehicles/" + vehicleID + "/commands/security/lock"
  req, _ := http.NewRequest("POST", url, nil)
  req.Header.Set("Authorization", "Bearer "+accessToken)
  req.Header.Set("sc-user-id", userID)

  res, err := http.DefaultClient.Do(req)
  if err != nil {
      return err
  }
  defer res.Body.Close()
  ```

  ```java Java theme={null}
  HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://vehicle.api.smartcar.com/v3/vehicles/" + vehicleId + "/commands/security/lock"))
      .header("Authorization", "Bearer " + accessToken)
      .header("sc-user-id", userId)
      .POST(HttpRequest.BodyPublishers.noBody())
      .build();

  HttpResponse<String> response = HttpClient.newHttpClient()
      .send(request, HttpResponse.BodyHandlers.ofString());
  ```
</CodeGroup>

## Verify a webhook signature

Every webhook carries an `SC-Signature` header with an HMAC-SHA256 of the raw body, keyed by your Application Management Token. Verify it before processing the payload. Full per-language examples are in [Payload Verification](/docs/integrations/webhooks/payload-verification), and initial endpoint setup is in [Callback URI Verification](/docs/integrations/webhooks/callback-verification).

## Next steps

<CardGroup>
  <Card title="API Authentication" icon="key" href="/getting-started/how-to/api-authentication">
    Set up client credentials and obtain access tokens.
  </Card>

  <Card title="Payload Verification" icon="shield-check" href="/integrations/webhooks/payload-verification">
    Verify webhook signatures without an SDK.
  </Card>
</CardGroup>


# Integrate with Smartcar To Receive Vehicle Data
Source: https://smartcar.com/docs/getting-started/integration-overview

Welcome to the integration phase of your Smartcar journey! After configuring your application and connecting vehicles, the next crucial step is to integrate your systems with Smartcar to receive vehicle data.

## Choosing Webhooks or the REST API

Understanding the differences between webhooks and the REST API will help you choose the right integration method for your use case.

### When to Use Webhooks

**[Webhooks](/docs/integrations/webhooks/overview) are the recommended approach** for applications that need real-time or frequently updated vehicle data. Use webhooks when:

* You need real-time notifications when vehicle data changes
* You're monitoring vehicle data continuously (e.g., fleet tracking, charging monitoring)
* You're building applications that react to vehicle events (e.g., alerts, automation)
* You need to scale to monitor many vehicles efficiently
* You want to avoid rate limits and reduce server load

**Advantages of webhooks:**

* **Require less effort and resources** - no polling the API repeatedly
* **Scale better** - Scale effortlessly to monitor thousands of vehicles, with no complex polling logic to maintain
* **Near real-time updates** - receive data within seconds of changes being detected
* **Avoid rate limits** - Smartcar pushes data to you instead of you calling the API
* **More reliable** - no missed updates due to polling intervals
* **Automatic optimizations** - Smartcar continuously optimizes data retrieval, and your application benefits immediately without code changes

**Quick Start**: Deploy a production-ready webhook receiver in minutes with our [Webhook Receiver Recipe](/docs/getting-started/tutorials/webhook-receiver-recipe) - a complete AWS serverless solution that implements best practices for you.

Learn more about [Webhooks](/docs/integrations/webhooks/overview).

### When to Use the REST API

The Vehicles API is designed for **infrequent data retrieval and command execution**. Use the API when:

* You need vehicle data only once or occasionally (e.g., user profile display)
* You're issuing commands to vehicles (lock/unlock, start/stop charging)
* You're exploring available signals or testing your integration
* You have a small number of vehicles and don't need continuous monitoring

The Vehicles API is designed primarily for exploration and non-frequent data retrieval. This API is not designed for continuous polling or real-time monitoring. Data is typically updated once every 24 hours unless the vehicle is actively subscribed to a webhook, which enables more frequent updates. For most use cases, you should avoid polling the Vehicles API at high frequency leverage [webhooks](/docs/integrations/webhooks/overview) instead.

Learn more about the [Vehicles API](/docs/api-reference/intro).

<Warning>
  **Do not poll the Vehicles API for real-time monitoring.** The API is not designed for continuous polling. Frequent polling will:

  * Consume your API rate limit quota quickly
  * Put unnecessary load on your servers and Smartcar's infrastructure
  * Provide stale data (updated only every 24 hours without webhook subscriptions)
  * Not scale as your fleet grows

  Use webhooks instead for any use case requiring frequent or real-time data.
</Warning>

***

## CSVs (coming soon)

This integration will help you receive vehicle data in a CSV file where you can integrate analyze using your existing tools and workflows.

With CSV integrations, you will be able to:

* Receive vehicle data from Smartcar at a specified cadence (e.g., weekly, monthly)
* Choose the data fields you want to include in the CSV export (e.g., vehicle info, location, odometer, battery level)
* Have CSV files automatically delivered to your preferred destination, such as an SFTP server, cloud storage bucket, etc.
* Easily import Smartcar data into your analytics, reporting, or business intelligence tools

This solution is ideal for customers who need scheduled, automated data exports for compliance, reporting, or integration with legacy systems.

<Note>
  CSV integration is coming soon! If you are interested in early access or have specific requirements, please reach out to <a href="mailto:support@smartcar.com">[support@smartcar.com](mailto:support@smartcar.com)</a>.
</Note>


# Getting Started with Smartcar
Source: https://smartcar.com/docs/getting-started/introduction

Welcome to Smartcar's Developer Documentation! Here, you'll learn how to integrate your application with over 40 OEM brands, securely connect to vehicles, and receive the dynamic vehicle data you need, delivered directly to your systems.

<CardGroup>
  <Card title="Start a tutorial" icon="play" href="/getting-started/tutorials/ios">Learn how to configure your first application and connect a vehicle in under 10 minutes.</Card>
  <Card title="Browse Available Data" href="/api-reference/signals/schema" icon="database">Explore the complete catalog of vehicle data points (signals) you can access.</Card>
  <Card title="Read How-To Guides" href="/getting-started/how-to/configure-permissions" icon="graduation-cap">Solve common implementation challenges with step-by-step instructions.</Card>

  <Card title="Connecting Vehicles" href="/getting-started/connect-vehicles" icon="mobile">
    Learn how to use our patented consent management authorization flow, to connect vehicles to your application.
  </Card>

  <Card title="Help Center" href="/help/what-is-smartcar" icon="life-ring">
    Visit our Help Center for FAQs, troubleshooting tips, and to contact support.
  </Card>

  <Card title="Integrations" href="/getting-started/integration-overview" icon="square-terminal">Dive deep into our Smartcar integrations and learn how to connect with various services.</Card>
  <Card title="Browse our SDKs" href="/connect/connect-sdks" icon="computer">Connect with other developers, share ideas, and get help.</Card>
</CardGroup>

Learn how to connect your app to Smartcar so you can access [vehicle data signals](/docs/api-reference/signals/schema) like odometer, location, battery level, issue vehicle commands, and more. In this guide, you'll register your app, walk through the Smartcar Connect flow, and configure a webhook to receive data.

By the end of this guide, you’ll have a working setup with access to a vehicle’s data through Smartcar’s platform.

## Prerequisites

Before you begin, you’ll need:

* A [Smartcar Account](https://dashboard.smartcar.com)
* Your Application ID and Secret (found in the [Smartcar Dashboard](https://dashboard.smartcar.com/configuration))
* An application with a redirect URI (e.g. a local development server or staging environment), required if you use the Authorization Code flow (`response_type=code`)

<Steps>
  <Step title="Step 1: Register & Configure Your Application">
    1. Log in or sign up via the [Smartcar Dashboard](https://dashboard.smartcar.com)
    2. Fill in your app name, description, and redirect URI in the configuration page of the dashboard. The redirect URI is needed if you use the Authorization Code flow (`response_type=code`).
    3. Copy your `Client ID` and `Client Secret` in a safe location. These credentials identify your app during the authorization process. **Do not commit your client secret to version control**.
    4. Select the data you want to access from vehicles by choosing the data signals (e.g. `odometer`, `location`, etc.).

    The necessary permissions will be derived from these signals and presented to your users.
  </Step>

  <Step title="Step 2: Start Connecting Vehicles via Smartcar Connect">
    [Smartcar Connect](/docs/connect) is an OAuth 2.0 consent flow that lets your users link their vehicles securely.

    The vehicle access tab in the Smartcar Dashboard will generate a Connect URL for you. You can also generate the URL programmatically using one of our SDKs.

    ```javascript theme={null}

    const link = new Smartcar.AuthClient({ //Smartcar frontend SDK
      clientId: 'YOUR_CLIENT_ID',
      redirectUri: 'YOUR_REDIRECT_URI',
      scope: ['read_vehicle_info', 'read_odometer'], // add other scopes as needed
      mode: 'live', // use 'simulated' for testing with simulated vehicles
    });

    window.location.href = link.getAuthUrl();
    ```

    This will take your user to the Smartcar Connect screen to authorize access.
  </Step>

  <Step title="Step 3: Get Your Application Access Token">
    Smartcar uses the OAuth 2.0 Client Credentials flow for API authentication. Your application exchanges its credentials for a single access token that works across all connected vehicles.

    ```bash theme={null}
    curl --request POST \
      --url https://iam.smartcar.com/oauth2/token \
      --header 'Content-Type: application/x-www-form-urlencoded' \
      --data 'grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET'
    ```

    You’ll receive:

    * `access_token`: used to make API calls to any connected vehicle
    * `expires_in`: token validity (1 hour)

    There is no refresh token — simply request a new token when the current one expires. See the [API Authentication Overview](/docs/api-reference/authorization/overview) for more details.
  </Step>

  <Step title="Step 4: Configure an Integration To Receive Vehicle Data">
    Our recommended method is to use webhooks, allowing you to choose triggers (e.g. location changes, battery state of charge changes) and the data to be sent upon those triggers.

    **Quick Start**: Deploy a production-ready webhook receiver in minutes with our [Webhook Receiver Recipe](/docs/getting-started/tutorials/webhook-receiver-recipe) - a complete AWS serverless solution.
  </Step>
</Steps>

#### What’s Next?

* [Learn how to configure your application](/docs/getting-started/configure-application).
* [Connect your first vehicle](/docs/getting-started/connect-vehicles).
* [Build your first integration](/docs/getting-started/integration-overview).
* [Make API requests directly over HTTP](/docs/getting-started/how-to/making-api-requests).

Need help? Visit our Support Portal or contact us at [support@smartcar.com](mailto:support@smartcar.com).

Let’s get building!


# Android Tutorial
Source: https://smartcar.com/docs/getting-started/tutorials/android

In this tutorial, we will use the Android SDK to integrate Connect into your application.

<Warning>
  Our frontend SDKs handle getting an authorization code representing a vehicle owner's consent for your application to interact with their vehicle
  for the requested permissions. In order to make requests to a vehicle, please use one of our [backend SDKs](/docs/api-reference/api-sdks).

  For security, token exchanges and requests to vehicles **should not** be made client side.
</Warning>

# Overview

<Frame type="simple">
  <img />
</Frame>

<br />

1. The Mobile Application launches a `Chrome Custom Tab` with Smartcar Connect to request access to a user’s vehicle.
   On Connect, the user logs in with their vehicle credentials and grants the Application access to their vehicle.
2. The `Chrome Tab` is redirected to a specified `REDIRECT_URI` along with a `user_id` and `state`.
   This will be the custom scheme set on the application. The Smartcar Android SDK receives the response in a view listening
   for the specified custom scheme URI, and passes it to the Mobile Application.
3. The Mobile Application sends the received `user_id` to the Application’s backend service for storage.
4. The Application’s backend authenticates with the Smartcar API using the [OAuth 2.0 Client Credentials flow](/docs/api-reference/authorization/overview) to obtain an application-level access token.
5. Using the access token and the `sc-user-id` header, the Application can now send requests to the Smartcar API. It can access protected resources and send commands
   to and from the user’s vehicle via the backend service.

# Prerequisites

* [Sign up](https://dashboard.smartcar.com/signup) for a Smartcar account.
* Make a note of your `CLIENT_ID` and `CLIENT_SECRET` from the **Configuration** section on the Dashboard.
* Add a custom scheme redirect URI to your application configuration.
* Add the `app_server` redirect URI from [Setup step 2.](/docs/getting-started/tutorials/android#setup) to your application configuration.

<Note>
  For Android, we require the custom URI scheme to be in the format of `sc` + `clientId` + `://` + `hostname`.
  For now, you can just set it to `sc` + `clientId` + `://exchange`.

  Please see our [Connect Docs](/docs/connect/dashboard-config#redirect-uris) for more information.
</Note>

# Setup

1. Clone our repo and install the required dependencies:
   ```bash theme={null}
   $git clone https://github.com/smartcar/getting-started-android-sdk.git
   ```
   <Note>
     Do not “checkout from version control” with the Getting Started repo in Android Studio, as it will not open the proper module.
   </Note>

2. Open `getting-started-android-sdk/tutorial` in Android Studio as an existing project and build from existing sources.
   Android Studio should automatically import the required dependencies and build gradle. We're setting `app_server` to `http://10.0.2.2:8000`
   to pass the authorization `code` from the [Handle the Response](/docs/getting-started/tutorials/android#handle-the-response) step later on in the tutorial to our backend.
   ```xml strings.xml theme={null}
   <string name="smartcar_auth_scheme">sc[yourClientId]</string>
   <string name="client_id">[yourClientId]</string>
   <string name="app_server">http://10.0.2.2:8000</string>
   ```

# Build your Connect URL

1. Instantiate a `smartcarAuth` object in the `onCreate` function of the `MainActivity`.
   ```java MainActivity.java theme={null}
   // TODO: Authorization Step 1a: Initialize the Smartcar object
   private static String CLIENT_ID;
   private static String REDIRECT_URI;
   private static String[] SCOPE;
   private SmartcarAuth smartcarAuth;

   protected void onCreate(Bundle savedInstanceState) {
       ...
       
       // TODO: Authorization Step 1b: Initialize the Smartcar object
       CLIENT_ID = getString(R.string.client_id);
       REDIRECT_URI = getString(R.string.smartcar_auth_scheme) + "://" + getString(R.string.smartcar_auth_host);
       SCOPE = new String[]{"required:read_vehicle_info"};
       
       smartcarAuth = new SmartcarAuth(
           CLIENT_ID,
           REDIRECT_URI,
           SCOPE,
           true,
           new SmartcarCallback() {
               // TODO: Authorization Step 3b: Receive an authorization code
           }
       );
   }
   ```

<Info>
  The Android SDK does not support `simulated` mode at this time - only `test` and `live`.
  Feel free to set `testMode` to `false` where you instantiate your `SmartcarAuth` object to
  connect to a real vehicle.
</Info>

2. The Android application will launch a Chrome Tab with Smartcar Connect to request access to a user’s vehicle.
   On Connect, the user logs in with the username and password for their vehicle’s connected services account and grants the application access to their vehicle.

   To launch Connect, we can use the `addClickHandler` function that our `smartcarAuth` object has access to.

   ```java MainActivity.java theme={null}
   // TODO: Authorization Step 2: Launch Connect
   smartcarAuth.addClickHandler(appContext, connectButton);
   ```

# Registering your Custom Scheme

Once a user has authorized the application to access their vehicle, the user is redirected to the `REDIRECT_URI` with an authorization `code` as a query parameter.

Android applications use custom URI schemes to intercept calls and launch the relevant application. This is defined within the `AndroidManifest`.

```xml AndroidManifest.xml theme={null}
<!-- TODO: Authorization Step 3a: Receive an authorization code -->
<activity android:name="com.smartcar.sdk.SmartcarCodeReceiver">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:host="@string/smartcar_auth_host"
            android:scheme="@string/smartcar_auth_scheme" />
    </intent-filter>
</activity>
```

# Handle the response

Using the Android SDK, the application can receive the code in the `SmartcarCallback` object passed into the `SmartcarAuth` object.

```java MainActivity.java theme={null}
smartcarAuth = new SmartcarAuth(
    CLIENT_ID,
    REDIRECT_URI,
    SCOPE,
    true,
    new SmartcarCallback() {
        // TODO: Authorization Step 3b: Receive an authorization code
        @Override
        public void handleResponse(final SmartcarResponse smartcarResponse) {
            Log.i("MainActivity", smartcarResponse.getCode());

            // TODO: Request Step 1: Obtain an access token

            //TODO: Request Step 2: Get vehicle information
        }
    }
);
```

# Launching Connect

Build your application in Android Studio and click on the **Connect your vehicle** button.

<Info>
  This tutorial configures Connect to launch in `test` mode by default.
  In `test` mode, any `username` and `password` is valid for each brand.
</Info>

Smartcar showcases all the permissions your application is asking for - `read_vehicle_info` in this case.
Once you have logged in and accepted the permissions, you should see your authorization `code` printed to your console.

# Sending the user\_id to your backend

After the user completes the Connect flow, your Android application receives a `user_id`. Send this to your backend service for storage — your backend will use it as the `sc-user-id` header when making API requests on behalf of this user.

```java MainActivity.java theme={null}
public void handleResponse(final SmartcarResponse smartcarResponse) {
    final String userId = smartcarResponse.getUserId();
    final OkHttpClient client = new OkHttpClient();

    new Thread(new Runnable() {
        @Override
        public void run() {
            // Send the user_id to your backend for storage
            Request connectRequest = new Request.Builder()
                .url(getString(R.string.app_server) + "/connect?user_id=" + userId)
                .post(RequestBody.create(null, new byte[0]))
                .build();

            try {
                client.newCall(connectRequest).execute();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }).start();
}
```

<Warning>
  Token authentication should be handled entirely on your backend using the [OAuth 2.0 Client Credentials flow](/docs/api-reference/authorization/overview).
  Your mobile app should never handle access tokens directly. The backend obtains a single application-level token
  that works across all connected vehicles.
</Warning>

# Getting data from a vehicle

Once your backend has the `user_id` and an application-level access token, it can send requests to a vehicle using the Smartcar API. The Android app will
have to send a request to the backend service which in turn sends a request to Smartcar. We have to do this because
our frontend **does not** have the access token.

Assuming our backend has a `/vehicle` endpoint that returns the information of a user’s vehicle, we can make this query in
our `completion callback` and start another `activity` to show the returned vehicle attributes.

```java MainActivity.java theme={null}
public void handleResponse(final SmartcarResponse smartcarResponse) {
    ...

    // TODO: Request Step 2: Get vehicle information

    // send request to retrieve the vehicle info
    Request infoRequest = new Request.Builder()
        .url(getString(R.string.app_server) + "/vehicle")
        .build();

    try {
        Response response = client.newCall(infoRequest).execute();

        String jsonBody = response.body().string();
        JSONObject JObject = new JSONObject(jsonBody);

        String make = JObject.getString("make");
        String model = JObject.getString("model");
        String year = JObject.getString("year");

        Intent intent = new Intent(appContext, DisplayInfoActivity.class);
        intent.putExtra("INFO", make + " " + model + " " + year);
        startActivity(intent);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (JSONException e) {
        e.printStackTrace();
    }
}
```

# Setting up your backend

Now that our frontend is complete, we will need to create a backend service that stores the `user_id` and handles API authentication. Your backend will use the [OAuth 2.0 Client Credentials flow](/docs/api-reference/authorization/overview) to obtain an application-level access token and make requests to vehicles.
You can use any of our backend SDKs below to set up the service.

<Note>
  When setting up the environment variables for your  backend SDK, make sure to set `REDIRECT_URI` to the custom scheme
  used for this tutorial i.e. `sc + "clientId" + ://exchange`.
</Note>

<Snippet />


# iOS Tutorial
Source: https://smartcar.com/docs/getting-started/tutorials/ios

In this tutorial, we will use the iOS SDK to integrate Connect into your application.

<Warning>
  Our frontend SDKs handle getting an authorization code representing a vehicle owner's consent for your application to interact with their vehicle
  for the requested permissions. In order to make requests to a vehicle, please use one of our [backend SDKs](/docs/api-reference/api-sdks).

  For security, token exchanges and requests to vehicles **should not** be made client side.
</Warning>

<br />

# Overview

<Frame type="simple">
  <img />
</Frame>

<br />

1. The Mobile Application launches a `SafariView` with Smartcar Connect to request access to a user’s vehicle.
   On Connect, the user logs in with their vehicle credentials and grants the Application access to their vehicle.
2. The `SafariView` is redirected to a specified `REDIRECT_URI` along with a `user_id` and `state`.
   This will be the custom scheme set on the application. The Smartcar iOS SDK receives the response in a view listening
   for the specified custom scheme URI, and passes it to the Mobile Application.
3. The Mobile Application sends the received `user_id` to the Application’s backend service for storage.
4. The Application’s backend authenticates with the Smartcar API using the [OAuth 2.0 Client Credentials flow](/docs/api-reference/authorization/overview) to obtain an application-level access token.
5. Using the access token and the `sc-user-id` header, the Application can now send requests to the Smartcar API. It can access protected resources and send commands
   to and from the user’s vehicle via the backend service.

# Prerequisites

* [Sign up](https://dashboard.smartcar.com/signup) for a Smartcar account.
* Make a note of your `CLIENT_ID` and `CLIENT_SECRET` from the **Configuration** section on the Dashboard.
* Add a custom scheme redirect URI to your application configuration.
* Add the `appServer` redirect URI from [step 2](/docs/getting-started/tutorials/ios/#setup) below to your application configuration.

<Note>
  For iOS, we require the custom URI scheme to be in the format of `sc` + `clientId` + `://` + `hostname`.
  For now, you can just set it to `sc` + `clientId` + `://exchange`.

  Please see our [Connect Docs](/docs/connect/dashboard-config#redirect-uris) for more information.
</Note>

# Setup

1. Clone our repo and install the required dependencies:
   ```bash theme={null}
   $git clone https://github.com/smartcar/getting-started-ios-sdk.git
   $cd getting-started-ios-sdk/tutorial
   $pod install
   $open getting-started-ios-sdk.xcworkspace
   ```
2. Set the following constants in `Constants.swift`. We're setting `appServer` to `http://localhost:8000` to pass the authorization `code` from
   the [Handle the Response](/docs/getting-started/tutorials/ios#handle-the-response) step later on in the tutorial to our backend.
   ```swift Constants.swift theme={null}
   struct Constants {
       static let clientId = "<your-client-id>";
       static let appServer = "http://localhost:8000";
   }
   ```

# Build your Connect URL

Instantiate a `SmartcarAuth` object in the `viewdidLoad` function of the `ViewController`.
The iOS application will launch a `WebView` with Connect to request access to a user’s vehicle.
On Connect, the user logs in with the username and password for their vehicle’s connected services account
and grants the application access to their vehicle.

To launch Connect, we can use the `launchAuthFlow` function that our `SmartcarAuth` object has access to. We can place
this within the `connectPressed` action function.

```swift ViewController.swift theme={null}
let appDelegate = UIApplication.shared.delegate as! AppDelegate

func completionHandler(code: String?, state: String?, virtualKeyUrl: String?, err: AuthorizationError?,) -> Void {
// Receive authorization code
}

appDelegate.smartcar = SmartcarAuth(
  clientId: "afb0b7d3-807f-4c61-9b04-352e91fe3134",
  redirectUri: "scafb0b7d3-807f-4c61-9b04-352e91fe3134://exchange",
  scope: ["read_vin", "read_vehicle_info", "read_odometer"],
  mode: SCMode.simulated, //use SCMode.live to connect to a real vehicles
  completionHandler: completionHandler
)
let smartcar = appDelegate.smartcar

// Generate a Connect URL
let authUrl = smartcar.authUrlBuilder().build()

// Pass in the generated Connect URL and a UIViewController
smartcar.launchAuthFlow(url: authUrl, viewController: viewController)
```

<br />

# Registering your Custom Scheme

Once a user has authorized the application to access their vehicle, the user is redirected to the `REDIRECT_URI` with an authorization code as a query parameter.

iOS applications use custom URI schemes to intercept calls and launch the relevant application. This is defined within the `Info.plist`.

1. Open up `Info.plist` and click on the grey arrow next to **URL types**.
2. Next, click on the grey arrow next to the `Item 0` dictionary and `URL Schemes` array.
3. Finally, set your `Item 0` string to the redirect URI you set up in the [Prerequisites](/docs/getting-started/tutorials/ios#prerequisites) section (i.e. 'sc' + clientId).

<Frame>
  <img />
</Frame>

<br />

# Handle the response

1. The iOS application will now receive the request in the `application:(_:open:options:)` function within the AppDelegate.
   ```swift AppDelegate.swift theme={null}
   func application(_ application: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
       {/* TODO: Authorization Step 3a: Receive the authorization code */}
       window!.rootViewController?.presentedViewController?.dismiss(animated: true , completion: nil)
       smartcar!.handleCallback(with: url)
       
       return true
   }
   ```
2. Using the iOS SDK, the application can receive the code in the `completion callback` passed into the `SmartcarAuth` object.
   ```swift AppDelegate.swift theme={null}
   func completion(err: Error?, code: String?, state: String?) -> Any {
       {/* TODO: Authorization Step 3b: Receive the authorization code */}
       print(code!);
       {/* prints out the authorization code */}
   }
   ```

# Launching Connect

Build your application in XCode and click on the **Connect your vehicle** button.

<Info>
  This tutorial configures Connect to launch in `test` mode by default.
  In `test` mode, any `username` and `password` is valid for each brand.
</Info>

Smartcar showcases all the permissions your application is asking for - `read_vehicle_info` in this case.
Once you have logged in and accepted the permissions, you should see your authorization `code` printed to your console.

# Sending the user\_id to your backend

After the user completes the Connect flow, your iOS application receives a `user_id`. Send this to your backend service for storage — your backend will use it as the `sc-user-id` header when making API requests on behalf of this user.

```swift ViewController.swift theme={null}
// Send the user_id to your backend for storage
Alamofire.request("\(Constants.appServer)/connect?user_id=\(userId!)", method: .post)
    .responseJSON {_ in}
```

<Warning>
  Token authentication should be handled entirely on your backend using the [OAuth 2.0 Client Credentials flow](/docs/api-reference/authorization/overview).
  Your mobile app should never handle access tokens directly. The backend obtains a single application-level token
  that works across all connected vehicles.
</Warning>

# Getting data from a vehicle

Once your backend has the `user_id` and an application-level access token, it can send requests to a vehicle using the Smartcar API. The iOS app will
have to send a request to the backend service which in turn sends a request to Smartcar. We have to do this because
our frontend **does not** have the access token.

Assuming our backend has a `/vehicle` endpoint that returns the information of a user’s vehicle, we can make this query in
our `completion callback` and segue into another `view` to show the returned vehicle attributes.

```swift ViewController.swift theme={null}
func completion(err: Error?, code: String?, state: String?) -> Any {

    // send user_id to backend for storage
    Alamofire.request("\(Constants.appServer)/connect?user_id=\(userId!)", method: .post).responseJSON {_ in

        // TODO: Request Step 2: Get vehicle information
        // send request to retrieve the vehicle info
        Alamofire.request("\(Constants.appServer)/vehicle", method: .get).responseJSON { response in
            print(response.result.value!)

            if let result = response.result.value {
                let JSON = result as! NSDictionary

                let make = JSON.object(forKey: "make")!  as! String
                let model = JSON.object(forKey: "model")!  as! String
                let year = String(JSON.object(forKey: "year")!  as! Int)

                let vehicle = "\(year) \(make) \(model)"
                self.vehicleText = vehicle

                self.performSegue(withIdentifier: "displayVehicleInfo", sender: self)
            }
        }
    }

    return ""
}
```

# Setting up your backend

Now that our frontend is complete, we will need to create a backend service that stores the `user_id` and handles API authentication. Your backend will use the [OAuth 2.0 Client Credentials flow](/docs/api-reference/authorization/overview) to obtain an application-level access token and make requests to vehicles.
Call the Smartcar API directly over HTTP, no backend SDK required. The examples below show how to get an access token in each language.

<CardGroup>
  <Card title="Java" icon="java" href="/getting-started/how-to/making-api-requests#get-an-access-token" />

  <Card title="Node.js" href="/getting-started/how-to/making-api-requests#get-an-access-token" icon="node-js" />

  <Card title="Python" icon="python" href="/getting-started/how-to/making-api-requests#get-an-access-token" />

  <Card title="Ruby" href="/getting-started/how-to/making-api-requests#get-an-access-token" icon="gem" />
</CardGroup>


# React Tutorial
Source: https://smartcar.com/docs/getting-started/tutorials/react

In this tutorial, we will use the JavaScript SDK to integrate Connect into your application.

<Warning>
  Our frontend SDKs handle getting an authorization code representing a vehicle owner's consent for your application to interact with their vehicle
  for the requested permissions. In order to make requests to a vehicle, please use one of our [backend SDKs](/docs/api-reference/api-sdks).

  For security, token exchanges and requests to vehicles **should not** be made client side.
</Warning>

<br />

# Overview

<Frame type="simple">
  <img />
</Frame>

<br />

1. The Single-Page Application launches a pop-up window with Smartcar Connect to request access to a user’s vehicle.
   It does so by using the Smartcar JavaScript SDK. On Connect, the user logs in with the username and password for
   their vehicle’s connected services account and grants the Application access to their vehicle.
2. The user’s browser is redirected to a specified Smartcar-hosted `REDIRECT_URI` - the Smartcar JavaScript SDK redirect page.
3. The Smartcar JavaScript SDK redirect page will receive a `user_id` and `state` as query parameters. The redirect page will then
   send these to the Single-Page Application’s `onComplete` callback using the `postMessage` web API. **This step is handled entirely
   by the JavaScript SDK.**
4. The Single-Page Application sends the received `user_id` to the Application’s backend service for storage.
5. The Application’s backend authenticates with the Smartcar API using the [OAuth 2.0 Client Credentials flow](/docs/api-reference/authorization/overview) to obtain an application-level access token.
6. Using the access token and the `sc-user-id` header, the Application can now send requests to the Smartcar API. It can access protected resources and send commands
   to and from the user’s vehicle via the backend service.

# Prerequisites

* [Sign up](https://dashboard.smartcar.com/signup) for a Smartcar account.
* Make a note of your `CLIENT_ID` and `CLIENT_SECRET` from the **Configuration** section on the Dashboard.
* Add the special JavaScript SDK redirect URI to your application configuration.
* Add the `REACT_APP_SERVER` redirect URI from [Setup step 2.](/docs/getting-started/tutorials/react#setup) to your application configuration.

<Note>
  To use the JavaScript SDK, we require the special redirect URI to provide a simpler flow to retrieve authorization codes.
  For this tutorial you can use the following:

  `https://javascript-sdk.smartcar.com/v2/redirect?app_origin=http://localhost:3000`
</Note>

# Setup

1. Clone our repo and install the required dependencies:
   ```bash theme={null}
   $git clone https://github.com/smartcar/getting-started-javascript-sdk-react.git
   $cd getting-started-javascript-sdk-react/tutorial
   $npm install
   ```
2. Set the following environment variables. We will be setting up a server later for our React front-end to communicate with.
   For now, let’s assume our server is listening on `http://localhost:8000`.
   ```bash theme={null}
   $export REACT_APP_CLIENT_ID=<your-client-id>
   $export REACT_APP_REDIRECT_URI= https://javascript-sdk.smartcar.com/v2/redirect?app_origin=http://localhost:3000
   $export REACT_APP_SERVER=http://localhost:8000
   ```

<Note>
  Note: If you are using Windows, ensure you are appropriately setting environment variables for your shell.
  Please refer to this post which details how to set environment variables on Windows.
</Note>

# Build your Connect URL

1. Instantiate a `Smartcar` object in the `constructor` of the App component.
   ```js App.jsx theme={null}
   constructor(props) {
   ...
   // TODO: Authorization Step 1: Initialize the Smartcar object
   this.smartcar = new Smartcar({
       clientId: process.env.REACT_APP_CLIENT_ID,
       redirectUri: process.env.REACT_APP_REDIRECT_URI,
       scope: ['required:read_vehicle_info'],
       mode: 'test',
       onComplete: this.onComplete,
   });
   }
   ```

<Snippet />

2. A single-page application will launch a pop-up window with Smartcar Connect to request access to a user’s vehicle.
   On Connect, the user logs in with the username and password for their vehicle’s connected services account and grants
   the application access to their vehicle.

   To launch Connect, we can use the `openDialog` function that our `Smartcar` object has access to. We can place this is
   an `onClick` handler of an HTML button.

   ```js App.jsx theme={null}
   authorize() {
       // TODO: Authorization Step 2a: Launch Connect
       this.smartcar.openDialog({forcePrompt: true});
   }

   render() {
       // TODO: Authorization Step 2b: Render the Connect component
       return <Connect onClick={this.authorize} />;
   }
   ```

# Handle the response

1. Once a user has authorized the application to access their vehicle, the user is redirected to the `redirect_uri` with an
   authorization code as a query parameter and the pop-up dialog is closed. Using the JavaScript SDK, the frontend can
   receive this `code` in the `onComplete` callback passed into the `Smartcar` object.
   ```js App.jsx theme={null}
   onComplete(err, code, status) {
       //TODO: Authorization Step 3: Receive the authorization code
       console.log(code);
       //prints out the authorization code
   };
   ```

# Launching Connect

Restart your server, open up your browser and go to `http://localhost:3000/login`. You should be reciderect to Smartcar Connect.

<Info>
  This tutorial configures Connect to launch in `test` mode by default.
  In `test` mode, any `username` and `password` is valid for each brand.
</Info>

Smartcar showcases all the permissions your application is asking for - `read_vehicle_info` in this case.
Once you have logged in and accepted the permissions, you should see your authorization `code` printed to your console.

# Sending the user\_id to your backend

After the user completes the Connect flow, the React application receives a `user_id`. Send this to your backend service for storage — your backend will use it as the `sc-user-id` header when making API requests on behalf of this user.

<Warning>
  Token authentication should be handled entirely on your backend using the [OAuth 2.0 Client Credentials flow](/docs/api-reference/authorization/overview).
  Your frontend should never handle access tokens directly. The backend obtains a single application-level token
  that works across all connected vehicles.
</Warning>

We can add this logic in our `onComplete` callback:

```js App.jsx theme={null}
onComplete(err, userId, status) {
  // Send the user_id to your backend for storage
  return axios
    .post(`${process.env.REACT_APP_SERVER}/connect`, { user_id: userId });
}

```

# Getting data from a vehicle

Once your backend has the `user_id` and an application-level access token, it can send requests to a vehicle using the Smartcar API. The React app will
have to send a request to the backend service which in turn sends a request to Smartcar. We have to do this because
our frontend does not have the access token.

Assuming our backend has a `/vehicle` endpoint that returns the information of a user’s vehicle, we can make this query in
our `completion callback` and set the state of the React app with the returned vehicle attributes.

```js App.jsx theme={null}
onComplete(err, userId, status) {
  // Send user_id to backend, then fetch vehicle info
  return axios
    .post(`${process.env.REACT_APP_SERVER}/connect`, { user_id: userId })
    .then(_ => {
      return axios.get(`${process.env.REACT_APP_SERVER}/vehicle`);
    })
    .then(res => {
      this.setState({vehicle: res.data});
    });
}

```

Now that we have the vehicle attributes, we can render a simple Vehicle component that shows the vehicle attributes in a table.

```js App.jsx theme={null}
render() {
  // TODO: Request Step 2b: Get vehicle information
  return Object.keys(this.state.vehicle).length !== 0 ? (
    <Vehicle info={this.state.vehicle} />
  ) : (
    <Connect onClick={this.authorize} />
  );
}
```

# Setting up your backend

Now that our frontend is complete, we will need to create a backend service that stores the `user_id` and handles API authentication. Your backend will use the [OAuth 2.0 Client Credentials flow](/docs/api-reference/authorization/overview) to obtain an application-level access token and make requests to vehicles.
You can use any of our backend SDKs below to set up the service.

<Note>
  When setting up the environment variables for your  backend SDK, make sure to set `REDIRECT_URI` to the custom scheme
  used for this tutorial i.e. `https://javascript-sdk.smartcar.com/v2/redirect?app_origin=http://localhost:3000`.
</Note>

<Snippet />


# Webhook Receiver Recipe
Source: https://smartcar.com/docs/getting-started/tutorials/webhook-receiver-recipe

Deploy a production-ready AWS serverless webhook receiver in minutes using our complete TypeScript template with built-in validation, error handling, and scalability.

<Info>
  **Quick Start**: Deploy a complete webhook receiver to AWS in under 10 minutes with our battle-tested TypeScript recipe. Perfect for production workloads and new webhook implementations.
</Info>

## Overview

The Webhook Receiver Recipe is a production-ready, AWS-based webhook receiver template that helps developers quickly implement robust webhook handling for Smartcar integrations. This TypeScript recipe provides a deployable starting point that makes adding custom business logic easy, eliminating much of the complexity of building webhook infrastructure from scratch.

* **Repository**: [`smartcar/typescript-webhook-recipe`](https://github.com/smartcar/typescript-webhook-recipe)
* **Deployment Target**: AWS (Lambda + API Gateway + SQS)
* **Language**: TypeScript/Node.js v22+
* **Infrastructure**: AWS CDK (Infrastructure as Code)

## What You Get

### Complete Serverless Architecture

* **API Gateway**: Public HTTPS endpoint for webhook delivery
* **Lambda Functions**: Serverless processing with automatic scaling
* **SQS Queues**: Asynchronous message processing with built-in retry logic
* **Dead Letter Queues**: Error handling and failed message recovery
* **CloudWatch**: Comprehensive logging and monitoring

### Production-Ready Features

* **Webhook Verification**: Automatic payload signature validation
* **Error Handling**: Graceful failure handling with retries
* **Scalability**: Automatic scaling to handle traffic spikes
* **Security**: IAM roles with least-privilege access
* **Monitoring**: Built-in CloudWatch logging
* **Type Safety**: Full TypeScript support with Smartcar types

### Infrastructure as Code

* Complete AWS CDK setup for repeatable deployments
* Environment-specific configurations (development, staging, production)
* Easy customization and extension

## When to Use This Recipe

**Perfect for:**

* New webhook receiver implementations
* Teams using AWS as your cloud provider
* Production workloads requiring reliability and scale
* Teams wanting to deploy quickly without infrastructure complexity
* TypeScript/Node.js projects

## Architecture Overview

The recipe provides a complete serverless webhook receiver infrastructure on AWS. The diagram below shows the data flow from Smartcar webhooks through your deployment:

```mermaid theme={null}
graph TD
    A[Smartcar Webhooks] -->|HTTPS POST| B[API Gateway]
    B --> C[Receiver Lambda]
    C -->|Validate & Queue| D[SQS Queue]
    D --> E[Processor Lambda]
    E -->|Process Signals| F[Your Business Logic]
    E -->|Failed Processing| G[Dead Letter Queue]
    G --> H[Manual Review/Retry]
    
    style A fill:#FFB84D,stroke:#E69500,stroke-width:2px,color:#000
    style B fill:#FF9900,stroke:#CC7A00,stroke-width:2px,color:#000
    style C fill:#FF9900,stroke:#CC7A00,stroke-width:2px,color:#000
    style D fill:#FF9900,stroke:#CC7A00,stroke-width:2px,color:#000
    style E fill:#FF9900,stroke:#CC7A00,stroke-width:2px,color:#000
    style F fill:#d3d3d3,stroke:#666,stroke-width:2px,color:#000
    style G fill:#FF9900,stroke:#CC7A00,stroke-width:2px,color:#000
    style H fill:#d3d3d3,stroke:#666,stroke-width:2px,color:#000
```

<Note>
  **Orange components** are provided by the recipe and deployed automatically. **Gray components** represent external systems where your custom business logic would live.
</Note>

### Key Components

1. **Receiver Lambda**: Validates incoming webhooks and queues them for processing
2. **SQS Queue**: Decouples receiving from processing for reliability
3. **Processor Lambda**: Processes webhook payloads and executes business logic
4. **Dead Letter Queue**: Captures failed messages for investigation
5. **CloudWatch**: Monitoring, logging, and alerting

## Quick Start

### Prerequisites

* AWS Account with CLI configured
* Node.js v22+ installed
* Git
* **Smartcar Application** configured in the [Dashboard](https://dashboard.smartcar.com/)
  * You'll need your **Application Management Token** (found in Dashboard → Configuration)
  * Learn how to [configure your application](/docs/getting-started/configure-application)

### Deployment Steps

<Steps>
  <Step title="Clone the Repository">
    ```bash theme={null}
    git clone https://github.com/smartcar/typescript-webhook-recipe.git
    cd typescript-webhook-recipe
    ```
  </Step>

  <Step title="Build the Project">
    ```bash theme={null}
    make build
    ```
  </Step>

  <Step title="Deploy to AWS">
    The recipe uses AWS CDK for infrastructure deployment. First, create a secret to store your Application Management Token, then deploy the stack.

    ```bash theme={null}
    # Step 1: Create the secret for your Application Management Token
    make create-secret appName=your-app-name amt=your_smartcar_application_management_token

    # Step 2: Deploy the infrastructure
    make deploy appName=your-app-name

    # Note the ApiEndpointUrl from the output
    # Example: https://abc123.execute-api.us-east-1.amazonaws.com/prod/
    ```

    <Note>
      Use the same `appName` value for both commands. This name will be used to identify your CloudFormation stack and associated resources.
    </Note>

    For detailed deployment instructions including environment-specific configuration, see the [GitHub repository README](https://github.com/smartcar/typescript-webhook-recipe#usage).
  </Step>

  <Step title="Configure Webhook in Dashboard">
    Now that your receiver is deployed, configure the webhook integration in Smartcar Dashboard:

    1. Go to your [Smartcar Dashboard](https://dashboard.smartcar.com/integrations)
    2. Click **+ Add Integration** and select **Webhooks**
    3. Configure your webhook:
       * **Webhook URL**: Use the deployed URL from the previous step
       * **Trigger**: Choose when to send webhooks (e.g., "State of charge changes")
       * **Signals**: Select the vehicle data you want to receive (e.g., battery level, location, odometer)
    4. Click **Save** - Smartcar will automatically verify your endpoint

    <Note>
      The recipe automatically handles webhook verification. If verification fails, check CloudWatch logs for errors.
    </Note>

    For detailed webhook configuration guidance, see [Webhooks Setup](/docs/integrations/webhooks/overview).
  </Step>

  <Step title="Subscribe Vehicles (Optional)">
    Depending on your webhook configuration, you may need to manually subscribe vehicles:

    * **Auto-subscribe enabled**: New vehicle connections will automatically start sending webhook data
    * **Manual subscription**: Use the [Subscribe endpoint](/docs/api-reference/webhooks/subscribe-webhook) or Dashboard to subscribe specific vehicles

    Learn more about [subscribing vehicles to webhooks](/docs/integrations/webhooks/overview#subscribing-vehicles-to-a-webhook).
  </Step>
</Steps>

<Note>
  The deployment typically takes 2-3 minutes. The recipe will output your webhook URL and other important configuration details upon completion.
</Note>

## Customizing Your Webhook Processor

The recipe includes a sample processor that logs webhook data. To implement your business logic:

<CodeGroup>
  ```typescript src/lambdas/sqs/index.ts theme={null}
  import { Logger } from '@aws-lambda-powertools/logger';
  import { getSignalByCode, Signals, type TractionBatteryStateOfCharge } from "@smartcar/signals";
  import type { WebhookDataPayload } from '@smartcar/webhooks';
  import { parseEnvelope } from '@smartcar/webhooks';
  import { Context, SQSEvent, SQSHandler } from 'aws-lambda';

  const logger = new Logger();

  export const processor: SQSHandler = async (
    event: SQSEvent,
    context: Context
  ) => {
    const batchItemFailures: { itemIdentifier: string }[] = [];

    for (const record of event.Records) {
      try {
        const eventBody: WebhookDataPayload = parseEnvelope(record.body);
        const signals: Signals = eventBody.data.signals as Signals;
        const { errors } = eventBody.data;

        // Example: Process signals data
        if (signals && signals.length > 0) {
          const stateOfChargeSignal: TractionBatteryStateOfCharge | undefined = 
            getSignalByCode<TractionBatteryStateOfCharge>(signals, 'tractionbattery-stateofcharge');
          
          if (stateOfChargeSignal) {
            logger.info('State of Charge Signal', stateOfChargeSignal.body);
            
            // Replace with your business logic
            if (stateOfChargeSignal.body.value < 50) {
              logger.info('Battery below 50% - get charged!');
            }
          }
        }
        
        // Handle errors in webhook payload
        if (errors && errors.length > 0) {
          logger.warn('Errors in webhook payload', { errors });
        }
      } catch (err) {
        logger.error('Error during processing', { error: err, record });
        batchItemFailures.push({ itemIdentifier: record.messageId });
      }
    }

    return { batchItemFailures };
  };
  ```

  ```typescript External API Integration theme={null}
  // Example: Send data to external service
  async function sendToExternalAPI(payload: WebhookPayload) {
    const response = await fetch('https://your-api.com/webhook-data', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${process.env.API_TOKEN}`
      },
      body: JSON.stringify(payload)
    });
    
    if (!response.ok) {
      throw new Error(`API call failed: ${response.statusText}`);
    }
  }
  ```
</CodeGroup>

## Configuration Options

The recipe uses AWS CDK for infrastructure configuration. You can customize various aspects by modifying the CDK stack configuration in `lib/webhook-receiver-stack.ts`.

### Common Configuration Options

Use these CDK properties (not environment variables) to tune the stack. Their camelCase names match the props in `lib/webhook-receiver-stack.ts`.

| Configuration       | Description                             | Example                                                                                                                                              |
| ------------------- | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `logLevel`          | Logging verbosity for Lambda functions  | [See example](https://github.com/smartcar/typescript-webhook-recipe/blob/61485696ed459ee21ed5aa9d967373f5ecee651f/lib/webhook-receiver-stack.ts#L46) |
| `memorySize`        | Lambda function memory allocation in MB | [See example](https://github.com/smartcar/typescript-webhook-recipe/blob/61485696ed459ee21ed5aa9d967373f5ecee651f/lib/webhook-receiver-stack.ts#L41) |
| `visibilityTimeout` | SQS message visibility timeout          | [See example](https://github.com/smartcar/typescript-webhook-recipe/blob/61485696ed459ee21ed5aa9d967373f5ecee651f/lib/webhook-receiver-stack.ts#L29) |
| `maxReceiveCount`   | Max retries before dead letter queue    | [See example](https://github.com/smartcar/typescript-webhook-recipe/blob/61485696ed459ee21ed5aa9d967373f5ecee651f/lib/webhook-receiver-stack.ts#L30) |

For environment-specific configurations (dev, staging, production), you'll define these in your CDK code rather than using environment variables. This allows you to manage infrastructure differences across environments programmatically.

See the [GitHub repository](https://github.com/smartcar/typescript-webhook-recipe) for detailed configuration examples.

## Monitoring and Troubleshooting

### CloudWatch Logging

The recipe includes built-in CloudWatch logging for debugging and monitoring. You can:

* View Lambda execution logs
* Track webhook deliveries and failures
* Monitor SQS queue metrics

<Note>
  CloudWatch alarms are not included by default. You can add custom alarms on top of CloudWatch metrics based on your monitoring needs.
</Note>

### Common Issues

<AccordionGroup>
  <Accordion title="Webhook verification failing">
    * Check that your Smartcar Application Management Token is correct
    * Verify the webhook URL matches your deployed endpoint
    * Check CloudWatch logs for verification errors
  </Accordion>

  <Accordion title="Messages stuck in dead letter queue">
    * Review CloudWatch logs for processing errors
    * Check if external services (databases, APIs) are accessible
    * Verify IAM permissions for Lambda functions
  </Accordion>

  <Accordion title="High latency or timeouts">
    * Consider increasing Lambda memory allocation in CDK configuration
    * Optimize external API calls and database queries
    * Check for cold start issues in Lambda functions
  </Accordion>
</AccordionGroup>

### Debugging Commands

```bash theme={null}
# Monitor queue depths
aws sqs get-queue-attributes --queue-url <queue-url> --attribute-names ApproximateNumberOfMessages

# Redrive messages from dead letter queue
aws sqs receive-message --queue-url <dlq-url> --max-number-of-messages 10
```

## Next Steps

After deploying your webhook receiver:

1. **Test Your Integration**: Use the [Smartcar Dashboard](https://dashboard.smartcar.com/) to test webhook delivery
2. **Monitor Performance**: Set up CloudWatch alarms for error rates and queue depths
3. **Scale as Needed**: Adjust Lambda memory and SQS settings based on usage patterns
4. **Add Features**: Extend the processor logic for your specific use cases

## Support and Contributing

* **Issues**: Report bugs or request features in the [GitHub repository](https://github.com/smartcar/typescript-webhook-recipe/issues)
* **Discussions**: Ask questions in [GitHub Discussions](https://github.com/smartcar/typescript-webhook-recipe/discussions)
* **Documentation**: Full setup and customization details in the [repository README](https://github.com/smartcar/typescript-webhook-recipe#readme)

***

<CardGroup>
  <Card title="Repository" icon="github" href="https://github.com/smartcar/typescript-webhook-recipe">
    View the complete source code and documentation
  </Card>

  <Card title="Webhook Responses" icon="webhook" href="/integrations/webhooks/receiving-webhooks">
    Understand webhook payload structures
  </Card>
</CardGroup>


# Testing with Postman
Source: https://smartcar.com/docs/getting-started/using-vs-with-postman

Use the Smartcar Postman collection and a simulated vehicle to make your first API requests without a real car.

Postman is an API client that lets you send requests and inspect responses without writing any code. Pair it with a [simulated vehicle](/docs/getting-started/dashboard/simulator) and you can exercise the whole Smartcar API, including commands and webhooks, before you connect a real vehicle.

By the end of this guide you will have an access token, a simulated vehicle, and a working request that returns vehicle data.

## What you'll need

* A [Postman account](https://identity.getpostman.com/signup) and the [Postman app](https://www.postman.com/downloads/)
* A [Smartcar Dashboard account](https://dashboard.smartcar.com/signup)
* An application on the v3 API. See [API Authentication Setup](/docs/getting-started/how-to/api-authentication) if you aren't sure.

## Step 1: Fork the collection and environment

Smartcar publishes both a collection and an environment in the [Smartcar API workspace](https://www.postman.com/smartcar/smartcar-api) on the Postman API Network.

<Steps>
  <Step title="Fork the collection">
    Open the [Smartcar API Collection](https://www.postman.com/smartcar/smartcar-api/collection/btrmn6x/smartcar-api-collection) and select **Fork** to copy it into your own workspace.
  </Step>

  <Step title="Fork the environment">
    Do the same for the **SmartcarApi Variables** environment in that workspace. It holds the base URLs plus the placeholders you fill in below.
  </Step>

  <Step title="Select the environment">
    In Postman, choose **SmartcarApi Variables** from the environment selector. Requests fail with unresolved `{{variable}}` errors if no environment is selected.
  </Step>
</Steps>

The environment defines these variables:

| Variable                                                    | Description                                           |
| ----------------------------------------------------------- | ----------------------------------------------------- |
| `clientId`                                                  | Your application's client ID                          |
| `clientSecret`                                              | A client secret you generate in the Dashboard         |
| `accessToken`                                               | Set automatically when you run **Client Credentials** |
| `vehicleId`                                                 | The vehicle you want to query                         |
| `userId`                                                    | The user the vehicle is connected to                  |
| `iamUrl`, `vehicleUrl`, `managementUrl`, `compatibilityUrl` | Smartcar base URLs, prefilled                         |

## Step 2: Add your API credentials

In the [Smartcar Dashboard](https://dashboard.smartcar.com), go to **Configuration > API credentials**. Copy your **Client ID**, then generate a **Client Secret**.

<Frame type="simple">
  <img alt="API credentials tab in the Smartcar Dashboard Configuration page" />
</Frame>

Paste both values into the `clientId` and `clientSecret` variables in your Postman environment.

<Warning>
  The client secret is shown only once, and it grants access to every vehicle connected to your application. Store it somewhere secure and never commit it or share a Postman workspace that contains it.
</Warning>

## Step 3: Get an access token

Run the **Client Credentials** request. It posts your credentials to the token endpoint and returns an application-level access token:

```json theme={null}
{
  "access_token": "{access_token}",
  "token_type": "Bearer",
  "expires_in": 3600
}
```

The request has a test script that writes `access_token` into the `accessToken` environment variable, so every other request in the collection picks it up automatically.

<Note>
  Access tokens are valid for **1 hour** and there is no refresh token. When requests start failing, run **Client Credentials** again. See [Request an access token](/docs/api-reference/authorization/request-access-token) for the full reference.
</Note>

## Step 4: Create a simulated vehicle

In the Dashboard, open the **Simulator** tab and select **Add simulated vehicle**. Choose a powertrain type, give the vehicle a name, and leave **Automatically connect to application** enabled so the vehicle is ready to query straight away.

<Frame type="simple">
  <img alt="Add simulated vehicle modal in the Smartcar Dashboard" />
</Frame>

The powertrain type you pick (BEV, PHEV, HEV, or ICE) determines which signals and commands are available. Simulated vehicles are granted all compatible permissions by default.

Once the vehicle is created, copy its **Vehicle ID** and **User ID** from the Simulator table into the `vehicleId` and `userId` environment variables in Postman.

<Note>
  Simulated vehicles appear in your connections and logs with `Simulated` as the make and the powertrain type as the model, for example `2023 Simulated BEV`.
</Note>

## Step 5: Confirm the connection

Run the **Connections** request to list the vehicles connected to your application. To see only simulated vehicles, enable the `filter[vehicle.mode]` query parameter and set it to `simulated`.

Your new vehicle should appear with the same ID you copied in the previous step. If it doesn't, the vehicle was likely created in a disconnected state, so connect it from the Simulator before continuing.

## Step 6: Read vehicle data

With `accessToken`, `vehicleId`, and `userId` all set, run:

* **Vehicle** to get the vehicle's details
* **Signals** to read every signal the vehicle exposes
* **Signal** to read one signal, for example `charge-chargetimers`

Signal requests send the user's ID in the `sc-user-id` header, which the collection populates from `{{userId}}`. A request that returns an authorization error is usually missing that variable.

## Step 7: Send a command

Simulated vehicles support these commands:

* [Lock and unlock](/docs/api-reference/control-lock-unlock)
* [Start and stop charge](/docs/api-reference/evs/control-charge)
* [Set charge limit](/docs/api-reference/evs/set-charge-limit)
* [Send destination](/docs/api-reference/send-destination-to-vehicle)

Run **Commands security/lock**, then return to the vehicle in the Simulator and select **Refresh** to see the updated state.

## Step 8: Change the vehicle state

The Simulator gives you direct control over the vehicle's data. Open the vehicle's **Vehicle state** tab, edit any signals you want, and select **Publish**. Re-run your Postman requests and the responses reflect the new state.

<Frame type="simple">
  <img alt="Configuring vehicle signals in the Smartcar Vehicle Simulator" />
</Frame>

This is also how you reproduce errors. For example, set `Transmission.GearState` to `DRIVE` and a lock command returns a `VEHICLE_STATE:IN_MOTION` error, or uncheck a permission under `VehicleUserAccount.Permissions` and the matching request returns a permission error.

<Note>
  Simulated vehicles have no rate limits and no command latency, so responses come back immediately. Live vehicles behave differently on both counts.
</Note>

## Testing Smartcar Connect in simulated mode

The steps above use application-level tokens, which is the recommended way to reach both live and simulated vehicles. If your integration uses the OAuth 2.0 authorization code flow instead, you can rehearse the vehicle owner's experience against a simulated vehicle.

<Steps>
  <Step title="Create the vehicle disconnected">
    Turn off **Automatically connect to application** when creating the simulated vehicle, or disconnect an existing one.
  </Step>

  <Step title="Open the Connect modal">
    Select **Connect manually via Smartcar Connect** to get a Connect URL with `mode=simulated` and the credentials to sign in with.
  </Step>

  <Step title="Complete the flow">
    Launch the URL, pick any brand, and sign in with the generated credentials.
  </Step>
</Steps>

<Frame type="simple">
  <img alt="Smartcar Connect running in simulated mode" />
</Frame>

<Note>
  The simulated Connect flow uses `response_type=none`, so it does not return a per-vehicle access token. To receive an authorization code you can exchange, launch Connect with `response_type=code` and a configured redirect URI.
</Note>

## Troubleshooting

<AccordionGroup>
  <Accordion title="My requests return an unresolved variable error">
    Select the **SmartcarApi Variables** environment in Postman. Without it, `{{clientId}}` and the other placeholders are never substituted.
  </Accordion>

  <Accordion title="Requests that worked a moment ago now fail to authorize">
    Access tokens expire after 1 hour and there is no refresh token. Run **Client Credentials** again to mint a new one.
  </Accordion>

  <Accordion title="I'm getting a permission error on a signal or command">
    Check that the permission is still granted. Simulated vehicles grant all compatible permissions by default, but they can be toggled off under the `VehicleUserAccount.Permissions` signal. See [Permissions](/docs/api-reference/permissions).

    Also confirm the signal or command is supported by the powertrain type you chose.
  </Accordion>

  <Accordion title="My simulated vehicle doesn't appear in Connections">
    The vehicle was probably created with **Automatically connect to application** turned off, or it was disconnected later. Connect it from the Simulator, then run **Connections** again.
  </Accordion>
</AccordionGroup>

## What's next

<Card title="Test your webhooks" icon="webhook" href="/integrations/webhooks/overview">
  Subscribe a simulated vehicle to an integration and trigger deliveries by publishing state changes.
</Card>

<Card title="Browse the signals catalog" icon="signal" href="/api-reference/signals-catalog">
  See every signal you can read and configure.
</Card>

<Card title="Generate a client" icon="code" href="/api-reference/openapi-specs">
  Download the raw OpenAPI documents to generate code or feed the schema into your own tooling.
</Card>


# Accessing the Smartcar Support Center
Source: https://smartcar.com/docs/help/accessing-support-center

The Smartcar Support Center provides helpful resources including a knowledge base, ticket submission form, AI chat assistant, and a ticket center to manage your requests.

<Note>This feature is available on paid plans.</Note>

You can access the Support Center in two ways:

### Option 1: Visit the Support Center directly

Go to [support.smartcar.com](https://support.smartcar.com). You’ll be redirected to the Smartcar Dashboard to log in with your Dashboard credentials.

### Option 2: From the Smartcar Dashboard

1. Log in at [dashboard.smartcar.com](https://dashboard.smartcar.com).
2. Click the **Help** icon in the bottom-left corner, or the **Help Hub** icon in the bottom-right. <img alt="Help Hub" />
3. Select the **Support Center** option to be redirected to the full Support Center. <img alt="Support Center Button" />

***

For information about email, changelog, status, and brand reliability subscriptions, see [Subscribing to Smartcar Updates and Notifications](/docs/help/smartcar-updates).


# Smartcar Usage Limits
Source: https://smartcar.com/docs/help/api-limits

Learn about limits you may encounter when using Smartcar.

## Overview

There are several types of limits that govern your use of Smartcar. The nature of telematics requires us to carefully manage vehicle connections and traffic to ensure the stability of our platform and those of our upstream providers.

There are two major types of limits - **Billing Limits** and **Operational Rate Limits**.

# Billing Limits

### [BILLING : VEHICLE\_REQUEST\_LIMIT](/docs/errors/api-errors/billing-errors#vehicle-request-limit)

Your Smartcar plan specifies a maximum number of API calls you are permitted to make to each single vehicle in a given month. If you exceed this limit, you will receive the `VEHICLE_REQUEST_LIMIT` error.

For example: you have been allocated 500 API calls per vehicle per month, but you made the 501<sup>st</sup> call to a single vehicle during the billing period.

**This limit can be changed.** If you require more calls per vehicle per month, contact [support@smartcar.com](mailto:support@smartcar.com) or your Account Manager and we can work with you to understand your options.

### [BILLING : VEHICLE\_LIMIT](/docs/errors/api-errors/billing-errors#vehicle-request-limit)

Your Smartcar plan specifies a maximum number of vehicles that you may have connected at any one time. This limit applies to vehicle connections, and is separate from the limit regarding the number of API calls to those vehicles. If you receive this error, you have exceeded your maximum number of connected vehicles.

**This limit can be changed.** Reach out to [support@smartcar.com](mailto:support@smartcar.com) or your Account Manager to discuss your options.

# Operational Rate Limits

### [RATE\_LIMIT : SMARTCAR\_API](/docs/errors/api-errors/rate-limit-errors#smartcar-api)

Smartcar limits the total number of requests a single application can make over a given period of time to ensure platform stability for all customers. The Smartcar API Limit is defined as a "bucket" of requests that refills at a constant rate over time.

The default Smartcar API Limit is a **bucket of 120 requests that refills at a rate of 2 requests per minute.**

If you receive a `RATE_LIMIT:SMARTCAR_API` response, your application has exceeded this limit. You should implement an exponential backoff strategy when retrying requests.

**This limit can be changed.** Reach out to [support@smartcar.com](mailto:support@smartcar.com) or your Account Manager to discuss your options.

### [RATE\_LIMIT : VEHICLE](/docs/errors/api-errors/rate-limit-errors#vehicle)

Sending telematics requests to a vehicle causes it to wake up from its sleep state and consume energy and data resources. Excessive requests to a single vehicle can result in:

* EV battery drain
* 12 volt battery drain
* `UPSTREAM:RATE_LIMIT` errors that prevent you from making requests for a longer period of time

Smartcar enforces a per-vehicle rate limit that governs the rate of requests to a single vehicle and mitigates these potential issues. These limits can differ based on the vehicle manufacturer and a number of other factors, and are set by Smartcar to ensure consistent and timely data can be retrieved from vehicles.

**This limit cannot be changed.** If you receive this response, refer to the `retry-after` header (returned as seconds) for when to retry the request.

### [UPSTREAM : RATE\_LIMIT](/docs/errors/api-errors/upstream-errors#rate-limit)

Vehicle manufacturers sometimes impose rate limits on requests to vehicles. The Smartcar Vehicle Rate Limit will generally prevent those limits from being reached, but outside requests from other providers may cause the upstream limit to be exceeded. If the OEM upstream rate limit is exceeded, you will receive `UPSTREAM:RATE_LIMIT` from the Smartcar API for the affected vehicle until the limit is reset.

**This limit cannot be changed.** Smartcar cannot control rate limits imposed by our upstream providers. If you consistently receive this response for a single vehicle, reach out to [support@smartcar.com](mailto:support@smartcar.com) and we can investigate.


# Assist AI features in Slack
Source: https://smartcar.com/docs/help/assist-ai-slack

As part of our Enterprise Slack support offering, Smartcar includes access on select Enterprise plans to an AI-powered assistant that can help you get answers quickly, submit tickets, and navigate support resources—all without leaving your Slack workspace.

## 1. Ask a Question

In your dedicated Slack support channel, send a message with your question. The AI Agent will attempt to answer it based on Smartcar’s support documentation and past support interactions. <img alt="Ask a Question" />

## 2. Submit a Support Ticket

If your question requires deeper support, simply click **"Create a Ticket"** at the bottom of the AI-generated response within the Slack channel. This will open a form to submit a formal, trackable support request. <img alt="Create a Ticket" /> <img alt="Ticket Form" />

## 3. View Open Tickets

To check the status of an existing ticket, navigate to the Slack thread where the ticket was created and click the **"View Ticket Info"** icon. This will display the current status and details of your support request. <img alt="View Open Ticket" />

## 4. Navigate to the Support Center

Need more detailed help? You can access your ticket by clicking the **ticket ID** that appears after submitting a request using the **"Create a Ticket"** option. Alternatively, from the **"View Ticket Info"** window, you can click the **ticket number** to be redirected to the Smartcar Developer Dashboard. If you're already logged into an active session, you'll be taken directly to the ticket details within the Support Center. Otherwise, you'll be prompted to log in first.

In the Support Center, you can:

* Browse our documentation
* Submit new support requests
* View and update your existing tickets

For step-by-step instructions on how to log into the Smartcar Support Center, please see the following article: [Accessing the Smartcar Support Center](/docs/help/accessing-support-center)


# Beta
Source: https://smartcar.com/docs/help/beta

Understand Smartcar's approach to features in beta.

Beta is an option that allows developers to test and integrate new Smartcar features before they are fully released. Beta refers to a phase where certain features are made available for testing and feedback prior to general availability. These features are functional but may still be under development or refinement.

## Benefits of Beta Features

Participating in beta allows developers to get a head start on integrating new features, a chance to influence the feature in development through feedback and help Smartcar ensure your app’s needs are met.

## Considerations for features in Beta

When working with beta features, keep in mind that features may change before final release. As such, extra caution is advised when using these features in production environments.

## How to Participate

If you would like to get involved in testing a beta features, contact your Account Manager or our Support team at [support@smartcar.com](mailto:support@smartcar.com) for guidance.


# Brand Quirks
Source: https://smartcar.com/docs/help/brand-quirks

Brand specific quirks to keep in mind while building out your application.

## Acura

### Ignition On

Depending on model year, certain Acura vehicles do not return data when the ignition/engine is on.

### Sleep State

Most Acuras will go into a sleep state after about a week of inactivity,

## Audi

### Primary Key User

In order to have access to all vehicle functionality the account that connects to Smartcar will need to be flagged as a Key User by Audi.

## BMW/MINI

### Authentication requirements for BMW/MINI vary by region.

* **Outside the EU:** Web-based consent flows are currently unavailable. To authenticate vehicles in these regions, you must use the Smartcar [Android or iOS SDKs](https://smartcar.com/docs/connect/connect-sdks).
* **Inside the EU:** Smartcar integrates via the BMW Energy API. For specific details on this integration, please refer to our [BMW Energy API guide](https://smartcar.com/docs/help/oem-integrations/bmw/energy-integration).

### CONNECTED\_SERVICES\_ACCOUNT - SUBSCRIPTION errors

Smartcar API will throw a CONNECTED\_SERVICES\_ACCOUNT - SUBSCRIPTION when the data we receive from the vehicle is older than a month as this normally indicates a subscription issue.

## BYD

### Concurrent login requirement

BYD accounts can only maintain one active session at a time. Vehicle owners should sign in with a dedicated BYD login for Smartcar that is separate from the credentials used in the BYD mobile app. If the same account signs into the OEM app after connecting through Smartcar, the Smartcar session will be revoked and require re-authentication.

If customers reach out about being logged out of their BYD mobile app, we recommend instructing users to create a secondary BYD account exclusively for your app.

## GM (Buick, Chevrolet, Cadillac, GMC)

### VEHICLE\_STATE - ASLEEP errors

After 3-4 days of no activity, GM vehicles will enter a deep sleep state at which point they will no longer respond to API requests to preserve their 12v battery. In order to get data from the vehicle again, the car will need to go through an ignition cycle.

### UPSTREAM - RATE\_LIMIT errors

In order to avoid hitting UPSTREAM - RATE\_LIMIT errors use batch requests and ping no more than once every 30 minutes. Use of the OEM app also counts towards the rate limit.

### Charging follows an in-car schedule

GM EVs do not expose a true remote "start charging" button the way some other brands do. Charging is controlled by an in-car **Charge Now** / **Charge Later** setting (and any departure / "ready by" schedule the owner configures on the vehicle screen):

* **Charge Now** — the vehicle is willing to charge as soon as it is plugged in (up to its target charge level).
* **Charge Later** — the vehicle stays idle when plugged in and only starts charging in its scheduled window. An idle car in this mode is working as intended, not stuck; it will still charge later when the schedule says so.

That Charge Now / Charge Later preference is stored on the vehicle and persists across plug / unplug cycles. Unplugging ends the current charge session, but it does not clear the schedule or switch the car back to Charge Now.

Scheduling and the Charge Now / Charge Later toggle can only be changed from the vehicle screen. Neither the OEM mobile app nor the Smartcar API can rewrite that schedule or flip the car into Charge Now remotely.

### Start charge cannot override a charging schedule

A remote start-charge command (and raising the charge limit) only works for on-demand charging when the vehicle is already on **Charge Now**. If it is on **Charge Later**:

* A start-charge or charge-limit change will not make it start immediately.
* Only selecting **Charge Now** on the car will override the schedule for the current session.
* GM may still accept the remote command and return a success-looking response even though the vehicle stays paused on its schedule.

When Smartcar can tell that start charge was blocked by an active charge schedule, the API surfaces that as a [CHARGE\_FAULT](/docs/errors/api-errors/vehicle-state-errors#charge-fault) rather than a generic upstream failure, so clients can treat it as a vehicle configuration conflict instead of retrying forever.

### Charge and plug status can lag

GM [charge status](/docs/api-reference/signals/charge#ischarging) and plug status sometimes hold a stale value, so a car that is actually charging can still report as not charging (or the reverse). [State of charge](/docs/api-reference/signals/tractionbattery#stateofcharge) stays much more reliable. To confirm whether a car is charging, watch SOC rise over a few minutes rather than trusting charge status alone.

## Hyundai/Kia

### Telemetry Update Behavior

#### Pre-2025 Models (Gen 2 Navigation)

Hyundai/Kia vehicles have event-based logic that sends telemetry updates based on state changes such as:

* Every 10% of SoC while charging
* 5 minutes after ignition off
* Vehicle doors are left unlocked for 5 minutes
* After a command successfully completes
* Whenever charging stops

#### 2025+ Models (Gen 3 / CCnC Navigation)

Newer Hyundai/Kia models update more frequently, as often as every five minutes, including while the vehicle is driving.

### US: periodic re-authentication required

Hyundai and Kia vehicles in the US cap connection validity at 30 days. Owners must reconnect through Connect at least once a month to keep data flowing. This is a Hyundai/Kia US requirement, not a Smartcar limitation. Until the owner re-authorizes, the connection stops returning data and can look like a broken connection. Plan for the periodic reconnect in your onboarding and re-auth handling.

## Mercedes

### Control charge behaviour in the EU

In the EU, only EQ models support control charge at this time. For EQE and EQS models, if the state of charge is lower than 20%, stop commands are rejected by Mercedes. For all other EQ models, if the state of charge is below 50%, stopping the charging process is rejected by Mercedes and the car will continue to charge until it reaches at least 50% for vehicle reliability reasons. [See here for more details.](https://smartcar.com/docs/help/oem-integrations/mercedes/whats-new)

## Nissan

### “Vehicle has been found” MyNISSAN notifications

Vehicle owners may receive a notification from the MyNISSAN app stating “Success! We found the location of your vehicle. Check the map for the location of your YYYY Model.” every time the location endpoint is hit.

The app appears to have an option to edit notifications, but as of Feb 2024 they are not available in the app. Notifications may need to be turned off at the iOS/Android level by the vehicle owner.

## PSA Group (Citroen, DS, Opel, Peugeot, Vauxhall)

### Requesting control\_charge permissions

If you request control\_charge permissions for PSA EVs, upon login owners will be presented with a PIN and MFA screen in Connect upon submitting their credentials. They will need to have set this up on their OEMs application in order to grant your application this permission.

## Polestar

### Stop charge command limitations

Smartcar cannot fulfill stop charge commands if the vehicle is below 40% state of charge due to limitations with the current Polestar APIs.

## Rivian

### MFA

If MFA is enabled the vehicle owner will need to re-authorize via Connect about every 2 weeks.

## Tesla

### Remote Access

It may take a few hours or up to a full day for the REMOTE\_ACCESS\_DISABLED errors to subside after remote access is enabled.

### Charge Billing Records

In order to retrieve charge billing records, the main Tesla account must connect the vehicle, as driver profiles do not have access to this data.

### Virtual Key

Tesla now requires virtual keys for 3rd-party applications in order to issue commands for the following models:

* All Cybertrucks, Model 3 and Model Y
* 2021+ Model S and X

Please see [Virtual Keys](/docs/help/oem-integrations/tesla/virtual-key-tesla) for more information.

### Data streaming for legacy Model S and X

Legacy Model S and X vehicles (model year 2020 and earlier) don't support Virtual Keys. On firmware 2025.20 and later they support third-party data streaming instead. The owner must turn on **Allow Third-Party App Data Streaming** in the vehicle's **Safety** menu to maintain a reliable connection. When it's disabled, Smartcar falls back to a reduced polling rate and data may be delayed. Smartcar shows owners how to enable it during Connect.

<Frame>
  <img alt="Allow Third-Party App Data Streaming toggle in the vehicle's Safety menu" />
</Frame>

### Enterprise Tenant Configuration

<Warning>
  For enterprise customers, Tesla tenant setup must occur **before** any customer-facing Tesla vehicles are onboarded. Configure this during initial implementation, coordinated with Smartcar.
</Warning>

Changing Tesla tenant configurations after vehicles are already connected will require all affected users to re-authenticate. See [OEM Migrations and Re-authentication](/docs/connect/re-auth/oem-migrations) for guidance on handling this scenario.

## Volkswagen

### Control charge limits

Volkswagen limits charge commands to safeguard battery longevity based on environmental and system conditions. Excessive consecutive requests may result in being temporarily rate limited. To restore functionality, the vehicle must be driven again.

### CONNECTED\_SERVICES\_ACCOUNT errors on lock/unlock commands

In addition to verifying the VW account with the activation code, some cars will need to undergo the VW Ident Process before you can access remote lock/unlock functionality. This involves contacting the dealership to verify your ownership of the vehicle.

### Missing Subscription (European VWs)

Upon purchasing (or activating the free trial), VW needs to review the request. You will get an email confirmation once they've cleared everything on their side.

### Primary Driver Status

In order to fully interact with Smartcar, the credentials need to be flagged as the primary driver. You'll need to tap the "become primary driver" flow in the VW app. Depending on the model, this may require you to be in the car to interact with the infotainment system.

A vehicle owner can verify whether or not they are the primary driver by following the steps below:

1. Open the VW mobile app tap the profile icon in the bottom right
2. Go to **Vehicle Management**
3. If there’s an **Additional Users** section, tap their name to see whether it says **Primary User** or **Additional User**

## Volvo

### Lock/unlock commands

Volvo is an outlier regarding how unlock requests are processed. After initiating the request, after about 10 seconds you'll need to open the trunk (boot) to successfully complete the request. You'll know the car is ready to unlock the trunk as the hazard lights will flash. We recommend adding a notification for Volvos as part of the request loading animation to inform the user of this process.

### Phone number username

Smartcar Connect currently checks for an email format, as such phone number usernames cannot be used. The owner will need to add their email to their Volvo account via the web portal.

### Compatibility

Some models are not compatible because the device needs to be physically in the vehicle during authentication, which Connect doesn’t support at the moment:

* 2021+: XC40 Recharge
* 2022+: S90, S90 Recharge, V90, V90 Recharge, V90 Cross Country, XC60, XC60 Recharge, C40 Recharge
* 2023+: All models with the exception of the XC40

Even if the vehicle has been connected to and shows up in the Volvo app, if they go through Connect the account will present as if there are no vehicles on the account.

### Charge Schedules

Volvo enforces the following requirements for [charge schedule](/docs/api-reference/commands/overview#charge-schedules) requests:

* **Create or delete:** The vehicle must be at the [precise location](/docs/api-reference/signals/location) of the schedule.
* **Create only:** The vehicle must be actively [charging](/docs/api-reference/signals/charge#ischarging).

Requests that don't meet these conditions return a [`VEHICLE_STATE`](/docs/errors/api-errors/v3/vehicle-state-errors#oem_business_rule_not_met) error with code `OEM_BUSINESS_RULE_NOT_MET`.


# Brand Subscription Information
Source: https://smartcar.com/docs/help/brand-subscriptions

Below you can find the connected service name for each brand as well as any specific subscription packages needed to connect to the vehicle via Smartcar.

| Make                        | Region                      | Connected Service                           | Package                                           | Subscription Cost                                                                                             |
| --------------------------- | --------------------------- | ------------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| Acura                       | US, Canada                  | ACURALINK                                   | Remote                                            | 3 year free trial (2023 and Newer Models), 6 month free trial (2022 and Older Models). \$110/year thereafter. |
| Alfa Romeo                  | US, Europe                  | My Alfa Connect                             | My Car and My Remote                              | 3 - 5 years included.                                                                                         |
| Audi                        | US                          | myAudi                                      | CARE                                              | -                                                                                                             |
|                             | Europe, Canada              | Audi Connect                                | Remote                                            | Free for three years after delivery of a new vehicle. \~£120/year thereafter.                                 |
| BMW                         | All                         | BMW Connected                               | -                                                 | Free trial varies with model year. \~\$120/year thereafter.                                                   |
| Buick                       | US, Canada                  | OnStar                                      | Remote Access                                     | Free trial varies with model year. \$14.99/month for standalone Remote Access package.                        |
| BYD                         | Europe                      | BYD (Connected Services)                    | -                                                 | -                                                                                                             |
| Cadillac                    | US, Canada                  | OnStar                                      | Remote Access                                     | Free trial varies with model year. \$14.99/month for standalone Remote Access package.                        |
| Chevrolet                   | US, Canada                  | OnStar                                      | Remote Access                                     | Free trial varies with model year. \$14.99/month for standalone Remote Access package.                        |
| Chrysler                    | US, Canada                  | Uconnect                                    | Sirius XM Guardian (Remote Package)               | 1 year free trial. \$12.99/month for the Remote Package thereafter.                                           |
| Citroën                     | Europe                      | My Citroën                                  | ë-remote services needed for remote commands      | -                                                                                                             |
| CUPRA                       | Europe                      | CUPRA CONNECT                               | Remote Access Services                            | 3 years free for the Born model, 1 year free for others. Price varies with region.                            |
| Dacia                       | Europe                      | My Dacia                                    | -                                                 |                                                                                                               |
| Dodge                       | US, Canada                  | Uconnect                                    | Sirius XM Guardian (Remote Package)               | 1 year free trial. \$12.99/month for the Remote Package thereafter.                                           |
| DS                          | Europe                      | MyDS                                        | E-TENSE Remote                                    | -                                                                                                             |
| Fiat                        | Europe                      | FIAT                                        | My Car and My Remote                              | 6 month free trial.                                                                                           |
|                             | US                          | FIAT Connect                                | Assistance Package                                | 3 month free trial with select vehicles. \$14.99/month.                                                       |
| Ford                        | All                         | FordPass                                    | -                                                 | -                                                                                                             |
| GMC                         | US, Canada                  | OnStar                                      | Remote Access                                     | Free trial varies with model year. \$14.99/month for standalone Remote Access package.                        |
| Honda                       | US                          | HondaLink                                   | EV Access for EV Data. Remote Access for Commands | EV Access 8 year trial. \$14.99/month for standalone Remote Access package.                                   |
| Hyundai                     | All                         | Hyundai BlueLink                            | -                                                 | 3 year free trial for new vehicles. \$9.90/month per package thereafter.                                      |
|                             | US                          | Hyundai BlueLink (2023 IONIQ 6 & all 2024+) | BlueLink+                                         | -                                                                                                             |
| Infiniti                    | US                          | MyINFINITI                                  | -                                                 | 1 year free trial. \$12.99/month thereafter.                                                                  |
| Jaguar                      | All                         | Jaguar InControl                            | -                                                 | 3 year free trial. \~\$100/year thereafter.                                                                   |
| Jeep                        | US, Canada                  | Uconnect                                    | Sirius XM Guardian (Remote Package)               | 1 year free trial. \$12.99/month for the Remote Package thereafter.                                           |
|                             | US, Canada                  | Jeep Connect                                | Sirius XM Guardian (Remote Package)               | 1 year free trial. \$12.99/month for the Remote Package thereafter.                                           |
| Kia                         | US, Canada                  | Kia Access                                  | Plus                                              | 1 year free trial. \$149/year thereafter.                                                                     |
|                             | Europe                      | Kia Connect                                 | -                                                 | 7 year free trial starting on sale to the first owner.                                                        |
| Land Rover                  | All                         | Land Rover InControl                        | -                                                 | 3 year free trial. \~\$100/year thereafter.                                                                   |
| Lexus                       | US, Canada                  | Lexus Enform                                | REMOTE                                            | Free trial up to 3 years, varies with model year. \$80/year thereafter.                                       |
| Lincoln                     | US                          | Lincoln Way                                 | -                                                 | -                                                                                                             |
| Mazda                       | US, Europe                  | MyMazda                                     | -                                                 | 3 year free trial. \$10/month thereafter.                                                                     |
| Mercedes                    | All                         | MeConnect                                   | -                                                 | 1 year free trial. \~\$15/year there after.                                                                   |
| Mini                        | All                         | Mini Connected                              | -                                                 | Free trial varies with model year. \~\$120/year thereafter.                                                   |
| Nissan                      | US                          | NissanConnect Services                      | - Convenience   - Select (EV data)                | Free trial varies with model year. $9.99 - $ 21.98/month thereafter.                                          |
|                             | Europe                      | NissanConnect                               | -                                                 | Free trial varies with model year. \~£1.99/month thereafter.                                                  |
| Opel                        | Europe                      | myOpel                                      | e-Remote services needed for remote commands      | -                                                                                                             |
| Peugeot                     | Europe                      | MYPEUGEOT                                   | E-REMOTE CONTROL needed for remote commands       | -                                                                                                             |
| Polestar                    | All                         | Polestar                                    | -                                                 | Included (no separate paid Remote package required).                                                          |
| Porsche                     | US, Europe                  | My Porsche                                  |                                                   | 1 year free trial after initial purchase. \$299/year there after.                                             |
| RAM                         | US, Canada                  | Uconnect                                    | Sirius XM Guardian (Remote Package)               | 1 year free trial. \$12.99/month for the Remote Package thereafter.                                           |
|                             | US, Canada                  | Ram Connect                                 | Sirius XM Guardian (Remote Package)               | 1 year free trial. \$12.99/month for the Remote Package thereafter.                                           |
| Renault                     | Europe                      | My Renault                                  | -                                                 | -                                                                                                             |
| Rivian                      | US                          | Rivian                                      | -                                                 | -                                                                                                             |
| SEAT                        | Europe                      | SEAT CONNECT                                | Remote Access                                     | 1-year free trial included for new eligible vehicles. Renewal price varies by region.                         |
| Skoda                       | Europe                      | MySKODA                                     | Care Connect                                      | \~£36/year.                                                                                                   |
| Subaru (excluding Solterra) | US                          | MySubaru                                    | STARLINK Security Plus                            | 6-month free trial. \$4.95/month thereafter.                                                                  |
| Subaru Solterra             | US                          | Solterra Connect                            | Remote Connect                                    | One-year trial included, \$8/month after trial.                                                               |
| Tesla                       | All                         | Tesla                                       | -                                                 | -                                                                                                             |
| Toyota                      | US, Canada                  | Toyota Connected Services                   | Remote Connect                                    | 1 year free trial. \$80/year thereafter.                                                                      |
| Vauxhall                    | Europe                      | myVauxhall                                  | e-Remote services needed for remote commands      | -                                                                                                             |
| Volkswagen                  | US                          | Car-Net                                     | Remote Access                                     | -                                                                                                             |
|                             | Europe (non-ID) 2018 - 2022 | Car-Net                                     | -                                                 | -                                                                                                             |
|                             | Europe (non-ID) ≤ 2023      | We Connect                                  | -                                                 | -                                                                                                             |
|                             | Europe (non-ID) 2024+       | VW Connect                                  | -                                                 | -                                                                                                             |
|                             | Europe (ID) Firmware \<3    | We Connect Start                            | -                                                 | -                                                                                                             |
|                             | Europe (ID) Firmware v3+    | We Connect ID                               | -                                                 | -                                                                                                             |
| Volvo                       | All                         | Volvo Cars                                  | -                                                 | Free trial varies with model year. \~\$200/year thereafter.                                                   |

## Notes

### Audi

* Owners will need to ensure they're the Primary or Key user for the vehicle connected to their account in order to access all Smartcar functionality.

### Ford and Lincoln

* Owners that use a username to login to their connected services app will need to migrate to using their email address under account settings in their Ford Pass or Lincoln Way portal.

### OnStar

* Chevy Bolts MY 2020+ come with the **EV Mobile Command** service included for 5 years with the purchase of a new vehicle. Location data is not included in the package. Bolt owners will need to also subscribe to **Remote Access** to be able to get access to location data.
* For all other OnStar accounts, we require the modern **Remote Access** plan as our base subscription. This plan comes with the **Vehicle Status** feature set, which is what enables our remote access to data from cars. More information can be found [in this PDF](https://my.chevrolet.com/content/dam/gmownercenter/gmna/dynamic/onstar/comparePlans/nbm/OC_Compare-Plans-Chevy.pdf).
* There are certain legacy OnStar accounts floating around with similar names. A good check on whether a customer has the correct plan or not is the ability to view vehicle information like fuel level, EV battery level, odometer, or tire pressure from within their vehicle’s mobile app.

### Nissan US

* Convenience features are included as part of the Premium package.

### Toyota

* The Remote Connect subscription is tied to the audio package purchased with the vehicle. Compatible audio package availability is determined based on the trim of the vehicle model and varies model year to model year. Toyota provides PDFs for Remote Connect availability [here](https://www.toyota.com/connected-services/#:~:text=Learn%20about%20your%20Connected%20Services).

### Uconnect

* For all Uconnect accounts, we require the ability to interact with vehicle information through the Uconnect portal
* A Uconnect account may have access to Mopar, but not all Mopar accounts have access to Uconnect. If a user can see information in Mopar but not Uconnect, they'll need to reach out to Uconnect support to set up the right Uconnect plan for their vehicle.
* 2021+ Jeeps have their own connected service - Jeep Connect
* 2022+ Rams have their own connected service - Ram Connect
* 2022+ Jeep Wagoneers have their own connected service - Wagoneer Connect
* Canada has limited support listed [here](https://www.driveuconnect.ca/en/sirius-xm-guardian-vehicles)

### Volkswagen ID Series

* Model year 2021 and certain 2022 Volkswagen ID vehicles require an upgrade to vehicle software version 3 which will allow you to get location and odometer data. This is a requirement for both US and European vehicles.


# Compatible Vehicles
Source: https://smartcar.com/docs/help/compatibility





# Connect your car
Source: https://smartcar.com/docs/help/connect-your-car





# Diagnostic Systems
Source: https://smartcar.com/docs/help/diagnostic-systems

To support our System Status endpoint, reference the below list of unified systems.

The [System Status](https://smartcar.com/docs/api-reference/get-system-status) endpoint returns a list of systems reported by any given vehicle, as well as their current state which may be "OK" or "ALERT".

## System IDs

|                                   |                                                           |
| --------------------------------- | --------------------------------------------------------- |
| `SYSTEM_ABS`                      | Antilock Braking Systems                                  |
| `SYSTEM_ACTIVE_SAFETY`            | Active Safety Systems                                     |
| `SYSTEM_AIRBAG`                   | Airbag Systems                                            |
| `SYSTEM_BRAKE_FLUID`              | Brake Fluid Level                                         |
| `SYSTEM_DRIVER_ASSISTANCE`        | Driver Assistance Systems                                 |
| `SYSTEM_EMISSIONS`                | Emissions Systems                                         |
| `SYSTEM_ABS`                      | Antilock Braking Systems                                  |
| `SYSTEM_ENGINE`                   | Engine Systems                                            |
| `SYSTEM_EV_BATTERY_CONDITIONING`  | EV Battery Conditioning Systems                           |
| `SYSTEM_EV_CHARGING`              | EV Charging Systems                                       |
| `SYSTEM_EV_DRIVE_UNIT`            | EV Drive Unit Systems                                     |
| `SYSTEM_EV_HV_BATTERY`            | EV High-Voltage Battery Systems                           |
| `SYSTEM_LIGHTING`                 | Lighting Systems                                          |
| `SYSTEM_MIL`                      | Malfunction Indiciator Lamp Systems (Check Engine Lights) |
| `SYSTEM_OIL_LIFE`                 | Oil Life Systems                                          |
| `SYSTEM_OIL_PRESSURE`             | Oil Pressure Systems                                      |
| `SYSTEM_OIL_TEMPERATURE`          | Oil Temperature Systems                                   |
| `SYSTEM_TELEMATICS`               | Telematics Systems                                        |
| `SYSTEM_TIRE_PRESSURE`            | Tire Pressure Systems                                     |
| `SYSTEM_TIRE_PRESSURE_MONITORING` | Tire Pressure MonitoringSystems                           |
| `SYSTEM_TRANSMISSION`             | Transmission Systems                                      |
| `SYSTEM_WASHER_FLUID`             | Washer Fluid Systems                                      |
| `SYSTEM_WATER_IN_FUEL`            | Water in Fuel Detection Systems                           |


# Frequently Asked Questions (FAQs)
Source: https://smartcar.com/docs/help/faqs



Below you'll find answers to some of the most frequently asked questions about Smartcar.

<AccordionGroup>
  <Accordion title="Does Smartcar make apps?">
    Smartcar does not build applications ourselves. Rather, we provide the building blocks that our customers need in order to build applications for a variety of use cases.
  </Accordion>

  <Accordion title="Do I need a connected services account?">
    Yes. For instance, if you own a VW, you will need to have Car-Net activated in the US or WeConnect in Europe. You can read more about connected service subscriptions [here](/docs/help/brand-subscriptions).
  </Accordion>

  <Accordion title="What countries does Smartcar work in?">
    Take a look at our [Global Compatibility page](https://smartcar.com/global/) for the latest information on where Smartcar works.

    Smartcar is always expanding and working hard to ensure supported countries are stable and reliable. If your country is not currently supported, but you think we'll be a good fit for your use case, [schedule a demo](https://smartcar.com/demo/) and let's see how we can help you!
  </Accordion>

  <Accordion title="Which languages does Smartcar support?">
    [Smartcar Connect](/docs/connect/what-is-connect) is available in English, Danish, German, Spanish (Spain), Spanish (Latin America), French, Italian, Dutch, Norwegian, and Swedish providing vehicle owners a native experience as they onboard vehicles to your platform.
  </Accordion>

  <Accordion title="How fresh is my data?">
    Smartcar will always try to pull the latest data point from any given vehicle. Each API response includes an [sc-data-age header](https://smartcar.com/docs/api#response-headers) that will contain the timestamp of when that data was last saved.

    Although each OEM saves data at different times, the data age header should not be older than the last time the vehicle was used.
  </Accordion>

  <Accordion title="How many cars is Smartcar compatible with?">
    <Tip>
      For a list of compatible vehicles, visit [our website](https://smartcar.com/product/compatible-vehicles/).
    </Tip>

    Smartcar is compatible with **161 million vehicles** across the US, Canada and Europe.

    **United States** <br />
    Smartcar is compatible with **29 car brands** in the United States.

    **Europe** <br />
    Smartcar is compatible with **19 car brands** in Europe.

    **Canada** <br />
    Smartcar is compatible with **21 car brands** in Canada.
  </Accordion>

  <Accordion title="Why isn't my car supported?">
    **If your make isn't supported...**

    We work hard to ensure that supported brands are stable and reliable, which takes time. If you don't see your make on our [compatibility page](https://smartcar.com/product/compatible-vehicles/) but you would like it to be, reach out to [support@smartcar.com](mailto:support@smartcar.com) to see how you can help speed up the process!

    **If we support your make, but not your model...**

    We might just need to do some additional testing. Sign up to our [research fleet](https://smartcar.com/research-fleet) and we'll reach out to see what we can do for you!

    **If we support your make, model, but not your year...**

    The majority of automakers only started adding internet connectivity to their cars around 2014. If you're able to access your car through a smartphone application and believe it should be supported, reach out to us and we'll be happy to take a look.
  </Accordion>

  <Accordion title="Smartcar versus Aftermarket Hardware">
    While on-board diagnostics dongles are versatile and useful for tracking and diagnostics of many kinds, they are far from ideal when it comes to mileage verification.
    They can be inaccurate, inconvenient, expensive and unreliable.Smartcar is only one example of a pure software alternative that uses API technology to offer the perfect
    mileage verification solution to auto insurance companies. Compared with traditional OBD-II devices, our API is accurate, cost efficient and tamper-resistant.

    You can read more about why using our API is a great choice on our [blog](https://smartcar.com/blog/obd-mileage-verification/).
  </Accordion>

  <Accordion title="Why do I see requests that resulted in a 460 status code with different error codes and error types on the Smartcar Dashboard?">
    In the event that we receive a response from the OEM after the connection is closed, we will show the error code and error type we would have responded with on the Dashboard if the connection had been kept open.
  </Accordion>
</AccordionGroup>


# Submit a Feature Request
Source: https://smartcar.com/docs/help/feature-request



## Help Us Improve Smartcar!

Your feedback shapes our future. Have an idea or improvement you’d love to see? Submit your suggestions using the form below, and let us know how we can better serve your needs.

If you have trouble seeing the form below, please visit [this link](https://smartcarapi.notion.site/215f1477e9d380538219cb34866b8540?pvs=105) to submit your feature request.

<iframe />


# Data Freshness Frequencies
Source: https://smartcar.com/docs/help/frequencies

Smartcar's goal is to provide as close to real-time data as possible based on available technologies and capabilities from OEMs. Although real-time is not yet available across all OEMs outside of commercial fleets, Smartcar continues to improve these frequencies as platforms and technologies evolve.

## Understanding Real Vehicle Data Freshness Frequencies

At Smartcar, we are committed to transparency about our data. When we report data freshness, we're referring to actual data retrieved directly from vehicles, not cached information. Cached data can be returned instantly.

### What Does The Table Data Mean

* **True Vehicle Freshness**: A frequency range of 30 minutes means how often the vehicle can safely provide new data without side effects. Even if we attempt to fetch it every 5 seconds, the data won't change for 30 minutes.
* **Data Delivery**: Rather than polling our API to determine when the data has changed, create a [Webhook](/docs/integrations/webhooks/overview) and Smartcar will send you data as frequently as it changes. It provides both the convenience of immediate notifications AND the reliability of truly fresh vehicle data.

### Why This Matters

**Honest Reporting**: We publish actual vehicle data freshness rates rather than platform latency rates that can be misleading. Developers need to understand the true age of the data they're receiving to build reliable applications. When you come across promises of data "every minute" for a brand we show as 30 minutes, this often means you're repeatedly receiving the same cached information at that frequency, not retrieving fresh data from the vehicle.

***

<Note>
  The values below indicate a range of how quickly you can expect to see fresh data and not how frequent you can receive data from Smartcar. i.e. You may request/receive odometer every three minutes from Smartcar, but its value won't change until it is refreshed by the OEM.
</Note>

**Data Frequency**: This indicates the frequency at which you receive vehicle data updates that Smartcar delivers to you via webhooks. This frequency can vary based on the vehicle make, the data type (such as location, odometer, or battery), and how frequently the vehicle is driven. In general, you can expect updates to arrive anywhere from every few minutes to once every few hours. While our slowest data rates for all OEMs is an hour, for many vehicles (including the fastest), when the vehicle is idle or "asleep", no updates will be provided since no change has occurred.

Smartcar automatically adjusts polling frequency based on vehicle status to balance timely updates with efficient resource use. While we aim to provide near real-time data when possible, exact timing depends on factors outside of Smartcar's control, such as OEM behavior and vehicle connectivity.

| Make          | Region     | Data Frequency Range (in min) |
| ------------- | ---------- | ----------------------------- |
| ACURA         | US, Canada | 30-60                         |
| ALFA ROMEO    | Global     | 5-10                          |
| AUDI          | Europe     | 4-5                           |
| AUDI          | US         | 3-5                           |
| BMW           | Europe     | 1-3                           |
| BMW           | US, Canada | 5-10                          |
| BUICK         | US, Canada | 30-45                         |
| BYD           | Europe     | 1-3                           |
| CADILLAC      | US, Canada | 30-45                         |
| CHEVROLET     | US, Canada | 30-45                         |
| CHRYSLER      | Global     | 5-10                          |
| CITROEN       | Europe     | 5-10                          |
| CUPRA         | Europe     | 4-5                           |
| DACIA         | Europe     | 10-15                         |
| DODGE         | Global     | 5-10                          |
| DS            | Europe     | 5-10                          |
| FIAT          | Global     | 5-10                          |
| FORD          | Global     | 15-30                         |
| GMC           | US, Canada | 30-45                         |
| HONDA         | US, Canada | 15-30                         |
| HYUNDAI       | Global     | 5                             |
| INFINITI      | US         | 5-10                          |
| JAGUAR        | Global     | 15-30                         |
| JEEP          | Global     | 5-10                          |
| KIA           | Global     | 5                             |
| LAND ROVER    | Global     | 15-30                         |
| LEXUS         | US         | 5-10                          |
| LINCOLN       | Global     | 5-10                          |
| MAZDA         | Global     | 1-3                           |
| MERCEDES BENZ | Europe     | 1-3                           |
| MERCEDES BENZ | US, Canada | 5-10                          |
| MG            | Europe     | 5-10                          |
| MINI          | Europe     | 1-3                           |
| MINI          | US, Canada | 5-10                          |
| NISSAN        | Europe     | 5-10                          |
| NISSAN        | US         | 5-10                          |
| OPEL          | Europe     | 5-10                          |
| PEUGEOT       | Europe     | 5-10                          |
| POLESTAR      | Global     | 1-3                           |
| PORSCHE       | Europe     | 30-60                         |
| RAM           | Global     | 5-10                          |
| RENAULT       | Europe     | 10-15                         |
| RIVIAN        | Global     | 3-5                           |
| SEAT          | Europe     | 4-5                           |
| SKODA         | Europe     | 4-5                           |
| SUBARU        | US         | 5-10                          |
| TESLA\*       | Global     | 1 sec - 5 min                 |
| TOYOTA        | US         | 30-60                         |
| VAUXHALL      | Europe     | 5-10                          |
| VOLKSWAGEN    | Europe     | 4-5                           |
| VOLKSWAGEN\*  | US         | 1-3                           |
| VOLVO         | Global     | 1-3                           |

## Notes

### \* Tesla

<Info>
  For Tesla vehicles capable of streaming, 3 minutes is the average of how often the data is refreshed. Depending on the data point and how often it changes, you may see data refreshed faster. For vehicles that do not support streaming, Smartcar fetches data from the vehicle every 5 minutes when the vehicle is awake.
</Info>

### \* Volkswagen US

<Info>
  For Volkswagen vehicles in the US, 3 minutes is the average of how often the data is refreshed. For EVs, you may see data refreshed faster when the vehicle is plugged in.
</Info>


# How to Submit a Ticket in the Support Center
Source: https://smartcar.com/docs/help/how-to-submit-ticket

Learn how to submit a support ticket through the Smartcar Support Center, including step-by-step instructions and eligibility details based on your plan.

<Info>
  For information on how to access the Smartcar Support Center, please visit the following article: [Accessing the Smartcar Support Center](/docs/help/accessing-support-center)
</Info>

***

### **How to Submit a Support Ticket**

**1. Select "Submit a Ticket"**\
Once in the Support Center, click **"Submit a Ticket"** at the top right corner of the page to begin creating your ticket. <img alt="Submit a Ticket" />

**2. Fill Out the Ticket Form**\
Provide details such as:

* Subject
* Description
  * Please include as much relevant context as possible such as Session IDs, Vehicle IDs, screenshots, etc.
* The Smartcar Component affected
* The issue type

<img alt="Fill Out the Ticket Form" />

**3. Submit Your Ticket**\
Click **Submit**, and your request will be sent to our Support team.

**4. Track Your Request**\
You can view and track the status of your tickets under **"My Tickets"** in the Support Center. <img alt="Track Your Requests" />

**5. Update or Close a Request**\
Select the ticket you'd like to update or close from the **"My Tickets"** view. Once you're on the ticket page:

* Click **"Reply"** at the bottom left to add more information or request a status update.
* Click **"Close Ticket"** at the bottom right to mark the request as **Closed - Resolved** if you no longer need assistance. <img alt="Update or Close a Request" />

***

### **Who can submit tickets?**

Ticket submission is available to users on **Build** and **Custom** **Enterprise** plans.

**Free plan users** can access the Docs Center and AI Agent within the Dashboard for assistance but do not have access to submit tickets.


# mySmartcar
Source: https://smartcar.com/docs/help/my-smartcar

With [mySmartcar](https://my.smartcar.com/login), you can see which apps are connected to your vehicle and manage their permissions anytime.

## Log in

Log into [mySmartcar](https://my.smartcar.com/login) by providing your preferred email address. A 6-digit code will be sent to you by email, which will grant access to mySmartcar.

<Frame>
  <img />
</Frame>

## Connect your OEM account

Now press "Connect your Car" and follow the on-screen prompts to pair your Connected Services account with mySmartcar.

<Frame>
  <img />
</Frame>

## Review and manages connected apps

Once your OEM account is connected, Smartcar will provide a list of each application connected via Smartcar to your Connected Services account. Here you can see when the app was first granted access and the permissions requested.

Should you wish to disconnect an application, click "Revoke Access" and confirm to remove access to your vehicle's data for that application.

<Frame>
  <img />
</Frame>


# BMW Energy APIs for European Markets
Source: https://smartcar.com/docs/help/oem-integrations/bmw/energy-integration

Access charging data and remote charge control for BMW and MINI EVs in Europe through Smartcar's BMW Energy API integration.

Smartcar's integration with BMW's Energy API gives you access to charging data and remote charge control for BMW and MINI electric vehicles across Europe. This integration is designed for energy providers building smart charging, demand response, and fleet management solutions.

## Capabilities

With this integration, you can:

* **Monitor charging status** — Get visibility into charging state, energy flow, and battery level.
* **Control AC charging** — Remotely start and stop AC charging sessions.
* **Build smart charging solutions** — Support use cases like dynamic load balancing, demand response, off-peak optimization, and charge cost tracking.

## Supported Data

The BMW Energy integration provides charging and battery data through Smartcar's standardized signal schema.

| Data Category       | Available Data                                                                    |
| ------------------- | --------------------------------------------------------------------------------- |
| Charging            | Connector type, cable connection status, charging state, detailed charging status |
| Charging Parameters | Charge timers, charge limits, time to complete, charging wattage                  |
| Battery             | State of charge (SOC), remaining electric range, nominal capacity                 |
| Location            | High-precision GPS position (when vehicle is within Geofence)                     |

### Smartcar Signals

* [`Charge.ChargingConnectorType`](/docs/api-reference/signals/charge#charging-connector-type)
* [`Charge.IsChargingCableConnected`](/docs/api-reference/signals/charge#is-charging-cable-connected)
* [`Charge.IsCharging`](/docs/api-reference/signals/charge#is-charging)
* [`Charge.DetailedChargingStatus`](/docs/api-reference/signals/charge#detailed-charging-status)
* [`Charge.ChargeTimers`](/docs/api-reference/signals/charge#charge-timers)
* [`Charge.ChargeLimits`](/docs/api-reference/signals/charge#charge-limits)
* [`Charge.TimeToComplete`](/docs/api-reference/signals/charge#time-to-complete)
* [`Charge.Wattage`](/docs/api-reference/signals/charge#wattage)
* [`TractionBattery.StateOfCharge`](/docs/api-reference/signals/tractionbattery#state-of-charge)
* [`TractionBattery.Range`](/docs/api-reference/signals/tractionbattery#range)
* [`TractionBattery.NominalCapacity`](/docs/api-reference/signals/tractionbattery#nominal-capacities)
* [`Location.PreciseLocation`](/docs/api-reference/signals/location#location)

### Commands

* [Start Charge](/docs/api-reference/evs/control-charge)
* [Stop Charge](/docs/api-reference/evs/control-charge)

## Coverage

### Supported Vehicles

This integration supports all Battery Electric Vehicles (BEV) and Plug-in Hybrid Electric Vehicles (PHEV) from BMW and MINI.

<Warning>
  **ICE vehicles are no longer supported in Europe.** BMW and MINI internal combustion engine (ICE) vehicles cannot connect through this integration. Customers attempting to connect ICE vehicles in Europe will be redirected to the BMW Energy API, which does not support ICE vehicles.
</Warning>

### Supported Markets

The integration is available in 17 European markets: Austria, Belgium, Denmark, Finland, France, Germany, Great Britain, Ireland, Italy, Luxembourg, Netherlands, Norway, Poland, Portugal, Spain, Sweden, and Switzerland.

## Geofence restriction

<Warning>
  Data and commands are only available when the vehicle is within approximately 200 meters of the consented address. Data streaming from BMW to Smartcar and from Smartcar to your app automatically stops when the vehicle exits the Geofence.
</Warning>

When vehicle owners grant consent, they specify a single address where managed charging will occur. This Geofence defines where data streaming and charge commands are available. This design ensures data privacy and compliance with BMW's requirements.

## Consent Flow

Vehicle owners grant consent through the BMW Connected Drive Portal as part of the Smartcar Connect flow. During this process, they:

1. Log in with their BMW ID
2. Select the vehicle(s) to connect
3. Specify the address where managed charging will occur
4. Accept BMW's terms for data sharing

## Limitations

<Info>
  Keep these constraints in mind when building your integration.
</Info>

* **EV and PHEV only** — ICE (internal combustion engine) vehicles are not supported and cannot connect through any BMW integration in Europe.
* **Charging-only scope** — This integration focuses on charging and battery data. Broader vehicle data (odometer, tire pressure, etc.) is not available through the Energy API.
* **Geofence-restricted** — Data and commands only work within the \~200m Geofence radius.
* **AC charging only** — Remote charge control is limited to AC charging sessions.
* **No public charging data** — Data from public charging sessions is not supported.
* **No cross-border data** — Cross-border data streaming is not currently supported.
* **Charge stop rate limit** — BMW enforces a rolling 30-day limit of 80 charge stop commands per vehicle.

If you have any questions about these limitations or need additional capabilities, please our support team. We're continuously working with BMW to expand the integration's features and coverage.


# Important Updates
Source: https://smartcar.com/docs/help/oem-integrations/mercedes/whats-new

Updates regarding the Mercedes-Benz Smartcar Integration.

## December 15th, 2025

Smartcar is excited to announce the availability of the Mercedes-Benz Connectivity Services partner integration. This integration enables developers to connect Mercedes-Benz electric vehicles in Europe and access vehicle data for smart charging, energy management, and mobility applications.

### VIN Verification in Connect Flow

When connecting a Mercedes-Benz vehicle through Smartcar Connect, vehicle owners will be prompted to enter their Vehicle Identification Number (VIN) as part of the authentication process. This additional verification step is a requirement from Mercedes to enroll a vehicle.

<Frame type="simple">
  <img />
</Frame>

<Note>
  The VIN can be found in various places such as the Mercedes mobile app, Mercedes web portal, the vehicle's registration documents, insurance papers, or on the vehicle itself (typically on the driver's side dashboard or door jamb).
</Note>

### Supported Vehicle Types

Currently, the Mercedes-Benz integration supports the following powertrain types for **new connections**:

* **BEV (Battery Electric Vehicles)** - Fully electric Mercedes-Benz vehicles
* **PHEV (Plug-in Hybrid Electric Vehicles)** - Mercedes-Benz plug-in hybrid vehicles

### Need Support for Other Vehicle Types?

**Existing Connections**: If you have existing connections to Mercedes-Benz vehicles with other powertrain types (such as traditional internal combustion engine vehicles), these connections will continue to work, but re-authentication is not supported at this time. If your application requires support for Mercedes-Benz vehicles with other powertrain types, please [contact our team](mailto:support@smartcar.com) to discuss your specific requirements. We're continuously working with Mercedes to expand compatibility across different vehicle types and would love to hear about your use case.

### Supported Smartcar Signals:

* [Charge.IsChargingCableConnected](/docs/api-reference/signals/charge#is-charging-cable-connected)
* [Charge.IsCharging](/docs/api-reference/signals/charge#is-charging)
* [Charge.DetailedChargingStatus](/docs/api-reference/signals/charge#detailed-charging-status)
* [Charge.ChargeTimers](/docs/api-reference/signals/charge#charge-timers)
* [Charge.ChargeLimits](/docs/api-reference/signals/charge#charge-limits)
* [Charge.TimeToComplete](/docs/api-reference/signals/charge#time-to-complete)
* [Charge.Wattage](/docs/api-reference/signals/charge#wattage)
* [TractionBattery.StateOfCharge](/docs/api-reference/signals/tractionbattery#state-of-charge)
* [TractionBattery.Range](/docs/api-reference/signals/tractionbattery#range)
* [TractionBattery.NominalCapacity](/docs/api-reference/signals/tractionbattery#nominal-capacities)
* [Location.PreciseLocation](/docs/api-reference/signals/location#location)
* [Odometer.TraveledDistance](/docs/api-reference/signals/odometer#traveled-distance)

### Supported Commands:

* Charge Start
* Charge Stop

### Notes

This Mercedes-Benz integration is automatically enabled for your application when connecting vehicles out of Europe.

* Supported European markets: Reach customers in Austria, Belgium, Denmark, Finland, France, Germany, Great Britain, Ireland, Italy, Luxembourg, Netherlands, Norway, Poland, Portugal, Spain, Sweden, and Switzerland
* As part of this integration, drivers will be asked to enter their Vehicle Identification Number (VIN) during the new consent authentication flow. We recommend preparing your customer guidance and support content accordingly
* If charge control permissions are requested by the connecting application only EQA, EQB, EQE and EQS vehicles are compatible
* Only EQ models support control charge at this time. For EQE and EQS models, if the state of charge is lower than 20%, stop commands are rejected by Mercedes. For all other EQ models, if the state of charge is below 50%, stopping the charging process is rejected by Mercedes and the car will continue to charge until it reaches at least 50% for vehicle reliability reasons,

For more information about compatible vehicle data and features, see the [compatibility matrix](https://smartcar.com/product/compatible-vehicles).


# Tesla Business Fleet enrollment
Source: https://smartcar.com/docs/help/oem-integrations/tesla/business-fleet-onboarding

How to enroll Tesla vehicles purchased through Tesla's B2B program into Smartcar.

## Overview

Tesla vehicles purchased through Tesla's Business-to-Business (B2B) program can be enrolled with Smartcar through Tesla Business Suite. Once enrolled, your B2B-acquired vehicles appear alongside your other Smartcar-connected Tesla vehicles, and data and commands flow through your existing Smartcar integration.

Business Fleet enrollment is set up per fleet account. To begin, [contact Smartcar support](mailto:support@smartcar.com) with the email address of the business contact who manages access for the fleet.

## Enrollment flow

Enrollment has three customer-facing steps, followed by an automatic configuration phase that Smartcar runs on your behalf.

### Step 1: Smartcar sends a consent link

After you let us know which fleet to enroll, Smartcar generates a Tesla Business Suite sign-in link and emails it to the business contact you designate. The contact you provide must have Tesla Business Suite permissions to manage access for the fleet you want to enroll.

### Step 2: Your business contact grants access

The business contact opens the link, signs in to Tesla Business Suite, reviews the requested permissions, and approves them. We recommend using **Select All** so that every Smartcar feature you use is available for your fleet vehicles. The permissions requested match the ones already configured for your existing Tesla integration with Smartcar.

<Frame>
  <img />
</Frame>

Once submitted, Tesla records the consent and binds it to the fleet account.

### Step 3: Smartcar receives consent

Tesla confirms the grant to Smartcar automatically, and Smartcar begins the post-consent setup.

## What happens after consent

Once Smartcar receives consent, the following runs automatically for vehicles purchased through Tesla's B2B program:

1. **Vehicle connection.** Smartcar establishes a connection with each vehicle.
2. **Virtual key pairing.** Smartcar pairs the Tesla Virtual Key for each vehicle. No action is required from you.
3. **Daily fleet sync.** Smartcar evaluates fleet membership on a daily basis and automatically adds new B2B-purchased vehicles or removes vehicles that have left the fleet.

Vehicles associated with the fleet account that were not purchased through Tesla's B2B program are excluded from this automated enrollment and require manual Virtual Key installation per vehicle.

## Managing your fleet in the Smartcar Dashboard

After enrollment, your Tesla Business Fleet vehicles are visible in the **Vehicles** tab of the [Smartcar Dashboard](https://dashboard.smartcar.com).

<Frame>
  <img />
</Frame>

From this view, you can:

* **Review every vehicle on the fleet**, including make, model, year, Vehicle ID, User ID, connection date, and webhook subscription count.
* **Filter the list** by connection date, make, mode, or Vehicle ID.
* **See which vehicles need attention.** Vehicles flagged with **Action required** need manual Virtual Key pairing before they can deliver data or accept commands.

## Accessing data and issuing commands

Data for Tesla Business Fleet vehicles is delivered through [Webhooks](/docs/integrations/webhooks/overview). Commands are issued through the [Smartcar API](/docs/api-reference/authorization/overview), authenticated with a [Machine-to-Machine access token](/docs/getting-started/how-to/api-authentication).

<Note>
  Tesla Business Fleet vehicles are not compatible with per-vehicle (v2) access tokens or v2 API endpoints. Use Webhooks for data and V3 API endpoints with M2M authentication for commands.
</Note>

All commands and data signals available for individual Tesla vehicles on Smartcar are also supported for Business Fleet vehicles, with the exception of driver-specific signals (such as user profile), which are not exposed for fleet-mode vehicles.

## Getting started

To enroll your Tesla Business Fleet vehicles, [contact Smartcar support](mailto:support@smartcar.com). Have the following ready:

* The email address of the business contact who will grant access on Tesla Business Suite
* Confirmation that the contact has permissions to manage access for the fleet under your Tesla Business account


# Tesla Permission Info
Source: https://smartcar.com/docs/help/oem-integrations/tesla/developers

This page has information regarding Smartcar's upgraded Tesla integration.

## Updating access with Tesla

You can use either of the following URLs to prompt users for more Tesla
permissions in the event you need additional access from the
vehicle owner due to:

* A [PERMISSION](/docs/errors/api-errors/permission-errors) error from API

* A [CONNECTED\_SERVICES\_ACCOUNT:PERMISSION](/docs/errors/api-errors/connected-services-account-errors#permission) error from API

* Needing access to an endpoint out of scope for your existing permissions

If one or more of the Smartcar scopes you pass map to a new Tesla permission(s)
for the account, the user will be prompted to update access after they log in
with Tesla.

To prompt users to update their Tesla permissions, use the reauthentication flow. This allows users to grant additional permissions without requiring a new vehicle connection.

```
    https://connect.smartcar.com/oauth/reauthenticate?
    response_type=vehicle_id
    &make=TESLA
    &application_id=8229df9f-91a0-4ff0-a1ae-a1f38ee24d07
    &scope=read_odometer control_security
```

| name             | type            | required | description                                                                                                                                                                                                                                                                                                            |
| ---------------- | --------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `response_type`  | `string`        | true     | This should be set to `vehicle_id`.                                                                                                                                                                                                                                                                                    |
| `make`           | `string`        | true     | Specifies the brand to update access to. Currently, the only make available for this flow is `TESLA`.                                                                                                                                                                                                                  |
| `application_id` | `string`        | true     | The application’s unique identifier. This is available on the credentials tab of the Smartcar Dashboard.                                                                                                                                                                                                               |
| `scope`          | `[permissions]` | true     | A space-separated list of permissions that your application is requesting access to. The valid permission names can be found in the [permissions](/docs/api-reference/permissions) section. When reauthenticating, the user will be required to grant the corresponding OEM permissions before being able to exit the flow. |

<Info>
  The reauthentication flow does not redirect the user back to your application or issue new credentials. Your existing application-level access token continues to work for all connected vehicles.
</Info>

## Requiring Tesla Permissions

To ensure users select the necessary permissions with Tesla before
being able to connect their vehicle via Smartcar, please append the `required:`
prefix to Smartcar scopes in your Connect URL e.g. `required:read_location`.

As a result if they do not select the necessary permissions with Tesla, they will see the
following screen and be prompted to return to Tesla to update their permissions.

<Frame>
  <img />
</Frame>

## Permission Mappings

Tesla provides a limited set of permissions. To ensure vehicle data is shared only with explicit consent, Smartcar has mapped Tesla’s permissions into its existing more granular options. For example, granting access to “vehicle commands” in a Tesla account allows an application to start or stop charging, lock or unlock doors, enable or disable Sentry Mode, and more. Smartcar separates these permissions so that applications must request access to control charging separately from access to vehicle security, control navigation, etc. Smartcar does not use or share vehicle data beyond the permissions listed in this table. An application with the ability to control the charge status of a vehicle, does not have access to control other aspects of the car unless explictly requested and granted by a vehicle owner.

| Smartcar Permission          | Tesla Permission                                    |
| ---------------------------- | --------------------------------------------------- |
| `control_charge`             | Vehicle Charge Management (vehicle\_charging\_cmds) |
| `control_climate`            | Vehicle Commands (vehicle\_cmds)                    |
| `control_navigation`         | Vehicle Commands (vehicle\_cmds)                    |
| `control_pin`                | Vehicle Commands (vehicle\_cmds)                    |
| `control_security`           | Vehicle Commands (vehicle\_cmds)                    |
| `control_trunk`              | Vehicle Commands (vehicle\_cmds)                    |
| `read_battery`               | Vehicle Information (vehicle\_device\_data)         |
| `read_charge_records`        | Vehicle Charge Management (vehicle\_charging\_cmds) |
| `read_charge`                | Vehicle Information (vehicle\_device\_data)         |
| `read_climate`               | Vehicle Information (vehicle\_device\_data)         |
| `read_compass`               | Vehicle Information (vehicle\_device\_data)         |
| `read_engine_oil`            | Vehicle Information (vehicle\_device\_data)         |
| `read_extended_vehicle_info` | Vehicle Information (vehicle\_device\_data)         |
| `read_fuel`                  | Vehicle Information (vehicle\_device\_data)         |
| `read_location`              | Vehicle Location (vehicle\_location)                |
| `read_odometer`              | Vehicle Information (vehicle\_device\_data)         |
| `read_security`              | Vehicle Information (vehicle\_device\_data)         |
| `read_speedometer`           | Vehicle Information (vehicle\_device\_data)         |
| `read_thermometer`           | Vehicle Information (vehicle\_device\_data)         |
| `read_tires`                 | Vehicle Information (vehicle\_device\_data)         |
| `read_user_profile`          | Profile Information (user\_data)                    |
| `read_vehicle_info`          | Vehicle Information (vehicle\_device\_data)         |
| `read_vin`                   | Vehicle Information (vehicle\_device\_data)         |


# Tesla FAQs
Source: https://smartcar.com/docs/help/oem-integrations/tesla/faqs

FAQs on our new Tesla integration. For an overview of the changes see [this page](https://smartcar.com/docs/help/oem-integrations/tesla/whats-new).

#### What happens if I connect to one of my applications with the legacy flow and another with the new flow?

As long as you have access to the same set of permissions on Tesla’s side and have added our virtual key there will not be any conflicts while the legacy API is active.

#### If my users have more than one Tesla on their account, will they need to add the virtual key to all of their vehicles?

Yes. You will need to add our virtual key to each vehicle on the Tesla account.

#### What happens if I issue a command but Smartcar’s virtual key hasn’t been added to the vehicle?

We will throw a `CONNECTED_SERVICES_ACCOUNT:VIRTUAL_KEY_REQUIRED` error.

## Do all vehicles need a virtual key?

2020 and earlier Model S and X **do not** require a virtual key installation. However, these vehicles can support streaming data access (faster, more frequent updates) if the owner enables a streaming toggle within the vehicle settings. Smartcar Connect will prompt users about this option and can send email instructions on how to enable it.

Older models without streaming enabled, Smartcar will poll these vehicles in the background every 5 minutes for data. These requests **will not** wake the vehicle.

#### How can users enable streaming for 2020 and earlier Model S/X?

During the Smartcar Connect flow, users will be prompted to enable streaming for eligible vehicles. They can request email instructions that will guide them through toggling the streaming setting in their vehicle's infotainment screen. This does not require Virtual Key installation.

#### What happens if a user does not add a virtual key for vehicles that support streaming?

If a vehicle is streaming capable via virtual key and does not yet have a virtual key installed,
requests to the vehicle will be limited to 1 request every 8 hours for data. These requests **will
not** wake the vehicle. Older models that are streaming capable via in-vehicle toggle, will continue to be polled every 5 minutes for data if the toggle is off.

#### What happens if I issue a command but the owner has revoked access through their Tesla portal?

We will throw a `CONNECTED_SERVICES_ACCOUNT:PERMISSION` error.

#### What happens if a user doesn’t select the correct permissions on Tesla’s side?

Connect maps Tesla’s permissions to Smartcar’s and only grants your application access to the ones requested. If we do not get the corresponding permission from Tesla, we will not grant your application access and throw the `PERMISSION:NULL` error as per usual when you make an API request.

Your users will need to [revoke access](/docs/help/oem-integrations/tesla/faqs#how-can-my-users-update-their-permissions-with-tesla) through the Tesla portal, then step through the flow again in order to fix this.

#### How can I tell which cars have gone through the new flow?

The [Migration Status](/docs/api-reference/tesla/get-migration-status) make specific endpoint indicates if a vehicle still needs to be migrated to Tesla's new API.

#### Can owner and driver accounts authorize access with Smartcar through Connect?

Yes. Either account type can go through the Connect flow. As long as the Tesla account is attached to the vehicle, you can make requests to it.

#### Does the user need to be next to vehicle when adding a virtual key?

Owner accounts can add a virtual key remotely. Driver accounts need to be in
Bluetooth range in order to add a virtual key.

#### Can driver accounts add a virtual key?

Yes. However, driver accounts can only pair virtual keys via Bluetooth. They
cannot add a virtual key remotely.

#### Why are my users are seeing a location sharing notification on their navigation unit?

With the [recent changes to data
access](/docs/help/oem-integrations/tesla/whats-new), vehicles will transmit their
live location if your application has requested access to location data. This
notification was put in place by Tesla to ensure transparency for owners about
what data is being shared and with whom.

The domain displayed will match the Virtual Key for your application.

<img />

#### How can my users update their permissions with Tesla?

Please [this guide](/docs/help/oem-integrations/tesla/developers#updating-access-with-tesla) for details on how to do facilitate this for your users.


# Virtual Keys
Source: https://smartcar.com/docs/help/oem-integrations/tesla/virtual-key-tesla

This page has information regarding the use of Virtual Keys for Tesla vehicles.

## What is a Virtual Key?

A Virtual Key is a digital access method required by Tesla for third-party
applications to issue commands to Tesla vehicles and the preferred method for accessing data.
Please see [this
section](/docs/help/oem-integrations/tesla/developers#adding-a-virtual-key)
for more information.

### Adding the Virtual Key

Smartcar handles this step on your behalf in the Connect flow. You can get started with the default Smartcar Virtual Key with no configurations required.

If you're on an **Enterprise** plan, please reach out to your Account Manager or
Solutions Architect for information on setting up a custom Virtual Key with your own brand name.

## Where can I find my Virtual Key?

Although Smartcar handles this step on your behalf, the Virtual Key URL for your application is sent back along with the authorization code after a user completes the Connect flow. You can redirect users to this URL if they need to add the Virtual Key again.

### Vehicle Owners adding a Virtual Key

Smartcar Connect will present Tesla vehicle owners a prompt to install the Tesla Virtual Key after granting access and prior to redirecting them back to your application.

<Frame>
  <img />
</Frame>

The Virtual Key is a URL in the form:

<Tabs>
  <Tab title="Free or Build Plans">
    ```
    https://www.tesla.com/_ak/smartcar.com
    ```
  </Tab>

  <Tab title="Enterprise Plan">
    ```
    https://www.tesla.com/_ak/{{custom_subdomain}}.app.car
    ```
  </Tab>
</Tabs>

After prompting your users to open the link, depending on their device, they will be redirected to the Tesla app or prompted to scan a QR code.

<Tip>
  Adding a Virtual Key will need to be done after a user has granted your application access to their Tesla account in the Connect flow.

  Please see our [FAQs](/docs/help/oem-integrations/tesla/faqs#can-owner-and-driver-accounts-authorize-access-with-smartcar-through-connect) for details on adding a virtual key for accounts with multiple vehicles and different account types.
</Tip>

<Tabs>
  <Tab title="Mobile Device">
    On mobile devices, they will be redirected to the Tesla app and prompted to add the Virtual Key

    <Frame>
      <img />
    </Frame>
  </Tab>

  <Tab title="Desktop">
    On Desktop, they will be prompted to scan the QR code which in turn opens up the Tesla app and prompts them to add a Virtual Key

    <Frame>
      <img />
    </Frame>
  </Tab>
</Tabs>

Virtual Key status can be checked at any time from the Tesla infotainment screen under Settings, Locks.

<Frame>
  <img />
</Frame>

## Do all vehicles need a virtual key?

2020 and earlier Model S and X **do not** require a virtual key installation. However, to enable streaming data access (faster, more frequent updates), owners can enable streaming by toggling a setting within the vehicle.

### Enabling Streaming for 2020 and Earlier Model S/X

For 2020 or earlier Model S or X that supports streaming (requires a software update), users can enable streaming without installing a Virtual Key:

1. During the Smartcar Connect flow, drivers will be prompted about enabling streaming for their vehicle
2. Drivers can choose to receive email instructions on how to enable the streaming toggle in their vehicle
3. Access the streaming settings from the Tesla infotainment screen
4. Toggle the streaming setting on to enable faster data updates

Once streaming is enabled via the vehicle toggle, data will be refreshed more frequently without requiring Virtual Key installation for these modals. If streaming toggle is not enabled, data for these older models is refreshed every 5 minutes while the vehicle is awake.

## What if a streaming capable vehicle does not have a virtual key installed?

If a vehicle is streaming capable via virtual key and does not yet have a virtual key installed,
requests to the vehicle will be limited to 1 request every 8 hours for data. These requests **will
not** wake the vehicle.


# Important Updates
Source: https://smartcar.com/docs/help/oem-integrations/tesla/whats-new

Upcoming changes to data access and permissions in 2025

## May 20, 2025

Smartcar now handles adding Virtual Keys for Tesla vehicles on your behalf in the Connect flow. Virtual Keys are required for third-party applications to issue commands to Tesla vehicles and are the preferred method for accessing data.

<Frame type="simple">
  <img />
</Frame>

For more details, visit the [Virtual Key documentation](/docs/help/oem-integrations/tesla/virtual-key-tesla).

## January 10, 2025

Starting in March 2025, Tesla will require a new permission to access live
location data for its vehicles. Due to this change, you have two options:

**If your application needs live location data:**<br />
Users will need to reauthenticate and grant explicit access to the Vehicle
Location permission to continue receiving location data beyond March 2025, if
they haven’t already done so. This permission was previously included as part of
the Vehicle Information permission.

**If your application only needs to know whether the vehicle is at home:**<br />
A new boolean value will be available soon, and it will not require
reauthentication. Vehicle owners can set their home location in the Tesla
application.

### Why is this change occurring?

Tesla now provides users more granular data access control, and requires vehicle
owners to explicitly consent to sharing location data with 3rd parties like
Smartcar. This ultimately gives drivers more control and awareness of how and
what data they decide to share.

### Next steps if you need live location data

**1. Check existing permissions** <br />
Use the [User Access](/docs/api-reference/tesla/get-user-access) endpoint to verify whether a vehicle has already
been granted the required permission on Tesla's side.

**2. Update Smartcar Connect scopes**<br />
To ensure vehicle owners grant the new permission, append `required:` to your
scopes in the Smartcar Connect URL (for example, `required:read_location`). For
detailed instructions, please refer to [this guide](/docs/help/oem-integrations/tesla/developers#requiring-tesla-permissions).

**3. Prompt users to reauthenticate**<br />
If needed, guide users to reauthenticate their Tesla vehicles using the methods outlined
[here](/docs/help/oem-integrations/tesla/developers#updating-access-with-tesla).

<br />

<Warning>
  If the Vehicle Location permission isn’t granted by March 2025, you may
  encounter a `PERMISSION` error. As a result, your
  application will no longer receive live location data from affected Tesla
  vehicles until they reauthenticate.
</Warning>

## December 19, 2024

Starting **January 21, 2025**, a Virtual Key will be required to maintain access to
Tesla vehicle data. Failure to make the necessary changes could result in a
disruption to your service after this date. Below, we’ve outlined the steps you
need to take to prepare, depending on your situation.

### For new developers

If you're on an **Enterprise** plan, please reach out to your Account Manager or
Solutions Architect for information on setting up your own Virtual Key.

**Free** and **Build** customers can get started with the default Virtual Key.

### For existing developers

<AccordionGroup>
  <Accordion title="I'm using an app.car subdomain that Smartcar has created for me">
    **What’s changing?**

    Telsa is changing the way data can be accessed by 3rd party applications.

    **What do you need to do?**

    To ensure continuous data access, please have your users add your Virtual Key to
    their vehicles if they haven’t already.  They can follow [this
    guide](https://smartcar.com/docs/help/oem-integrations/tesla/developers#adding-a-virtual-key)
    for more information. If you already prompt users to add a Virtual Key as your
    application issues commands - no additional work is needed, please continue to
    do so.

    **What is a Virtual Key?**

    A virtual key is a digital access method required by Tesla for third-party
    applications to receive vehicle data and issue commands to Tesla vehicles.
    Please see [this
    guide](https://smartcar.com/docs/help/oem-integrations/tesla/developers#adding-a-virtual-key)
    for more information.

    **Where can I find my Virtual Key?**

    The Virtual Key URL for your application will be sent back along with the
    authorization code after a user completes the Connect flow.
    Alternatively, you can reach out to Support or your Account Manager and they'll be able to provide
    it to you.

    **What happens if my users do not add my Virtual Key?**

    Starting January 21, 2025 you will not be able to get data from Tesla vehicles
    you are connected to and will receive a `virtual_key_required` error instead
    ([docs](https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#virtual-key-required)).

    **What about vehicles that do not support Virtual Keys?**

    2020 and earlier Model S and X **do not** require a Virtual Key installation. However, these vehicles can support streaming data access if the owner enables a streaming toggle within the vehicle settings. Smartcar Connect will prompt users about this option and can send email instructions. Without streaming enabled, you may not always receive the latest data from the vehicle when you make an API request to Smartcar.

    **Will my users need to reauthenticate?**

    No. They simply need to add the Virtual Key to their vehicle.
  </Accordion>

  <Accordion title="I'm using Smartcar's default Tesla application">
    **What’s changing?**

    Tesla is changing the way data can be accessed by 3rd party applications.

    **What do you need to do?**

    To ensure continuous data access, please have your users add your Virtual Key to their vehicles if they haven’t already.  They can
    follow [this
    guide](https://smartcar.com/docs/help/oem-integrations/tesla/developers#adding-a-virtual-key)
    for more information. If you already prompt users to add a Virtual Key as your
    application issues commands - no additional work is needed, please continue to
    do so.

    **What is a Virtual Key?**

    A virtual key is a digital access method required by Tesla for third-party
    applications to receive vehicle data and issue commands to Tesla vehicles.
    Please see [this
    guide](https://smartcar.com/docs/help/oem-integrations/tesla/developers#adding-a-virtual-key)
    for more information.

    **Where can I find my Virtual Key?**

    The Virtual Key URL for your application will be sent back along with the
    authorization code after a user completes the Connect flow. The Virtual Key URL
    is:
    [`https://www.tesla.com/_ak/smartcar.com`](https://www.tesla.com/_ak/smartcar.com)

    **What happens if my users do not add my Virtual Key?**

    Starting January 21, 2025 you will not be able to get data from Tesla vehicles
    you are connected to and will receive a `virtual_key_required` error instead
    ([docs](https://smartcar.com/docs/errors/api-errors/connected-services-account-errors#virtual-key-required)).

    **What about vehicles that do not support Virtual Keys?**

    2020 and earlier Model S and X **do not** require a Virtual Key installation. However, these vehicles can support streaming data access if the owner enables a streaming toggle within the vehicle settings. Smartcar Connect will prompt users about this option and can send email instructions. Without streaming enabled, you may not always receive the latest data from the vehicle when you make an API request to Smartcar.

    **Will my users need to reauthenticate?**

    No. They simply need to add the Virtual Key to their vehicle.
  </Accordion>
</AccordionGroup>


# Important Updates
Source: https://smartcar.com/docs/help/oem-integrations/volvo/whats-new

Updates regarding the Volvo Cars Smartcar Integration.

## May 6th, 2026

Smartcar's partnership with Volvo Cars provides API access to all Volvo vehicles across the United States and Europe. The integration provides charging data, charge schedules, battery, location, odometer, closure, and fuel data through Smartcar's standardized signal schema.

### Capabilities

With this integration, you can:

* **Monitor charging status:** Get close to real-time visibility into charging state, energy flow, and vehicle range.
* **Control charging:** Create, read, and delete charge schedules to set when a Volvo vehicle charges.
* **Build smart charging solutions:** Support use cases like dynamic load balancing, demand response, off-peak optimization, and charge cost tracking.

### Supported Data

| Data Category       | Available Data                                                                    |
| ------------------- | --------------------------------------------------------------------------------- |
| Charging            | Connector type, cable connection status, charging state, detailed charging status |
| Charging Parameters | Charge timers, charge limits, time to complete, charging wattage                  |
| Battery             | State of charge (SOC), remaining electric range, nominal capacity                 |
| Closures            | Door status, window status, lock status                                           |
| Fuel                | Fuel level, fuel remaining, fuel range                                            |
| Location            | Last-parked location                                                              |
| Odometer            | Total traveled distance                                                           |

### Smartcar Signals

* [Charge.IsChargingCableConnected](/docs/api-reference/signals/charge#is-charging-cable-connected)
* [Charge.IsCharging](/docs/api-reference/signals/charge#is-charging)
* [Charge.DetailedChargingStatus](/docs/api-reference/signals/charge#detailed-charging-status)
* [Charge.ChargingConnectorType](/docs/api-reference/signals/charge#charging-connector-type)
* [Charge.ChargeTimers](/docs/api-reference/signals/charge#charge-timers)
* [Charge.ChargeLimits](/docs/api-reference/signals/charge#charge-limits)
* [Charge.TimeToComplete](/docs/api-reference/signals/charge#time-to-complete)
* [Charge.Wattage](/docs/api-reference/signals/charge#wattage)
* [Closure.Doors](/docs/api-reference/signals/closure#doors)
* [Closure.Windows](/docs/api-reference/signals/closure#windows)
* [Closure.IsLocked](/docs/api-reference/signals/closure#is-locked)
* [InternalCombustionEngine.AmountRemaining](/docs/api-reference/signals/internalcombustionengine#amount-remaining)
* [InternalCombustionEngine.FuelLevel](/docs/api-reference/signals/internalcombustionengine#fuel-level)
* [InternalCombustionEngine.Range](/docs/api-reference/signals/internalcombustionengine#range)
* [TractionBattery.StateOfCharge](/docs/api-reference/signals/tractionbattery#state-of-charge)
* [TractionBattery.Range](/docs/api-reference/signals/tractionbattery#range)
* [TractionBattery.NominalCapacity](/docs/api-reference/signals/tractionbattery#nominal-capacities)
* [Location.PreciseLocation](/docs/api-reference/signals/location#location)<sup>1</sup>
* [Odometer.TraveledDistance](/docs/api-reference/signals/odometer#traveled-distance)

### Charge Schedules

Charge schedules apply to BEV and PHEV Volvo vehicles. Apps can set up to ten location-based charge schedules per vehicle. Target state of charge is set independently from charge schedules on Volvo.

Available endpoints:

* `POST /v3.0/vehicles/{id}/schedules/charge-daily`, `charge-workweek`, and `charge-weekly`
* `GET /v3.0/vehicles/{id}/schedules`
* `DELETE /v3.0/vehicles/{id}/schedules/{scheduleId}`

Existing schedules can also be retrieved via Webhooks or by issuing a GET request to the [`Charge.ChargeTimers`](/docs/api-reference/signals/charge#charge-timers) signal.

### Commands

* Lock
* Unlock

### Coverage

**Supported Vehicles**

This integration supports all Volvo vehicles regardless of powertrain type, including Internal Combustion Engine (ICE), Battery Electric Vehicle (BEV), and Plug-in Hybrid Electric Vehicle (PHEV) models. Charge commands are not yet available for PHEV Classic models (without built-in Google Automotive Systems).

**Supported Markets**

* **Europe:** European Economic Area (EEA) countries plus United Kingdom and Switzerland
* **United States:** Full US coverage

### Consent Flow

Vehicle owners grant consent through Volvo's official portal as part of the Smartcar Connect flow. During this process, they:

1. Log in with their Volvo ID
2. Select the vehicle(s) to connect
3. Review the requested permissions
4. Accept Volvo's terms for data sharing

<Frame type="simple">
  <img />
</Frame>

<Frame type="simple">
  <img />
</Frame>

### Notes

* \***Location<sup>1</sup>:** Location is not live tracked. The location signal provides the last known GPS position when the ignition was turned off.

For more information about compatible vehicle data and features, see the [compatibility matrix](https://smartcar.com/product/compatible-vehicles).


# Important Updates
Source: https://smartcar.com/docs/help/oem-integrations/vw/whats-new

Updates regarding the Volkswagen Smartcar Integration.

## May 20th, 2026

Smartcar's partnership with Volkswagen Group spans all Smartcar-supported regions (US, Canada, and Europe). In the US and Canada, drivers of Volkswagen and Audi vehicles connect through Volkswagen's official consent flow as part of Smartcar Connect. In Europe, the same flow extends to Volkswagen, Audi, ŠKODA, CUPRA, and SEAT BEV and PHEV vehicles.

### Capabilities

With this integration, you can:

* **Monitor charging status:** Get close to real-time visibility into charging state, plug connection, charging power, and time to complete.
* **Track battery and range:** Read state of charge, remaining electric range, and nominal battery capacity.
* **Control charging remotely:** Start and stop charging sessions on demand.
* **Read odometer:** Total distance traveled.

### Commands

* Charge Start
* Charge Stop

### Coverage

The Volkswagen Group integration is available across all Smartcar-supported regions (US, Canada, and Europe). In Europe, the integration is available for Battery Electric (BEV) and Plug-in Hybrid Electric (PHEV) vehicles.

For data and command availability by make, model, year, region, and powertrain type, see the [compatibility matrix](https://smartcar.com/product/compatible-vehicles).

### Consent Flow

Vehicle owners grant consent through Volkswagen's official portal as part of the Smartcar Connect flow. The exact steps differ by region.

#### United States and Canada

Vehicle owners are redirected to Volkswagen's login page to authenticate, select their vehicles, and accept Volkswagen's terms.

<Frame type="simple">
  <img />
</Frame>

After completing the flow, vehicle owners will receive an email from Volkswagen notifying them of new services being added to their account.

<Frame type="simple">
  <img />
</Frame>

Vehicle owners can revoke access to Smartcar-powered applications at any time through the myVW Mobile App or by logging into their Volkswagen account online.

Drivers can check their role in the myVW app by navigating to **Account > Vehicle Management > Additional Users**. The primary driver is labeled as "Primary user".

<Frame type="simple">
  <img />
</Frame>

<Frame type="simple">
  <img />
</Frame>

<Frame type="simple">
  <img />
</Frame>

<Frame type="simple">
  <img />
</Frame>

#### Europe

Drivers can use their connected services account credentials to authenticate. In some cases, drivers may be asked to provide their Vehicle Identification Number (VIN) and current odometer reading as an alternate authentication method.

### Notes

* Only the primary account holder on the Volkswagen account can authorize access. Secondary drivers cannot complete the consent flow.
* For data freshness and polling frequency, see [Data frequencies for Volkswagen](/docs/help/frequencies).


# Reliability
Source: https://smartcar.com/docs/help/reliability-and-freshness

When making requests to vehicles, there is variation in how often data is updated and how many requests it can process in a given period. The tables below indicate the performance for each of Smartcar supported brands in each region.

**Data Reliability**<br />
This ranking represents how reliably the vehicle or OEM processes data requests. A rank of 1 indicates the highest reliability.

**Command Reliability**<br />
This ranking measures the effectiveness with which the vehicle or OEM handles command requests. A score of 1 reflects the most reliable command execution. N/A means there is not enough data to provide a score.

***

## United States

| <div>Brand</div> | <div>Data Reliability</div> | <div>Command Reliability</div> |
| ---------------- | --------------------------- | ------------------------------ |
| ACURA            | 1                           | 1                              |
| ALFA ROMEO       | 1                           | 1                              |
| AUDI             | 1                           | 2                              |
| BMW              | 1                           | 2                              |
| BUICK            | 1                           | 1                              |
| CADILLAC         | 1                           | 2                              |
| CHEVROLET        | 1                           | 3                              |
| CHRYSLER         | 1                           | 2                              |
| DODGE            | 1                           | 2                              |
| FIAT             | 1                           | N/A                            |
| FORD             | 1                           | 3                              |
| GMC              | 1                           | 2                              |
| HONDA            | 1                           | 2                              |
| HYUNDAI          | 1                           | 2                              |
| INFINITI         | 3                           | N/A                            |
| JAGUAR           | 1                           | 3                              |
| JEEP             | 1                           | 2                              |
| KIA              | 1                           | 3                              |
| LAND ROVER       | 1                           | 3                              |
| LEXUS            | 1                           | 3                              |
| LINCOLN          | 1                           | 3                              |
| MAZDA            | 1                           | 2                              |
| MERCEDES BENZ    | 1                           | 1                              |
| MINI             | 1                           | 1                              |
| NISSAN           | 1                           | 2                              |
| PORSCHE          | 1                           | 3                              |
| POLESTAR         | 1                           | N/A                            |
| RAM              | 2                           | 1                              |
| RIVIAN           | 1                           | 1                              |
| TESLA            | 1                           | 1                              |
| TOYOTA           | 1                           | 3                              |
| VOLKSWAGEN       | 1                           | 2                              |
| VOLVO            | 1                           | N/A                            |

## Canada

| <div>Brand</div> | <div>Data Reliability</div> | <div>Command Reliability</div> |
| ---------------- | --------------------------- | ------------------------------ |
| ACURA            | 1                           | N/A                            |
| AUDI             | 1                           | 1                              |
| BMW              | 1                           | 1                              |
| BUICK            | 1                           | N/A                            |
| CADILLAC         | 1                           | 2                              |
| CHEVROLET        | 1                           | 2                              |
| DODGE            | 1                           | 1                              |
| FIAT             | 1                           | N/A                            |
| FORD             | 1                           | N/A                            |
| GMC              | 1                           | 1                              |
| HONDA            | 1                           | N/A                            |
| HYUNDAI          | 2                           | 1                              |
| JAGUAR           | 1                           | 3                              |
| JEEP             | 1                           | 3                              |
| KIA              | 1                           | 1                              |
| LEXUS            | 1                           | 3                              |
| MINI             | 2                           | 1                              |
| RAM              | 1                           | 1                              |
| TESLA            | 1                           | 1                              |
| TOYOTA           | 1                           | 3                              |
| VOLVO            | 1                           | N/A                            |

## Europe

| <div>Brand</div> | <div>Data Reliability</div> | <div>Command Reliability</div> |
| ---------------- | --------------------------- | ------------------------------ |
| ALFA ROMEO       | 1                           | N/A                            |
| AUDI             | 1                           | 1                              |
| BMW              | 1                           | 1                              |
| BYD              | 1                           | N/A                            |
| CITROEN          | 1                           | 1                              |
| CUPRA            | 1                           | 1                              |
| DACIA            | 1                           | 1                              |
| DS               | 1                           | N/A                            |
| FIAT             | 1                           | 1                              |
| FORD             | 2                           | 3                              |
| HYUNDAI          | 1                           | 2                              |
| JAGUAR           | 1                           | 3                              |
| JEEP             | 1                           | N/A                            |
| KIA              | 1                           | 1                              |
| LAND ROVER       | 1                           | N/A                            |
| MAZDA            | 1                           | 1                              |
| MERCEDES BENZ    | 1                           | 1                              |
| MG               | 1                           | 1                              |
| MINI             | 1                           | 1                              |
| NISSAN           | 1                           | 3                              |
| OPEL             | 1                           | 1                              |
| PEUGEOT          | 1                           | 1                              |
| PORSCHE          | 1                           | 3                              |
| POLESTAR         | 1                           | N/A                            |
| RENAULT          | 1                           | 1                              |
| SEAT             | 1                           | 1                              |
| SKODA            | 1                           | 1                              |
| TESLA            | 1                           | 2                              |
| VAUXHALL         | 1                           | N/A                            |
| VOLKSWAGEN       | 1                           | 2                              |
| VOLVO            | 1                           | 1                              |


# Join the Research Fleet
Source: https://smartcar.com/docs/help/research-fleet



Smartcar is the easiest way to integrate apps with cars, funded by [a16z](https://a16z.com/), [NEA](https://www.nea.com/) and [Energize Capital](https://www.energizecap.com/).\
We enable companies like [Uber](https://smartcar.com/blog/uber), [Lyft](https://smartcar.com/blog/lyft), [Emulate](https://smartcar.com/blog/emulate), [Bluewave](https://smartcar.com/blog/bluwave-ai), [Neowatt](https://smartcar.com/blog/revenue-for-energy-retailers), and [more](https://smartcar.com/customers) to monitor a car's battery state of charge, verify mileage, manage EV charging, and much more.

We are always expanding to new makes and models of cars and we'd love your help!

## What are we asking for?

Building and maintaining our APIs is a complex endeavor. Smartcar operates a research fleet of vehicles across brands, models, and geographies to ensure we can provide the best product possible. **This is where you come in**. We'd like your help with understanding real-world vehicle behaviors with your car and improve the quality of our platform. Understanding things like:

* Does your car’s odometer update in real-time?
* What's the amount of fuel/battery your car has remaining?
* What data and remote actions are available for your specific car's brand, model, year?

## Perks of being part of the Research Fleet

* 💰 You will receive \$250 for the 6 months that your car is part of the fleet
* 🧥 Smartcar swag
* 🙋 Assistance setting up your car's connected services

## Sign up

<iframe />

## FAQs

<AccordionGroup>
  <Accordion title="How and when will I get paid?">
    The Smartcar team will schedule a check to be sent to your preferred address if your car is verified to be eligible for the Smartcar Research Fleet.
  </Accordion>

  <Accordion title="What exactly will Smartcar do with my car?">
    Smartcar will use your vehicle to retrieve and verify key data points such as your odometer and fuel tank/battery level. The team will inform you of all data and actions they will retrieve from your vehicle and the schedule at which they will be performing the verification. No action will be perfomed remotely without your permission.
  </Accordion>

  <Accordion title="How can I opt-out of the program?">
    You may opt-out at any point without any explanation. We simply ask that you give us a heads up that you no longer wish to participate by reaching out to [support@smartcar.com](mailto:support@smartcar.com).
  </Accordion>
</AccordionGroup>


# Subscribing to Smartcar Updates and Notifications
Source: https://smartcar.com/docs/help/smartcar-updates

Sign up for product announcements, marketing emails, changelog alerts, and status notifications so you can stay up to date with Smartcar.

Stay informed about Smartcar's latest updates, maintenance windows, and platform status by subscribing to our communication channels.

### Product Updates and Marketing Emails

Subscribe to receive product announcements, feature releases, and other important updates:

1. Visit the [Smartcar Marketing Preferences](https://smartcar.com/newsletter) page.
2. Enter your email address.
3. Select your communication preferences.
4. Click **Subscribe** to receive updates.

### Changelog Updates

Stay up to date with the latest product changes and improvements:

* Visit the [Smartcar Changelog](/docs/changelog/latest) to view recent updates.
* Subscribe to changelog notifications through your Smartcar Dashboard settings.

### Smartcar Status Page

Monitor the real-time status of the Smartcar platform and subscribe to incident notifications:

1. Visit [status.smartcar.com](https://status.smartcar.com).
2. Click **Subscribe to Updates** in the top-right corner.
3. Choose your preferred notification method:
   * **Email** - Receive notifications via email
   * **SMS** - Get text message alerts (mobile number required)
   * **Webhook** - Integrate status updates into your systems
   * **Slack** - Receive notifications in your Slack workspace
   * **RSS** - Subscribe via RSS feed
4. Select which components you want to monitor.
5. Choose the types of incidents you want to be notified about (e.g., all incidents or only major outages).

### Brand Reliability Status Page

Monitor the status of individual vehicle brands and their APIs:

1. Visit [brandreliability.smartcar.com](https://brandreliability.smartcar.com).
2. Click **Subscribe to Updates** in the top-right corner.
3. Choose your preferred notification method (Email, SMS, Webhook, Slack, or RSS).
4. Select specific vehicle brands you want to monitor or choose "All Components" for comprehensive coverage.
5. Configure your notification preferences for different incident types.

<Info>
  By subscribing to these channels, you'll receive proactive notifications about planned maintenance, service disruptions, and platform updates that may affect your integration.
</Info>


# Vehicle Simulator
Source: https://smartcar.com/docs/help/vehicle-simulator

Learn about what to expect from Vehicle Simulator and how it compares to Live mode.

Vehicle Simulator allows you to test your application in realistic scenarios with a simulated Smartcar-compatible vehicle. Simulator responds to API requests just like a real vehicle. You can choose a simulated trip for your vehicle to take, and track it over time.

You can use the simulator for initial testing before you have a real vehicle to connect, or as part of an end-to-end testing suite.

## Creating a Simulated Vehicle

Simulated vehicles are managed in the Smartcar Dashboard.

Select "Add a vehicle" and select a vehicle by Make, Model, and Year, or provide a VIN for a US-based vehicle that you want to simulate. You'll be able to preview the API endpoints that are supported for the vehicle model you select.

Once you create your simulated vehicle, you'll select a simulated trip profile that the vehicle will follow. This profile can run automatically over time, or you can manually select a stage of the trip for the vehicle in the Dashboard.

## Connecting a Simulated Vehicle

Simulated vehicles generate a special set of credentials that mimic what a real-world vehicle owner would have. You'll use these credentials to establish a vehicle connection through the same Smartcar Connect flow that you will use for live vehicles.

In order for Connect to know you're using credentials generated from Vehicle Simulator, you'll need to pass `mode=simulated` in the [Connect URL](/docs/connect/redirect-to-connect).

<Info>
  Please ensure you're passing or changing the country flag for Connect based on the region you've created your vehicle for.
  Failure to do so will result in an invalid credential error on login. You can read more about country selection for Connect [here](/docs/connect/advanced-config/country-flag).
</Info>

<AccordionGroup>
  <Accordion title="SDKs">
    You can set `mode` in the auth client builder to `simulated`.
  </Accordion>

  <Accordion title="No SDK">
    You'll need to pass `mode=simulated` in the Connect URL
  </Accordion>
</AccordionGroup>

## Making requests to a Simulated Vehicle

Once your simulated vehicle is connected, you can make API requests to it just as you would a real vehicle.

Supported endpoints for the simulated vehicle will send responses with simulated data - unsupported endpoints will return errors just as they would with a real vehicle.

You can also send commands to simulated vehicles, like start/stop charge or lock/unlock doors. These requests will send responses that mimic that of a real vehicle, but the vehicle state will continue to reflect the simulated trip that was selected.

## Expected Responses

### Data

| Permission          | Request Method / Path | Example Response                                                                            |
| ------------------- | --------------------- | ------------------------------------------------------------------------------------------- |
| `read_engine_oil`   | GET /engine/oil       | `{ lifeRemaining: 0.35 }`                                                                   |
| `read_battery`      | GET /battery          | `{ percentRemaining: 0.3, range: 40.5 }`                                                    |
| `read_battery`      | GET /battery/capacity | `{ capacity: 28 }`                                                                          |
| `read_charge`       | GET /charge           | `{ isPluggedIn: true, state: 'FULLY_CHARGED' }`                                             |
| `read_charge`       | GET /charge/limit     | `{ limit: 1 }`                                                                              |
| `read_fuel`         | GET /fuel             | `{ amountRemaining: 53.2, percentRemaining: 0.3, range: 40.5 }`                             |
| `read_location`     | GET /location         | `{ latitude: 37.4292, longitude: 122.1382 }`                                                |
| `read_odometer`     | GET /odometer         | `{ distance: 104.32 }`                                                                      |
| `read_tires`        | GET /tires/pressure   | `{ backLeft: 219.3, backRight: 219.3, frontLeft: 219.3, frontRight: 219.3 }`                |
| `read_vehicle_info` | GET /                 | `{ id: 36ab27d0-fd9d-4455-823a-ce30af709ffc, make: "TESLA", model: "Model S", year: 2014 }` |
| `read_vin`          | GET /vin              | `{ vin: 1234A67Q90F2T4567 }`                                                                |

### Commands

Below are the various action requests that can be made to simulated vehicles, and what responses to expect based on the simulated vehicle's current state or simulator support.

Not listed here are the standard API errors that will be returned if the vehicle does not support the capability or the application has not been granted permission.

| Permission         | Request (method / path) | Action request | Vehicle state                     | Response                                                       |
| ------------------ | ----------------------- | -------------- | --------------------------------- | -------------------------------------------------------------- |
| `control_security` | POST /security          | `LOCK`         | Parked / Charging                 | `{ status: "success" }`                                        |
| `control_security` | POST /security          | `UNLOCK`       | Parked / Charging                 | `{ status: "success" }`                                        |
| `control_security` | POST /security          | `LOCK`         | Driving                           | `{ type: VEHICLE_STATE, code: IN_MOTION }`                     |
| `control_security` | POST /security          | `UNLOCK`       | Driving                           | `{ type: VEHICLE_STATE, code: IN_MOTION }`                     |
| `control_charge`   | POST /charge            | `START`        | Charging                          | `{ status: "success" }`                                        |
| `control_charge`   | POST /charge            | `STOP`         | Charging                          | `{ status: "success" }`                                        |
| `control_charge`   | POST /charge            | `STOP`         | Parked / Driving (not plugged in) | `{ type: VEHICLE_STATE, code: CHARGING_PLUG_NOT_CONNECTED }`   |
| `control_charge`   | POST /charge            | `START`        | Parked / Driving (not plugged in) | `{ type: VEHICLE_STATE, code: CHARGING_PLUG_NOT_CONNECTED }`   |
| `control_charge`   | POST /charge-limit      | `<limit>`      | Charging                          | `{ "type": "COMPATIBILITY", "code": "SMARTCAR_NOT_CAPABLE", }` |
| `control_charge`   | POST /charge-limit      | `<limit>`      | Parked / Driving (not plugged in) | `{ type: VEHICLE_STATE, code: CHARGING_PLUG_NOT_CONNECTED }`   |

### Errors

| Event                                                                                                               | Error response                                                                     | Suggested resolution                                                                                                                                                                                                                                                                      |
| ------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Making an API request to a simulated vehicle before connecting the vehicle to your application via Smartcar Connect | `{ type: "PERMISSION", statusCode: 403, resolution: "REAUTHENTICATE" }`            | Locate the 'Connect Credentials' button at the top of the simulation screen in the Smartcar Dashboard for your simulated vehicle. There you will find the credentials necessary to connect the vehicle to your application as well as instructions for doing so through Smartcar Connect. |
| Making an API request to a simulated vehicle before a simulation has been started on Dashboard                      | `{ type: "CONNECTED_SERVICES_ACCOUNT", code: "ACCOUNT_ISSUE", statusCode: 400 }`   | Open the Simulator tab in the Smartcar Dashboard and navigate to your target vehicle. If you haven't yet selected a vehicle state, do so now, and then start the simulation using the 'Play' button on the simulation screen.                                                             |
| Making an API request to a simulated vehicle that is not associated with  your application                          | `{ type: "CONNECTED_SERVICES_ACCOUNT", code: "VEHICLE_MISSING", statusCode: 400 }` | Ensure the simulated vehicle you are making requests to has been created in the Simulator within your Smartcar Dashboard.                                                                                                                                                                 |

## Mode Comparison

| <div />Feature                                              | <div />Simulator | <div />Live |   |
| ----------------------------------------------------------- | ---------------- | ----------- | - |
| Single Select                                               | ✅                | ✅           |   |
| Brand Select                                                | ✅                | ✅           |   |
| [Compatible Vehicles](/docs/api-reference/compatible-vehicles)\* | ✅                | ✅           |   |
| `control_security`                                          | ✅                | ✅           |   |
| `control_charge`                                            | ✅                | ✅           |   |
| Make-Specific Endpoints                                     | ❌                | ✅           |   |
| Scheduled Webhooks                                          | ❌                | ✅           |   |
| Event Based Webhooks\*\*                                    | ❌                | ✅           |   |

<sub>
  <sup>
    \*When a real VIN is used either through `VIN@smartcar` for `test` mode, or generating a simulated vehicle with a real VIN.
  </sup>

  <sup>
    0SC and 1SC prefixed VINs will not work.
  </sup>
</sub>

<sub>
  <sup>
    \*\*For supported brands - Toyota, Ford and Tesla.
  </sup>
</sub>

## FAQs

<AccordionGroup>
  <Accordion title="How are tokens handled?">
    Smartcar uses the OAuth 2.0 Client Credentials flow for API authentication. Your application obtains a single application-level access token that works across all connected vehicles, including simulated ones.

    * Access tokens are valid for **1 hour**
    * There is no refresh token — request a new token when the current one expires
    * The same token works for all vehicles connected to your application

    See the [API Authentication Overview](/docs/api-reference/authorization/overview) for more details.
  </Accordion>

  <Accordion title="Are there any limits on how many vehicles I can create?">
    The number of simulated vehicles that can be created depends on your Smartcar plan tier. Please see [here](https://smartcar.com/pricing#plans) for more information.
  </Accordion>

  <Accordion title="I'm getting an invalid credentials error when I try to sign in to a connected service account.">
    * Please check that you have launched Connect with the `mode=simulated` parameter
    * Please check that you are passing the country feature flag for the region you've set up your vehicle with.
      Please see [Country Selection](/docs/connect/advanced-config/country-flag)for Connect for more information.
  </Accordion>
</AccordionGroup>


# What is a Connected Car?
Source: https://smartcar.com/docs/help/what-is-a-connected-car

Learn about how to build applications that connect to millions of vehicles around the world.

Connected cars are vehicles that have in-built cellular modems. Most vehicles manufactured after 2015 have been shipping with this connectivity, or "embedded telematics." This essentially makes cars "smart" allowing them to communicate with the Internet. Take a look at this blog post for an in depth primer.


# What is Smartcar?
Source: https://smartcar.com/docs/help/what-is-smartcar

Learn about how to build applications that connect to millions of vehicles around the world.

The Smartcar platform allows mobility businesses to easily connect with their customers’ cars. Whether you need to track a vehicle’s location,
verify its mileage, share a virtual key, start charging an EV, monitor a car’s fuel tank level, inspect the tire pressure, or check the engine
oil life, Smartcar lets you do so with a single API request.

Take a look at the video below for a quick overview of how Smartcar works.

<Frame type="simple">
  <iframe />
</Frame>


# Architecture Patterns
Source: https://smartcar.com/docs/integrations/webhooks/best-practices/architecture

Design patterns for reliable webhook processing

The most critical pattern for reliable webhook handling is separating acknowledgment from processing.

## Decouple Receipt from Processing

**Return 200 immediately, process asynchronously.** This is the foundation of a reliable webhook integration.

<Steps>
  <Step title="Receive the webhook">
    Your endpoint receives the POST request from Smartcar
  </Step>

  <Step title="Persist immediately">
    Write the raw payload to a queue, database, or object storage
  </Step>

  <Step title="Return 200">
    Acknowledge receipt with a 200 status code (within 15 seconds)
  </Step>

  <Step title="Process asynchronously">
    A background worker processes the persisted payload
  </Step>
</Steps>

### Why This Matters

* **Prevents timeouts** from slow business logic
* **Allows retry of processing** without requesting redelivery
* **Enables processing updates** without losing historical events
* **Survives outages** in downstream systems

### Implementation Examples

<CodeGroup>
  ```javascript Node.js (Express + AWS SQS) theme={null}
  const express = require('express');
  const AWS = require('aws-sdk');

  const app = express();
  const sqs = new AWS.SQS();

  app.post('/webhooks/smartcar', async (req, res) => {
    try {
      // 1. Get the raw payload
      const payload = req.body;
      
      // 2. Queue for processing
      await sqs.sendMessage({
        QueueUrl: process.env.WEBHOOK_QUEUE_URL,
        MessageBody: JSON.stringify(payload)
      }).promise();
      
      // 3. Return immediately
      res.status(200).json({ status: 'received' });
    } catch (error) {
      console.error('Failed to queue webhook:', error);
      res.status(500).json({ error: 'Internal error' });
    }
  });

  // Separate worker processes the queue
  async function processWebhook(payload) {
    const { eventType } = payload;
    
    if (eventType === 'VEHICLE_STATE') {
      await updateVehicleState(payload);
    } else if (eventType === 'VEHICLE_ERROR') {
      await handleVehicleError(payload);
    }
  }
  ```

  ```python Python (Flask + Redis Queue) theme={null}
  from flask import Flask, request
  from rq import Queue
  from redis import Redis

  app = Flask(__name__)
  redis_conn = Redis()
  queue = Queue(connection=redis_conn)

  @app.post("/webhooks/smartcar")
  def webhook_handler():
      # 1. Get the raw payload
      payload = request.get_json()
      
      # 2. Queue for processing
      queue.enqueue(process_webhook, payload)
      
      # 3. Return immediately
      return {"status": "received"}, 200

  def process_webhook(payload):
      # This runs asynchronously in a worker
      event_type = payload.get("eventType")
      
      if event_type == "VEHICLE_STATE":
          update_vehicle_state(payload)
      elif event_type == "VEHICLE_ERROR":
          handle_vehicle_error(payload)
  ```

  ```java Java (Spring Boot + RabbitMQ) theme={null}
  @RestController
  public class WebhookController {
      
      @Autowired
      private RabbitTemplate rabbitTemplate;
      
      @PostMapping("/webhooks/smartcar")
      public ResponseEntity<Map<String, String>> handleWebhook(
          @RequestBody String payload
      ) {
          // 1. Queue for processing
          rabbitTemplate.convertAndSend(
              "webhook-queue", 
              payload
          );
          
          // 2. Return immediately
          return ResponseEntity.ok(
              Map.of("status", "received")
          );
      }
  }

  @Component
  public class WebhookProcessor {
      
      @RabbitListener(queues = "webhook-queue")
      public void processWebhook(String payload) {
          // This runs asynchronously
          JsonNode json = objectMapper.readTree(payload);
          String eventType = json.get("eventType").asText();
          
          if ("VEHICLE_STATE".equals(eventType)) {
              updateVehicleState(json);
          } else if ("VEHICLE_ERROR".equals(eventType)) {
              handleVehicleError(json);
          }
      }
  }
  ```
</CodeGroup>

<Warning>
  **Don't do this:** If you perform heavy processing before returning a response, your endpoint may timeout and Smartcar will retry, creating duplicate processing work.

  ```python Bad Example theme={null}
  @app.post("/webhooks/smartcar")
  def webhook_handler():
      payload = request.get_json()
      
      # DON'T DO THIS: These operations might take too long
      update_database(payload)
      call_external_api(payload)
      send_notifications(payload)
      
      # Might timeout before reaching this line
      return {"status": "received"}, 200
  ```
</Warning>

***

## Production-Ready Pattern

For a complete serverless implementation, see the [Webhook Receiver Recipe](/docs/getting-started/tutorials/webhook-receiver-recipe), which provides:

* API Gateway for HTTPS endpoint
* Lambda function for webhook receipt
* SQS queue for async processing
* Dead letter queue for failed messages
* CloudWatch monitoring and alerts

***

## Next Steps

<CardGroup>
  <Card title="Security" icon="shield-check" href="/integrations/webhooks/best-practices/security">
    Verify payload signatures
  </Card>

  <Card title="Reliability" icon="shield" href="/integrations/webhooks/best-practices/reliability">
    Implement idempotency
  </Card>

  <Card title="Delivery Behavior" icon="truck-fast" href="/api-reference/webhooks/delivery-behavior">
    Understand retry policies
  </Card>

  <Card title="Webhook Recipe" icon="book" href="/getting-started/tutorials/webhook-receiver-recipe">
    Deploy serverless infrastructure
  </Card>
</CardGroup>


# Monitoring & Observability
Source: https://smartcar.com/docs/integrations/webhooks/best-practices/monitoring

Track webhook performance and detect issues early

Comprehensive logging and monitoring help you debug issues, track performance, and maintain reliability.

## Log Key Events

Track every stage of webhook processing for complete observability.

### What to Log

<AccordionGroup>
  <Accordion title="Webhook Receipt" icon="inbox">
    ```json theme={null}
    {
      "timestamp": "2025-01-15T10:30:45Z",
      "event": "webhook.received",
      "eventId": "abc123",
      "eventType": "VEHICLE_STATE",
      "vehicleId": "def456",
      "deliveryId": "ghi789"
    }
    ```
  </Accordion>

  <Accordion title="Signature Verification" icon="shield-check">
    ```json theme={null}
    {
      "timestamp": "2025-01-15T10:30:45Z",
      "event": "signature.verified",
      "eventId": "abc123",
      "valid": true
    }
    ```
  </Accordion>

  <Accordion title="Processing Start/End" icon="play">
    ```json theme={null}
    {
      "timestamp": "2025-01-15T10:30:46Z",
      "event": "processing.started",
      "eventId": "abc123",
      "eventType": "VEHICLE_STATE"
    }
    ```
  </Accordion>

  <Accordion title="Processing Errors" icon="triangle-exclamation">
    ```json theme={null}
    {
      "timestamp": "2025-01-15T10:30:47Z",
      "event": "processing.failed",
      "eventId": "abc123",
      "error": "Database connection timeout",
      "stackTrace": "..."
    }
    ```
  </Accordion>
</AccordionGroup>

***

## Critical Metrics

Monitor these metrics and set up alerts:

| Metric                              | What It Measures              | Alert Threshold                        |
| ----------------------------------- | ----------------------------- | -------------------------------------- |
| **Signature verification failures** | Invalid or spoofed requests   | > 5 in 5 minutes                       |
| **Processing error rate**           | Code or infrastructure issues | > 5% of events                         |
| **Queue depth**                     | Processing backlog            | > 1000 messages                        |
| **Response time**                   | Endpoint performance          | > 10 seconds (approaching 15s timeout) |
| **Duplicate processing**            | Idempotency check hits        | Track for debugging                    |
| **VEHICLE\_ERROR rate**             | Signal retrieval issues       | > 10% of vehicles                      |

***

## Implementation Examples

<CodeGroup>
  ```javascript Node.js (Winston) theme={null}
  const winston = require('winston');

  const logger = winston.createLogger({
    format: winston.format.json(),
    transports: [new winston.transports.Console()]
  });

  app.post('/webhooks/smartcar', async (req, res) => {
    const payload = req.body;
    const { eventId, eventType, vehicleId } = payload;
    
    // Log receipt
    logger.info('webhook.received', {
      eventId,
      eventType,
      vehicleId
    });
    
    // Verify signature
    const isValid = verifySignature(req.rawBody, req.headers['sc-signature']);
    logger.info('signature.verified', { eventId, valid: isValid });
    
    if (!isValid) {
      logger.warn('signature.failed', {
        eventId,
        sourceIp: req.ip
      });
      return res.status(401).json({ error: 'Invalid signature' });
    }
    
    // Queue and return
    await queue.add(payload);
    res.status(200).json({ status: 'received' });
  });

  async function processWebhook(payload) {
    const { eventId } = payload;
    const startTime = Date.now();
    
    logger.info('processing.started', { eventId });
    
    try {
      await updateVehicleData(payload);
      logger.info('processing.completed', {
        eventId,
        durationMs: Date.now() - startTime
      });
    } catch (error) {
      logger.error('processing.failed', {
        eventId,
        error: error.message,
        stack: error.stack
      });
      throw error;
    }
  }
  ```

  ```python Python (Structured Logging) theme={null}
  import structlog

  logger = structlog.get_logger()

  @app.post("/webhooks/smartcar")
  def webhook_handler():
      payload = request.get_json()
      event_id = payload.get("eventId")
      
      # Log receipt
      logger.info("webhook.received",
          event_id=event_id,
          event_type=payload.get("eventType"),
          vehicle_id=payload.get("vehicleId")
      )
      
      # Verify signature
      is_valid = verify_signature(request.data, request.headers.get('SC-Signature'))
      logger.info("signature.verified",
          event_id=event_id,
          valid=is_valid
      )
      
      if not is_valid:
          logger.warning("signature.failed",
              event_id=event_id,
              source_ip=request.remote_addr
          )
          return {"error": "Invalid signature"}, 401
      
      # Queue and return
      queue.enqueue(process_webhook, payload)
      return {"status": "received"}, 200

  def process_webhook(payload):
      event_id = payload.get("eventId")
      
      logger.info("processing.started", event_id=event_id)
      
      try:
          update_vehicle_data(payload)
          logger.info("processing.completed", 
              event_id=event_id,
              duration_ms=duration
          )
      except Exception as e:
          logger.error("processing.failed",
              event_id=event_id,
              error=str(e),
              exc_info=True
          )
          raise
  ```
</CodeGroup>

***

## Next Steps

<CardGroup>
  <Card title="VEHICLE_ERROR Events" icon="triangle-exclamation" href="/api-reference/webhooks/events/vehicle-error">
    Track error notifications and resolution
  </Card>

  <Card title="Reliability" icon="shield" href="/integrations/webhooks/best-practices/reliability">
    Implement idempotency
  </Card>

  <Card title="Testing" icon="flask" href="/integrations/webhooks/best-practices/testing">
    Test your monitoring setup
  </Card>
</CardGroup>


# Best Practices Overview
Source: https://smartcar.com/docs/integrations/webhooks/best-practices/overview

Build reliable and maintainable webhook integrations following industry standards

Follow these best practices to build a production-ready webhook integration that handles high volume, recovers from failures, and provides a great developer experience.

<Tip>
  **Looking for a quick start?** Our [Webhook Receiver Recipe](/docs/getting-started/tutorials/webhook-receiver-recipe) provides a production-ready implementation of these best practices. It's a serverless AWS solution that you can deploy in minutes with built-in queuing, signature verification, retry logic, and monitoring.
</Tip>

## Key Areas

<CardGroup>
  <Card title="Architecture Patterns" icon="diagram-project" href="/integrations/webhooks/best-practices/architecture">
    Decouple receipt from processing with queue-based patterns
  </Card>

  <Card title="Security" icon="shield-check" href="/integrations/webhooks/best-practices/security">
    Verify signatures and protect against spoofed requests
  </Card>

  <Card title="Reliability" icon="shield" href="/integrations/webhooks/best-practices/reliability">
    Implement idempotency and handle out-of-order delivery
  </Card>

  <Card title="Monitoring" icon="chart-line" href="/integrations/webhooks/best-practices/monitoring">
    Log events and set up alerts for critical metrics
  </Card>

  <Card title="Testing" icon="flask" href="/integrations/webhooks/best-practices/testing">
    Test locally and validate edge cases before production
  </Card>
</CardGroup>

***

## Quick Wins

Start with these essential practices for immediate impact:

<AccordionGroup>
  <Accordion title="1. Return 200 Immediately" icon="bolt">
    Persist the payload to a queue and return a 200 status within milliseconds. Process asynchronously in a background worker.

    **Impact:** Prevents timeouts and unnecessary retries
  </Accordion>

  <Accordion title="2. Verify All Signatures" icon="shield-halved">
    Check the `SC-Signature` header on every request to ensure the payload came from Smartcar.

    **Impact:** Prevents security vulnerabilities from spoofed requests
  </Accordion>

  <Accordion title="3. Use eventId for Deduplication" icon="fingerprint">
    Track processed `eventId` values to avoid processing the same event twice.

    **Impact:** Prevents duplicate database updates and notifications
  </Accordion>

  <Accordion title="4. Handle VEHICLE_ERROR Events" icon="circle-exclamation">
    Don't ignore error events. They contain critical information about signal failures and permission issues.

    **Impact:** Better user experience and faster issue resolution
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup>
  <Card title="Architecture Patterns" icon="diagram-project" href="/integrations/webhooks/best-practices/architecture">
    Learn the queue-based pattern
  </Card>

  <Card title="Security" icon="shield-check" href="/integrations/webhooks/best-practices/security">
    Implement signature verification
  </Card>

  <Card title="Delivery Behavior" icon="truck-fast" href="/api-reference/webhooks/delivery-behavior">
    Understand retry policies
  </Card>
</CardGroup>


# Reliability
Source: https://smartcar.com/docs/integrations/webhooks/best-practices/reliability

Build resilient webhook processing that handles retries and out-of-order delivery

Design your webhook integration to handle the realities of distributed systems: retries, out-of-order delivery, and duplicate events.

## Implement Idempotency

Use the `eventId` field to ensure you process each event exactly once, even if Smartcar retries delivery or you reprocess from your queue.

### Why Idempotency Matters

* Smartcar retries failed deliveries with the same `eventId`
* Your queue worker might process the same message multiple times
* Prevents duplicate database updates or notifications
* Enables safe reprocessing of historical events

### Implementation Strategies

<Tabs>
  <Tab title="Redis">
    ```python theme={null}
    import redis

    redis_client = redis.Redis()

    def process_webhook(payload):
        event_id = payload.get("eventId")
        
        # Check if already processed
        if redis_client.exists(f"processed:{event_id}"):
            print(f"Already processed {event_id}, skipping")
            return
        
        # Process the event
        process_vehicle_data(payload)
        
        # Mark as processed (expires after 7 days)
        redis_client.setex(
            f"processed:{event_id}",
            time=604800,  # 7 days
            value="1"
        )
    ```
  </Tab>

  <Tab title="DynamoDB">
    ```javascript theme={null}
    const processWebhook = async (payload) => {
      const { eventId } = payload;
      
      // Check if already processed
      const existing = await dynamodb.get({
        TableName: 'ProcessedEvents',
        Key: { eventId }
      }).promise();
      
      if (existing.Item) {
        console.log(`Already processed ${eventId}, skipping`);
        return;
      }
      
      // Process the event
      await processVehicleData(payload);
      
      // Mark as processed with TTL
      await dynamodb.put({
        TableName: 'ProcessedEvents',
        Item: {
          eventId,
          processedAt: new Date().toISOString(),
          ttl: Math.floor(Date.now() / 1000) + 604800 // 7 days
        }
      }).promise();
    };
    ```
  </Tab>

  <Tab title="PostgreSQL">
    ```python theme={null}
    def process_webhook(payload):
        event_id = payload.get("eventId")
        
        # Use unique constraint to prevent duplicates
        try:
            db.execute(
                "INSERT INTO processed_events (event_id, processed_at) VALUES (%s, NOW())",
                (event_id,)
            )
        except IntegrityError:
            # Already processed
            print(f"Already processed {event_id}, skipping")
            return
        
        # Process the event
        process_vehicle_data(payload)
    ```

    ```sql theme={null}
    -- Table schema
    CREATE TABLE processed_events (
        event_id VARCHAR(255) PRIMARY KEY,
        processed_at TIMESTAMP NOT NULL
    );

    -- Add TTL-style cleanup (run periodically)
    DELETE FROM processed_events 
    WHERE processed_at < NOW() - INTERVAL '7 days';
    ```
  </Tab>
</Tabs>

<Tip>
  **Retention period:** Store processed `eventId` values for at least 7 days to handle all retries and late reprocessing scenarios.
</Tip>

***

## Handle Out-of-Order Delivery

Webhook events are delivered **concurrently** and may arrive out of order. Never assume events arrive in chronological sequence.

### Use Timestamps for Freshness

Always check if incoming data is newer than your current stored state:

```python theme={null}
def update_vehicle_state(payload):
    vehicle_id = payload.get("vehicleId")
    delivered_at = payload["meta"]["deliveredAt"]
    
    # Get current stored state
    current = db.get_vehicle_state(vehicle_id)
    
    # Only update if this event is newer
    if current and current.updated_at > delivered_at:
        print(f"Ignoring older event for {vehicle_id}")
        return
    
    # Safe to update
    db.update_vehicle_state(vehicle_id, payload["data"], delivered_at)
```

### Why Order Matters

<AccordionGroup>
  <Accordion title="Network Delays" icon="network-wired">
    Events sent at different times may experience different network latencies, causing them to arrive out of sequence.
  </Accordion>

  <Accordion title="Retry Timing" icon="rotate">
    If an older event fails initially and is retried later, it might arrive after newer events that succeeded on first attempt.
  </Accordion>

  <Accordion title="Concurrent Delivery" icon="arrows-split-up-and-left">
    Smartcar delivers events concurrently for performance. Events sent milliseconds apart might arrive in reverse order.
  </Accordion>
</AccordionGroup>

### Timestamp-Based Updates

<CodeGroup>
  ```python Python theme={null}
  def update_signal_value(vehicle_id, signal_path, value, timestamp):
      """Update signal only if timestamp is newer"""
      with db.transaction():
          current = db.query(
              "SELECT value, updated_at FROM signals WHERE vehicle_id = %s AND path = %s",
              (vehicle_id, signal_path)
          )
          
          if current and current['updated_at'] >= timestamp:
              # Existing value is newer or same age
              return False
          
          # Update with newer value
          db.execute(
              "INSERT INTO signals (vehicle_id, path, value, updated_at) VALUES (%s, %s, %s, %s) ON CONFLICT (vehicle_id, path) DO UPDATE SET value = EXCLUDED.value, updated_at = EXCLUDED.updated_at WHERE signals.updated_at < EXCLUDED.updated_at",
              (vehicle_id, signal_path, value, timestamp)
          )
          return True
  ```

  ```javascript Node.js theme={null}
  async function updateSignalValue(vehicleId, signalPath, value, timestamp) {
    // Conditional update: only if timestamp is newer
    const result = await db.query(`
      UPDATE signals 
      SET value = $1, updated_at = $2
      WHERE vehicle_id = $3 
        AND path = $4 
        AND (updated_at < $2 OR updated_at IS NULL)
      RETURNING *
    `, [value, timestamp, vehicleId, signalPath]);
    
    return result.rowCount > 0;
  }
  ```
</CodeGroup>

***

## Handle Retries Gracefully

Smartcar automatically retries failed deliveries up to 3 times with exponential backoff.

### Retry Identification

Each delivery attempt receives a unique `deliveryId`, but the `eventId` remains constant:

```json theme={null}
{
  "eventId": "abc-123",         // Same across all retries
  "meta": {
    "deliveryId": "xyz-789",    // Unique per attempt
    "deliveredAt": "2025-01-15T10:30:45Z"
  }
}
```

### Processing Strategy

<Steps>
  <Step title="Check for duplicate eventId">
    Use idempotency check to skip already-processed events
  </Step>

  <Step title="Process the payload">
    Perform your business logic
  </Step>

  <Step title="Mark as processed">
    Store the eventId to prevent reprocessing
  </Step>

  <Step title="Return 200">
    Acknowledge successful processing
  </Step>
</Steps>

<Warning>
  **Don't trigger retries manually.** If you return a 2xx status code and then discover an issue, you cannot ask Smartcar to retry. The delivery is considered successful.
</Warning>

***

## Transactional Processing

Ensure database updates and idempotency tracking happen atomically:

<CodeGroup>
  ```javascript Node.js (PostgreSQL) theme={null}
  async function processWebhook(payload) {
    const { eventId } = payload;
    
    const client = await pool.connect();
    try {
      await client.query('BEGIN');
      
      // Try to insert processed event
      const result = await client.query(
        `INSERT INTO processed_events (event_id, processed_at) 
         VALUES ($1, NOW()) 
         ON CONFLICT (event_id) DO NOTHING 
         RETURNING event_id`,
        [eventId]
      );
      
      if (result.rowCount === 0) {
        // Already processed
        await client.query('ROLLBACK');
        return;
      }
      
      // Process within same transaction
      await updateVehicleData(client, payload);
      await sendNotifications(client, payload);
      
      await client.query('COMMIT');
    } catch (error) {
      await client.query('ROLLBACK');
      throw error;
    } finally {
      client.release();
    }
  }
  ```

  ```python Python (PostgreSQL) theme={null}
  def process_webhook(payload):
      event_id = payload.get("eventId")
      
      with db.transaction():
          # Check and mark as processed in one transaction
          result = db.execute(
              """
              INSERT INTO processed_events (event_id, processed_at)
              VALUES (%s, NOW())
              ON CONFLICT (event_id) DO NOTHING
              RETURNING event_id
              """,
              (event_id,)
          )
          
          if not result:
              # Already processed in another transaction
              return
          
          # Process within same transaction
          update_vehicle_data(payload)
          send_notifications(payload)
          
          # Both updates committed together
  ```
</CodeGroup>

***

## Recovery Strategies

### Dead Letter Queue

Route persistently failing events to a dead letter queue for manual investigation:

```javascript theme={null}
async function processWebhook(payload) {
  const maxRetries = 3;
  let retryCount = 0;
  
  while (retryCount < maxRetries) {
    try {
      await doProcessing(payload);
      return; // Success
    } catch (error) {
      retryCount++;
      if (retryCount >= maxRetries) {
        // Move to DLQ
        await dlq.send({
          payload,
          error: error.message,
          attempts: retryCount
        });
      } else {
        // Wait before retry
        await sleep(Math.pow(2, retryCount) * 1000);
      }
    }
  }
}
```

### Circuit Breaker

Stop processing if downstream dependencies are failing:

```python theme={null}
class CircuitBreaker:
    def __init__(self, failure_threshold=5):
        self.failure_count = 0
        self.failure_threshold = failure_threshold
        self.is_open = False
        self.last_failure_time = None
    
    def call(self, func, *args):
        if self.is_open:
            # Check if we should try again
            if time.time() - self.last_failure_time > 60:
                self.is_open = False
                self.failure_count = 0
            else:
                raise Exception("Circuit breaker is open")
        
        try:
            result = func(*args)
            self.failure_count = 0
            return result
        except Exception as e:
            self.failure_count += 1
            self.last_failure_time = time.time()
            
            if self.failure_count >= self.failure_threshold:
                self.is_open = True
            
            raise e

# Usage
breaker = CircuitBreaker()

def process_webhook(payload):
    try:
        breaker.call(update_database, payload)
    except Exception:
        # Return 503 to trigger Smartcar retry later
        return {"error": "Service unavailable"}, 503
```

***

## Next Steps

<CardGroup>
  <Card title="Monitoring" icon="chart-line" href="/integrations/webhooks/best-practices/monitoring">
    Track idempotency hits and processing failures
  </Card>

  <Card title="VEHICLE_ERROR Events" icon="triangle-exclamation" href="/api-reference/webhooks/events/vehicle-error">
    Handle error notifications and resolution tracking
  </Card>

  <Card title="Delivery Behavior" icon="truck-fast" href="/api-reference/webhooks/delivery-behavior">
    Understanding retry policies
  </Card>

  <Card title="Testing" icon="flask" href="/integrations/webhooks/best-practices/testing">
    Test retry scenarios
  </Card>
</CardGroup>


# Security
Source: https://smartcar.com/docs/integrations/webhooks/best-practices/security

Protect your webhook endpoint from spoofed and malicious requests

Always verify that webhook payloads actually came from Smartcar before processing them.

## Verify Payload Signatures

Every webhook payload includes an `SC-Signature` header containing an HMAC-SHA256 signature. **Always verify this signature** before processing the payload.

### How It Works

1. Smartcar creates an HMAC-SHA256 hash of the payload using your Application Management Token as the secret key
2. The hash is sent in the `SC-Signature` header
3. You recreate the hash using the same secret and compare it to the received signature
4. If they match, the payload is authentic

### Implementation

<CodeGroup>
  ```javascript Node.js theme={null}
  const crypto = require('crypto');

  function verifySignature(payload, signature, managementToken) {
    // Create HMAC hash
    const hmac = crypto
      .createHmac('sha256', managementToken)
      .update(payload)
      .digest('hex');
    
    // Use timingSafeEqual to prevent timing attacks
    return crypto.timingSafeEqual(
      Buffer.from(hmac),
      Buffer.from(signature)
    );
  }

  app.post('/webhooks/smartcar', express.raw({ type: 'application/json' }), (req, res) => {
    // Get signature from header
    const signature = req.headers['sc-signature'];
    
    // Get raw body
    const rawBody = req.body.toString();
    
    // Verify before processing
    if (!verifySignature(rawBody, signature, MANAGEMENT_TOKEN)) {
      return res.status(401).json({ error: 'Invalid signature' });
    }
    
    // Safe to process
    const payload = JSON.parse(rawBody);
    processWebhook(payload);
    res.status(200).json({ status: 'received' });
  });
  ```

  ```python Python theme={null}
  import hmac
  import hashlib

  def verify_signature(payload, signature, management_token):
      """Verify webhook payload authenticity"""
      expected = hmac.new(
          management_token.encode(),
          payload.encode(),
          hashlib.sha256
      ).hexdigest()
      
      # Use compare_digest to prevent timing attacks
      return hmac.compare_digest(expected, signature)

  @app.post("/webhooks/smartcar")
  def webhook_handler():
      # Get signature from header
      signature = request.headers.get('SC-Signature')
      
      # Get raw body (before JSON parsing)
      raw_body = request.data.decode('utf-8')
      
      # Verify before processing
      if not verify_signature(raw_body, signature, MANAGEMENT_TOKEN):
          return {"error": "Invalid signature"}, 401
      
      # Safe to process
      payload = request.get_json()
      process_webhook(payload)
      return {"status": "received"}, 200
  ```

  ```java Java theme={null}
  import javax.crypto.Mac;
  import javax.crypto.spec.SecretKeySpec;
  import java.security.MessageDigest;

  public class WebhookSecurity {
      
      public static boolean verifySignature(
          String payload, 
          String signature, 
          String managementToken
      ) throws Exception {
          // Create HMAC
          Mac hmac = Mac.getInstance("HmacSHA256");
          SecretKeySpec secretKey = new SecretKeySpec(
              managementToken.getBytes(), 
              "HmacSHA256"
          );
          hmac.init(secretKey);
          
          // Generate hash
          byte[] hash = hmac.doFinal(payload.getBytes());
          String expected = bytesToHex(hash);
          
          // Compare securely
          return MessageDigest.isEqual(
              expected.getBytes(),
              signature.getBytes()
          );
      }
      
      private static String bytesToHex(byte[] bytes) {
          StringBuilder result = new StringBuilder();
          for (byte b : bytes) {
              result.append(String.format("%02x", b));
          }
          return result.toString();
      }
  }
  ```
</CodeGroup>

<Warning>
  **Critical:** You must verify the signature against the raw request body, **before** parsing it as JSON. Many frameworks automatically parse JSON, which can alter the body and break signature verification.
</Warning>

***

## Why Signature Verification Matters

<AccordionGroup>
  <Accordion title="Prevents Spoofed Requests" icon="user-secret">
    Without verification, anyone could send fake webhook payloads to your endpoint. Signature verification proves the payload came from Smartcar.
  </Accordion>

  <Accordion title="Protects Against Replay Attacks" icon="rotate">
    While signatures don't prevent replays alone, combining them with `eventId` deduplication creates a complete defense.
  </Accordion>

  <Accordion title="Ensures Data Integrity" icon="shield-halved">
    If the payload is tampered with in transit, the signature won't match, alerting you to the modification.
  </Accordion>

  <Accordion title="Compliance Requirements" icon="building-columns">
    Many security standards and regulations require verification of external data sources.
  </Accordion>
</AccordionGroup>

***

## Additional Security Measures

### Use HTTPS Only

Smartcar only delivers webhooks to HTTPS endpoints with valid SSL certificates.

<Check>
  **Required:** Your callback URL must use HTTPS with a valid, trusted SSL certificate. Self-signed certificates are not supported.
</Check>

### Restrict Access by IP (Optional)

While Smartcar doesn't publish a fixed IP range (addresses may change), you can add an extra layer of security by:

1. Logging all webhook source IPs
2. Alerting on unusual source addresses
3. Rate limiting by IP to prevent abuse

<Note>
  **Don't rely on IP filtering alone.** Signature verification is the primary security mechanism. IP-based restrictions should be supplementary.
</Note>

### Rotate Management Tokens Periodically

Your Application Management Token is used to verify webhook signatures. Rotate it periodically for security:

<Steps>
  <Step title="Generate new token">
    Create a new Application Management Token in the Dashboard
  </Step>

  <Step title="Update your code">
    Deploy code that accepts either the old or new token temporarily
  </Step>

  <Step title="Switch to new token">
    Once deployed, switch Dashboard to use the new token
  </Step>

  <Step title="Remove old token">
    After confirming all webhooks use the new token, remove old token support
  </Step>
</Steps>

### Monitor Failed Verifications

Track and alert on signature verification failures:

```python theme={null}
@app.post("/webhooks/smartcar")
def webhook_handler():
    signature = request.headers.get('SC-Signature')
    raw_body = request.data.decode('utf-8')
    
    if not verify_signature(raw_body, signature, MANAGEMENT_TOKEN):
        # Log the failure
        logger.warning(
            "Invalid webhook signature",
            extra={
                "source_ip": request.remote_addr,
                "signature": signature,
                "payload_size": len(raw_body)
            }
        )
        
        # Alert if threshold exceeded
        if recent_failures_count() > 10:
            send_security_alert("High rate of invalid webhook signatures")
        
        return {"error": "Invalid signature"}, 401
```

***

## Next Steps

<CardGroup>
  <Card title="Payload Verification Guide" icon="book" href="/integrations/webhooks/payload-verification">
    Complete implementation details
  </Card>

  <Card title="Reliability" icon="shield" href="/integrations/webhooks/best-practices/reliability">
    Implement idempotency
  </Card>

  <Card title="Monitoring" icon="chart-line" href="/integrations/webhooks/best-practices/monitoring">
    Track verification failures
  </Card>

  <Card title="Architecture" icon="diagram-project" href="/integrations/webhooks/best-practices/architecture">
    Design secure webhook handlers
  </Card>
</CardGroup>


# Testing
Source: https://smartcar.com/docs/integrations/webhooks/best-practices/testing

Test your webhook integration before going to production

Thoroughly test your webhook integration to catch issues before they affect users.

## Test in Development

Use the Smartcar Dashboard to trigger test webhook deliveries.

<Steps>
  <Step title="Set up local tunnel">
    Use ngrok or similar to expose your local server:

    ```bash theme={null}
    ngrok http 3000
    ```

    This creates a public HTTPS URL that forwards to your local development server.
  </Step>

  <Step title="Configure webhook">
    In the Smartcar Dashboard, set your ngrok URL as the callback URI (e.g., `https://abc123.ngrok.io/webhooks/smartcar`)
  </Step>

  <Step title="Verify webhook">
    Complete the VERIFY challenge to activate the webhook
  </Step>

  <Step title="Trigger test events">
    Use the Dashboard to send test `VEHICLE_STATE` and `VEHICLE_ERROR` events to your endpoint
  </Step>

  <Step title="Verify handling">
    Check logs to confirm:

    * Signature verification works
    * Payload is queued successfully
    * Processing logic executes correctly
    * Idempotency prevents duplicates
  </Step>
</Steps>

***

## Next Steps

Once testing is complete, prepare for production deployment:

<CardGroup>
  <Card title="Monitoring" icon="chart-line" href="/integrations/webhooks/best-practices/monitoring">
    Set up production monitoring and alerts
  </Card>

  <Card title="Security" icon="shield-check" href="/integrations/webhooks/best-practices/security">
    Review security best practices for production
  </Card>

  <Card title="Webhook Receiver Recipe" icon="rocket" href="/getting-started/tutorials/webhook-receiver-recipe">
    Deploy production-ready AWS infrastructure
  </Card>

  <Card title="Delivery Behavior" icon="truck-fast" href="/api-reference/webhooks/delivery-behavior">
    Understand production retry and timeout policies
  </Card>
</CardGroup>


# Callback URI Verification
Source: https://smartcar.com/docs/integrations/webhooks/callback-verification

Verify your webhook endpoint can receive deliveries

<Info>
  **This page covers initial endpoint verification.** For verifying webhook payload signatures from vehicles, see [Payload Verification](/docs/integrations/webhooks/payload-verification).
</Info>

When you create a webhook or update a callback URI in the Smartcar Dashboard, Smartcar sends a one-time `VERIFY` event to confirm your endpoint is ready. Your endpoint must respond correctly before Smartcar will deliver any vehicle data.

## The VERIFY Event

Smartcar sends a challenge request to your callback URI in this format:

<CodeGroup>
  ```json Version 4.0 (NEW) theme={null}
  {
    "eventId": "52f6e0bb-1369-45da-a61c-9e67d092d6db",
    "eventType": "VERIFY",
    "data": {
      "challenge": "<random-string>"
    },
    "meta": {
      "version": "4.0",
      "webhookId": "5a8e5e38-1e12-4011-a36d-56f120053f9e",
      "webhookName": "Example Webhook",
      "deliveryId": "5d569643-3a47-4cd1-a3ec-db5fc1f6f03b",
      "deliveredAt": "2025-07-31T19:38:42.332Z"
    }
  }
  ```

  ```json Version 2.0 theme={null}
  {
    "version": "2.0",
    "webhookId": "<uuid>",
    "eventName": "verify",
    "payload": { 
      "challenge": "<random-string>" 
    }
  }
  ```
</CodeGroup>

## Required Response

Your endpoint must respond with:

1. **Status code**: `200 OK`
2. **Content-Type header**: `application/json`
3. **Response body**: A JSON object containing the HMAC-SHA256 hash of the challenge

### Generate the HMAC

Create an HMAC-SHA256 hash of the `challenge` string using your **Application Management Token** as the secret key:

<CodeGroup>
  ```js Node theme={null}
  const crypto = require('crypto');

  const hmac = crypto
    .createHmac('sha256', application_management_token)
    .update(payload.challenge)
    .digest('hex');
  ```

  ```python Python theme={null}
  import hmac
  import hashlib

  signature = hmac.new(
      application_management_token.encode(),
      payload['challenge'].encode(),
      hashlib.sha256,
  ).hexdigest()
  ```

  ```java Java theme={null}
  import javax.crypto.Mac;
  import javax.crypto.spec.SecretKeySpec;
  import java.nio.charset.StandardCharsets;

  Mac mac = Mac.getInstance("HmacSHA256");
  mac.init(new SecretKeySpec(application_management_token.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
  byte[] raw = mac.doFinal(payload.challenge.getBytes(StandardCharsets.UTF_8));
  StringBuilder sb = new StringBuilder();
  for (byte b : raw) {
    sb.append(String.format("%02x", b));
  }
  String hmac = sb.toString();
  ```

  ```ruby Ruby theme={null}
  require 'openssl'

  hmac = OpenSSL::HMAC.hexdigest(
    'SHA256',
    application_management_token,
    payload.challenge
  )
  ```
</CodeGroup>

### Return the Response

Return the hex-encoded hash in your response body with the key `challenge`:

```json Response Body theme={null}
{
  "challenge": "{HMAC-hex-string}"
}
```

<Warning>
  If your endpoint fails to respond correctly within 15 seconds, Smartcar will not activate the webhook. You can retry verification from the Dashboard at any time.
</Warning>

***

## Verify webhook challenges inside the Dashboard

Use the Smartcar Dashboard to understand exactly what Smartcar expects before you enable webhooks in production. The **Verify webhook** modal shows a sample challenge string plus language-specific snippets so you can implement the same HMAC signature in your code.

<Frame>
  <img alt="" />
</Frame>

<Steps>
  <Step title="Implement the signature in your handler">
    Copy the challenge string from the modal and use the embedded snippets (Python, Node, Java, or Ruby) as references while you code the signature logic on your server. Run your handler locally or in staging so it is ready to answer Smartcar’s challenge.
  </Step>

  <Step title="Trigger Smartcar’s verification call">
    Once your server is ready, click **Verify this webhook**. Smartcar sends the challenge payload to your callback URL, and your code responds with the signature it just produced.
  </Step>

  <Step title="Compare expected vs actual responses">
    The Response tab displays the HTTP status, the challenge Smartcar sent, the signature Smartcar expected, and the body your server returned. Use this side-by-side view to confirm success or adjust your implementation before retrying.
  </Step>
</Steps>

<Frame>
  <img alt="" />
</Frame>


# Creating Webhooks
Source: https://smartcar.com/docs/integrations/webhooks/creating-webhooks

Step-by-step guide to creating and configuring webhook integrations in the Smartcar Dashboard

Head over to the [Smartcar Dashboard](https://dashboard.smartcar.com/integrations) to set up your webhook integration. There are four main steps to create a webhook in Smartcar:

<Frame type="simple">
  <img alt="Application Configuration in Smartcar Dashboard" />
</Frame>

<Steps>
  <Step title="Select an Integration Type">
    From the integrations page, start by creating a new integration and choosing webhook. For most use cases, webhooks are the recommended option.
  </Step>

  <Step title="Choose a Trigger">
    Define **when** Smartcar should send you a webhook. This is the vehicle event or condition that causes data to be delivered.

    **Example triggers:**

    * Vehicle's battery percentage changes
    * Vehicle is plugged in or unplugged
    * Odometer changes
    * Doors or windows open
    * Vehicle location changes
  </Step>

  <Step title="Select the Data (Signals)">
    After choosing a trigger, specify **what** vehicle data ("signals") should be included in the webhook payload. Browse the complete [Vehicle Signals catalog](/docs/api-reference/signals/schema) to see all available data points.

    <Note>
      **All selected signals are delivered in every webhook event**, not just the signals that triggered it. This ensures you always receive complete vehicle state data.
    </Note>

    Your selection directly maps to the permissions that the vehicle owner granted your application during the connection process. Smartcar offers over 20 specific [permissions](https://smartcar.com/docs/api-reference/permissions) for granular control.
  </Step>

  <Step title="Provide a Callback URI & Verify Your Webhook">
    Enter the destination URL where Smartcar should send the data. This should be your application's endpoint to receive webhook payloads.

    Your callback URI must handle the `"eventType": "VERIFY"` received in the request payload and respond with a `200` status code and a `{"challenge": "{HMAC}"}` body.

    <Info>
      **Optional: Separate Error Callback URI**

      You can optionally configure a separate callback URI specifically for `VEHICLE_ERROR` events. If not specified, all events (`VEHICLE_STATE` and `VEHICLE_ERROR`) will be sent to the same callback URI.
    </Info>

    **Resources:**

    * [Callback Verification Guide](/docs/integrations/webhooks/callback-verification) - Learn how to verify your endpoint
    * [Webhook Receiver Recipe](/docs/getting-started/tutorials/webhook-receiver-recipe) - Deploy a pre-built, verified receiver
    * [Receiving Webhooks](/docs/integrations/webhooks/receiving-webhooks) - Build your own receiver from scratch
  </Step>
</Steps>

***

## Next Steps

After creating your webhook, you'll need to subscribe vehicles to start receiving data.

<Card title="Subscribe Vehicles to Your Webhook" icon="car" href="/integrations/webhooks/subscribing-vehicles">
  Learn how to subscribe vehicles using auto-enrollment, the Dashboard, or the API
</Card>

<CardGroup>
  <Card title="Receiving Webhooks" icon="code" href="/integrations/webhooks/receiving-webhooks">
    Learn how to handle incoming webhook deliveries
  </Card>

  <Card title="Event Reference" icon="list" href="/api-reference/webhooks/events/overview">
    Complete reference of webhook events and payloads
  </Card>

  <Card title="Verify Your Webhook" icon="shield-check" href="/integrations/webhooks/callback-verification">
    Secure your webhook endpoint with verification
  </Card>

  <Card title="Delivery Behavior" icon="truck-fast" href="/api-reference/webhooks/delivery-behavior">
    Understand retry policies and delivery guarantees
  </Card>
</CardGroup>


# Webhooks Overview
Source: https://smartcar.com/docs/integrations/webhooks/overview

Receive real-time vehicle data automatically with Smartcar's event-based webhooks

Smartcar's webhooks provide a scalable, event-driven way to receive vehicle data in real-time. Instead of polling the API, your application receives automatic updates when vehicle state changes—reducing latency, server load, and API costs.

<Info>
  Webhooks are the recommended way to receive real-time vehicle data from Smartcar. You can still use the REST API for retrieving data and issuing commands, but webhooks are the most scalable and reliable option for most use cases.
</Info>

## How Webhooks Work

1. **Configure triggers** - Define which vehicle events should send you data (e.g., battery percentage changes, location changes, etc.)
2. **Select signals** - Choose what data points to include in webhook payloads (see [available signals](/docs/api-reference/signals/schema))
3. **Receive events** - Smartcar automatically sends HTTP POST requests to your endpoint when conditions are met
4. **Process data** - Your application handles incoming webhook deliveries and updates your system

## Webhook Components

Understanding Smartcar's webhook system involves three main areas:

### 1. Setup & Configuration

* [Creating Webhooks](/docs/integrations/webhooks/creating-webhooks) - Configure webhooks in the Smartcar Dashboard
* [Callback Verification](/docs/integrations/webhooks/callback-verification) - Verify your endpoint URL
* [Receiving Webhooks](/docs/integrations/webhooks/receiving-webhooks) - Build your webhook receiver

### 2. Security & Validation

* [Payload Verification](/docs/integrations/webhooks/payload-verification) - Validate webhook signatures
* [Best Practices](/docs/integrations/webhooks/best-practices/overview) - Secure your integration

### 3. Technical Reference

* [Event Reference](/docs/api-reference/webhooks/events/overview) - Complete event and payload documentation
* [Delivery Behavior](/docs/api-reference/webhooks/delivery-behavior) - Retry policies, ordering, and guarantees

***

## Next Steps

<CardGroup>
  <Card title="Create Your First Webhook" icon="plus" href="/integrations/webhooks/creating-webhooks">
    Configure a webhook in the Dashboard
  </Card>

  <Card title="Receiving Webhooks" icon="code" href="/integrations/webhooks/receiving-webhooks">
    Build your webhook endpoint
  </Card>

  <Card title="Event Reference" icon="book" href="/api-reference/webhooks/events/overview">
    Complete payload documentation
  </Card>
</CardGroup>


# Payload Verification
Source: https://smartcar.com/docs/integrations/webhooks/payload-verification

Verify webhook payloads are authentic using signature verification

<Info>
  **This page covers verifying ongoing webhook payloads.** For initial endpoint verification when creating a webhook, see [Callback URI Verification](/docs/integrations/webhooks/callback-verification).
</Info>

Always verify that webhook payloads actually came from Smartcar before processing them. Every webhook includes an `SC-Signature` header containing an HMAC-SHA256 signature of the payload.

## Why Verification Matters

Without signature verification:

* Anyone could send fake webhook payloads to your endpoint
* Malicious actors could inject false vehicle data
* You have no guarantee the payload came from Smartcar

Signature verification ensures:

* The payload was sent by Smartcar
* The payload wasn't tampered with in transit
* You can safely process the data

***

## How Signature Verification Works

1. Smartcar creates an HMAC-SHA256 hash of the raw request body using your **Application Management Token** as the secret key
2. The hash is sent in the `SC-Signature` header
3. You recreate the hash using the same secret and compare it to the received signature
4. If they match, the payload is authentic and unmodified

***

## Implementation

Recreate the HMAC-SHA256 of the raw request body using your Application Management Token as the key, then compare it to the `SC-Signature` header:

<CodeGroup>
  ```javascript Node.js theme={null}
  const crypto = require('crypto');

  function verifyWebhookSignature(payload, signature, managementToken) {
    // Create HMAC hash of the raw body
    const hmac = crypto
      .createHmac('sha256', managementToken)
      .update(payload)
      .digest('hex');
    
    // Securely compare (prevents timing attacks)
    return crypto.timingSafeEqual(
      Buffer.from(hmac),
      Buffer.from(signature)
    );
  }

  // Important: Use raw body parser
  app.post('/webhooks/smartcar', 
    express.raw({ type: 'application/json' }), 
    (req, res) => {
      // Get the signature from headers
      const signature = req.headers['sc-signature'];
      
      // Get the raw body
      const rawBody = req.body.toString();
      
      // Verify signature
      if (!verifyWebhookSignature(rawBody, signature, MANAGEMENT_TOKEN)) {
        return res.status(401).json({ error: 'Invalid signature' });
      }
      
      // Now safe to process
      const payload = JSON.parse(rawBody);
      processWebhook(payload);
      res.status(200).json({ status: 'received' });
    }
  );
  ```

  ```python Python theme={null}
  import hmac
  import hashlib

  def verify_webhook_signature(payload, signature, management_token):
      """Verify the SC-Signature header matches the payload"""
      # Create HMAC hash of the raw body
      expected = hmac.new(
          management_token.encode(),
          payload.encode(),
          hashlib.sha256
      ).hexdigest()
      
      # Securely compare (prevents timing attacks)
      return hmac.compare_digest(expected, signature)

  @app.post('/webhooks/smartcar')
  def webhook_handler():
      # Get the signature from headers
      signature = request.headers.get('SC-Signature')
      
      # Get the raw body (BEFORE parsing as JSON)
      raw_body = request.data.decode('utf-8')
      
      # Verify signature
      if not verify_webhook_signature(raw_body, signature, MANAGEMENT_TOKEN):
          return {"error": "Invalid signature"}, 401
      
      # Now safe to process
      payload = request.get_json()
      process_webhook(payload)
      return {"status": "received"}, 200
  ```

  ```java Java theme={null}
  import javax.crypto.Mac;
  import javax.crypto.spec.SecretKeySpec;
  import java.security.MessageDigest;

  public class WebhookVerification {
      
      public static boolean verifySignature(
          String payload, 
          String signature, 
          String managementToken
      ) throws Exception {
          // Create HMAC-SHA256
          Mac hmac = Mac.getInstance("HmacSHA256");
          SecretKeySpec secretKey = new SecretKeySpec(
              managementToken.getBytes(), 
              "HmacSHA256"
          );
          hmac.init(secretKey);
          
          // Generate hash
          byte[] hash = hmac.doFinal(payload.getBytes());
          String expected = bytesToHex(hash);
          
          // Securely compare
          return MessageDigest.isEqual(
              expected.getBytes(),
              signature.getBytes()
          );
      }
      
      private static String bytesToHex(byte[] bytes) {
          StringBuilder result = new StringBuilder();
          for (byte b : bytes) {
              result.append(String.format("%02x", b));
          }
          return result.toString();
      }
  }

  @PostMapping("/webhooks/smartcar")
  public ResponseEntity<?> handleWebhook(
      @RequestBody String rawBody,
      @RequestHeader("SC-Signature") String signature
  ) {
      // Verify signature
      if (!WebhookVerification.verifySignature(rawBody, signature, MANAGEMENT_TOKEN)) {
          return ResponseEntity.status(401).body(Map.of("error", "Invalid signature"));
      }
      
      // Now safe to process
      processWebhook(rawBody);
      return ResponseEntity.ok(Map.of("status", "received"));
  }
  ```

  ```ruby Ruby theme={null}
  require 'openssl'

  def verify_webhook_signature(payload, signature, management_token)
    # Create HMAC hash of the raw body
    expected = OpenSSL::HMAC.hexdigest(
      'SHA256',
      management_token,
      payload
    )
    
    # Securely compare
    Rack::Utils.secure_compare(expected, signature)
  end

  post '/webhooks/smartcar' do
    # Get the signature from headers
    signature = request.env['HTTP_SC_SIGNATURE']
    
    # Get the raw body
    raw_body = request.body.read
    
    # Verify signature
    unless verify_webhook_signature(raw_body, signature, MANAGEMENT_TOKEN)
      halt 401, { error: 'Invalid signature' }.to_json
    end
    
    # Now safe to process
    payload = JSON.parse(raw_body)
    process_webhook(payload)
    
    status 200
    { status: 'received' }.to_json
  end
  ```
</CodeGroup>

<Warning>
  **Critical:** You must verify the signature against the **raw request body** before parsing it as JSON. Many frameworks automatically parse JSON, which can alter the body and break signature verification.
</Warning>

***

## Best Practices

<AccordionGroup>
  <Accordion title="Always verify signatures" icon="shield-check">
    Never skip signature verification, even in development. It's your only guarantee that payloads are authentic.
  </Accordion>

  <Accordion title="Use the raw body" icon="file-code">
    Verify against the raw request body before JSON parsing. Parsed JSON may have different whitespace/ordering that breaks verification.
  </Accordion>

  <Accordion title="Reject invalid signatures" icon="ban">
    Return `401 Unauthorized` for invalid signatures. Don't process the payload or return `200`.
  </Accordion>

  <Accordion title="Keep tokens secure" icon="lock">
    Store your Application Management Token securely (environment variables, secrets manager). Never commit it to source control.
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup>
  <Card title="Best Practices" icon="star" href="/integrations/webhooks/best-practices/security">
    Complete security best practices guide
  </Card>

  <Card title="Event Reference" icon="book" href="/api-reference/webhooks/events/overview">
    Understand webhook event structures
  </Card>

  <Card title="Receiving Webhooks" icon="code" href="/integrations/webhooks/receiving-webhooks">
    Build your webhook endpoint
  </Card>

  <Card title="Delivery Behavior" icon="truck-fast" href="/api-reference/webhooks/delivery-behavior">
    Learn about retries and timeouts
  </Card>
</CardGroup>


# Receiving Webhooks
Source: https://smartcar.com/docs/integrations/webhooks/receiving-webhooks

Set up an endpoint to receive and parse webhook payloads from Smartcar

Learn how to build a basic webhook endpoint that receives, parses, and acknowledges Smartcar webhook deliveries.

<Tip>
  **Want to skip the manual setup?**

  Deploy a production-ready webhook receiver to AWS in minutes with our [Webhook Receiver Recipe](/docs/getting-started/tutorials/webhook-receiver-recipe). It includes complete serverless infrastructure (Lambda + API Gateway + SQS), built-in signature verification, automatic error handling, and TypeScript type safety.

  **Perfect for:** New implementations, AWS environments, or teams wanting to deploy quickly without infrastructure overhead.
</Tip>

## Basic Requirements

Your webhook endpoint must meet these requirements:

* **Accept POST requests** - Smartcar sends all webhooks as HTTP POST requests
* **Return 2xx status code** - Any status code from 200-299 acknowledges successful receipt
* **Use HTTPS** - Your endpoint must use HTTPS with a valid SSL certificate
* **Respond within 15 seconds** - Return a status code before the timeout window
* **Publicly accessible** - Your endpoint must be accessible from the public internet

***

## Quick Start Examples

Here are minimal webhook receivers that handle the required `VERIFY` event and acknowledge all other events:

<CodeGroup>
  ```javascript Node.js (Express) theme={null}
  const express = require('express');
  const crypto = require('crypto');
  const app = express();

  app.use(express.json());

  app.post('/webhooks/smartcar', (req, res) => {
    const { eventType, data } = req.body;
    
    // Handle VERIFY event (required)
    if (eventType === 'VERIFY') {
      const hmac = crypto
        .createHmac('sha256', process.env.SMARTCAR_MANAGEMENT_TOKEN)
        .update(data.challenge)
        .digest('hex');
      return res.status(200).json({ challenge: hmac });
    }
    
    // Log other events
    console.log('Received webhook:', eventType);
    
    // Acknowledge receipt
    res.status(200).json({ status: 'received' });
    
    // Process asynchronously (recommended)
    // processWebhook(req.body);
  });

  app.listen(3000);
  ```

  ```python Python (Flask) theme={null}
  from flask import Flask, request, jsonify
  import hmac
  import hashlib
  import os

  app = Flask(__name__)

  @app.post('/webhooks/smartcar')
  def webhook_handler():
      payload = request.get_json()
      event_type = payload.get('eventType')
      
      # Handle VERIFY event (required)
      if event_type == 'VERIFY':
          signature = hmac.new(
              os.environ['SMARTCAR_MANAGEMENT_TOKEN'].encode(),
              payload['data']['challenge'].encode(),
              hashlib.sha256,
          ).hexdigest()
          return jsonify({"challenge": signature}), 200
      
      # Log other events
      print(f"Received webhook: {event_type}")
      
      # Acknowledge receipt
      return jsonify({"status": "received"}), 200
      
      # Process asynchronously (recommended)
      # process_webhook(payload)

  if __name__ == '__main__':
      app.run(port=3000)
  ```

  ```java Java (Spring Boot) theme={null}
  import javax.crypto.Mac;
  import javax.crypto.spec.SecretKeySpec;
  import java.nio.charset.StandardCharsets;
  import org.springframework.web.bind.annotation.*;
  import org.springframework.http.ResponseEntity;
  import java.util.Map;

  @RestController
  public class WebhookController {
      
      @PostMapping("/webhooks/smartcar")
      public ResponseEntity<Map<String, String>> handleWebhook(
          @RequestBody Map<String, Object> payload
      ) throws Exception {
          String eventType = (String) payload.get("eventType");
          
          // Handle VERIFY event (required)
          if ("VERIFY".equals(eventType)) {
              Map<String, Object> data = (Map<String, Object>) payload.get("data");
              String challenge = (String) data.get("challenge");
              
              Mac mac = Mac.getInstance("HmacSHA256");
              mac.init(new SecretKeySpec(System.getenv("SMARTCAR_MANAGEMENT_TOKEN").getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
              byte[] raw = mac.doFinal(challenge.getBytes(StandardCharsets.UTF_8));
              StringBuilder sb = new StringBuilder();
              for (byte b : raw) {
                  sb.append(String.format("%02x", b));
              }
              String hmac = sb.toString();
              return ResponseEntity.ok(Map.of("challenge", hmac));
          }
          
          // Log other events
          System.out.println("Received webhook: " + eventType);
          
          // Acknowledge receipt
          return ResponseEntity.ok(Map.of("status", "received"));
          
          // Process asynchronously (recommended)
          // processWebhook(payload);
      }
  }
  ```

  ```ruby Ruby (Sinatra) theme={null}
  require 'sinatra'
  require 'openssl'
  require 'json'

  post '/webhooks/smartcar' do
    payload = JSON.parse(request.body.read)
    event_type = payload['eventType']
    
    # Handle VERIFY event (required)
    if event_type == 'VERIFY'
      hmac = OpenSSL::HMAC.hexdigest(
        'SHA256',
        ENV['SMARTCAR_MANAGEMENT_TOKEN'],
        payload['data']['challenge']
      )
      
      status 200
      content_type :json
      return { challenge: hmac }.to_json
    end
    
    # Log other events
    puts "Received webhook: #{event_type}"
    
    # Acknowledge receipt
    status 200
    content_type :json
    { status: 'received' }.to_json
    
    # Process asynchronously (recommended)
    # process_webhook(payload)
  end
  ```
</CodeGroup>

<Warning>
  **VERIFY event required** - Your endpoint must successfully respond to the `VERIFY` event before Smartcar delivers any vehicle data. See [Callback Verification](/docs/integrations/webhooks/callback-verification) for detailed instructions and troubleshooting.
</Warning>

<Tip>
  **Best practice:** Return 200 immediately and process the webhook asynchronously. See [Architecture Best Practices](/docs/integrations/webhooks/best-practices/architecture) for the queue-based pattern.
</Tip>

<Info>
  **Any 2xx works:** You can return 200, 201, 202, 204, or any other 2xx status code. Smartcar treats all 2xx responses as successful delivery.
</Info>

***

## What Happens After Verification

After your endpoint successfully responds to the `VERIFY` event, Smartcar will begin delivering `VEHICLE_STATE` and `VEHICLE_ERROR` events for [subscribed vehicles](/docs/integrations/webhooks/subscribing-vehicles).

<Info>
  **Understanding payloads:** For detailed payload structure, field definitions, and event-specific schemas, see the [Event Reference Overview](/docs/api-reference/webhooks/events/overview).
</Info>

***

## Next Steps

<Warning>
  **Complete the VERIFY challenge first** - Your endpoint must successfully respond to the `VERIFY` event before Smartcar delivers any vehicle data. See [Quick Start Examples](#quick-start-examples) above.
</Warning>

Once your endpoint is verified and receiving webhooks, continue implementing your integration with these guides:

<CardGroup>
  <Card title="Payload Verification" icon="shield-check" href="/integrations/webhooks/payload-verification">
    Verify all payloads are authentic using the SC-Signature header
  </Card>

  <Card title="Event Reference" icon="list" href="/api-reference/webhooks/events/overview">
    Understand VEHICLE\_STATE, VEHICLE\_ERROR, and VERIFY event structures
  </Card>

  <Card title="Best Practices" icon="star" href="/integrations/webhooks/best-practices/overview">
    Implement idempotency, queuing, monitoring, and error handling
  </Card>

  <Card title="Delivery Behavior" icon="truck-fast" href="/api-reference/webhooks/delivery-behavior">
    Learn about retry policies, timeouts, and ordering guarantees
  </Card>
</CardGroup>

***

## FAQ

<AccordionGroup>
  <Accordion title="Why isn't my webhook receiving vehicle data?" icon="triangle-exclamation">
    Your endpoint must successfully respond to the `VERIFY` event before Smartcar delivers any `VEHICLE_STATE` or `VEHICLE_ERROR` events. Check the Dashboard to confirm your webhook shows "Verified" status.
  </Accordion>

  <Accordion title="How do I test locally?" icon="laptop">
    Use [ngrok](https://ngrok.com) or similar to expose your local server:

    ```bash theme={null}
    ngrok http 3000
    ```

    Then use the ngrok URL in Dashboard as your callback URI.
    Note that you will have to re-verify the webhook after changing the callback URI.
  </Accordion>

  <Accordion title="What about signature verification?" icon="key">
    Always verify the `SC-Signature` header to ensure payloads are authentic. See [Payload Verification](/docs/integrations/webhooks/payload-verification).
  </Accordion>

  <Accordion title="Should I process webhooks synchronously?" icon="clock">
    No. Return 200 immediately and process asynchronously using a queue. This prevents timeouts and retry storms. See [Architecture Best Practices](/docs/integrations/webhooks/best-practices/architecture).
  </Accordion>
</AccordionGroup>


# Subscribing Vehicles
Source: https://smartcar.com/docs/integrations/webhooks/subscribing-vehicles

Learn how to subscribe and unsubscribe vehicles to webhooks using auto-enrollment, the Dashboard, or the API

Once you've [created a webhook](/docs/integrations/webhooks/creating-webhooks), you need to subscribe vehicles to it before they'll start receiving data. Smartcar offers three methods to manage vehicle subscriptions: automatic enrollment, Dashboard management, and programmatic API control.

<Info>
  Data will only be sent after your webhook has been verified. See [Callback Verification](/docs/integrations/webhooks/callback-verification) for details.
</Info>

***

## Subscription Methods

<CardGroup>
  <Card title="Auto-Enrollment" icon="wand-magic-sparkles" href="/integrations/webhooks/subscribing-vehicles#method-1-auto-enrollment-recommended-for-production">
    Automatic subscription for all connected vehicles
  </Card>

  <Card title="Dashboard" icon="browser" href="/integrations/webhooks/subscribing-vehicles#method-2-dashboard-management">
    Manual subscription through the Smartcar Dashboard
  </Card>

  <Card title="API" icon="code" href="/integrations/webhooks/subscribing-vehicles#method-3-api-subscription">
    Programmatic subscription via REST API
  </Card>
</CardGroup>

***

## Method 1: Auto-Enrollment (Recommended for Production)

The simplest way to manage subscriptions is to enable auto-enrollment when creating your webhook. This automatically subscribes all vehicles connected to your application.

<Warning>
  **All vehicles will be subscribed immediately.** When you enable auto-enrollment, all currently connected vehicles will be subscribed to the webhook right away. Only enable this feature when you're ready to receive data for all vehicles in your application.
</Warning>

### How It Works

When auto-enrollment is enabled:

* **Existing vehicles** are immediately subscribed to the webhook
* **New connections** are automatically subscribed when users connect vehicles
* **No manual management** required for individual vehicles

### Enable Auto-Enrollment

<Steps>
  <Step title="Navigate to Dashboard">
    Go to the [Smartcar Dashboard](https://dashboard.smartcar.com/integrations) and create or edit a webhook
  </Step>

  <Step title="Enable Auto-Subscribe">
    Check the "Automatically subscribe all vehicles" option during webhook creation
  </Step>

  <Step title="Save Configuration">
    Complete webhook creation - all vehicles will be subscribed automatically
  </Step>
</Steps>

<Check>
  **Best for:** Production deployments where all connected vehicles should receive webhook data
</Check>

***

## Method 2: Dashboard Management

For selective subscription, you can manually subscribe individual vehicles through the Dashboard.

### Subscribe via Dashboard

<Steps>
  <Step title="Access Vehicle List">
    Navigate to [Vehicles](https://dashboard.smartcar.com/vehicles) in the Dashboard
  </Step>

  <Step title="Select Vehicle">
    Click on the vehicle you want to subscribe
  </Step>

  <Step title="Manage Subscriptions">
    In the vehicle details, find the "Webhook Subscriptions" section

    <Frame type="simple">
      <img alt="Webhook Subscription in Smartcar Dashboard" />
    </Frame>
  </Step>

  <Step title="Add or Remove">
    Click "Subscribe" to add the vehicle to a webhook, or "Unsubscribe" to remove it
  </Step>
</Steps>

<Check>
  **Best for:** Testing and development, selective vehicle management, or gradual rollouts
</Check>

***

## Method 3: API Subscription

For programmatic control, use the subscribe and unsubscribe API endpoints.

* [Subscribe Endpoint](https://smartcar.com/docs/api-reference/create-subscription) - Full API reference for subscribing vehicles
* [Unsubscribe Endpoint](https://smartcar.com/docs/api-reference/remove-subscription) - Full API reference for unsubscribing vehicles

<Check>
  **Best for:** Dynamic subscription management, custom business logic, or bulk operations
</Check>

***

## Common Questions

<AccordionGroup>
  <Accordion title="Can I use multiple subscription methods together?">
    Yes! You can enable auto-enrollment for most vehicles and use the API or Dashboard for exceptions. However, be aware that auto-enrollment will automatically subscribe new vehicles.
  </Accordion>

  <Accordion title="What happens if I unsubscribe a vehicle?">
    The vehicle immediately stops receiving webhook deliveries. You can re-subscribe at any time, and a new first payload will be sent.
  </Accordion>

  <Accordion title="How do I know which vehicles are subscribed?">
    You can view all vehicle subscriptions in the [Dashboard](https://dashboard.smartcar.com/vehicles) or use the [Connections API](/docs/api-reference/list-connections) to programmatically list connections.
  </Accordion>

  <Accordion title="Is there a limit to how many vehicles I can subscribe?">
    No, you can subscribe as many vehicles as are connected to your application. Webhooks scale automatically to handle your fleet size.
  </Accordion>

  <Accordion title="Do I need different webhooks for different vehicle types?">
    Not necessarily. You can use one webhook for all vehicles and handle signal availability differences using the `VEHICLE_ERROR` events for unsupported signals.
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup>
  <Card title="Receiving Webhooks" icon="code" href="/integrations/webhooks/receiving-webhooks">
    Requirements for building your webhook endpoint
  </Card>

  <Card title="Event Reference" icon="list" href="/api-reference/webhooks/events/overview">
    Understand all types of available payloads
  </Card>

  <Card title="Delivery Behavior" icon="truck-fast" href="/api-reference/webhooks/delivery-behavior">
    Learn about retry policies and guarantees
  </Card>

  <Card title="Callback URI Verification" icon="shield-check" href="/integrations/webhooks/callback-verification">
    Ensure your endpoint passes Smartcar's verification challenge
  </Card>
</CardGroup>