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

# Create Webhook

> Register a webhook endpoint for real-time event notifications.

`POST /v1/webhooks`

<Note>
  **v1.0 schema lock.** The response shape on this page, the webhook envelope, the per-event `data` payload, and the HMAC signature algorithm are all part of the locked v1.0 contract. We will never remove a documented field, never rename a field, and never change a field's type without bumping to v2 (see [Versioning](/get-started/versioning)). New event types may be added additively; your receiver must tolerate unknown event types and unknown keys.
</Note>

Register a webhook endpoint to receive real-time event notifications via HTTP POST. Each delivery includes an `X-Autosnap-Signature` header for verification. Failed deliveries are retried with exponential backoff.

## Request Body

| Field           | Type           | Required | Default | Description                                                                                                                                          |
| --------------- | -------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `api_key`       | string         | Yes      | —       | Your API key. Accepted in body (canonical) or `?api_key=…` query string.                                                                             |
| `url`           | string         | Yes      | —       | The HTTPS endpoint URL that will receive webhook payloads                                                                                            |
| `event_types`   | array\[string] | Yes      | —       | List of event types to subscribe to. See values below.                                                                                               |
| `secret`        | string         | Yes      | —       | A secret string you provide (minimum 16 characters) used to generate the `X-Autosnap-Signature` header for payload verification                      |
| `dealership_id` | string         | No       | all     | Scope the webhook to a specific dealership (public ID, e.g. `dlr_8cfc0b00a98b`). If omitted, events for all dealerships under your account are sent. |
| `max_failures`  | integer        | No       | `10`    | Number of consecutive delivery failures before the webhook is automatically disabled                                                                 |

### Event Types

All event names use period as the segment separator: `<scope>.<event>` or `<scope>.<subscope>.<event>`. Underscores appear only inside multi-word event names (e.g. `dealer.config.auto_updated`).

#### Website Inventory Events

| Event             | Description                                                                        |
| ----------------- | ---------------------------------------------------------------------------------- |
| `setup.complete`  | A dealer setup job finishes successfully                                           |
| `setup.failed`    | A dealer setup job fails                                                           |
| `import.complete` | A scheduled or on-demand website-scrape inventory import finishes for a dealership |
| `vehicle.created` | A new vehicle is added to a dealership's inventory (website-scrape source)         |
| `vehicle.updated` | An existing vehicle's data changes (price, photos, mileage, status, etc.)          |
| `vehicle.removed` | A vehicle is removed from a dealership's inventory                                 |

#### IMS Feed Events

| Event                 | Description                                                                                |
| --------------------- | ------------------------------------------------------------------------------------------ |
| `ims.import.complete` | An IMS feed file was successfully imported (new/updated/removed vehicle counts in payload) |
| `ims.vehicle.created` | A new vehicle appears in an IMS feed                                                       |
| `ims.vehicle.updated` | A vehicle's IMS-feed row changes                                                           |
| `ims.vehicle.removed` | A vehicle is removed from an IMS feed (marked inactive)                                    |
| `ims.feed.stale`      | An IMS feed file hasn't been updated within the configured staleness threshold             |

#### Dealer Health Check Events

| Event                        | Description                                                                            |
| ---------------------------- | -------------------------------------------------------------------------------------- |
| `dealer.config.auto_updated` | A dealership's scraper configuration was automatically repaired (e.g. changed site ID) |
| `dealer.provider.changed`    | A dealership switched to a different website provider                                  |

You can subscribe to one or more event types per webhook.

## Example

```bash theme={null}
curl -X POST "https://api.autosnap.com/v1/webhooks" \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "YOUR_API_KEY",
    "url": "https://your-server.com/webhooks/autosnap",
    "event_types": ["setup.complete", "setup.failed", "import.complete", "vehicle.created", "vehicle.updated", "vehicle.removed"],
    "secret": "whsec_your_secret_string_here",
    "dealership_id": "dlr_8cfc0b00a98b"
  }'
```

## Response

```json theme={null}
{
  "success": true,
  "created": [
    { "webhook_id": 42, "event_type": "setup.complete" },
    { "webhook_id": 43, "event_type": "setup.failed" },
    { "webhook_id": 44, "event_type": "import.complete" },
    { "webhook_id": 45, "event_type": "vehicle.created" },
    { "webhook_id": 46, "event_type": "vehicle.updated" },
    { "webhook_id": 47, "event_type": "vehicle.removed" }
  ],
  "skipped": [],
  "url": "https://your-server.com/webhooks/autosnap",
  "dealership_id": "dlr_8cfc0b00a98b"
}
```

<Note>
  The API creates one webhook record per event type. If you subscribe to 6 event types, the `created` array will have 6 entries, each with its own `webhook_id`.
</Note>

## Signature Verification

Every webhook delivery includes an `X-Autosnap-Signature` header. Verify it by computing an HMAC-SHA256 of the raw request body using the `secret` you provided:

```python theme={null}
import hmac, hashlib

def verify_signature(payload_body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), payload_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)
```

## Error Codes

| Status | Condition                                                                |
| ------ | ------------------------------------------------------------------------ |
| `400`  | `event_types` is empty or contains invalid event types                   |
| `400`  | `url` is not an HTTPS URL                                                |
| `400`  | `secret` is shorter than 16 characters                                   |
| `404`  | `dealership_id` was provided but no matching dealership was found        |
| `409`  | All requested event types already have active subscriptions for this URL |

See [Handling Webhooks](/guides/handling-webhooks) for a full end-to-end integration guide.


## OpenAPI

````yaml POST /v1/webhooks
openapi: 3.0.3
info:
  title: AutosnapAI Origin API
  description: Dealer resolution, inventory management, and webhook APIs
  version: 1.0.0
servers:
  - url: https://api.autosnap.com
    description: Production
security: []
paths:
  /v1/webhooks:
    post:
      tags:
        - origin
      summary: Create Webhook
      description: |-
        Register webhook subscriptions for one or more event types.

        Creates one DB row per event type, all sharing the same URL and secret.
        Returns all created subscription IDs.
      operationId: create_webhook_v1_webhooks_post
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookCreateRequest'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema: {}
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
components:
  schemas:
    WebhookCreateRequest:
      properties:
        api_key:
          type: string
          title: Api Key
        url:
          type: string
          title: Url
        event_types:
          items:
            type: string
          type: array
          title: Event Types
        secret:
          type: string
          title: Secret
        dealership_id:
          type: integer
          nullable: true
          title: Dealership Id
        max_failures:
          type: integer
          nullable: true
          title: Max Failures
          default: 10
      type: object
      required:
        - api_key
        - url
        - event_types
        - secret
      title: WebhookCreateRequest
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError

````