Skip to main content
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:
Content-Type
string
required
Always set to application/json. All webhook payloads are JSON-encoded.
SC-Signature
string
required
HMAC-SHA256 signature for payload verification. See Payload Verification for details on how to validate this signature.
User-Agent
string
required
Identifies requests as coming from Smartcar. Format: Smartcar/{version}.

Request Body

The request body contains a JSON payload matching one of the event types documented in Event Reference. 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.
HTTP/1.1 200 OK
Content-Type: application/json

{}
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.
Response body is ignored. Smartcar only checks the HTTP status code. You can return an empty body or a simple acknowledgment object.

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

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:
AttemptWait TimeTotal Elapsed
1st (initial)0s0s
2nd25 seconds25 seconds
3rd50 seconds1 minute 15 seconds
4th (final)100 seconds2 minutes 55 seconds
If all 4 delivery attempts fail, the payload is permanently dropped. Future events will still be attempted as long as the webhook remains active.

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

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:
{
  "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
Use eventId for deduplication, not deliveryId. The eventId uniquely identifies the webhook event, while deliveryId only identifies the specific delivery attempt.
See Idempotency & Deduplication 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.
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

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:
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:
{
  "eventType": "VEHICLE_STATE",
  "data": {
    "triggers": ["Charge.IsCharging", "TractionBattery.StateOfCharge", "TractionBattery.Range"],
    "signals": {
      "Charge.IsCharging": { "value": true, ... },
      "TractionBattery.StateOfCharge": { "value": 85, ... },
      "TractionBattery.Range": { "value": 250, ... }
    }
  }
}
If a vehicle reports the same 3 signals as separate changes in quick succession, Smartcar delivers three separate VEHICLE_STATE events:Delivery 1:
{
  "eventType": "VEHICLE_STATE",
  "data": {
    "triggers": ["Charge.IsCharging"],
    "signals": { "Charge.IsCharging": { "value": true, ... }, ... }
  }
}
Delivery 2:
{
  "eventType": "VEHICLE_STATE",
  "data": {
    "triggers": ["TractionBattery.StateOfCharge"],
    "signals": { "TractionBattery.StateOfCharge": { "value": 85, ... }, ... }
  }
}
Delivery 3:
{
  "eventType": "VEHICLE_STATE",
  "data": {
    "triggers": ["TractionBattery.Range"],
    "signals": { "TractionBattery.Range": { "value": 250, ... }, ... }
  }
}
The behavior depends on the vehicle manufacturer. Some OEMs batch updates, while others stream individual changes. Your integration should handle both patterns.

Payload Size Limits

The maximum webhook payload size is 50 KB. This limit applies to the entire JSON payload.
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.
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 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
Use the dashboard logs to:
  • Debug delivery failures
  • Monitor webhook health
  • Track which signals triggered events
  • Verify retry behavior

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
Set up monitoring alerts for:
  • Success rate drops below 95%
  • Average response time exceeds 5 seconds
  • Consecutive failures for the same vehicle

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

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
Use timestamps to establish order. Each signal includes meta.oemUpdatedAt and meta.fetchedAt timestamps. Compare these values to determine the actual sequence of events:
function isNewerThan(signalA, signalB) {
  return signalA.meta.oemUpdatedAt > signalB.meta.oemUpdatedAt;
}

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
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.
Always implement idempotent processing using the unique eventId. See Idempotency & Deduplication 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
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.

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
Most deliveries complete within 1-5 seconds of Smartcar detecting a change, but OEM latency can vary significantly by manufacturer.

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.
Avoid IP-based firewall rules. Instead of allowlisting specific IP addresses, use signature verification to authenticate webhook requests. See Payload Verification.

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 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
Set up alerts for:
  • Delivery success rate drops below 95%
  • Average response time exceeds 5 seconds
  • Consecutive delivery failures (3+)

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.