Try this endpoint in the Playground →
Page Monitoring
Monitor web pages for content changes on a schedule. When a change is detected, WebPeel calls your webhook with a diff of what changed.
All watch endpoints require authentication. Watches are scoped to your account — you can only read and modify your own watches.
Endpoints
POST/v1/watchAuth Required
Create a new watch on a URL.
GET/v1/watchAuth Required
List all watches for your account.
GET/v1/watch/:idAuth Required
Get details for a single watch.
POST/v1/watch/:id/checkAuth Required
Manually trigger an immediate content check.
PATCH/v1/watch/:idAuth Required
Update a watch — change interval, webhook URL, pause, or resume.
DELETE/v1/watch/:idAuth Required
Delete a watch permanently.
POST /v1/watch — Create Watch
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | Required | The URL to monitor. Must be a valid HTTP/HTTPS URL, max 2048 chars. |
| webhookUrl | string | Optional | Endpoint to receive change notifications. WebPeel will POST a JSON diff here when content changes. |
| checkIntervalMinutes | number | Optional | How often to check the page for changes. Default: 60 minutes. Range: 1–44640 (31 days). |
| selector | string | Optional | CSS selector to monitor only a specific part of the page (e.g. #price, .article-body). |
Response — 201 Created
{
"ok": true,
"watch": {
"id": "wch_01J8XKZP4T...",
"accountId": "acc_...",
"url": "https://example.com/pricing",
"webhookUrl": "https://your-server.com/webhooks/webpeel",
"checkIntervalMinutes": 60,
"selector": null,
"status": "active",
"lastCheckedAt": null,
"lastChangedAt": null,
"createdAt": "2024-03-04T12:00:00.000Z"
}
}
PATCH /v1/watch/:id — Update Watch
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| status | string | Optional | Set to "paused" to pause checks, or "active" to resume. |
| webhookUrl | string | Optional | Update the webhook destination URL. |
| checkIntervalMinutes | number | Optional | Update the check frequency. Range: 1–44640. |
| selector | string | Optional | Update the CSS selector to monitor. |
POST /v1/watch/:id/check — Manual Check
Immediately checks the watched URL for changes, regardless of the schedule. Returns a diff if content has changed since the last check.
Response
{
"ok": true,
"diff": {
"changed": true,
"previous": "Price: $29",
"current": "Price: $39",
"changedAt": "2024-03-04T13:00:00.000Z"
}
}
Webhook Payload
When a content change is detected, WebPeel POSTs this payload to your webhookUrl:
{
"event": "change_detected",
"watchId": "wch_01J8XKZP4T...",
"url": "https://example.com/pricing",
"checkedAt": "2024-03-04T14:00:00.000Z",
"diff": {
"changed": true,
"previous": "...",
"current": "...",
"changedAt": "2024-03-04T14:00:00.000Z"
}
}
Examples
curl -X POST https://api.webpeel.dev/v1/watch \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/pricing",
"webhookUrl": "https://your-server.com/webhooks/price-change",
"checkIntervalMinutes": 30,
"selector": "#pricing-table"
}'
# List all watches
curl https://api.webpeel.dev/v1/watch \
-H "Authorization: Bearer YOUR_API_KEY"
# Get a specific watch
curl https://api.webpeel.dev/v1/watch/wch_01J8XKZP4T... \
-H "Authorization: Bearer YOUR_API_KEY"
# Pause a watch
curl -X PATCH https://api.webpeel.dev/v1/watch/wch_01J8XKZP4T... \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "paused" }'
# Resume a watch and change interval
curl -X PATCH https://api.webpeel.dev/v1/watch/wch_01J8XKZP4T... \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "active", "checkIntervalMinutes": 15 }'
const API_KEY = process.env.WEBPEEL_API_KEY;
const BASE = 'https://api.webpeel.dev';
// Create a watch
const res = await fetch(`${BASE}/v1/watch`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
url: 'https://example.com/pricing',
webhookUrl: 'https://your-server.com/webhooks/change',
checkIntervalMinutes: 60,
}),
});
const { watch } = await res.json();
console.log(`Watch created: ${watch.id}`);
// Manually trigger a check
const checkRes = await fetch(`${BASE}/v1/watch/${watch.id}/check`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${API_KEY}` },
});
const { diff } = await checkRes.json();
if (diff.changed) {
console.log('Content changed!', diff);
}
Watch Object
| Field | Type | Description |
|---|---|---|
| id | string | Unique watch ID. |
| url | string | The monitored URL. |
| status | string | active or paused. |
| checkIntervalMinutes | number | Check frequency in minutes. |
| selector | string|null | CSS selector being monitored, or null for full page. |
| webhookUrl | string|null | Notification endpoint. |
| lastCheckedAt | string|null | ISO timestamp of last check. |
| lastChangedAt | string|null | ISO timestamp of last detected change. |
| createdAt | string | ISO timestamp when watch was created. |