---
title: "Website Change Monitoring API (Watch) with Webhooks"
description: "POST /v2/watch re-renders a URL on a schedule, diffs each capture against the last and sends an HMAC-signed webhook or an email when the page changes. Private beta on paid plans."
canonical: "https://www.enconvert.com/website-change-monitoring-api"
locale: "en"
---

# Watch, the website change monitoring API

Register a URL once and get a signed webhook when it changes.

[See the plans](/pricing.md)[Read the docs](/docs/coming-soon/watch.md)

Private beta on paid plans. Watchers cost no ops.

`POST /v2/watch`

Copy

```
curl -X POST https://api.enconvert.com/v2/watch \
  -H "X-API-Key: sk_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.enconvert.com/changelog",
    "frequency_minutes": 60,
    "notify_email": false
  }'
```

`201 Created`

Trimmed

```
{
  "watcher_id": "wat_791ed7976871477990157a13cfd27feb",
  "url": "https://www.enconvert.com/changelog",
  "status": "active",
  "frequency_minutes": 60,
  "diff_mode": "auto",
  "next_check_at": "2026-11-11T14:29:57.166558Z"
}
```

`GET /v2/watch/{watcher_id}/snapshots`

```
{"checked_at": "2026-11-11T14:31:03.539021Z", "has_changes": false, "similarity": 1.0, "render_quality": 1.0, "change_count": 0, "changes": []}
```

## A watcher and its first check

The first check sets the baseline. Every later one is diffed against it.

The watcher, active on creation

```
{
  "watcher_id": "wat_791ed7976871477990157a13cfd27feb",
  "url": "https://www.enconvert.com/changelog",
  "status": "active",
  "frequency_minutes": 60,
  "diff_mode": "auto",
  "track_fields": null,
  "webhook_url": null,
  "notify_email": false,
  "consecutive_errors": 0,
  "checks_count": 0,
  "last_check_at": null,
  "next_check_at": "2026-11-11T14:29:57.166558Z",
  "created_at": "2026-11-11T14:29:57.166558Z"
}
```

Its first check, the baseline

```
{
  "checked_at": "2026-11-11T14:31:03.539021Z",
  "has_changes": false,
  "similarity": 1.0,
  "render_quality": 1.0,
  "change_count": 0,
  "changes": []
}
```

Real output, captured 2026-11-11. \[…\] marks a cut.

## What you send and get

| Field | What it does |
| --- | --- |
| `url` | The page to watch. Each check re-renders it in headless Chrome, with no stored credentials. |
| `frequency_minutes` | From 60, the hourly floor, to 43,200, which is 30 days. |
| `diff_mode` | Auto, text, structured, tables or metadata. track\_fields narrows the diff to the fields you name. |
| `webhook_url` | An HMAC-signed POST when a check detects a change. An email to the owner is optional. |
| `changes` | One record per change, with its section, kind, field, before and after. |

## What one watcher replaces

-   ### A cron job

    The schedule lives with the watcher, hourly at the fastest.

-   ### A diffing script

    Each good render is diffed against the last good one.

-   ### Alarms from bad renders

    A blocked or low-scoring render never becomes a baseline or fires a notification.

![Left: binoculars on a tripod and an alarm clock aimed at a web page. Right: the same page with one block changed and a bell ringing above it.](/landing/watch-720.webp)

## Your first watcher

1.  ### Pick a paid plan

    [`Indie, Studio or Production`](/pricing.md)
2.  ### Register a URL

    [`POST /v2/watch`](/docs/coming-soon/watch.md)
3.  ### Receive the change

    [`has_changes: true`](/docs/coming-soon/watch.md#snapshot-history)

## More of the same API

-   [URL to Markdown API](/url-to-markdown-api.md)

    Any URL as clean Markdown, with a score.

    `Perceive POST /v2/perceive`
-   [Web Scraping API](/web-scraping-api.md)

    One render, every output, each read scored.

    `Perceive POST /v2/perceive`
-   [RAG Ingestion API](/rag-ingestion-api.md)

    A site or a set of files in, one chunked JSONL out.

    `Ingest POST /v2/ingest`
-   [Structured Data Extraction API](/structured-data-extraction-api.md)

    Your schema in, exactly that JSON out.

    `Distill POST /v2/distill`
-   [Web Search API](/web-search-api.md)

    A query in, ranked results and their pages out.

    `Lookup POST /v2/lookup`

## Questions about change monitoring

### How do I get a webhook when a page changes?

Pass webhook\_url when you create the watcher with POST /v2/watch, or add it later with PATCH /v2/watch/{watcher\_id}. When a check detects a change, EnConvert sends an HMAC-signed POST to that URL.

### How often can it check a page?

frequency\_minutes sets the cadence, from 60 (the hard hourly floor) to 43,200 (30 days). The poller scans every 60 seconds, so a check fires within a minute of its scheduled time.

### Can I watch only part of a page, like a price or a table?

Yes. track\_fields narrows the diff to changes whose section, field or key matches a tracked term, and diff\_mode can restrict detection to one strategy such as tables, structured, text or metadata.

### Why did my watcher pause itself?

Three consecutive render failures pause a watcher and email the owner if notify\_email is on. PATCH it back to active to re-arm the schedule; one successful check resets the error count.

### Is Watch generally available?

Not yet. Watch is in private beta: it is callable today with your normal API key on any paid plan, and the request and response shapes can change without notice. The free Founding plan cannot create watchers.

### What does it cost?

Watchers cost no ops. A plan holds a number of active watchers instead: 20 on Indie, 100 on Studio and 500 on Production.

## Watch your first page

[See the plans](/pricing.md)[Read the docs](/docs/coming-soon/watch.md)
