Risk scores and reasons

How scores, levels and verdicts work, and every reason code we return with its impact and meaning.

Every check returns the same risk block:

"risk": {
  "score": 64,
  "level": "medium",
  "verdict": "review",
  "reasons": [
    { "code": "domain_brand_new", "impact": 55, "message": "acme-trial.io was registered 3 days ago." },
    { "code": "role_account", "impact": 15, "message": "info@ is usually a shared team inbox, not a person." }
  ]
}

Score, level and verdict

Score Level Verdict Suggested action
0–29 low admit Let them in.
30–69 medium review Let them in with friction: email or phone verification, or hold rewards until verified.
70–100 high refuse Block, or ask for different details.

Impact is how strongly one reason, on its own, points to a fake or unusable signup. Reasons combine like independent odds: score = 100 × (1 − Π(1 − impact/100)).

Codes are stable and safe to branch on. New codes may be added over time, so treat unknown codes by their impact.

Email reasons

Code Impact Meaning
invalid_syntax 100 Not a valid email address.
domain_not_found 95 The domain doesn't exist.
domain_refuses_mail 95 The domain publishes a null MX: it accepts no email.
mailbox_not_found 95 The mail server says this mailbox doesn't exist (mailbox verification only).
disposable_domain 90 A throwaway inbox provider.
no_mail_server 90 The domain has no mail server.
mx_shared_with_disposable 75 The domain's mail server also serves known throwaway domains. Catches new throwaway brands.
domain_brand_new 55 Registered less than 7 days ago.
domain_new 35 Registered less than 30 days ago.
possible_typo 30 Looks like a misspelling of a popular provider, such as gmial.com.
catch_all_domain 20 The server accepts mail for any address, so the mailbox can't be confirmed.
role_account 15 A shared inbox, like info@ or support@.
random_local_part 12 The part before the @ looks machine-generated.
dns_unavailable 10 DNS couldn't be reached, so mail servers are unknown.
no_email_authentication 8 The domain publishes neither SPF nor DMARC.
plus_addressed 5 The address uses a +tag.

IP reasons

Code Impact Meaning
invalid_ip 100 Not a valid IPv4 or IPv6 address.
tor_exit_node 85 A current Tor exit node.
vpn_network 60 A hosting network mainly used by commercial VPNs.
datacenter_ip 45–55 A cloud or hosting provider, not a home or mobile network.
non_public_ip 40 A private or reserved address: you're probably sending your own proxy's IP.
privacy_relay 20 Traffic relayed through a CDN or privacy service.

Phone reasons

Code Impact Meaning
unparseable_number 100 Not a phone number, or missing its country code.
invalid_number 85–95 Wrong length, or an unassigned range.
premium_rate_number 80 Premium-rate line.
toll_free_number 60 Toll-free business line.
pager_number, voicemail_number 60 Can't receive SMS codes.
voip_number 50 VoIP range.
shared_cost_number 40 Business line.
personal_number, uan_number 30 Forwarding or switchboard number.
country_mismatch 15 The number's country differs from the one you passed.

Domain reasons

The domain check uses the same codes as the email check, with lower impact for "doesn't receive mail" (a website domain may legitimately not use email): domain_refuses_mail 60, no_mail_server 50.

Signup cross-checks

Code Impact Meaning
automation_pattern 40 Throwaway email from a datacenter or Tor network.
phone_ip_country_mismatch 15 Phone country differs from IP country.