Create a watch, receive a signed webhook when meaningful
content changes, and inspect history and usage. Every command below uses
the implemented API.
Before you start
Keep the API key in an environment variable rather than in scripts,
shell history, source control, URLs, or browser code. The key is shown once
when it is issued; if it leaks, contact support to revoke it and issue a new
one. Never send the full API key to support.
Set BASE_URL to the WebChange API host. The value below is the intended production hostname; confirm availability for your environment before relying on it.
The watch and webhook URLs below are placeholders for the documented request shape. They are not the WebChange API hostname (https://webchange.exuere.com). WebChange does not host a live demonstration page or webhook receiver. Substitute your own HTTPS page URL and your own HTTPS webhook endpoint before running the commands.
This illustrative HTML shows how a CSS selector narrows monitoring. In the example, #pricing .price selects the price paragraph and monitors only its visible text ($12 / month). Edits outside that element—such as the footer—do not count as a change. Replace the placeholder page URL (https://example.com/pricing) with your own HTTPS page before running commands; it is not the WebChange API host (https://webchange.exuere.com).
The selector picks the first matching element. Whitespace is normalized and script, style, noscript, and template content is ignored. The page is fetched as served HTML; JavaScript is not executed, so content rendered only in the browser cannot be selected. Without a selector, the whole page body is compared.
check_interval_seconds sets the scheduled check cadence in seconds. For the documented paid plan, the minimum is 900 (15 minutes). Longer intervals are supported—for example 1800 (30 minutes) and 3600 (1 hour). Manual and scheduled checks share one monthly allowance, so running every watch at the minimum interval can exhaust that allowance before the month ends.
Walkthrough
1.
How to verify your API key
Every request authenticates with the X-API-Key header. A missing header returns 401authentication_required; a wrong, revoked, or expired key returns 401invalid_api_key.
bash
curl -sS -X GET "$BASE_URL/v1/auth/me" \
-H "X-API-Key: $WEBCHANGE_API_KEY"
The response confirms which account and plan the key belongs to.
2.
How to create a watch
Choose one of the options below. Create a single watch, copy its id into WATCH_ID, and use that watch for the rest of this walkthrough—you do not need to run both options. Replace the placeholder page URL (https://example.com/pricing) with your own HTTPS page. The selector field is optional. check_interval_seconds sets the scheduled check cadence in seconds. For the documented paid plan, the minimum is 900 (15 minutes). Longer intervals are supported—for example 1800 (30 minutes) and 3600 (1 hour). Manual and scheduled checks share one monthly allowance, so running every watch at the minimum interval can exhaust that allowance before the month ends.
Option A: Monitor the entire page
Omit selector to compare the full page body after normalization.
Creating a watch does not fetch the page. Copy the returned id: export WATCH_ID="<id>".
3.
How to configure a webhook
Replace the placeholder webhook URL with your own HTTPS receiver. Destinations must use HTTPS; deliveries to private or internal addresses are refused. Each PUT creates or replaces the configuration and rotates the signing secret.
The first successful check stores a baseline. A baseline does not create a change event and does not send a webhook.
5.
How to detect a webpage change
After the baseline, change the monitored content on your own webpage, then run another check. Later checks compare the selected text with the previous snapshot. A second check with no content change returns unchanged. In this documented example the price changed from $12 to $15.
bash
curl -sS -X POST "$BASE_URL/v1/watches/$WATCH_ID/check" \
-H "X-API-Key: $WEBCHANGE_API_KEY"
outcome is changed when the selected text differs; the background worker then delivers a signed watch.changed webhook, retrying with backoff on failure. If the selected text is identical the outcome is unchanged, change_event_id is null, and no webhook is sent.
6.
How to view detected changes
Change history is returned newest first; limit accepts 1 to 100.
bash
curl -sS -X GET "$BASE_URL/v1/watches/$WATCH_ID/changes?limit=10" \
-H "X-API-Key: $WEBCHANGE_API_KEY"
Expected status: 200
json
[
{
"id": "8b0e4d2a-1c3f-4e5a-9b6c-7d8e9f0a1b2c",
"previous_hash": "<sha256 of previous text>",
"current_hash": "<sha256 of current text>",
"diff": "--- previous\n+++ current\n@@ -1 +1 @@\n-$12 / month\n+$15 / month\n",
"created_at": "2026-11-02T12:20:00Z"
}
]
The diff is a unified diff of the normalized selected text. A watch with no changes returns an empty array.
7.
How to check your usage
Manual and scheduled checks share one monthly allowance. A check that reaches the target consumes usage even if it fails.
bash
curl -sS -X GET "$BASE_URL/v1/usage" \
-H "X-API-Key: $WEBCHANGE_API_KEY"
next_check_at shows when scheduled monitoring will next run the watch.
9.
How to update an existing watch
PATCH /v1/watches/$WATCH_ID modifies an existing watch without recreating it. Supported fields are name, url, selector, check_interval_seconds, and is_enabled. This example lengthens the scheduled interval from 900 seconds (15 minutes) to 3600 seconds (1 hour).
Provide at least one field. An empty PATCH body is rejected. Changing check_interval_seconds does not immediately recalculate the existing next_check_at; the new interval applies after the next scheduled check.
10.
How to disable a watch
DELETE stops monitoring and frees an active-watch slot.
DELETE is a logical disable: the watch and its change history remain readable, and further checks return 409watch_disabled. Re-enable with PATCH and {"is_enabled": true}.
Baseline, unchanged, changed, and no match
baseline: the first successful check stores the
selected text. A baseline never sends a webhook notification.
unchanged: the selected text is identical, for
example when only the footer changed. No change event or webhook.
changed: the selected text differs. A change event
with a diff is stored and a signed watch.changed webhook is
delivered if one is configured.
no match: if no element matches, the check fails
with 422selector_not_found. The failure is
recorded, still consumes one check, and does not replace the previous
snapshot.
Manual and scheduled checks
Scheduled monitoring runs each enabled watch when its next_check_at is due, then schedules the next run from the watch's check_interval_seconds. Manual checks run immediately but do not advance next_check_at. Both kinds consume the same monthly allowance.
Verify webhook signatures
Each delivery is a JSON POST with these headers:
WebChange-Event-Id: the change event ID; retries reuse
it, so use it to ignore duplicates.
WebChange-Timestamp: Unix seconds for this attempt.
WebChange-Signature: v1= followed by the
lowercase hex HMAC-SHA256 of timestamp + "." + raw request
body, keyed with your signing secret.
Compute the HMAC over the raw request body bytes before parsing JSON, compare in constant time, and reject old timestamps. The five-minute tolerance below is a receiver choice, not a WebChange setting. Return a 2xx status quickly; other responses and timeouts are retried with backoff for a limited number of attempts.