webclaw

Watch

Monitor a public URL for content changes. Webclaw periodically scrapes the page, compares it to the previous snapshot, and notifies you via webhook when something changes.

Note
Maximum 20 watches per user. Each check consumes 1 scrape credit.

Create a watch

POST/v1/watch

Create a new URL watch with a check interval and optional webhook.

json
{
  "url": "https://example.com/pricing",
  "name": "Example Pricing Page",
  "interval_minutes": 1440,
  "webhook_url": "https://hooks.example.com/webclaw"
}

Parameters

FieldTypeRequiredDescription
urlstringYesThe URL to monitor.
namestringNoHuman-readable label for the watch.
interval_minutesintegerNoCheck interval in minutes (60-10080). Default: 1440 (daily).
webhook_urlstringNoURL to receive POST notifications when changes are detected.

Interval options

IntervalMinutesCredits / month (est.)
Hourly60~720
Every 6 hours360~120
Daily1440~30
Weekly10080~4

List watches

GET/v1/watch

List all watches for the authenticated user.

Example response (limit=20, offset=0)
{
  "watches": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "url": "https://example.com/pricing",
      "name": "Example Pricing Page",
      "interval_minutes": 1440,
      "webhook_url": "https://hooks.example.com/webclaw",
      "active": true,
      "last_checked_at": "2026-03-19T08:00:00Z",
      "last_changed_at": "2026-03-18T08:00:00Z",
      "created_at": "2026-03-10T14:22:00Z"
    }
  ]
}

Watch details

GET/v1/watch/{id}

Get a watch and its snapshot timeline.

json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "url": "https://example.com/pricing",
  "name": "Example Pricing Page",
  "interval_minutes": 1440,
  "webhook_url": "https://hooks.example.com/webclaw",
  "active": true,
  "created_at": "2026-03-10T14:22:00Z",
  "snapshots": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440001",
      "content_hash": "a1b2c3d4e5f6",
      "word_count": 1240,
      "status": "changed",
      "title": "Pricing — Example",
      "diff_summary": "+85 words, +1 links",
      "word_count_delta": 85,
      "links_added": 1,
      "links_removed": 0,
      "checked_at": "2026-03-19T08:00:00Z"
    },
    {
      "id": "550e8400-e29b-41d4-a716-446655440002",
      "content_hash": "f6e5d4c3b2a1",
      "word_count": 1155,
      "status": "initial",
      "title": "Pricing — Example",
      "diff_summary": null,
      "word_count_delta": 0,
      "links_added": 0,
      "links_removed": 0,
      "checked_at": "2026-03-10T14:22:00Z"
    }
  ]
}

Snapshot object

FieldTypeDescription
idstringUnique snapshot identifier.
content_hashstringHash of the extracted content for quick comparison.
word_countintegerWord count of the page content.
statusstring"initial" (first check), "same" (no change), or "changed".
titlestringPage title at check time.
diff_summarystring | nullSummary of detected changes. May be null.
word_count_deltaintegerChange in word count from previous snapshot.
links_addedintegerNumber of new links found on the page.
links_removedintegerNumber of links removed since the last check.
checked_atstringISO 8601 timestamp of the check.

Update a watch

PATCH/v1/watch/{id}

Update watch settings. Only provided fields are changed.

json
{
  "name": "Updated Name",
  "interval_minutes": 360,
  "webhook_url": "https://hooks.example.com/new-endpoint",
  "active": false
}

Delete a watch

DELETE/v1/watch/{id}

Permanently remove a watch and all its snapshots.

Trigger manual check

POST/v1/watch/{id}/check

Start a background check. Returns checking immediately; retrieve the watch later for snapshots.

json
{ "status": "checking" }

Webhook payload

When a change is detected and a webhook_url is configured, Webclaw sends a POST request with this payload:

json
{
  "event": "watch.changed",
  "watch_id": "550e8400-e29b-41d4-a716-446655440000",
  "url": "https://example.com/pricing",
  "summary": "+50 words",
  "word_count_delta": 50,
  "checked_at": "2026-03-19T15:30:00Z"
}

SDK examples

Python

python
from webclaw import Webclaw

client = Webclaw(api_key="wc_...")

# Create a daily watch
watch = client.watch_create(
    url="https://example.com/pricing",
    name="Pricing Page",
    interval_minutes=1440,
    webhook_url="https://hooks.example.com/webclaw"
)

# List all watches
watches = client.watch_list()

# Trigger a manual check
client.watch_check(watch.id)
# Check runs in the background. Read GET /v1/watch/{id} for snapshots.

TypeScript

typescript
import { Webclaw } from "@webclaw/sdk";

const client = new Webclaw({ apiKey: "wc_..." });

// Create a daily watch
const watch = await client.watchCreate({
  url: "https://example.com/pricing",
  name: "Pricing Page",
  interval_minutes: 1440,
  webhook_url: "https://hooks.example.com/webclaw",
});

// List all watches
const response = await client.watchList();
console.log(response);

// Trigger a manual check
await client.watchCheck(watch.id);
// Check runs in the background. Read GET /v1/watch/{id} for snapshots.

cURL

bash
# Create a watch
curl -X POST https://api.webclaw.io/v1/watch \
  -H "Authorization: Bearer wc_..." \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/pricing", "interval_minutes": 1440}'

# List watches
curl https://api.webclaw.io/v1/watch \
  -H "Authorization: Bearer wc_..."

# Trigger manual check
curl -X POST https://api.webclaw.io/v1/watch/550e8400-e29b-41d4-a716-446655440000/check \
  -H "Authorization: Bearer wc_..."
Note
A failed check does not guarantee a snapshot or automatically pause the watch. Check the latest snapshot timestamp and set active: false to pause checks when needed.

Get started

Ready to build? Start extracting.

Cancel anytime. One key for every format and endpoint.

View on GitHub