Step 1: Run the check on your server
The API key is a secret, so the browser should only ever talk to your own backend. Do a cheap local check first, so that an empty field or a missing @ never uses a credit. Then call the API from your signup route with a short timeout.
Checking when the form is submitted is the simplest approach. Checking when the field loses focus gives faster feedback, but it uses more credits because people often correct and re-enter an address, so debounce it and only call once the address looks complete.
Step 2: Turn each result into one decision
Keep the decision in one function that returns what to do and what to say. This example rejects undeliverable and disposable addresses and allows everything else. If the check itself fails, the signup goes through.
type Decision = { allow: boolean; message?: string; suggestion?: string };
export async function checkSignupEmail(email: string): Promise<Decision> {
try {
const url = new URL("https://app.veridock.io/v1/verify");
url.searchParams.set("email", email);
url.searchParams.set("timeout", "3000");
const res = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.VERIDOCK_API_KEY}` },
signal: AbortSignal.timeout(4000),
});
if (!res.ok) return { allow: true }; // No answer: don't block anyone.
const { status, reason, suggestion } = await res.json();
if (status === "undeliverable") {
return {
allow: false,
suggestion: suggestion ?? undefined,
message: "We can't deliver to this address. Please check it for typos.",
};
}
if (reason === "disposable") {
return { allow: false, message: "Please use a permanent email address." };
}
return { allow: true };
} catch {
return { allow: true }; // Timeout or network error.
}
}Step 3: Write messages that help people recover
The person seeing this message has probably made a small mistake, so tell them how to fix it and don't accuse them of anything. When the API returns a suggestion, offer it as one click: "Did you mean jane@gmail.com?". Never apply it silently, because the original address might be correct. Avoid wording like "invalid email" for a real address the mail server rejected, since the person knows their address exists and may have mistyped only one letter.
- Keep what they typed in the field so they can edit it.
- Show the message next to the email field, and move focus there.
- Show a short loading state, as the check can take a few seconds on a slow mail server.
Step 4: Decide what to do with risky results
A risky result is a reason to apply a rule, not a reason to reject. Role addresses such as billing@ and catch-all domains include plenty of real business customers, so allow them and store the reason. Disposable addresses are the main exception, and only if your free tier is worth abusing. A paid product with a card on file may not need to block them at all.
Step 5: Stop your endpoint being abused
If your signup form returns a different message for each address, anyone can use it as a free verification service, paid for with your credits. Rate limit the route by IP address, and put bot protection on the form if it is public. Setting a hard spend cap on the API key limits the damage from anything you missed. Use a separate key for signups, so its usage is easy to see.
Step 6: Keep the confirmation email
Verification shows that a mailbox can receive mail. Only a confirmation link shows that this person controls it, so someone can still sign up with another person's real address. Run verification first, so your confirmation email has a good chance of arriving, then let the link activate the account.
Step 7: Test it, then watch what it blocks
Use a vd_test_ key in development and CI, because test keys return fixed results and never use credits. Test the failure path as well: point the URL at a host that does not respond, and confirm that the signup still completes.
After launch, store the status and reason with each signup attempt, without sending the addresses to your analytics. If a reason is blocking far more people than you expected, or support hears from real customers who were rejected, loosen that rule. If you tighten rules, do it one reason at a time so you can see the effect.
Key takeaways
0/4Try it on a real address
Run syntax, DNS, MX, disposable, and role checks on any address. No signup needed.
Enter an address and press Check.
Runs real syntax, DNS and mail-server checks.
This demo checks syntax, domain, mail server, disposable and role-address rules. Sign up free for live mailbox checks.
Frequently asked questions
Verify addresses with one API call.
250 free checks every month, recurring. Unknown results are never billed.