Monitors

Watch a page and get a signed webhook when it changes

A scheduled check — a CSS selector’s text, or an LLM-extracted set of fields — hashed and compared, pushing an HMAC-signed webhook to your callback only when the watched value actually moves.

create_monitor

What it is

The job: Know when something on a page changed, without polling it yourself.

A monitor is a URL, a cadence and a definition of what counts as “the value”. check_type "observe" watches a CSS selector’s text (or the page map when you give no selector) and is deterministic and cheap. check_type "extract" watches LLM-extracted fields or a natural-language description — more expensive, and the only option when the thing you care about is not addressable by a selector.

Each scheduled check reads the value, hashes it and compares it to the last hash. Nothing happens on an unchanged check beyond the credit for having looked. On a change, your callback_url receives a webhook, HMAC-signed when you set a callback_secret.

The minimum interval is 60 seconds. A monitor whose tenant runs out of credits is paused rather than silently dropped, and get_monitor_history shows you every check with its outcome, so a monitor that has been quietly failing is visible rather than mistaken for a page that never changes.

The call

Call it exactly like this.

Copied from the tool's registration and the route handler — not paraphrased.

MCPcreate_monitor.mcp.jsonjson
// MCP tool call — server "twin-browser"
{
  "tool": "create_monitor",
  "arguments": {
    "name": "pricing page",
    "check_type": "observe",
    "url": "https://example.com/pricing",
    "selector": ".price-table",
    "interval_seconds": 3600,
    "callback_url": "https://your.app/hooks/price",
    "callback_secret": "whsec_…"
  }
}
POST /api/v1/monitorsrequest.shbash
curl -X POST https://twin-browser.com/api/v1/monitors \
  -H "Authorization: Bearer $TWIN_API_KEY" \
  -H "content-type: application/json" \
  -d '{"name":"pricing page","check_type":"observe","url":"https://example.com/pricing","selector":".price-table","interval_seconds":3600,"callback_url":"https://your.app/hooks/price","callback_secret":"whsec_…"}'
Parameters accepted by create_monitor
ParameterTypeWhat it does
name*stringA label for the monitor.
check_type*"observe" | "extract"How the watched value is read. observe watches a selector’s text deterministically; extract runs a model over the page.
url*stringThe page URL to watch.
interval_seconds*numberHow often to check, in seconds. Minimum 60.
callback_url*stringThe http(s) URL that receives the change webhook.
selectorstringCSS selector scoping an observe check to one element. Without it, an observe check watches the page map.
watch_fieldsarray | objectFor extract: the fields to watch — names, or { name, description }.
nl_watchstringFor extract: a natural-language description of what to watch.
callback_secretstringSecret used to HMAC-sign the change webhook. Set it — otherwise you cannot authenticate the delivery.
proxystringYour own egress proxy URL for the checks.

Returns

response.jsonjson
HTTP 201 — the created monitor (secrets excluded).

What it costs

Free to create — 1 or 5 credits per check

Creating a monitor costs nothing; the recurring cost is the check. An observe check bills 1 credit, the same as observe_page. 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.

See the full rate card

Which one

When a different tool is the right call.

The honest answer is often the neighbouring tool. These are the trades.

observe_page

A monitor is observe_page on a timer with change detection and a webhook attached. If you only need the value once, call observe_page and skip the schedule.

observe_page
submit_crawl

A crawl reads many pages once. A monitor reads one page many times. Neither substitutes for the other.

submit_crawl

Questions

create_monitor, answered.

Which check type should I use?
observe, if the value has a stable selector. It is deterministic, cheap and cannot hallucinate a change. Reach for extract only when what you care about is not addressable — “has the status line stopped saying ‘in stock’ anywhere on the page” — and accept that it costs the extract floor on every check.
What happens if my balance runs out?
The monitor is paused rather than silently skipped, and the pause is recorded in your audit log. Top up and re-enable it; you do not lose the definition or its history.
Do I get a webhook on every check?
No — only on a change. The check hashes the watched value and compares it to the last one; an unchanged check does nothing except appear in get_monitor_history. That is what makes a one-minute cadence survivable on your side, even though it is not free on ours.