Snag Watcher API https://watcher-api-staging.manwhas.shop

API reference

Create a watcher

POST /v1/watchers

Creates a watcher and schedules its first run. Returns the watcher object and, when notify has a webhook, webhook_secret.

Body

FieldType
targetobjectRequired. What to watch. Matching products
conditionsobjectRequired. { "all": [...] } or { "any": [...] }, 1 to 10. Conditions
whereobjectRequired. sites (1 to 10) and aggregate
scheduleobjectRequired. every and until, optionally start_at and burst. Schedules
notifyobjectWhere results go. Webhooks
locationobjectcountry, zip, radius, currency
fetchobjectproxy and accept_site_terms
thenobjectA follow-up watcher. Follow-up watchers

target

FieldType
querystringRequired. A URL, an identifier or words, by match
matchstringRequired. url, sku, exact, line, category, listing
attributesobjectVariant filters, such as { "size": 10, "color": "Black" }. A list means any of them
excludestring[]Phrases that drop a product, as whole words

Condition

FieldType
fieldstringRequired. price, price_drop, availability, quantity, version, release_status, release_date, date, opens_at, seller, or an attribute
opstringRequired. = != < <= > >= in not_in exists changed
valueanyA number, "$19.99", "10%", a date, a status, or a list for in
compare_tostringfirst_snapshot or last_snapshot
overobjectkey (sizes, dates, items), require (all, any, min_n), n, same (site, seller)

where

FieldType
sitesstring[]Required. Hosts, repos or URLs
aggregatestringeach (default), best, first, dedupe

schedule

FieldType
everystringRequired. "15m", "1h", "1d"
untilstringRequired. A date, "+30d", "after_first_match" or "never"
start_atstringFirst run, ISO 8601. UTC without an offset
burstobjectnear (release_date, opens_at), window, every

notify

FieldType
channelsstring[]Required. ["webhook"] with an API key
webhookobjecturl (https) and events: matched, changed, field_found, blocked, clamped
repeatstringonce, on_change (default), every_match
cooldownstringShortest gap between sends. Default "6h"

location and fetch

FieldType
location.zipstringUS ZIP. With radius, keeps places within that distance
location.radiusstring"25mi" or "40km"
location.countrystringUS
location.currencystringUSD
fetch.proxystringauto (default) or off
fetch.accept_site_termsbooleanRequired for sites whose robots.txt restricts the data. Sites

Request

Shell
curl https://watcher-api-staging.manwhas.shop/v1/watchers \
  -H "Authorization: Bearer $SNAG_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: wool-runner-10" \
  -d '{
    "target": { "query": "https://www.allbirds.com/products/mens-wool-runners", "match": "url", "attributes": { "size": 10 } },
    "conditions": { "all": [{ "field": "availability", "op": "=", "value": "back_in_stock" }] },
    "where": { "sites": ["allbirds.com"] },
    "schedule": { "every": "1h", "until": "+30d" },
    "notify": { "channels": ["webhook"], "webhook": { "url": "https://you.example/snag", "events": ["matched", "blocked"] } }
  }'

Response

201 Created

JSON
{
  "watcher_id": "wch_dhjqcvaqnhrchsnv7gtc",
  "kind": "availability",
  "status": "active",
  "mode": "test",
  "parent_id": null,
  "request": { "target": { "query": "https://www.allbirds.com/products/mens-wool-runners", "match": "url", "attributes": { "size": 10 } } },
  "schedule": { "every": "1h", "next_run_at": "2026-11-04T19:38:44.390Z", "until": "2026-12-04T19:38:43.902Z" },
  "clamped": [],
  "warnings": [],
  "created_at": "2026-11-04T19:38:43.902Z",
  "last_run_at": null,
  "first_match_at": null,
  "last_snapshot": null,
  "events": [],
  "webhook_secret": "whsec_Qm9vcGllcy1hcmUtbm90LWEta2V5"
}

request is shortened here; it holds the full body you sent. A broken rule returns 422 with every error at once. See Errors.