CAPABILITY · MONITORS

Watch a page on a schedule, get a signed webhook on change

A monitor reads a value on a cadence, hashes it, compares it to last time, and posts an HMAC-signed webhook only when it actually moved.

POST /api/v1/monitors

Capability

Inside change monitoring

A monitor is a URL, a cadence, and a definition of what counts as "the value". Each scheduled check reads that value, hashes it, and compares the hash to the previous one. An unchanged check does nothing except appear in the history. A change posts a monitor.changed webhook to your callback, signed when you set a secret — which is what makes a tight cadence survivable on your side.

Two check types, two price points

check_type "observe" watches a CSS selector's text (or the page map with no selector) deterministically and cheaply. check_type "extract" watches LLM-extracted fields or a natural-language description — the only option when the value is not addressable by a selector.

Hash-compared, not diffed

The value is normalized and SHA-256 hashed. The webhook carries both hashes and an excerpt of the current value, so your handler sees what changed without you storing the previous state.

Signed like the job callbacks

With callback_secret set, the delivery carries x-twin-signature: sha256=<hex HMAC of the raw body> and x-twin-event: monitor.changed.

History you can audit

GET /monitors/{id}/history returns recent checks with changed / unchanged / error plus value excerpts — so a monitor that has been quietly failing is visible rather than mistaken for a page that never changes.

How it works

The mechanism, in execution order

4 stages, in the order the runtime performs them — not a summary of them.

  1. 1Define the valuePick check_type, a URL, and either a selector (observe) or watch_fields / nl_watch (extract).
  2. 2Set the cadenceinterval_seconds, minimum 60. Multiply it by the per-check price before you choose it.
  3. 3Check and hashEach scheduled run reads the value, normalizes it and hashes it against the last hash.
  4. 4Fire only on changeA differing hash posts monitor.changed to callback_url with the previous hash, the new hash and an excerpt of the value.

In practice

A call you can paste and run

The webhook carries both hashes and an excerpt of the new value — enough to act on without storing previous state yourself.

monitors.shbash
curl -X POST https://twin-browser.com/api/v1/monitors \
  -H "Authorization: Bearer $TWIN_API_KEY" \
  -H "content-type: application/json" \
  -d '{"name":"competitor pricing",
      "check_type":"observe",
      "url":"https://competitor.example.com/pricing",
      "selector":".price-table",
      "interval_seconds":3600,
      "callback_url":"https://your.app/hooks/price",
      "callback_secret":"whsec_REPLACE_ME"}'
# → 201 (the monitor, secrets excluded)

# The change webhook:
#   x-twin-event: monitor.changed
#   x-twin-signature: sha256=<hex>
# {
#   "event": "monitor.changed", "monitorId": "…", "name": "competitor pricing",
#   "checkType": "observe", "url": "https://…", "changedAt": "…",
#   "previous": { "hash": "…" },
#   "current":  { "hash": "…", "value": "…excerpt…" }
# }
api.twin-browser.com
  1. Define the valuedone
  2. Set the cadencerunning
  3. Check and hashqueued
  4. Fire only on changequeued

What it costs, how to switch it on

Priced from the same rate card the API serves

Every credit figure on this page is read from the rate card behind GET /api/v1/pricing — it is not typed into the copy, so it cannot drift from what you are billed.

Free to create · 1 or 5 credits per check

Creating, listing and deleting a monitor cost nothing. The recurring cost is the check: an observe check bills 1 credit, the same as POST /api/v1/observe; an extract check bills the 5-credit extract floor, settled higher-of against the model cost. Multiply by your cadence before you set interval_seconds to 60 — a one-minute observe monitor is 1,440 checks a day.

Full rate card

Turning it on

  1. 1Prefer observeIf the value has a stable CSS selector, check_type "observe" is deterministic, cheap, and cannot hallucinate a change.
  2. 2Set a secretcallback_secret is what makes the delivery verifiable. Without it you cannot tell a real change webhook from anyone else's POST.
  3. 3Choose the cadence with the price in front of youinterval_seconds has a 60-second floor, and every check is billed whether or not anything changed.
  4. 4Watch the historyGET /monitors/{id}/history shows changed / unchanged / error per check. A monitor erroring silently looks exactly like a page that never changes.

At a glance

The contract, in the fewest rows that say it

PropertyTwin Browser
CreatePOST /api/v1/monitors → 201
Check types"observe" (selector) · "extract" (fields)
Cadence`interval_seconds`, minimum 60
Eventmonitor.changed
Signaturex-twin-signature: sha256=<hex>
HistoryGET /api/v1/monitors/{id}/history

Limits

Where it stops, and what it deliberately does not do

A capabilities page with no limits section is a brochure. These are the ceilings, the defaults that will surprise you, and the things this capability is not.

Limits and defaults

  • Minimum interval is 60 seconds.
  • Every check is billed, including the ones that find nothing changed.
  • A monitor whose tenant runs out of credits is paused rather than silently dropped — top up and re-enable it.
  • The webhook carries an EXCERPT of the current value, not the whole page.

What it does not do

  • It does not push on every check. Only a changed hash fires a webhook.
  • It does not diff for you. It reports the previous hash, the new hash and an excerpt; interpreting the change is your handler's job.
  • It does not act on the change. A monitor observes; kicking off a run in response is something your webhook handler does.
  • It does not retain unlimited history — GET /monitors/{id}/history is paginated with a limit of 200 per page.

FAQ

Questions about change monitoring

Which check type should I use?
observe, whenever the value has a stable selector: it is deterministic, cheap, and cannot invent a change. Reach for extract only when what you care about is not addressable — and accept that it bills the extract floor on every check.
Do I get a webhook on every check?
No. The check hashes the watched value and compares it to the last hash; an unchanged check does nothing except appear in the history. That is what makes a tight cadence survivable on your side, even though it is not free on ours.
How do I verify a monitor webhook?
Set callback_secret. The delivery carries x-twin-signature: sha256=<hex>, an HMAC-SHA256 of the raw body. It is the same verification you would write for the job callbacks.
What happens if my balance runs out?
The monitor is paused rather than silently skipped, and the pause is recorded. You do not lose the definition or its check history.

Put your agent to work. Keep the decision.

Start free. Hand your agent a goal on a site you authorize, set the guardrails, and let the first successful run compile the skill every run after it replays.