Docs/Guides

Understanding Scores

How to interpret the quality score.

Every email verification returns a score from 0-100. It summarizes the strength of the address, domain-routing, and mailbox evidence available at verification time. It is not a sender-reputation or inbox-placement score.

Score Ranges

ScoreDeliverabilityRecommendation
80-100HighSafe to send
50-79MediumProceed with caution
25-49LowHigh risk
0-24RiskyDo not send

How Scores Are Calculated

The score follows the strongest deliverability evidence rather than adding unrelated heuristics:

EvidenceScoreMeaning
Mailbox accepted; random address rejected as nonexistent95High-confidence mailbox evidence
Mailbox and random address both accepted55Catch-all domain; specific mailbox remains unproven
Mailbox reported full45Mailbox evidence exists, but delivery is currently impaired
SMTP temporary, policy, or inconclusive result35Domain routes mail, but mailbox status is unresolved
Mailbox rejected as nonexistent5Strong evidence the mailbox will not accept mail
Invalid or null-MX domain0Domain cannot receive mail

Disposable status, role accounts, plus addressing, character patterns, provider identity, SPF, DMARC, and secure-email-gateway detection remain useful response signals, but they do not change the deliverability score. Apply those separate fields according to your own product and abuse policy.

Score Examples

High Score (95)

{
  "email": "[email protected]",
  "valid": true,
  "score": 95,
  "deliverability": "high",
  "disposable": false,
  "role_account": false,
  "catch_all": false,
  "free_email": false,
  "syntax_valid": true,
  "domain_valid": true,
  "mailbox_valid": true,
  "provider": "google",
  "mx_host": "aspmx.l.google.com.",
  "suggestion": null,
  "dns": null
}

This email has everything going for it: valid syntax, established domain, proper MX records, and a verified mailbox.

Medium Score (55)

{
  "email": "[email protected]",
  "valid": true,
  "score": 55,
  "deliverability": "medium",
  "disposable": false,
  "role_account": true,
  "catch_all": true,
  "free_email": false,
  "syntax_valid": true,
  "domain_valid": true,
  "mailbox_valid": false,
  "provider": null,
  "mx_host": "mx1.newstartup.io.",
  "suggestion": null,
  "dns": {
    "has_spf": true,
    "has_dmarc": true,
    "dmarc_policy": "quarantine"
  }
}

The domain is a catch-all (accepts all addresses), so we can't verify the specific mailbox exists. The role-account flag is still available for application policy, but it does not imply that delivery will fail.

High Deliverability, Disposable Address (95)

{
  "email": "[email protected]",
  "valid": false,
  "score": 95,
  "deliverability": "high",
  "disposable": true,
  "role_account": false,
  "catch_all": false,
  "free_email": false,
  "syntax_valid": true,
  "domain_valid": true,
  "mailbox_valid": true,
  "provider": null,
  "mx_host": "mx.tempmail.net.",
  "suggestion": null,
  "dns": null
}

The mailbox can accept mail, so its deliverability evidence is high. The separate disposable signal makes valid false under the API's default policy and lets your application reject or challenge likely throwaway addresses without misreporting their bounce risk.

Using Scores in Your Application

Simple Threshold

const result = await verifyEmail(email);

if (!result.valid || result.score < 50) {
  return { error: 'Please use a different email address' };
}

Tiered Approach

const result = await verifyEmail(email);

if (!result.valid) {
  return { error: 'Please use a non-disposable, valid email address' };
} else if (result.score >= 80) {
  // Delivery is likely, but ownership still requires confirmation
  await createAccount(email, { verified: false });
  await sendVerificationEmail(email);
} else if (result.score >= 50) {
  // Require email confirmation
  await createAccount(email, { verified: false });
  await sendVerificationEmail(email);
} else {
  // Reject signup
  return { error: 'Please use a valid email address' };
}

Using Deliverability Rating

const result = await verifyEmail(email);

if (!result.valid) {
  return { error: 'Please use a non-disposable, valid email address' };
}

switch (result.deliverability) {
  case 'high':
    // Delivery is likely; still confirm mailbox ownership
    await sendVerificationEmail(email);
    break;
  case 'medium':
    // Require confirmation
    await sendVerificationEmail(email);
    break;
  case 'low':
  case 'risky':
    return { error: 'Please use a valid email address' };
}

Scores vs. Validity

valid applies the API's address/domain/disposable policy, while the score describes deliverability evidence. A domain can therefore be valid even when its specific mailbox was rejected or could not be confirmed:

ScenariovalidScoreReason
Gmail address, verifiedtrue95Everything checks out
Disposable, mailbox acceptedfalse95Deliverable, but separately flagged by policy
Catch-all domaintrue55Can't confirm mailbox
Mailbox rejected as nonexistenttrue5Domain is valid, mailbox is not
Invalid or null-MX domainfalse0Domain cannot receive mail

Best Practices

  1. Always verify ownership separately - SMTP acceptance never proves the user controls the mailbox
  2. Set appropriate thresholds - Different use cases need different standards
  3. Monitor score distributions - Track average scores to detect trends
  4. Combine with other signals - IP reputation, behavior patterns, etc.

Report Delivery Outcomes

Observed provider outcomes are the best way to measure verification accuracy on your own traffic. Submit each provider event once with a stable event ID:

curl -X POST "https://tinyvalidator.com/api/v1/verification-outcomes" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "external_event_id": "provider-event-123",
    "email": "[email protected]",
    "outcome": "delivered",
    "source": "your-email-provider",
    "occurred_at": "2026-07-10T12:00:00.000Z"
  }'

Supported outcomes are delivered, hard_bounce, soft_bounce, and complaint. Events are idempotent per API user and are matched to the latest prior verification of the same normalized email within 30 days. GET /api/v1/verification-outcomes returns match coverage and disagreement rates; unmatched events remain counted but are excluded from the disagreement denominators.