> ## Documentation Index
> Fetch the complete documentation index at: https://smartcar.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Event Reference

> Complete reference of all webhook events delivered by Smartcar

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

<CardGroup cols={3}>
  <Card title="VERIFY" icon="shield-check" href="#verify">
    One-time challenge to verify your callback URL
  </Card>

  <Card title="VEHICLE_STATE" icon="car" href="#vehicle-state">
    Fired when any monitored signal changes value
  </Card>

  <Card title="VEHICLE_ERROR" icon="triangle-exclamation" href="#vehicle-error">
    Fired when signal retrieval fails or enters error state
  </Card>
</CardGroup>

***

## `VERIFY`

A one-time event sent when you first create a webhook to verify that Smartcar can successfully deliver payloads to your callback URL.

### 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": "<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 (Legacy) theme={null}
  {
    "version": "2.0",
    "webhookId": "<uuid>",
    "eventName": "verify",
    "payload": { 
      "challenge": "<random-string>" 
    }
  }
  ```
</CodeGroup>

### Required Response

Your endpoint must respond with a `200` status code and return the challenge hashed with your Application Management Token.

**Response Requirements:**

* Status code: `200`
* Content-Type: `application/json`
* Body: `{ "challenge": "<HMAC-SHA256-hex>" }`

**Generating the HMAC:**

Create an HMAC-SHA256 hash of the `challenge` value using your Application Management Token as the secret key, then hex-encode the result.

<CodeGroup>
  ```python Python theme={null}
  import smartcar

  hmac = smartcar.hash_challenge(
      application_management_token, 
      challenge
  )

  # Return in response body
  return {"challenge": hmac}
  ```

  ```javascript Node.js theme={null}
  const smartcar = require('smartcar');

  const hmac = smartcar.hashChallenge(
      application_management_token, 
      challenge
  );

  // Return in response body
  res.json({ challenge: hmac });
  ```

  ```java Java theme={null}
  import com.smartcar.sdk.Smartcar;

  String hmac = Smartcar.hashChallenge(
      application_management_token, 
      challenge
  );

  // Return in response body
  return Map.of("challenge", hmac);
  ```

  ```ruby Ruby theme={null}
  require 'smartcar'

  hmac = Smartcar.hash_challenge(
      application_management_token, 
      challenge
  )

  # Return in response body
  { challenge: hmac }
  ```
</CodeGroup>

<Warning>
  If your endpoint fails to respond correctly, Smartcar will not activate the webhook. You can retry verification from the Dashboard at any time.
</Warning>

<Info>
  For step-by-step implementation guidance, see [Callback URI Verification](/integrations/webhooks/callback-verification).
</Info>

***

## `VEHICLE_STATE`

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.

### When This Event Fires

The `VEHICLE_STATE` event fires when Smartcar detects a signal value change for any trigger signal.

<Warning>
  **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.
</Warning>

### 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

    This initial delivery typically occurs within seconds of subscription, but may be delayed if:

    * The vehicle is offline or not communicating with the OEM

    **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" required>
  Unique identifier for this event. Use this for idempotency.
</ResponseField>

<ResponseField name="eventType" type="string" required>
  Always `"VEHICLE_STATE"` for this event type.
</ResponseField>

<ResponseField name="data" type="object" required>
  Container for event data.

  <Expandable title="data object">
    <ResponseField name="user" type="object" required>
      Information about the user who connected the vehicle.

      <ResponseField name="id" type="string">
        Smartcar user ID
      </ResponseField>
    </ResponseField>

    <ResponseField name="vehicle" type="object" required>
      Vehicle information

      <ResponseField name="id" type="string">
        Smartcar vehicle ID
      </ResponseField>

      <ResponseField name="make" type="string">
        Vehicle manufacturer (e.g., `"TESLA"`)
      </ResponseField>

      <ResponseField name="model" type="string">
        Vehicle model (e.g., `"Model 3"`)
      </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" required>
      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"`)
      </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" required>
      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"`)
      </ResponseField>

      <ResponseField name="body" type="object">
        Signal-specific data structure. See [Signals Reference](/api-reference/signals/schema) for schemas.
      </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" required>
  Webhook delivery metadata

  <Expandable title="meta object">
    <ResponseField name="version" type="string">
      Webhook API version (e.g., `"4.0"`)
    </ResponseField>

    <ResponseField name="deliveryId" type="string">
      Unique identifier for this delivery attempt
    </ResponseField>

    <ResponseField name="deliveredAt" type="integer">
      Unix timestamp (milliseconds) when the webhook was delivered
    </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)
    </ResponseField>

    <ResponseField name="signalCount" type="integer">
      Number of signals included in this `VEHICLE_STATE` event (only present for `VEHICLE_STATE` events)
    </ResponseField>

    <ResponseField name="mode" type="string">
      Environment mode: `"LIVE"` or `"TEST"`
    </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",
      "data": {
        "user": {
          "id": "93b3ea96-ca37-43a9-9073-f4334719iok7"
        },
        "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",
        "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",
      "data": {
        "user": {
          "id": "93b3ea96-ca37-43a9-9073-f4334719iok7"
        },
        "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",
        "signalCount": 3,
        "mode": "LIVE"
      }
    }
    ```
  </Tab>
</Tabs>

### Signal Reference

The `signals` array contains data structured according to the [Signals Schema Reference](/api-reference/signals/schema). Each signal type has a specific shape:

* [Charge Signals](/api-reference/signals/charge)
* [Traction Battery Signals](/api-reference/signals/tractionbattery)
* [Location Signals](/api-reference/signals/location)
* [All Signals](/api-reference/signals/schema)

### 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 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 a complete list of possible error codes and types, see the [VEHICLE\_ERROR section](#vehicle-error) below.

***

## `VEHICLE_ERROR`

Triggered when Smartcar encounters an error while attempting to retrieve signal data from a vehicle. This event helps you monitor data availability and handle errors gracefully.

### When This Event Fires

The `VEHICLE_ERROR` event fires when:

1. Smartcar detects an error while retrieving signal data
2. The vehicle manufacturer's API returns an error
3. The vehicle is offline or unreachable
4. Authentication, permission, or compatibility errors occur

### 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" required>
  Unique identifier for this event. Use this for idempotency.
</ResponseField>

<ResponseField name="eventType" type="string" required>
  Always `"VEHICLE_ERROR"` for this event type.
</ResponseField>

<ResponseField name="data" type="object" required>
  Container for event data.

  <Expandable title="data object">
    <ResponseField name="user" type="object" required>
      Information about the user who connected the vehicle.

      <ResponseField name="id" type="string">
        Smartcar user ID
      </ResponseField>
    </ResponseField>

    <ResponseField name="vehicle" type="object" required>
      Vehicle information

      <ResponseField name="id" type="string">
        Smartcar vehicle ID
      </ResponseField>

      <ResponseField name="make" type="string">
        Vehicle manufacturer (e.g., `"TESLA"`)
      </ResponseField>

      <ResponseField name="model" type="string">
        Vehicle model (e.g., `"Model 3"`)
      </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" required>
      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
      </ResponseField>

      <ResponseField name="suggestedUserMessage" type="string">
        User-friendly error message suitable for display to end users
      </ResponseField>

      <ResponseField name="docURL" type="string">
        Link to detailed error documentation
      </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
        </ResponseField>

        <ResponseField name="name" type="string">
          Human-readable signal name
        </ResponseField>

        <ResponseField name="group" type="string">
          Signal category
        </ResponseField>
      </ResponseField>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="meta" type="object" required>
  Webhook delivery metadata (same structure as `VEHICLE_STATE`)
</ResponseField>

### Example Payload

```json theme={null}
{
  "eventId": "5a537912-9ad3-424b-ba33-65a1704567e9",
  "eventType": "VEHICLE_ERROR",
  "data": {
    "user": {
      "id": "93b3ea96-ca37-43a9-9073-f4334719iok7"
    },
    "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"
          }
        ]
      }
    ],
    "vehicle": {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "make": "TESLA",
      "model": "Model 3",
      "mode": "live",
      "powertrainType": "BEV",
      "year": 2020
    }
  },
  "meta": {
    "version": "4.0",
    "deliveryId": "48b25f8f-9fea-42e1-9085-81043682cbb8",
    "deliveredAt": 1761896351529,
    "webhookId": "123e4567-e89b-12d3-a456-426614174000",
    "webhookName": "Bad Webhook",
    "mode": "LIVE"
  }
}
```

### Error Handling Best Practices

<CardGroup cols={2}>
  <Card title="Log and Monitor" icon="chart-line">
    Track error patterns to identify systemic issues or vehicles requiring attention
  </Card>

  <Card title="Retry with Backoff" icon="rotate">
    For transient errors (`ASLEEP`, `UNREACHABLE`), implement exponential backoff retries
  </Card>

  <Card title="User Notifications" icon="envelope">
    Use `suggestedUserMessage` to notify vehicle owners when action is required
  </Card>

  <Card title="Graceful Degradation" icon="shield-halved">
    Handle missing data gracefully in your application UI
  </Card>
</CardGroup>

<Tip>
  Use the `docURL` field in error payloads to link users to detailed troubleshooting documentation.
</Tip>

### 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 |

### Error Resolution

When an error condition is resolved (e.g., a vehicle comes back online or a user renews their subscription), Smartcar sends another `VEHICLE_ERROR` event with `state` set to `"RESOLVED"`:

```json theme={null}
{
  "eventId": "8d9e0f1a-2b3c-4d5e-6f7a-8b9c0d1e2f3a",
  "eventType": "VEHICLE_ERROR",
  "data": {
    "user": {
      "id": "93b3ea96-ca37-43a9-9073-f4334719iok7"
    },
    "errors": [
      {
        "type": "VEHICLE_STATE",
        "code": "UNREACHABLE",
        "state": "RESOLVED",
        "description": "The vehicle is now reachable.",
        "signals": [
          {
            "code": "location-preciselocation",
            "name": "PreciseLocation",
            "group": "Location"
          }
        ]
      }
    ],
    "vehicle": {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "make": "TESLA",
      "model": "Model 3",
      "year": 2020,
      "mode": "live",
      "powertrainType": "BEV"
    }
  },
  "meta": {
    "version": "4.0",
    "deliveryId": "9f8e7d6c-5b4a-3c2b-1d0e-9f8e7d6c5b4a",
    "deliveredAt": 1761898351529,
    "webhookId": "123e4567-e89b-12d3-a456-426614174000",
    "webhookName": "Battery Monitoring",
    "mode": "LIVE"
  }
}
```

<Info>
  **Track error state**: Use the `state` field to differentiate between new errors (`"ERROR"`) and resolved issues (`"RESOLVED"`). This allows you to implement automatic recovery workflows and user notifications.
</Info>

***

## Event Delivery Guarantees

All webhook events follow these delivery characteristics:

* **At-least-once delivery**: Events may be delivered more than once. Use `eventId` for deduplication.
* **Ordering**: Events are not guaranteed to arrive in chronological order. Use timestamps to determine sequence.
* **Idempotency**: The `eventId` field remains constant across delivery retries for the same event.
* **Retries**: Failed deliveries are retried with exponential backoff up to 3 days.

See [Delivery Behavior](/api-reference/webhooks/delivery-behavior) for complete details.

***

## Related Resources

<CardGroup cols={2}>
  <Card title="Payload Schema" icon="brackets-curly" href="/api-reference/webhooks/event-types">
    Complete schema reference for webhook payloads
  </Card>

  <Card title="Signals Reference" icon="signal-bars" href="/api-reference/signals/schema">
    Signal-specific data structures
  </Card>

  <Card title="Delivery Behavior" icon="truck-fast" href="/api-reference/webhooks/delivery-behavior">
    Retry policies and delivery semantics
  </Card>

  <Card title="Error Reference" icon="circle-exclamation" href="/errors/api-errors">
    Detailed error code documentation
  </Card>
</CardGroup>
