Skip to content

Watchlist

A watchlist is your list of operators you care about, plus the automation layer that fires events when any of them changes. Add an operator once, get alerted whenever its licence status flips, a regulatory action lands, or an expiry date approaches — without writing polling loops against every endpoint we offer.

Plan limits (also in pricing):

TierWatchlist capWebhooksPolling
Starter25 operators1 endpoint10 / hour
Pro250 operators5 endpoints60 / hour
Businessunlimited20 endpoints600 / hour
Enterpriseunlimitedunlimitedunlimited

Webhooks are the primary alert channel. Polling exists for agents that can’t accept inbound HTTP (corporate networks, air-gapped analytics, local dev) and as a backfill mechanism during webhook outages.

Sign in and open app.igregulator.io/watchlist. Type an operator name — we typeahead against every operator slug we know about. Click to add. Click remove to drop.

Same surface via bearer token:

Terminal window
# Current watchlist + count + plan cap
curl -H "Authorization: Bearer igk_..." \
https://api.igregulator.io/v1/watchlist
# Add an operator by slug (lowercase, hyphens)
curl -X POST -H "Authorization: Bearer igk_..." \
-H "Content-Type: application/json" \
-d '{"operator_slug":"888-uk-limited"}' \
https://api.igregulator.io/v1/watchlist/operators
# Remove (idempotent)
curl -X DELETE -H "Authorization: Bearer igk_..." \
https://api.igregulator.io/v1/watchlist/operators/888-uk-limited
# Paginated listing with current licence status per operator
curl -H "Authorization: Bearer igk_..." \
"https://api.igregulator.io/v1/watchlist/operators?limit=50&offset=0"

Discover slugs with GET /v1/operators/search?q=<name>.

Create an endpoint with the watchlist_only: true flag (default). Deliveries fire for operators in your watchlist only — no firehose, no noise. Events covered:

  • license.status_changed
  • license.expiring_30d / _60d / _90d
  • license.expired
  • license.issued (only if you were watching the operator when the new licence was detected)
  • regulatory_action.added

See /docs/webhooks for the signing + retry protocol. Quickstart in 2 minutes: /docs/webhooks/quickstart.

GET /v1/watchlist/events returns the same envelope events, pulled. Cursor-paginated so you don’t re-process events between runs. Rate-limited per plan (see §1). Every response carries X-Poll-RateLimit-Limit, -Remaining, -Reset, -Window, and a X-Poll-Recommended-Interval hint in seconds.

Terminal window
# Bootstrap: 30-day window (matches event retention)
curl -H "Authorization: Bearer igk_..." \
"https://api.igregulator.io/v1/watchlist/events?since=2026-04-01T00:00:00Z&limit=100"
# Steady state: use the next_cursor from the previous response
curl -H "Authorization: Bearer igk_..." \
"https://api.igregulator.io/v1/watchlist/events?cursor=eyJ0cy...&limit=100"

Response:

{
"events": [
{
"event": "license.status_changed",
"event_id": "evt_...",
"api_version": "2026-04-20",
"timestamp": "...",
"livemode": true,
"data": { ... }
}
],
"next_cursor": "eyJ0c...",
"has_more": true
}

events payloads are identical to the webhook envelope (minus the signature — polling authenticates via your API key, not per-delivery HMAC). Dedupe on event_id whether you’re receiving via webhook or poll; you’ll use the same key for both.

  • Persist the cursor. Save next_cursor after each successful batch to your own DB / disk. On restart, resume from it.
  • Dedupe on event_id. Crash windows can cause you to re-process the last batch; same dedupe path you’d use for webhooks covers this.
  • Respect X-Poll-Recommended-Interval. It’s ceil(3600 / limit) — sleeping that long between polls guarantees you never hit the hour ceiling. Starter = 360 s, Pro = 60 s, Business = 6 s.
  • On 429, wait until reset_at. Don’t exponential-backoff — the window resets deterministically on the hour boundary. See /docs/rate-limits.
  • Hybrid webhooks + polling is the resilient pattern. Webhooks for low latency, polling for the few-hour windows where your receiver was down and deliveries abandoned. Both ship the same event_id, so dedupe makes double-processing a no-op. Example in /docs/webhooks § Pattern C.

That matches our event retention. Older values fail with 400 since_exceeds_retention_window. Rare in practice — the first call uses since, every subsequent call uses the cursor.

If you exceed your watchlist cap mid-month, the next POST /v1/watchlist/operators returns 403 watchlist_quota_exceeded with the current count + cap. Remove an operator or upgrade.

Polling ceiling hits return 429 watchlist_events_poll_limit with a concrete reset_at timestamp — not exponential backoff, deterministic hour-boundary reset. Webhooks do not count against this limit.

5. What events don’t fire for watched operators

Section titled “5. What events don’t fire for watched operators”
  • coverage.degraded / coverage.restored — these are jurisdiction-level, not operator-level. They’re emitted regardless of watchlist membership; anyone subscribed to the event type gets them.
  • webhook.endpoint_degraded — self-notification about your own endpoints. Ignores watchlist.
  • No events arriving — your watchlist may be empty, or the operators you track haven’t had any changes this month. Run GET /v1/watchlist/events?since=2026-04-01T00:00:00Z to confirm what would have fired over a month.
  • Too many events — too-broad subscription. Each of the three expiry windows fires separately; narrow to the one(s) you act on.
  • Events for operators I don’t watch — your webhook might have watchlist_only: false. Check PATCH /v1/webhooks/:id with { "watchlist_only": true }.

Related: /docs/webhooks, /docs/rate-limits.