A verification API for people
POST /v1/verify/send and /v1/verify/check, by email or SMS, with expiry, attempt limits and risk scoring handled on the platform. Disposable domains are refused before a code is generated.
An email verification API tells you whether mail could be delivered to an address. It cannot tell you whether anyone will read it. This page separates the two, says exactly what Notix offers for each, and names the one thing it does not have.
Every verification service runs some subset of five checks. Each one answers a narrower question than its name suggests.
| Check | What it tells you | What it misses |
|---|---|---|
| Syntax | The address is shaped like an address: one @, a local part, a domain with a dot. | Nothing about whether the mailbox exists. Most typos are valid syntax. |
| MX record | The domain publishes a mail server, so mail can at least be attempted. | Whether that server accepts this local part. Catch-all domains accept everything. |
| Disposable domain | The domain belongs to a throwaway-mailbox service. | New disposable domains appear daily; a list is always a little behind. |
| Role address | The local part is a role (info@, admin@, noreply@), not a person. | Some roles are read by a person every day. It is a signal, not a verdict. |
| Mailbox probe | An SMTP conversation up to RCPT TO, without sending, to see if the server rejects the address. | Gmail, Yahoo and catch-all domains answer yes to everything. Repeated probes get your IP blocked. |
Put together, these checks are good at rejecting what is obviously wrong and poor at confirming what is right. A list that passes all five still bounces; a list that fails the disposable check is still worth refusing at sign-up.
A one-time code proves what no address check can: a human opened the mailbox and typed what was in it. Two calls, and the disposable and risk checks run on the first one before a code exists.
curl -X POST https://app.usenotix.dev/api/v1/verify/send \
-H "Authorization: Bearer $NOTIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "to": "user@example.com", "appName": "Acme", "clientIp": "203.0.113.10" }'
# 201 { "id": "ver_abc123", "status": "pending", "attemptsRemaining": 5,
# "risk": { "score": 0, "level": "LOW", "reasons": [] } }
curl -X POST https://app.usenotix.dev/api/v1/verify/check \
-H "Authorization: Bearer $NOTIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "id": "ver_abc123", "code": "482913" }'
# 200 { "id": "ver_abc123", "verified": true, "status": "verified" }
import { Notix } from "notix-js";
const notix = new Notix(process.env.NOTIX_API_KEY);
// At sign-up: a code goes to the address. A disposable domain is refused
// here with 422 RISK_REFUSED, before any code exists.
const { data, error } = await notix.verify.send({
to: form.email,
appName: "Acme",
clientIp: request.ip,
});
if (error) return respond(error);
session.verificationId = data.id;
// When the user types the code: the address is now known to reach a person.
const check = await notix.verify.check({ id: session.verificationId, code: form.code });
if (check.data?.verified) session.emailVerified = true;
import os
from notix import Notix
notix = Notix(os.environ["NOTIX_API_KEY"])
data, error = notix.verify.send(
{"to": form["email"], "appName": "Acme", "clientIp": request.remote_addr}
)
if error:
return respond(error) # 422 RISK_REFUSED for a disposable domain
session["verification_id"] = data["id"]
check, error = notix.verify.check(
{"id": session["verification_id"], "code": form["code"]}
)
if check and check["verified"]:
session["email_verified"] = True
The send call scores the request. A disposable domain or a burst of requests from one address or IP answers 422 RISK_REFUSED with the reasons, so your sign-up form can ask for a different address instead of creating a dead account. The full limits, the SMS channel and the risk modes are on the OTP page.
POST /v1/verify/send and /v1/verify/check, by email or SMS, with expiry, attempt limits and risk scoring handled on the platform. Disposable domains are refused before a code is generated.
POST /v1/deliverability/check scores an email before it goes: an unverified from domain, marketing without an unsubscribe link, a raw-IP link or a spam score of 10 block the send. See the deliverability check.
There is no endpoint that takes a list and returns which addresses are valid. Hard bounces and complaints go on the suppression list on receipt, so an old list cleans itself as you send, and you can import a suppression list from a previous provider.
The API reference for the verification endpoints is in the docs.
What a pre-send deliverability check looks at, the verdict and score it returns, and the four findings that block a send.
Use casesSend one-time codes by email or SMS with two API calls, with expiry, length and risk scoring handled for you.
LearnHard bounces against soft bounces, what happens to the address automatically, and the bounce webhook payload your code receives.
LearnWhy a suppression list exists, the three reasons an address lands on it, and why one list across transactional and marketing matters.
NotixThe quickstart: verify a domain, copy an API key, send the first email.
Verify a domain, copy an API key, make one call. The free plan does not ask for a card.