Lead validator template

  • Next.js
  • React

Score a lead from its email and phone number: throwaway inboxes, typos, VoIP and temporary numbers.

A Next.js app that checks a signup or contact-form lead before it reaches your CRM. Enter an email and a phone number, and it runs both through APIVerve at once, lists every check with a pass, warning or fail, and scores the lead out of 100. Deploy it as-is to screen leads by hand, or lift the API route into your own form.

The lead validator app running

What it does

Catches fake emails
Flags disposable inboxes, domains with no mail server, and shared addresses like info@ or sales@.
Spots typos
Warns when a domain looks misspelled, like gmial.com, and suggests the fix on paid plans.
Checks the phone number
Confirms the number is real for its country and flags temporary and VoIP numbers.
Scores the lead
Starts at 100, takes 40 off per fail and 15 per warning, so you can sort or filter leads by one number.
Keeps your key private
The browser only talks to your own API route, which holds the key and limits each visitor to 10 checks a minute.

How it works

The API route: it calls both APIs, turns each response into checks, and scores the result.

app/api/validate/route.js
async function callApi(url, params) {
  const res = await fetch(`${url}?${new URLSearchParams(params)}`, {
    headers: { 'x-api-key': API_KEY },
    cache: 'no-store'
  });
  const body = await res.json().catch(() => null);
  if (!res.ok || body?.status !== 'ok') {
    throw new Error(body?.error || `APIVerve returned ${res.status}`);
  }
  return body.data;
}

/**
 * Each check is pass, warn or fail. A fail costs 40 points, a warning 15.
 * Only free-plan fields are used, so the score works on every plan.
 */
function emailChecks(d) {
  // suggestedCorrection (paid plans) can catch a typo hasTypo misses.
  const typo = d.hasTypo || !!d.suggestedCorrection;
  return [
    { label: 'Deliverable', status: d.isValid && d.isMxValid ? 'pass' : 'fail',
      detail: d.isMxValid ? 'Domain accepts mail' : 'Domain has no mail server' },
    { label: 'Not disposable', status: d.isDisposable ? 'fail' : 'pass',
      detail: d.isDisposable ? 'Throwaway inbox' : 'Permanent inbox' },
    { label: 'No typo', status: typo ? 'warn' : 'pass',
      detail: typo ? (d.suggestedCorrection ? `Did they mean ${d.suggestedCorrection}?` : 'Looks like a misspelled domain') : 'Domain spelled correctly' },
    { label: 'Personal inbox', status: d.isRoleAccount ? 'warn' : 'pass',
      detail: d.isRoleAccount ? 'Shared address (info@, sales@)' : 'Reaches a person' },
    { label: 'Work email', status: 'info',
      detail: d.isCompanyEmail ? 'Company domain' : d.isFreeEmail ? 'Free provider (Gmail, Yahoo…)' : 'Unknown provider' }
  ];
}

function phoneChecks(d) {
  return [
    { label: 'Valid number', status: d.isValid ? 'pass' : 'fail',
      detail: d.isValid ? d.formatted?.international || 'Valid' : 'Not a real number for this country' },
    { label: 'Not disposable', status: d.isDisposable ? 'fail' : 'pass',
      detail: d.isDisposable ? 'Temporary number' : 'Permanent number' },
    { label: 'Not VoIP', status: d.isVoip ? 'warn' : 'pass',
      detail: d.isVoip ? 'Internet number, easy to create' : 'Carrier-issued' },
    { label: 'Line type', status: 'info',
      detail: d.isMobile ? 'Mobile' : (d.type || 'unknown').replace(/_/g, ' ') }
  ];
}

function score(checks) {
  const penalty = checks.reduce((n, c) => n + (c.status === 'fail' ? 40 : c.status === 'warn' ? 15 : 0), 0);
  return Math.max(0, 100 - penalty);
}

See the whole file on GitHub

Deploy it

  1. Get a free API key

    The free plan includes 200 credits a month, no card needed. Create your key.

  2. Deploy it

    Click Deploy to Vercel. Vercel copies the repo to your GitHub account and asks for APIVERVE_API_KEY: paste your key there.

  3. Open your app

    Vercel builds it and gives you a live URL, usually in about a minute. Every push to the repo redeploys it.

Try the Email Validator API — the call this template makes

Request
GETapi.apiverve.com/v1/emailvalidator?email=support%40myspace.com
Query parameters
Verification
Format

No key required to try it. Get a key to use it in your app.

Example
{
  "status": "ok",
  "error": null,
  "data": {
    "email": "[email protected]",
    "domain": "myspace.com",
    "username": "support",
    "isRegexValid": true,
    "hasTypo": false,
    "isMxValid": true,
    "isValid": true,
    "isFreeEmail": false,
    "isCompanyEmail": true,
    "isDisposable": false,
    "isRoleAccount": true,
    "suggestedCorrection": null,
    "riskScore": 10,
    "riskLevel": "low"
  }
}

Build your own with Email Validator. Start with 200 free credits. One key unlocks all 300+ APIs.

Explore the catalog

300+ APIs on the same key and the same response shape.

Browse all APIs