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

# Webhooks

You can configure a webhook to receive real-time updates when a scraper job runs.

To enable it, pass a `webhook` object in your job request.

<Info>
  Webhook delivery is async and retries automatically on failure (3 attempts)
</Info>

## Example

```json theme={null}
{
  "webhook": {
    "url": "https://yourdomain.com/webhook",
    "events": ["scraper.job.finished", "scraper.data.scraped"],
    "headers": {
      "x-custom-header": "custom header value"
    }
  }
}
```

## Supported Events

* `scraper.job.started` — Sent when the job starts processing
* `scraper.data.scraped` — Sent as data is collected (may trigger multiple times)
* `scraper.job.finished` — Sent when the job is complete

## Custom Headers

You can pass custom HTTP headers in the `headers` field. These headers will be included in every webhook request. Use it to include auth tokens or signatures.

## Payload

Each webhook event will include:

* `event` — Event name
* `jobId` — ID of the related job
* `timestamp` — ISO timestamp of the event
* `data` — Job Results

Example payload:

```json theme={null}
{
  "event": "scraper.job.finished",
  "jobId": "abc123",
  "jobStatus": "finished",
  "timestamp": "2025-04-14T12:00:00Z"
}
```

```javascript theme={null}
{
  "event": "scraper.data.scraped",
  "timestamp": "2025-04-11T14:30:00Z",
  "jobId": "dd1a8c53-2d47-4444-977d-8d653a6a3c82",
  "jobStatus": "in_progress",
  "data": [
    {
      "text": "Extracted text here...",
      "statusCode": 200,
      "statusText": "OK",
      "url": "https://hasdata.com/blog",
      "depth": 1,
      "title": "Blog | HasData"
    },
    /*...*/
    {
      "text": "Extracted text here...",
      "statusCode": 200,
      "statusText": "OK",
      "url": "https://hasdata.com/datasets/",
      "depth": 1,
      "title": "Ready-to-use datasets | HasData"
    }
  ]
}
```
