Skip to main content
Webhooks let AutosnapAI push events to your server instead of making you poll. When a vehicle is added, updated, removed, or when an inventory import completes, we send a signed HTTP POST to a URL you configure.

When to use webhooks

  • Real-time inventory sync — keep your database in lockstep with AutosnapAI without polling
  • Marketing automation — trigger an email when a “Great Deal” vehicle hits inventory
  • Data warehouse pipelines — stream events into BigQuery, Snowflake, or similar
  • Alerting — notify your team when an important dealer’s inventory stops updating

Event types

Website Inventory Events

Dealer Health Check Events

IMS Feed Events

Website inventory events and IMS feed events are independent. If a dealership has both a website scraper and an IMS feed, you’ll receive events from both sources. Use the event prefix (ims.* vs no prefix) to distinguish the source.

Creating a webhook

You provide a secret (minimum 16 characters) when creating the webhook. This secret is used to sign every delivery so you can verify it came from AutosnapAI.
Response
The API creates one webhook record per event type. If you subscribe to 4 event types, the response created array will have 4 entries, each with its own webhook_id.

Webhook delivery format

Every webhook delivery is an HTTP POST with these headers:
The payload structure:

Per-Event Data Schemas

setup.complete

website_url is the dealership’s canonical host (scheme, www and path removed) — the same identifier the rest of the API uses. setup_id is the ID the setup endpoint returned with its 202 and requested_url is the URL exactly as you submitted it; use either (or the envelope’s dealership_id) to map the event back to your own request.

setup.failed

The envelope’s dealership_id is null on setup.failed when the failure happened before a dealership record existed — setup_id and requested_url still identify the request.

import.complete

website_url is the dealership’s canonical host. inserted = vehicles new to this import, updated = vehicles seen again (of which changed had a field change and unchanged did not), vehicles_deactivated = vehicles removed by this import, active_vehicle_count = active vehicles after it.

vehicle.created / vehicle.updated / vehicle.removed

The data field is the vehicle object directly (not wrapped in a {"vehicle": {...}} envelope). It is the same vehicle object POST /v1/inventory/fetch returns for that car, with the same fields, prices, price breakdown and photos, plus dealership_id and dealer_name. Vehicle events are checked after each inventory refresh for the dealership. A new dealership’s first inventory import sends vehicle.created for each vehicle it adds. If you subscribe to a dealership whose inventory we already have, events describe changes from then on: take the starting inventory from /v1/inventory/fetch.
Events are scoped per dealership. Each event’s top-level envelope includes the dealership_id the event belongs to. When a dealer group shares used-inventory across multiple rooftops, the same VIN may generate parallel events from each participating dealership — each event is legitimate for its own dealership scope. Deduplicate on (dealership_id, vin) if you need a unified view. See Concepts: Vehicles — Core identifiers for details.

ims.import.complete

Both events fire for every IMS feed import. If you subscribe to both, you will receive two webhooks per import with the same payload. Subscribe to one or the other, not both.

ims.feed.stale

ims.vehicle.created / ims.vehicle.updated / ims.vehicle.removed

For vehicle events (vehicle.created, vehicle.updated, vehicle.removed), the data field contains the vehicle object directly — it is NOT wrapped in a {"vehicle": {...}} envelope.
X-Autosnap-Event-Id is a unique ID for each event delivered to your webhook. If we retry a delivery, the retry has the same ID and the exact same body. Use it to skip events you have already processed.

Signature verification

Always verify the signature on every webhook before acting on the payload. Anyone can POST to a public URL — signatures prove the request actually came from AutosnapAI. The X-Autosnap-Signature header contains an HMAC-SHA256 hex digest of the raw request body, computed using the secret you provided when creating the webhook:

Retry and delivery semantics

  • At-least-once delivery. Every event is saved before we send it, so it is not lost if your endpoint is down. You may receive the same event more than once: use X-Autosnap-Event-Id to skip duplicates.
  • Retry schedule. Server errors (5xx), timeouts, connection errors, 408 and 429 are retried. Other client errors (4xx) mean your endpoint rejected the event, and are not retried. The gaps between attempts grow: 30 seconds, 2 minutes, 5 minutes, 15 minutes, 30 minutes, 1 hour, 2 hours, 3 hours, then every 4 hours. We keep retrying for 24 hours from when the event happened.
  • Endpoint down. If several deliveries to your endpoint fail in a row, we pause and resend the waiting events once it recovers, instead of sending each one into a failing endpoint.
  • Auto-disable. A webhook is deactivated only after your endpoint has been unreachable or failing (server errors, timeouts, connection errors, 408, 429) continuously for 24 hours with no successful delivery. A 4xx rejection of an individual event does not count toward this. Use the reactivate endpoint to turn it back on. Events from those 24 hours that could not be delivered are not resent; use POST /v1/inventory/fetch to resync.
  • Timeout. Your endpoint must respond within 10 seconds. Longer responses are treated as failures and retried. Do the minimum work synchronously (queue the event for background processing) and return a 2xx immediately.
  • Ordering. Events for the same vehicle sent to the same URL are always delivered in order (vehicle.created before vehicle.updated before vehicle.removed), including across retries, even when you subscribe to each event type separately. Events for different vehicles or dealerships, or to different URLs, may arrive in any order.

Test and production keys

A webhook belongs to the environment of the API key that created it. Create your Pre-Prod webhooks with a test key and your Production webhooks with a production key, and each environment only receives its own events: There is one inventory per dealership, so a test webhook needs a dealership_id to receive vehicle or import events. Create one test webhook per dealership you want to test with. Without a dealership_id, a test webhook receives setup events only. A test key lists and manages only test webhooks. It can’t delete or change webhooks or dealerships created with a production key; those requests return 403. All dealerships on your account can be read with either key, so you don’t need to set them up again for testing.

Inspecting deliveries

Returns delivery attempts (default 50, max 100) with status codes, response times, and error messages. Use the limit query parameter to control how many results are returned. Useful for debugging when events aren’t reaching your server.

Managing webhooks

Handling webhooks

Full end-to-end guide with receiver code and deployment tips

Webhook endpoints

Full webhook API reference