Verify many domains in one request (KYB sweep)
POST /v1/check/batch
Authenticated batch of /v1/check (domains only) — one round trip for a KYB sweep or affiliate-list audit instead of N sequential calls. Each result carries verdict / verdict_detail / match / confidence / match_absence_reason exactly as the single check does, and _meta.register when a jurisdiction matched — but not alternatives, the dual-licence jurisdictions list or as_of; a dual-licensed row’s verdict_detail says how many other links GET /v1/check would show. checked_jurisdictions and _meta (checked_at, stale_jurisdictions) are returned once at the top to stay token-lean. Up to 100 domains per request — paginate beyond. Each entry is normalised as the single check normalises domain (case, a trailing dot, an internationalised name → punycode); query.domain is what was looked up and query.input echoes the entry as sent. An entry that is not a hostname — too long, not a string, a URL — comes back as a per-row error (with error_detail, and no verdict) rather than failing the whole batch; only a body that is not { domains: [1–100 entries] } is a 400. Rows carry related_hosts when the related-host stage answered. Counts as one request against your plan quota today.
Authorizations
Section titled “Authorizations ”Request Body required
Section titled “Request Body required ”object
Example
{ "domains": [ "bet365.com", "www.virginbet.com", "casino.com" ]}Responses
Section titled “ Responses ”Per-domain results.
object
object
When this batch was computed.
Covered registers past their freshness SLA (often []) — once for the whole batch. Each weakens every not_found / generic_term / name_match_only row.
A covered jurisdiction whose latest register read is past its freshness SLA. A domain its regulator listed after last_read_at would not be in our data yet, so each entry weakens a “not found”.
object
Jurisdiction code — UKGC, MGA, CW (Curaçao), KH (Kahnawake), AN (Anjouan), TGC (Tobique) or IOM (Isle of Man). GET /v1/jurisdictions lists them with names and licence types.
object
object
The normalised hostname looked up. Absent on an error row.
The entry exactly as sent (any JSON value on an invalid_input row).
As on the single check. Absent on an error row.
As on the single check. Absent on an error row.
Present when the row matched a jurisdiction.
object
When we last read the matched jurisdiction’s register, and whether that read is inside its freshness SLA — the same rule and numbers as /v1/health/coverage (24 h for UKGC, AN, TGC, IOM; 48 h for MGA, CW, KH). A stale register means a change the regulator published since last_read_at is not in this answer.
object
Jurisdiction code — UKGC, MGA, CW (Curaçao), KH (Kahnawake), AN (Anjouan), TGC (Tobique) or IOM (Isle of Man). GET /v1/jurisdictions lists them with names and licence types.
The newest last_verified_at among the jurisdiction’s licences — when a load last confirmed its register. Cached up to 10 minutes.
last_read_at is less than sla_hours old. null if never read.
{ "jurisdiction": "UKGC", "last_read_at": "2026-09-30T03:00:26.364Z", "fresh": true, "sla_hours": 24}object
How sure we are WHICH OPERATOR this is — a statement about the match, not about the licence. high = the domain (or its www-counterpart, or — match_type: related_host — another host on the same registrable domain), or the licence number, is listed under this operator in a register we cover. medium = no register we cover ties this domain to one operator; its root closely matches one of the operator’s trading or legal names, so we can name the operator but not prove the domain is theirs (it may be a lookalike). low = a weak name resemblance; operator is a guess. (A generic gambling label such as bestcasino is not a low match: match is null and match_absence_reason is generic_term.) Whether the site is licensed is status together with domain_status, never confidence.
domain_exact — a register lists the queried host, or its www-counterpart (www.x.com and x.com are one site; matched_domain says which spelling is stored). related_host — the queried host is NOT listed; another host on its registrable domain is, under this one operator, and the match describes that host (matched_domain; verdict related_host_listed) — a listing covers the host the regulator names, so this is never licensed. license_number — a ?license_number= query. trading_name_fuzzy / name_similarity — a name resembled the operator’s (confidence medium/low).
Jurisdiction code — UKGC, MGA, CW (Curaçao), KH (Kahnawake), AN (Anjouan), TGC (Tobique) or IOM (Isle of Man). GET /v1/jurisdictions lists them with names and licence types.
The regulator’s name, as GET /v1/jurisdictions gives it (e.g. Curaçao Gaming Authority, UK Gambling Commission) — no second call needed to say who licenses it. null when jurisdiction is.
The licence’s iGregulator UUID — the input to GET /v1/licenses/{license_id} (full record, not_listed_since, last_listed_at) and /v1/licenses/{license_id}/history. null when no licence is attached (name_similarity matches).
The licence number as the regulator’s register prints it — except for KH (Kahnawake), TGC (Tobique) and IOM (Isle of Man), whose registers publish none. For those three it is an iGregulator reference we assign: KH/IG/<slug> or KH/CSPA/<slug>, TGC/B2C/<slug> or TGC/B2B/<slug>, IOM/OGRA/<company key>. The reference is stable and /v1/check?license_number= accepts it, but no regulator issued it: do not present it to a user as the licence number.
true for KH, TGC and IOM: those registers publish no licence number, so license_number is an iGregulator reference — never present it as the regulator’s number. false everywhere else (and when there is no licence).
Where THIS status was published — provenance is per status, not per licence (the same field as on /v1/licenses/{id}). Often not the register the licence is listed in: a Curaçao or Anjouan revocation comes from the enforcement / revoked-licences page, a Kahnawake termination from its advisory notice. Cite it when you report the status. null for a status set before we tracked provenance.
The latest read of status_source_url that still said this status. When the status CHANGED is in /v1/licenses/{license_id}/history.
See the LicenseStatus schema. Approve only on active. not_in_register (the register no longer lists the licence; upstream_status is then null) and surrendered (the operator gave it up) are not revocations, and unknown means we could not read the regulator’s wording — read upstream_status and decide for yourself. We do not guess. This is the LICENCE’s status: for the domain read domain_status too, and on a medium/low match it is the named operator’s licence, not a statement about this domain. null on a domain match (with license_number and license_id) when the regulator lists the domain under an operator that holds no licence that can cover a website — a UKGC licensee with non-remote licences only, an MGA one with no B2C licence; jurisdiction names the regulator that lists it and verdict is licence_not_active.
Populated for domain matches (domain_exact, related_host) only. direct = licensee runs the domain; white_label = licensee authorises a third-party brand on the domain. null for licence-number and fuzzy matches.
The regulator’s own words for the licence status, verbatim, before our enum mapping (e.g. Surrendered → surrendered, Revoked - Non Payment of Fee → revoked, N/A Indefinite → active). Always informative; essential when status is unknown. null when status is not_in_register — there is no current upstream word, and repeating the last one we read as if it were current is how a page came to say ‘revoked · upstream: valid’. Also null when the register’s word says the licence is in force (valid, Active, Licensed, Assessment in progress…) and status is revoked, suspended, surrendered or expired: that status was read from another publication (an enforcement register, an advisory notice), and the register row it would sit next to had not caught up. The reverse is never suppressed — a negative word next to active is always shown.
Set when status is right but not the whole truth; null otherwise. provisional_under_assessment: a Curaçao licence the CGA register lists as ”status is active (the operator may trade), and expires_at may be in the past; a decision is outstanding. Treat as licensed, and re-check: the licence can become final or end. Derived from upstream_status.
The status of matched_domain under this operator, which is not the status of the licence. delisted = the domain is no longer listed on this licence — this site is not covered by it; the licence’s own status is in status, whatever that is. On a related_host match it is the RELATED host’s status, not the queried host’s (which is not listed at all). Simplest: branch on verdict. Field by field, the site is licensed only when match_type is domain_exact, status is active AND domain_status is active. null for licence-number queries and for fuzzy matches (no register ties the domain to this operator).
The hostname the register lists, which this match describes. Usually the query itself; its www-counterpart when only that spelling is stored (www.virginbet.com for virginbet.com — one site, verdict as for the query); or, on a related_host match, another host of the same registrable domain (fi.unibet.com for zz.unibet.com — NOT the queried host, verdict related_host_listed). null for licence-number queries and name matches.
When a regulator source last listed matched_domain on this licence — the latest register, certificate or seal read that wrote this link as listed. Present only while domain_status is active. null when the domain is delisted: we do not keep the time it was last listed before the de-listing, nor since when it has been de-listed, and we will not approximate either. Also null for licence-number queries and name matches.
The regulator’s OWN per-domain verification page for this match, when the regulator publishes one — a Curaçao certificate (cert.cga.cw) or a Tobique validation seal (validate.thetgc.ca). Fetch or link it to confirm the verdict against the primary source directly. We re-read these pages to keep domain_status current: every Tobique seal nightly, each Curaçao certificate every few days (a rolling nightly batch, oldest first) — so the page itself can be newer than our domain_status. null where the regulator has no such page (UKGC, MGA, KH, AN) or for non-domain matches. A legacy cert.gcb.cw link is served on cert.cga.cw, which it redirects to.
On a match from a register row: the licence status that page printed at our latest read of it, verbatim (Active, Revoked…). null when we hold no such reading. When it is not in-force wording, the page is not confirmation — say what it reads and when (verification_page_read_at). It moves no status by itself: a revocation comes only from a regulator publication (status_source_url).
When we read verification_page_status off the page.
As on the single check.
Another stored host on the queried host’s registrable domain (Public Suffix List, private section included: a hosting platform’s customers are not each other’s related hosts). Its listing is about IT, not about the queried host.
object
The operator’s licence jurisdiction; null when it holds none.
That host’s link status under that operator.
invalid_hostname: the entry is a string but not a hostname (too long, a URL, a path, an underscore…). invalid_input: the entry is not a string. match is null and there is no verdict.
One sentence saying what is wrong with the entry.
Invalid query / parameters.
object
Human-readable error summary.
HTTP-status-level class. Stable enum; branch on details.reason for finer control. Current values: invalid_query, invalid_slug, invalid_license_id, invalid_jurisdiction_code, invalid_pagination, not_found, auth_required, auth_invalid, auth_revoked, payment_required, quota_exceeded, rate_limited, server_error.
object
Machine-readable refinement of the top-level code. Stable vocabulary; branch on this in clients. Examples: invalid_input, missing_required_parameter, conflicting_parameters, operator_not_found, license_not_found, jurisdiction_not_found, route_not_found, api_key_missing, malformed_header, api_key_invalid, api_key_revoked, quota_exceeded, export_requires_pro, export_daily_limit_reached, as_of_not_supported, dataset_not_found, internal_error.
Present only when the error maps to a specific request input field (query param, path param, body key). Omitted for errors that aren’t field-scoped (e.g. rate_limited, auth_revoked).
Optional human-readable / agent-actionable hint describing how to resolve the error.
{ "reason": "api_key_revoked", "suggestion": "Generate a new API key at https://app.igregulator.io/api-keys. Revoked keys cannot be restored."}{ "error": "API key has been revoked", "code": "auth_revoked", "details": { "reason": "api_key_revoked", "suggestion": "Generate a new API key at https://app.igregulator.io/api-keys. Revoked keys cannot be restored." }}Missing / malformed / revoked API key.
object
Human-readable error summary.
HTTP-status-level class. Stable enum; branch on details.reason for finer control. Current values: invalid_query, invalid_slug, invalid_license_id, invalid_jurisdiction_code, invalid_pagination, not_found, auth_required, auth_invalid, auth_revoked, payment_required, quota_exceeded, rate_limited, server_error.
object
Machine-readable refinement of the top-level code. Stable vocabulary; branch on this in clients. Examples: invalid_input, missing_required_parameter, conflicting_parameters, operator_not_found, license_not_found, jurisdiction_not_found, route_not_found, api_key_missing, malformed_header, api_key_invalid, api_key_revoked, quota_exceeded, export_requires_pro, export_daily_limit_reached, as_of_not_supported, dataset_not_found, internal_error.
Present only when the error maps to a specific request input field (query param, path param, body key). Omitted for errors that aren’t field-scoped (e.g. rate_limited, auth_revoked).
Optional human-readable / agent-actionable hint describing how to resolve the error.
{ "reason": "api_key_revoked", "suggestion": "Generate a new API key at https://app.igregulator.io/api-keys. Revoked keys cannot be restored."}{ "error": "API key has been revoked", "code": "auth_revoked", "details": { "reason": "api_key_revoked", "suggestion": "Generate a new API key at https://app.igregulator.io/api-keys. Revoked keys cannot be restored." }}The key’s plan does not cover this request — canceled or no plan (plan_inactive), or a legacy trial key calling anything but /v1/check and the other endpoints that work without a key (endpoint_requires_paid_plan), or a plan below Pro asking for an export (export_requires_pro). Paid plans are not on sale yet: email founder@igregulator.io and we will sort it out.
object
Human-readable error summary.
HTTP-status-level class. Stable enum; branch on details.reason for finer control. Current values: invalid_query, invalid_slug, invalid_license_id, invalid_jurisdiction_code, invalid_pagination, not_found, auth_required, auth_invalid, auth_revoked, payment_required, quota_exceeded, rate_limited, server_error.
object
Machine-readable refinement of the top-level code. Stable vocabulary; branch on this in clients. Examples: invalid_input, missing_required_parameter, conflicting_parameters, operator_not_found, license_not_found, jurisdiction_not_found, route_not_found, api_key_missing, malformed_header, api_key_invalid, api_key_revoked, quota_exceeded, export_requires_pro, export_daily_limit_reached, as_of_not_supported, dataset_not_found, internal_error.
Present only when the error maps to a specific request input field (query param, path param, body key). Omitted for errors that aren’t field-scoped (e.g. rate_limited, auth_revoked).
Optional human-readable / agent-actionable hint describing how to resolve the error.
{ "reason": "api_key_revoked", "suggestion": "Generate a new API key at https://app.igregulator.io/api-keys. Revoked keys cannot be restored."}{ "error": "API key has been revoked", "code": "auth_revoked", "details": { "reason": "api_key_revoked", "suggestion": "Generate a new API key at https://app.igregulator.io/api-keys. Revoked keys cannot be restored." }}Rate limit reached. Public endpoints: 10 req / IP / hour — a free API key (no card, 10,000 requests / month) from https://app.igregulator.io/signup lifts it. Authenticated: per plan tier; paid tiers are not open yet, so email founder@igregulator.io for a higher limit. Retry after the window surfaced in X-RateLimit-Reset.
object
Human-readable error summary.
HTTP-status-level class. Stable enum; branch on details.reason for finer control. Current values: invalid_query, invalid_slug, invalid_license_id, invalid_jurisdiction_code, invalid_pagination, not_found, auth_required, auth_invalid, auth_revoked, payment_required, quota_exceeded, rate_limited, server_error.
object
Machine-readable refinement of the top-level code. Stable vocabulary; branch on this in clients. Examples: invalid_input, missing_required_parameter, conflicting_parameters, operator_not_found, license_not_found, jurisdiction_not_found, route_not_found, api_key_missing, malformed_header, api_key_invalid, api_key_revoked, quota_exceeded, export_requires_pro, export_daily_limit_reached, as_of_not_supported, dataset_not_found, internal_error.
Present only when the error maps to a specific request input field (query param, path param, body key). Omitted for errors that aren’t field-scoped (e.g. rate_limited, auth_revoked).
Optional human-readable / agent-actionable hint describing how to resolve the error.
{ "reason": "api_key_revoked", "suggestion": "Generate a new API key at https://app.igregulator.io/api-keys. Revoked keys cannot be restored."}{ "error": "API key has been revoked", "code": "auth_revoked", "details": { "reason": "api_key_revoked", "suggestion": "Generate a new API key at https://app.igregulator.io/api-keys. Revoked keys cannot be restored." }}Headers
Section titled “Headers ”Unix epoch seconds.
Unexpected server error.
object
Human-readable error summary.
HTTP-status-level class. Stable enum; branch on details.reason for finer control. Current values: invalid_query, invalid_slug, invalid_license_id, invalid_jurisdiction_code, invalid_pagination, not_found, auth_required, auth_invalid, auth_revoked, payment_required, quota_exceeded, rate_limited, server_error.
object
Machine-readable refinement of the top-level code. Stable vocabulary; branch on this in clients. Examples: invalid_input, missing_required_parameter, conflicting_parameters, operator_not_found, license_not_found, jurisdiction_not_found, route_not_found, api_key_missing, malformed_header, api_key_invalid, api_key_revoked, quota_exceeded, export_requires_pro, export_daily_limit_reached, as_of_not_supported, dataset_not_found, internal_error.
Present only when the error maps to a specific request input field (query param, path param, body key). Omitted for errors that aren’t field-scoped (e.g. rate_limited, auth_revoked).
Optional human-readable / agent-actionable hint describing how to resolve the error.
{ "reason": "api_key_revoked", "suggestion": "Generate a new API key at https://app.igregulator.io/api-keys. Revoked keys cannot be restored."}{ "error": "API key has been revoked", "code": "auth_revoked", "details": { "reason": "api_key_revoked", "suggestion": "Generate a new API key at https://app.igregulator.io/api-keys. Revoked keys cannot be restored." }}