Validate Email
This guide covers best practices for integrating VerifNow’s email validation into your application — from simple form validation to advanced use cases.
Basic email validation
Send a POST request to /api/v1/validate/email with the value to validate:
POST https://api.verifnow.io/api/v1/validate/email
X-API-KEY: your_api_key_here
Content-Type: application/json
{
"value": "user@example.com"
}Example response
{
"valid": true,
"message": "Email address is valid but has risk factors",
"normalizedValue": "user@example.com",
"originalValue": "user@example.com",
"validationLevel": "PREMIUM",
"emailDetails": {
"signals": {
"syntax_valid": true,
"mx_valid": true,
"typo_detected": false,
"suggested_domain": null,
"disposable": false,
"role_based": false,
"free_provider": false,
"domain_age_days": 11554,
"mx_provider": "google",
"mx_quality_score": 0.9
},
"risk_score": 30,
"risk_level": "MEDIUM",
"deliverability": "RISKY",
"applied_level": "PREMIUM"
}
}Understanding the email signals
syntax_valid
Validates the email against standard syntax rules. An invalid syntax will result in valid: false.
mx_valid
Checks whether the email domain has valid MX (mail exchange) DNS records. Without MX records, the domain cannot receive email.
disposable
Detects whether the address is from a known disposable/temporary email provider (e.g., Mailinator, Guerrilla Mail, 10MinuteMail).
// Example: disposable email detected
{
"valid": true,
"emailDetails": {
"signals": {
"disposable": true
},
"risk_level": "HIGH"
}
}role_based
Flags email addresses that are typically shared by multiple people or auto-generated:
info@,admin@,support@noreply@,no-reply@postmaster@,webmaster@
typo_detected & suggested_domain
If VerifNow detects a likely typo (e.g., gmal.com instead of gmail.com), typo_detected is true and suggested_domain contains the correction:
{
"valid": false,
"emailDetails": {
"signals": {
"typo_detected": true,
"suggested_domain": "gmail.com"
}
}
}Use this to prompt users to correct their email before submitting.
domain_age_days
The age of the email domain in days. Very young domains may indicate spam or fraud.
mx_provider & mx_quality_score
Identifies the mail provider (e.g., google, apple, microsoft) and assigns a quality score between 0 and 1.
risk_score & risk_level
A 0–100 risk score and a categorical risk level (LOW, MEDIUM, HIGH). Lower scores mean less risk.
deliverability
An overall deliverability assessment: DELIVERABLE, RISKY, UNDELIVERABLE, or UNKNOWN.
Acceptance strategy
Choose the right acceptance strategy based on your use case:
Strict
Strict — Block any risky or undeliverable email:
function isEmailAccepted(result) {
return result.valid &&
result.emailDetails.deliverability === 'DELIVERABLE' &&
!result.emailDetails.signals.disposable &&
!result.emailDetails.signals.role_based
}Best for: paid signups, enterprise SaaS, financial services
Integration examples
React form validation
import { useState } from 'react'
async function validateEmail(email: string) {
const response = await fetch('/api/validate-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ value: email }),
})
return response.json()
}
export function SignupForm() {
const [email, setEmail] = useState('')
const [error, setError] = useState('')
const [suggestion, setSuggestion] = useState('')
const [loading, setLoading] = useState(false)
async function handleSubmit(e: React.FormEvent) {
e.preventDefault()
setLoading(true)
setError('')
setSuggestion('')
const result = await validateEmail(email)
if (result.emailDetails?.signals?.typo_detected && result.emailDetails?.signals?.suggested_domain) {
const [local] = email.split('@')
setSuggestion(`Did you mean ${local}@${result.emailDetails.signals.suggested_domain}?`)
}
if (!result.valid) {
setError('Please enter a valid, reachable email address.')
setLoading(false)
return
}
// Continue with form submission...
setLoading(false)
}
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={e => setEmail(e.target.value)}
placeholder="your@email.com"
/>
{suggestion && <p className="text-yellow-600">{suggestion}</p>}
{error && <p className="text-red-600">{error}</p>}
<button type="submit" disabled={loading}>
{loading ? 'Validating...' : 'Sign Up'}
</button>
</form>
)
}Next.js API route (server-side proxy)
// app/api/validate-email/route.ts
import { NextRequest, NextResponse } from 'next/server'
export async function POST(req: NextRequest) {
const body = await req.json()
const { value } = body
if (!value) {
return NextResponse.json({ error: 'value is required' }, { status: 400 })
}
const response = await fetch('https://api.verifnow.io/api/v1/validate/email', {
method: 'POST',
headers: {
'X-API-KEY': process.env.VERIFNOW_API_KEY!,
'Content-Type': 'application/json',
},
body: JSON.stringify({ value }),
})
const data = await response.json()
return NextResponse.json(data)
}Security tip: Always proxy API calls through your backend to keep your API key secret. Never call the VerifNow API directly from client-side JavaScript.