Endpoints
Every endpoint has full schemas in the API reference and an interactive executor in the playground. This page is a map, not a reference — use it to pick which surface you need.
Public (no key)
Section titled “Public (no key)”10 requests per IP per hour on each of these without a key; with a valid key, your plan’s quota applies instead (rate limits).
| Endpoint | Use |
|---|---|
GET /v1/check | Verify a domain or licence number in one round trip. Answers with a verdict (licensed, licensed_provisional, licence_not_active, domain_not_listed, related_host_listed, name_match_only, not_found, generic_term) and a quotable verdict_detail; a host and its www. counterpart are the same site, other subdomains are not (related_hosts[]); match names the regulator (regulator_name), the licence (license_id for /v1/licenses/{id}) and where its status was published (status_source_url, status_observed_at); _meta.register / _meta.stale_jurisdictions say how fresh the registers behind it are. Dual-licensed domains carry a jurisdictions[] array, and match.verification_url links to the regulator’s own verification page where one exists (CW cert / TGC seal). See the confidence guide. |
GET /v1/jurisdictions | List the seven jurisdictions we cover, with name / country / currency / licence types. |
GET /v1/operators/search?q=… | Search operators by display name, slug or registered (legal) name — a case-insensitive substring match. Trading names and domains are not searched; use /v1/check for a domain. Unauthenticated: capped at 3 rows. |
GET /v1/health/coverage | Per-jurisdiction scraper freshness — last successful scrape, age in hours, fresh vs stale flag per our SLA (UKGC / AN / TGC / IOM 24 h, MGA / CW / KH 48 h) — plus domain_coverage (methodology). |
Authenticated (Bearer token)
Section titled “Authenticated (Bearer token)”| Endpoint | Use |
|---|---|
POST /v1/check/batch | Up to 100 domains in one request, resolved like /v1/check — verdict, verdict_detail, match, confidence on every row, but no jurisdictions[], alternatives[] or as_of; an entry we can’t look up is a per-row error with no verdict; checked_jurisdictions and _meta.stale_jurisdictions once at the top. POST only: any other method is 405 method_not_allowed with Allow: POST, key or no key. See batch. |
GET /v1/jurisdictions/:code | Single jurisdiction detail. The code is case-insensitive. |
GET /v1/jurisdictions/:code/operators | Paginated operators holding at least one licence (any status) in that jurisdiction. ?limit= 1–200 (default 50), ?offset=. Ordered by internal operator id — stable across pages, not alphabetical. The code is case-insensitive (ukgc); an unknown code is 404 jurisdiction_not_found, as on /v1/jurisdictions/:code, not an empty list. |
GET /v1/operators/:slug | Full operator detail — metadata + licences + domains. Each licence carries status_qualifier and license_reference_is_ours (true for KH, TGC, IOM: license_number is our reference), with issued_date / expiry_date as YYYY-MM-DD. Each domain carries verification_url (the regulator’s own page, where one exists) and verification_page_status / verification_page_read_at — what that page printed about the licence at our latest read, verbatim, and when; a word that isn’t “in force” means the page is not proof (verification_url). The slug is case-insensitive. Supports ?as_of=. |
GET /v1/operators/:slug/licenses | Every licence for one operator (not paginated), with the same status_qualifier and license_reference_is_ours. Append ?include_history=true for each licence’s status-change log. |
GET /v1/operators/:slug/regulatory-actions | Enforcement actions linked to one operator — fines, warnings, suspensions, revocations. ?limit= 1–100 (default 20), ?offset=, ?sort=date_desc (default) / date_asc / amount_desc / type_asc. An empty list means none is linked to this operator, not a clean record: many published actions aren’t matched to an operator yet (UKGC 107 of 107 linked, MGA 2 of 160, CW 0 of 18 on 2026-09-28). The response says so itself: _meta.note says what the list does and doesn’t mean (on an empty list: that it is not a clean record), and _meta.sources_read lists the regulator publications we read. |
GET /v1/licenses/:license_id | Licence by uuid. Useful when you want a pinned detail page. Carries the status’s own provenance: status_source_url, status_observed_at, last_listed_at, not_listed_since; status_qualifier; license_reference_is_ours; issued_date / expiry_date as YYYY-MM-DD. Supports ?as_of=. |
GET /v1/licenses/:license_id/history | Status-change timeline for a single licence (the whole timeline, not paginated). Each event has a note and the evidence hash (snapshot_sha256, snapshot_fetched_at) — events are never deleted. Only corrected_at means an event was withdrawn: it is set, with correction_note saying why, when we later found the event wrong. A correction_note without corrected_at is a reworded note on an event that stands. |
GET /v1/export/:dataset | Pro and above. A whole dataset — licences, operators or domains (links) — as one CSV or NDJSON file (?format=csv|json), optionally sliced by ?jurisdiction= / ?status=; each row carries its status provenance. 10 exports a day on Pro, 100 on Business; below Pro → 402 export_requires_pro. No as_of. See export. |
Watchlist
Section titled “Watchlist”| Endpoint | Use |
|---|---|
GET /v1/watchlist | Summary: { count, limit, operators } — your plan’s cap and the 50 most recently added operators. |
GET /v1/watchlist/operators | Your watched operators with a current licence status each. ?limit= 1–200 (default 50), ?offset=. |
POST /v1/watchlist/operators | Add { "operator_slug": "…" } → 201. Already watched → 409. |
DELETE /v1/watchlist/operators/:slug | Remove → 204, whether or not it was on the list. |
GET /v1/watchlist/events | Poll for events (the webhook envelope, pulled). ?since= or ?cursor=, ?limit= 1–500 (default 100); a per-hour poll ceiling per plan. See watchlist. |
Webhooks
Section titled “Webhooks”| Endpoint | Use |
|---|---|
POST /v1/webhooks | Create { url, events, watchlist_only?, description? } → 201 with the signing secret, shown once. |
GET /v1/webhooks | List your endpoints (no secrets). |
PATCH /v1/webhooks/:id | Change url, events, active, watchlist_only or description. |
DELETE /v1/webhooks/:id | Delete the endpoint → 204. Its secrets and delivery history, pending deliveries included, go with it. |
POST /v1/webhooks/:id/rotate_secret | Issue a new secret; the old one keeps signing for 7 days. |
GET /v1/webhooks/:id/deliveries | Recent deliveries, newest first. ?status=all / pending / delivered / failed / abandoned, ?limit= 1–200 (default 100). |
POST /v1/webhooks/:id/test | Send a signed test.ping now; returns { delivered, http_status, response_body, latency_ms, error }. |
See webhooks.
System
Section titled “System”| Endpoint | Use |
|---|---|
GET /v1/health | Liveness probe. 200 if postgres + redis are reachable, 503 otherwise. |
GET /v1/stats | Headline counts — licence records by status, per-jurisdiction licences and last register read (with the same fresh/stale rule as /v1/health/coverage), operators, linked domains and how many carry the regulator’s own certificate or seal, brand pages, status changes read in the last 30 days, withdrawn events — each with its definition in the body (definitions). No key and no per-IP cap: one payload for everyone, recounted at most every 10 minutes. The igregulator.io homepage prints it. |
GET /openapi.json | Canonical OpenAPI 3.1 spec. Consume it, generate a client, etc. |
Response shape conventions
Section titled “Response shape conventions”-
Paginated lists take
?limit=+?offset=and returntotal,limit,offsetnext to the rows:GET /v1/operators/search→{ q, total, limit, offset, operators, _meta }GET /v1/jurisdictions/:code/operators→{ jurisdiction_code, total, limit, offset, operators }GET /v1/operators/:slug/regulatory-actions→{ operator_slug, total, limit, offset, sort, regulatory_actions }GET /v1/watchlist/operators→{ total, limit, offset, operators }
Defaults and maxima differ per endpoint — see pagination.
-
Unpaginated lists return everything in one envelope:
GET /v1/operators/:slug/licenses→{ operator_slug, licenses }GET /v1/licenses/:license_id/history→{ license_id, license_number, history, _meta }GET /v1/jurisdictions→{ jurisdictions };GET /v1/webhooks→{ endpoints }
-
GET /v1/watchlist/eventsis cursor-paginated:{ events, next_cursor, has_more }. -
Detail endpoints:
GET /v1/jurisdictions/:codeandGET /v1/licenses/:license_idreturn the row itself (the licence with a_metablock).GET /v1/operators/:slugreturns{ operator, licenses, domains, _meta }— itslicenses[]anddomains[]are complete, bare arrays;/licensesreturns the same licences, plus optional history. -
Timestamps are ISO-8601 UTC (
2026-04-19T12:00:00.000Z). -
Dates — a licence’s
issued_dateandexpiry_date,/v1/check’smatch.expires_at, a regulatory action’sdecision_date— areYYYY-MM-DDstrings: the register publishes a day, not an instant. -
as_oftakes aYYYY-MM-DDdate or an ISO-8601 datetime with a UTC offset, nothing else (point-in-time). -
UUIDs are lowercase, hyphenated, v4.
-
Operator slugs are lowercase;
/v1/operators/:slug…resolves one in any case (Flutter-UK-Limitedfindsflutter-uk-limited). Jurisdiction codes are uppercase and resolve in any case too.