POST Create Monitor
Create a scheduled website-change monitor
Last updated Jul 9, 2026
https://api.anakin.io/v1/monitorsCreate a monitor that checks a URL every intervalMinutes and records a change whenever the page differs from the previous check.
A monitor has a scope: page (default) watches a single URL, site crawls the whole site each run and reports pages added, removed, and changed, and wire runs a managed Wire API action each run and diffs the JSON it returns. See Site monitors and Wire monitors for the scope-specific config, endpoints, and change shape.
Request Body
{
"url": "https://example.com/product/123",
"watchMode": "specific_data",
"outputSchema": {
"type": "object",
"properties": { "price": { "type": "number" }, "inStock": { "type": "boolean" } },
"required": ["price"]
},
"intervalMinutes": 60,
"aiMode": true,
"aiGoal": "only when the price drops or it goes out of stock",
"country": "us",
"alertWebhookUrl": "https://your-app.com/hooks/anakin",
"alertEmails": "you@example.com"
}Only url and intervalMinutes are required. Every other field is optional — the defaults below are used when you omit it.
| Parameter | Type | Description |
|---|---|---|
url required | string | Page (or, for site scope, the root URL) to monitor. Must start with http:// or https://. |
intervalMinutes required | number | How often to check, in minutes. Minimum 15. |
scope optional | string | page (default) — watch this one URL. site — crawl the whole site each run and diff the page set. wire — run a Wire action each run and diff its JSON. |
maxPages site only | number | Organic crawl budget — how many discovered pages to crawl per run, on top of any pinned includePatterns URLs. Total per run is capped at 50. Bills 1 credit per page crawled. |
maxDepth site only | number | Link hops to follow from the root during the organic crawl (1–5). Default 2. |
includePatterns site only | string[] | Pin pages to always track. A full URL is crawled directly every run — fetched even if discovery misses it — in addition to the organic crawl of up to maxPages more pages (this is how the dashboard's Inspect/Import hand-picking is stored). A bare path glob (e.g. /blog/*) filters the organically-discovered pages. URLs must be on the monitor's own site — off-site URLs are dropped. |
excludePatterns site only | string[] | Skip URLs matching these globs. |
wireActionId required for wire | string | The Wire action to run each check, e.g. amazon.search_products. See Wire monitors. |
wireCatalogSlug wire only | string | Catalogue slug of the Wire site the action belongs to, e.g. amazon. Optional but recommended. |
wireCredentialId wire only | string | A connected identity's credential id, required only when the action's auth mode is required. |
wireParams wire only | object | Parameters passed to the action, e.g. { "query": "usb-c cable" }. Shape depends on the action. |
wireWatchPaths wire only | string[] | JSON paths from the action's result to diff (e.g. ["results.0.rank"]). Empty = diff the whole payload. See Wire monitors. |
watchMode optional | string | full_page (default) or specific_data. Site monitors always use full_page; wire monitors always diff the returned JSON (specific_data, set server-side). |
watchFormat optional | string | full_page only — what to diff: markdown (default), html, or cleaned_html. Ignored for specific_data. |
outputSchema required for specific_data | object | JSON Schema of the fields to track (AI-extracted). Only used — and required — in specific_data mode; ignored for full_page. |
aiMode optional | boolean | Filter trivial noise and summarize meaningful changes. Adds +1 credit/check. Requires an LLM-enabled server. Default false. |
aiGoal optional | string | Optional even when aiMode is on. A natural-language hint that narrows what counts as meaningful (e.g. "only when the price drops or it goes out of stock"). Omit it and the AI flags any meaningful change on its own. |
useBrowser optional | boolean | Render with a headless browser (needed for JS-heavy pages). Default false. Forced true when sessionId is set. |
country optional | string | Proxy country code. Default "us". See Supported Countries. |
sessionId optional | string | Saved browser session for monitoring logged-in pages. |
isActive optional | boolean | Start active or paused. Default true. |
expiresAt optional | string | End date — an ISO 8601 timestamp or YYYY-MM-DD date. After it passes, the monitor auto-pauses (expired: true) and can be resumed. Must be in the future. Null/omitted = no end date (runs until you pause it or run out of credits). |
alertWebhookUrl optional | string | Webhook to POST each detected change to (HMAC-signed). See Alerts. |
alertEmails optional | string | Comma-separated email recipients. Requires email alerts to be enabled on the server. |
Response
201 CreatedReturns the full Monitor object. When you set alertWebhookUrl, the response includes a freshly generated alertWebhookSecret — store it now, it's what you use to verify webhook signatures.
{
"id": "b1e7c2a4-…",
"url": "https://example.com/product/123",
"watchMode": "specific_data",
"intervalMinutes": 60,
"isActive": true,
"aiMode": true,
"creditCostPerRun": 4,
"nextRunAt": "2026-01-01T12:00:00Z",
"alertWebhookUrl": "https://your-app.com/hooks/anakin",
"alertWebhookSecret": "whsec_9f2c…",
"createdAt": "2026-01-01T11:00:00Z",
"updatedAt": "2026-01-01T11:00:00Z"
}The first check runs on the next scheduler tick (usually within a minute). Poll GET /v1/monitors/{id} for lastCheckedAt, or list changes.
Errors
| Status | error | When |
|---|---|---|
400 | invalid_request | Missing/invalid url, intervalMinutes < 15, bad watchMode/watchFormat, missing outputSchema for specific_data, or malformed emails. |
402 | monitor_limit_reached | You're at your plan's active-monitor cap (Free 5 / Pro 20 / Scale 100). |
Code Examples
curl -X POST https://api.anakin.io/v1/monitors \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/product/123",
"watchMode": "specific_data",
"outputSchema": { "type": "object", "properties": { "price": { "type": "number" } }, "required": ["price"] },
"intervalMinutes": 60,
"alertWebhookUrl": "https://your-app.com/hooks/anakin"
}'import requests
res = requests.post(
"https://api.anakin.io/v1/monitors",
headers={"X-API-Key": "your_api_key"},
json={
"url": "https://example.com/product/123",
"watchMode": "specific_data",
"outputSchema": {
"type": "object",
"properties": {"price": {"type": "number"}},
"required": ["price"],
},
"intervalMinutes": 60,
"alertWebhookUrl": "https://your-app.com/hooks/anakin",
},
)
monitor = res.json()
print("Created", monitor["id"], "— save secret:", monitor.get("alertWebhookSecret"))const res = await fetch("https://api.anakin.io/v1/monitors", {
method: "POST",
headers: { "X-API-Key": "your_api_key", "Content-Type": "application/json" },
body: JSON.stringify({
url: "https://example.com/product/123",
watchMode: "specific_data",
outputSchema: { type: "object", properties: { price: { type: "number" } }, required: ["price"] },
intervalMinutes: 60,
alertWebhookUrl: "https://your-app.com/hooks/anakin",
}),
});
const monitor = await res.json();
console.log("Created", monitor.id, "— save secret:", monitor.alertWebhookSecret);