Confidence scoring
The /v1/check endpoint returns a match object with a confidence
field. This page explains what each level means, how we pick it, and
how UIs should render it.
The three levels
Section titled “The three levels”confidence | What it means | Render as |
|---|---|---|
high | Exact or root-domain match in our authoritative registry. | Green check. Safe to say “this site is licensed by X”. |
medium | Domain root matched a trading name or operator name. We can identify the operator but can’t prove this domain is theirs. | Amber / neutral. “Likely operated by X” phrasing. |
low | A weak fuzzy match (operator returned, but below the strong-similarity bar), or the domain root is a generic gambling term (casino.com, poker.com) where too many operators share the label to pick one. | Gray / warning. “We can’t confirm this domain.” |
A fourth value — none — appears in the top-level confidence field
(not match.confidence) when match is null.
Why a query missed: match_absence_reason
Section titled “Why a query missed: match_absence_reason”When match is null, low/none on its own is ambiguous — it used to
conflate “generic term” with “we checked and it isn’t there”. So on a miss
the response carries two extra fields (present only when match is
null) so you can phrase the answer precisely instead of guessing:
match_absence_reason | Meaning | Say to your user |
|---|---|---|
generic_term | The label is an ultra-generic gambling word (casino.com); we can’t map it to one operator. | ”Can’t identify a specific operator from this domain.” |
no_record_found | A specific query we checked against every covered register and did not find. | ”Not found in any of the N jurisdictions iGregulator covers.” — never an unqualified “unlicensed”. |
checked_jurisdictions accompanies the miss — the exact register codes we
checked (e.g. ["AN","CW","KH","MGA","TGC","UKGC"]) — so a “not licensed”
claim is always scoped to our coverage, never stated as an absolute.
{ "query": { "domain": "some-unknown-site.com" }, "match": null, "confidence": "none", "match_absence_reason": "no_record_found", "checked_jurisdictions": ["AN", "CW", "KH", "MGA", "TGC", "UKGC"]}These fields are absent when there’s a match — check match === null
first, then branch on match_absence_reason.
match_type
Section titled “match_type”Tells you how we arrived at the match, useful for debugging and UX differentiation.
match_type | Source |
|---|---|
domain_exact | Found the domain in the domains table — sourced from the regulator’s official register. Carries domain_association (direct or white_label). |
trading_name_fuzzy | Trigram similarity ≥ 0.55 against operators.trading_names[] after stripping the TLD. Used when the domain isn’t registered but the brand exists. 0.55 was picked empirically against the UKGC register: it catches legitimate variants (paddypower ↔ paddy-power, skybet ↔ sky-bet) while rejecting the long tail of single-syllable collisions (gold, star, royal) where the label is too generic to mean one operator. Below 0.55 we land in low-confidence territory either way; above it the trigger is stable. |
name_similarity | Last-chance similarity against operators.display_name — rarely fires for B2C domains, useful when no trading name was populated upstream. |
domain_association
Section titled “domain_association”When match_type = domain_exact, we differentiate:
direct— the licensee runs the site themselves. Theoperatorfield is the company your end-user is gambling with.white_label— the licensee has authorised a third-party brand to trade on the domain under their permit. Theoperatorfield is the licensee, not the brand. UK-licensed white-label arrangements are legal and common; surfacing the relationship lets you show “operated by Brand X under ProgressPlay’s UKGC permit”.
Fuzzy matches (trading_name_fuzzy, name_similarity) don’t populate
domain_association — we don’t have a domain row to read it from, so
the field is null.
domain_status vs status
Section titled “domain_status vs status”status is the licence; domain_status is the domain. They
move independently: a regulator can withdraw one site from a licensee’s
permitted surface while the licence itself stays active. domain_status: "delisted" means exactly that — check it before treating status: "active" as a green light for the site you were asked about.
verification_url — check us against the regulator
Section titled “verification_url — check us against the regulator”Where the regulator publishes a per-domain verification page of its
own, match.verification_url links straight to it:
- Curaçao — the CGA certificate portal (
cert.cga.cw), including/tokencluster certificates listing every approved domain under the licence. - Tobique — the TGC validation seal (
validate.thetgc.ca), listing the licence’s whole registered-website cluster.
null for regulators with no such page (UKGC, MGA, KH, AN) and for
fuzzy matches. We re-read every stored verification page nightly
and update domain_status only from a clean read of the regulator’s
own words — so the URL is not just a citation, it’s the mechanism that
keeps the row fresh. Surface it next to the verdict: “verify on the
regulator’s own page” is the strongest trust signal we can hand you.
jurisdictions[] — dual-licensed domains
Section titled “jurisdictions[] — dual-licensed domains”A brand can be licensed by different legal entities in different
jurisdictions at the same time (spinsup.com: Anjouan + Tobique;
me88.com: Anjouan + Curaçao). When the matched domain has more than
one (operator, jurisdiction) pair, the response carries a best-first
jurisdictions[] array — jurisdictions[0] is the pair match
reports — each entry with its own status, domain_status,
domain_association, and verification_url.
Per-link status matters: the same domain can be active under one
register and delisted under another — both true at once. Before
phrasing a single-jurisdiction verdict (“licensed in Anjouan”), check
whether the array is present and report the full picture. Absent for
ordinary single-licence domains.
Tiebreaking for equal similarity
Section titled “Tiebreaking for equal similarity”Brand names like Paddy Power trigram-match several sister companies
(PPB Counterparty, PPB Entertainment, PPB GE, Power Leisure
Bookmakers) at similarity 1.0. To keep the primary match stable
across DB reindex and VACUUM, /v1/check applies a documented
tiebreaker cascade whenever the top candidates are tied on similarity:
- similarity DESC — closeness wins first, as ever.
- has_active DESC — operators with at least one
activelicence are preferred over operators whose licences are all expired / revoked. - oldest_active_issued ASC — among active-licence candidates, the one whose oldest active licence issued first wins. Stability signal: a parent entity that has been licensed longest is the most useful “who actually runs this brand” answer.
- total_licenses DESC — more licences across the register → more likely a parent entity rather than a single-purpose subsidiary.
- operator_slug ASC — lexicographic final fallback. Always deterministic even when every previous rank is tied.
Clients that cache domain → operator mappings can rely on the primary result remaining stable between index rebuilds; any change in primary reflects a change in the underlying registry data, not PG query randomness.
alternatives[]
Section titled “alternatives[]”Up to 3 runner-up candidates, sorted by similarity descending.
- On
confidence: medium, these are operators with the same or similar trading name that we ranked below the primary match. - On
confidence: low(generic label), this is always[]— we refuse to guess when the label is ambiguous. - On
confidence: high/none, also[].
Why the generic-label filter exists
Section titled “Why the generic-label filter exists”Without it, GET /v1/check?domain=casino.com would return “Casino MK
Limited” with confidence: medium — deterministically, because “casino”
matches that trading name at similarity 1.0. But the actual casino.com
is licensed elsewhere (MGA, Gibraltar) which we don’t cover, and the
answer “yes, Casino MK owns it” would be wrong.
The blocklist is a substring regex over the normalised label —
casino, poker, bingo, gambling, bet, slot/slots,
sportsbook, roulette, blackjack, wager, lottery,
gaming. Matches anywhere in the label, so casino.com,
bestcasino.com, and casino-bonus.com all return confidence: low with empty alternatives[]. Licensed brands containing one
of these keywords (bet365.com, pokerstars.com) still resolve
to high because the domain-exact match runs before the generic
gate.