Skip to main content
This guide walks you through everything you need to set up a production-grade webhook receiver — creating a webhook, verifying signatures, processing events idempotently, and handling failures.

Step 1 — Build a receiver endpoint

Your endpoint needs to:
  1. Accept POST requests with a JSON body
  2. Read the X-Autosnap-Signature header
  3. Verify the signature using the secret you provided when creating the webhook
  4. Respond with 2xx within 10 seconds
  5. Process events idempotently (the same event may arrive more than once)

Example: FastAPI

For vehicle events (vehicle.created, vehicle.updated, vehicle.removed), the data field contains the vehicle object directly. For import.complete, data contains website_url and stats. The dealership_id is always at the top level of the payload, not inside data.

Example: Node/Express

Step 2 — Create the webhook

Once your endpoint is live and reachable:
The response confirms which webhooks were created:

Step 3 — Test the webhook

Send a test delivery from the dashboard or programmatically by triggering an inventory refresh on one of the dealerships. Inspect the delivery results:
Returns delivery attempts (default 50, max 100) with status codes, response times, and error messages.

Idempotency is critical

Webhooks are delivered at-least-once, not exactly-once. Your handler must produce the same end state regardless of how many times it sees the same event. A simple pattern:
  1. Use the X-Autosnap-Event-Id header as the deduplication key. It is unique per event and the same on every retry of that event
  2. At the start of handling, check if you’ve already processed this event
  3. If yes, return early. If no, process it.

Always respond fast

The receiver endpoint must return 2xx within 10 seconds. If you do heavy work synchronously (writing to your database, calling other APIs, sending emails), you’ll time out and we’ll retry — flooding your endpoint with duplicates. The pattern:
  1. Verify the signature (~1ms)
  2. Reject if invalid (~1ms)
  3. Parse the JSON (~1ms)
  4. Push to a background queue (~10ms)
  5. Return 2xx
Background workers do the actual data writes, calls to other services, etc.

Retry behavior

Every event is saved before it is sent. Server errors (5xx), timeouts, connection errors, 408 and 429 are retried with growing gaps for 24 hours: Every retry carries the same X-Autosnap-Event-Id and the exact same body. Other client errors (4xx) mean your endpoint rejected the event. They are not retried. 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 PATCH /v1/webhooks/{id}/reactivate to re-enable it after fixing the issue. This keeps your subscription configuration.

Security best practices

1

Always verify signatures

Never act on webhook payloads without first verifying the HMAC signature. Anyone can POST to a public URL.
2

Use HTTPS

Webhook URLs must be https://. Plain HTTP is rejected at webhook creation time.
3

Use a unique URL path

Use a unique, hard-to-guess path for your webhook endpoint (e.g. /webhooks/autosnap-a3f2c8b4) so it’s not easily discoverable.
4

Change secrets after a leak

If your webhook secret is exposed, delete the webhook and create a new one with a new secret.

Common pitfalls

Webhooks concept

Event types, payload format, signature verification

Webhook API endpoints

Full endpoint reference