VerifyGeniusEarly access

Know an address exists before you send a thing.

VerifyGenius tells you which of the contact data you already hold is safe to use, starting with email. It asks the company’s own mail server whether a business address is real, then hangs up. No email is ever sent, and only addresses we can prove are called safe to send.

Built for UK business domains. Email today; phone numbers and postal addresses are next. Private for now, running for our own products.

api.verifygenius.commx.acme-dental.example
  1. 1EHLO api.verifygenius.com250 mx.acme-dental.example
  2. 2MAIL FROM:<verify@verifygenius.com>250 2.1.0 OK
  3. 3RCPT TO:<zz4c19e07a2b91d3f6e0@acme-dental.example>550 5.1.1 User unknownMade-up address first. The server says no, so its yes will mean something.
  4. 4RCPT TO:<jane.cole@acme-dental.example>250 2.1.5 OK
  5. DATANever sent. No message, ever.
  6. 5QUIT221 Bye
ValidInvalidCatch-allUnknownSuppressedBad syntax
Valid, safe to send for 30 days. Same server, made-up address refused, real one accepted. Illustration: example domains, not a live check.

Six answers. Only one of them means send.

Most checkers round “probably” up to “valid”. We don’t. If the server can’t prove it, we say so, and you keep your bounce rate.

ResultWhat it meansSend?
validThe server refused a made-up address and accepted this one, on the same machine.Yes, for 30 days
invalidThe server said there is no such user, or the domain has no mail server at all.No
catch_allThe server accepts any address, real or not, so its “yes” proves nothing.No
unknownNo clear answer: greylisting, a policy reply, an unreachable server, or a reply we haven’t calibrated.No
suppressedThe address, company or domain has opted out. We didn’t check it and won’t.No
bad_syntaxNot an email address, so nothing was checked.No

What happens in one check

The order matters. Each step exists because a real mail server taught us to add it.

  1. 1

    Opt-outs first

    If the address, its company or its domain (parent domains included) has opted out, we stop here and return suppressed. No connection is made.

  2. 2

    Find the mail server

    We look up the domain’s MX records. No mail server means invalid; a DNS failure means unknown, never a guess.

  3. 3

    Ask about someone who doesn’t exist

    A made-up address goes first, the same one for that domain all month, so greylisting can clear on the retry. If the server accepts it, the domain is catch_all and we stop.

  4. 4

    Ask about the real address

    The answer only counts if it comes from the same server that refused the made-up one. A different server answering is unknown.

  5. 5

    Read the reply with calibrated rules

    Only a clear “no such user” is invalid. Anything naming a policy, our IP or the sender stays unknown. Microsoft 365’s 550 5.4.1 counts only when another address at the same company has been accepted, because Microsoft also uses it for faults that affect a whole tenant.

  6. 6

    Hang up

    QUIT before DATA, every time. A greylisted server gets one more try, 20 minutes later. Then we move on.

We tried to fool it 530 times. It never said yes.

One square per made-up address. A square would be filled if we had called it valid. None are.

0 of 152
addresses gave a different answer when asked again hours later. A day later, 100 of 100 matched.
149 of 207
addresses printed on companies’ own websites came back valid. 3 had gone stale, and those are the ones that bounce.
0 refusals
because of our IP address. It isn’t on Spamhaus, SpamCop, Barracuda, PSBL, Mailspike or UCEPROTECT.
22% undecided
of domains, on purpose. It was 67% before the reply rules, and 16% outside Microsoft 365. We’d rather tell you “unknown” than guess.

Method: 200 UK companies with a website proven by their company number, about 1,030 checks from the production IP address across four passes, 27 September 2026, plus a repeat the next day. Each company got a made-up address and up to three addresses published on its own site.

API

JSON over HTTPS, one bearer key per product. The same API runs our own products today. Early-access keys come with your base URL; examples use $VG_BASE.

Quick start

curl -s "$VG_BASE/v1/check" \
  -H "Authorization: Bearer $VG_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "jane.cole@acme-dental.example"}'

Response, 200:

{
  "email": "jane.cole@acme-dental.example",
  "status": "valid",
  "reason": null,
  "smtp_code": 250,
  "smtp_text": "2.1.5 OK",
  "mx_host": "mx.acme-dental.example",
  "checked_at": "2026-09-28 11:02:13.482117+00:00",
  "job_id": "5b0e7d0c-3f6a-4c55-9a1e-0f3c2d8b7a14"
}

Keys

Send Authorization: Bearer vg_… on every request except health and the OpenAPI document. Each product gets its own key. We store only a SHA-256 hash, so a key is shown once, when it is issued; if you lose it, we revoke it and issue another. Jobs are private to the key that created them.

POST /v1/check

Checks one address and waits up to 60 seconds for the answer. Most answers take a few seconds. A slow server or greylisting returns 202 with the item still pending or checking; keep the job_id and read it later.

{ "email": "jane.cole@acme-dental.example" }

POST /v1/jobs

Queues up to 5,000 addresses and returns at once. Addresses that aren’t addresses come back as bad_syntax without a check.

{ "emails": ["jane.cole@acme-dental.example", "accounts@acme-dental.example"] }
{ "job_id": "9d2f4b61-8c0e-4e7a-b3d5-2a6f1c9e0b87", "total": 2 }

GET /v1/jobs/{id}

The job and its results so far, up to 1,000 per page: pass offset and limit, and follow next_offset (null on the last page). done counts finished items across the whole job; poll until it equals total. A job created with a different key returns 404.

{
  "id": "9d2f4b61-8c0e-4e7a-b3d5-2a6f1c9e0b87",
  "requested_by": "your-product",
  "total": 2,
  "done": 2,
  "created_at": "2026-09-28 11:04:50.017342+00:00",
  "items": [
    { "email": "jane.cole@acme-dental.example", "status": "valid", "reason": null,
      "smtp_code": 250, "smtp_text": "2.1.5 OK", "mx_host": "mx.acme-dental.example",
      "checked_at": "2026-09-28 11:05:02.311904+00:00" },
    { "email": "accounts@acme-dental.example", "status": "invalid", "reason": null,
      "smtp_code": 550, "smtp_text": "5.1.1 User unknown", "mx_host": "mx.acme-dental.example",
      "checked_at": "2026-09-28 11:05:06.908215+00:00" }
  ]
}

Result fields

status
pending · checking · valid · invalid · catch_all · unknown · suppressed · bad_syntax. Only valid is sendable, for 30 days from checked_at.
reason
Why, when the status alone doesn’t say: domain accepts any address, no_mx, mail server unreachable, answered by a different MX than the probe, microsoft 5.4.1 on every address: not trusted, catch-all undecided (451). Otherwise null.
smtp_code, smtp_text
The server’s own reply to RCPT TO, so you can see the evidence rather than take our word for it.
mx_host
The mail server that answered.
checked_at
When the answer came back (UTC). Empty while pending.
flags
role (info@, sales@…), free_mail (Gmail, Outlook…), disposable (throwaway domains, from a public list) and plus_address (name+tag@). Worked out from the address alone; a flag never changes the verdict.
suggestion
A likely intended address when the domain looks like a typo of a common provider, such as jane@gmial.com → jane@gmail.com. Otherwise null.
score, reasons
0–100 for sorting, never a second opinion: valid 95, catch_all 45, unknown 25, everything else 0; a role address costs 5, a disposable domain caps it at 10. reasons lists every rule that applied, e.g. ["status_valid", "role_address"]. Empty while pending.

Errors

400Bad JSON, no addresses, or more than 5,000 in one job, or a bad offset/limit. The body says which.
401Missing or revoked key: {"error": "a valid key is required (Authorization: Bearer vg_...)"}
404No such job for your key, or no such route.
500Our fault. Safe to retry.

Limits, and why they’re low

Checks leave from one IP address with a published name, at up to 20 a minute, one conversation per domain at a time. A circuit breaker pauses everything if servers start refusing us. That pace keeps us welcome on the servers you want answers from. Hand-started checks jump the queue ahead of background work.

GET /v1/status · /v1/health · /v1/openapi.json

/v1/status returns queue counts, checks in the last hour, and whether the sending IP appears on any of eight blocklists. /v1/health needs no key. /v1/openapi.json is the machine-readable version of this page.

Saw us in your mail logs?

If api.verifygenius.com (169.58.33.41) connected to your server, that was a mailbox check, not an email. It asked whether one business address exists, then disconnected.

  • It never sends a message

    EHLO, MAIL FROM, RCPT TO, QUIT. The conversation ends before DATA.

  • It is slow on purpose

    One conversation per domain at a time, 20 checks a minute in total, and a pause whenever servers push back.

  • It says who it is

    Reverse DNS, HELO and SPF all name api.verifygenius.com. The sender is verify@verifygenius.com.

  • It checks business addresses

    Addresses published on UK companies’ own websites, or built from the names of a company’s registered directors, so later business emails don’t bounce.

  • Stop checks for your domain

    Opt out here or email postmaster@verifygenius.com. Opt-outs are applied before any further check.

Questions

Can I use it today?

Not yet. VerifyGenius runs privately for Rajoka’s own products, including InsightBase and Certivus. We’re gauging interest before opening it up. Tell us your volume and use below and we’ll get in touch.

Is it only for email?

Email is first. VerifyGenius is a data sanitisation service: it checks contact data you already have, without contacting anyone. We plan to add phone numbers and postal addresses, with the same rule of showing the evidence behind every answer. Tell us in the form which you need.

What will it cost?

We haven’t set prices. Your answer on monthly volume helps us set them. Nobody is charged for joining the early-access list.

Why is so much “unknown”?

Because some servers won’t give a straight answer, and guessing is how you end up bouncing. Microsoft 365 is the main one: when a company’s tenant rejects every address, we can’t tell a missing mailbox from a tenant-wide block, so we say unknown. Outside Microsoft 365, 16% of domains stayed undecided in our tests.

Why isn’t catch-all “valid”?

A catch-all server says yes to anything, including addresses we made up a second earlier. That yes carries no information about the address you asked for, so we won’t call it safe to send.

Does it work on Gmail or personal addresses?

It is built and calibrated for business domains, mostly in the UK. Big free-mail providers often don’t answer mailbox questions honestly, and we don’t claim results we haven’t tested.

Where does it run?

On servers we run ourselves. Checks leave from a single IP address, 169.58.33.41, with its own reverse DNS, and nothing about a check is shared with anyone else.

Ask for early access

Tell us roughly how many addresses you check each month and what you’d use it for. We read every answer and reply by email.

We use these details only to reply to you about VerifyGenius. See how we handle them.

Addresses a month

Your details, if you use the form

Rajoka Limited collects your name, work email, company and answers so it can reply about early access and gauge demand for VerifyGenius. We rely on our legitimate interest in responding to your request. Your details are stored on our own servers, and each request is emailed to our team through Resend, our email provider. They are never sold, and are deleted within 24 months, or sooner if you ask. To see, correct or delete them, email postmaster@verifygenius.com. You can complain to the Information Commissioner’s Office at ico.org.uk. This site is served through Cloudflare, and the form uses Cloudflare Turnstile to block spam. We count visits with Plausible analytics, self-hosted on Rajoka infrastructure in the United Kingdom, which uses no cookies.