Overview
The Εerot Email Verification API validates email addresses in real-time verifying format, DNS/MX records, disposable status, typos, and assigns a risk score β all in a single API call.
The API is available via RapidAPI marketplace or directly through this website at a 10% discount.
Features
- Format Validation β RFC-compliant email syntax checking
- MX Record Lookup β Real-time DNS queries for mail server verification
- Disposable Detection β 800+ known disposable/temporary email providers
- Typo Detection β Smart suggestions for common domain misspellings
- Risk Scoring β 0-100 risk score with severity levels
- Redis Caching β Fast repeated lookups with intelligent caching
Authentication
The API uses two authentication methods:
1. API Key (for verification requests)
Pass your API key in the X-API-Key header:
X-API-Key: nrt_your_api_key_here
API keys are prefixed with nrt_ and generated when you register an account.
2. JWT Token (for account management)
For auth endpoints like /me, use a Bearer token obtained from login:
Authorization: Bearer eyJhbGciOi...
JWT tokens expire after 24 hours. Re-authenticate via the login endpoint to get a new token.
Quick Start
Get started in 3 steps:
- Register β Create an account at the homepage or via the register endpoint.
- Save your API key β Displayed once at registration. Starts with
nrt_. - Make a request β Send a POST to
/api/v1/verifywith your API key and email.
curl -X POST https://email-verification-api.nerot.me/api/v1/verify \
-H "Content-Type: application/json" \
-H "X-API-Key: nrt_YOUR_KEY" \
-d '{"email": "test@gmail.com"}'
Base URL
All API endpoints are served over HTTPS. HTTP requests are redirected to HTTPS automatically.
If using RapidAPI, the base URL and headers are configured automatically through the RapidAPI proxy.
POST Register
Create a new user account and receive an API key.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| username | string | Yes | 3-50 chars, alphanumeric + underscores |
| string | Yes | Valid email address | |
| password | string | Yes | Min 8 chars, must include uppercase, lowercase, digit |
Response
curl -X POST https://email-verification-api.nerot.me/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"username": "johndoe",
"email": "john@example.com",
"password": "SecurePass123"
}'
import requests
resp = requests.post(
"https://email-verification-api.nerot.me/api/v1/auth/register",
json={
"username": "johndoe",
"email": "john@example.com",
"password": "SecurePass123"
}
)
data = resp.json()
print("API Key:", data["user"]["api_key"])
print("Token:", data["access_token"])
const resp = await fetch(
"https://email-verification-api.nerot.me/api/v1/auth/register",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
username: "johndoe",
email: "john@example.com",
password: "SecurePass123"
})
}
);
const data = await resp.json();
console.log("API Key:", data.user.api_key);
<?php
$ch = curl_init("https://email-verification-api.nerot.me/api/v1/auth/register");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode([
"username" => "johndoe",
"email" => "john@example.com",
"password" => "SecurePass123"
]),
CURLOPT_RETURNTRANSFER => true
]);
$data = json_decode(curl_exec($ch), true);
echo $data["user"]["api_key"];
Success Response (201)
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"username": "johndoe",
"email": "john@example.com",
"plan": "basic",
"api_key": "nrt_a1b2c3d4e5f6..."
}
}
β οΈ Important: The api_key field is only shown at registration. Save it securely β it cannot be retrieved later.
POST Login
Authenticate with username and password to receive a JWT token.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| username | string | Yes | Your username |
| password | string | Yes | Your password |
Success Response (200)
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"user": {
"id": "550e8400-...",
"username": "johndoe",
"email": "john@example.com",
"plan": "basic"
}
}
GET Current User
Get the authenticated user's profile. Requires JWT Bearer token.
curl https://email-verification-api.nerot.me/api/v1/auth/me \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
POST Verify Email
Validate an email address with comprehensive checks including format, MX records, disposable detection, typo suggestions, and risk scoring.
Headers
| Header | Value | Required |
|---|---|---|
| Content-Type | application/json | Yes |
| X-API-Key | nrt_your_api_key | Yes |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Email address to verify |
Code Examples
curl -X POST https://email-verification-api.nerot.me/api/v1/verify \
-H "Content-Type: application/json" \
-H "X-API-Key: nrt_YOUR_KEY" \
-d '{"email": "user@gmail.com"}'
import requests
response = requests.post(
"https://email-verification-api.nerot.me/api/v1/verify",
headers={
"Content-Type": "application/json",
"X-API-Key": "nrt_YOUR_KEY"
},
json={"email": "user@gmail.com"}
)
data = response.json()
print(f"Valid: {data['is_valid_format']}")
print(f"Disposable: {data['is_disposable']}")
print(f"Risk: {data['risk_score']} ({data['risk_level']})")
if data["typo_check"]["is_typo"]:
print(f"Did you mean: {data['typo_check']['suggestion']}?")
const response = await fetch(
"https://email-verification-api.nerot.me/api/v1/verify",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "nrt_YOUR_KEY"
},
body: JSON.stringify({ email: "user@gmail.com" })
}
);
const data = await response.json();
console.log(`Valid: ${data.is_valid_format}`);
console.log(`Risk: ${data.risk_score} (${data.risk_level})`);
if (data.typo_check.is_typo) {
console.log(`Did you mean: ${data.typo_check.suggestion}?`);
}
<?php
$ch = curl_init("https://email-verification-api.nerot.me/api/v1/verify");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: nrt_YOUR_KEY"
],
CURLOPT_POSTFIELDS => json_encode(["email" => "user@gmail.com"]),
CURLOPT_RETURNTRANSFER => true
]);
$result = json_decode(curl_exec($ch), true);
echo "Risk: " . $result["risk_score"] . " (" . $result["risk_level"] . ")\n";
Success Response (200)
{
"email": "user@gmail.com",
"domain": "gmail.com",
"is_valid_format": true,
"mx_records": {
"has_mx": true,
"records": [
"gmail-smtp-in.l.google.com",
"alt1.gmail-smtp-in.l.google.com"
]
},
"is_disposable": false,
"typo_check": {
"is_typo": false,
"suggestion": null
},
"risk_score": 5,
"risk_level": "low",
"message": "Email appears valid"
}
Typo Detection Example
{
"email": "user@gmial.com",
"domain": "gmial.com",
"is_valid_format": true,
"mx_records": { "has_mx": false, "records": [] },
"is_disposable": false,
"typo_check": {
"is_typo": true,
"suggestion": "user@gmail.com"
},
"risk_score": 65,
"risk_level": "high",
"message": "Email has potential typo"
}
Disposable Email Example
{
"email": "user@tempmail.com",
"domain": "tempmail.com",
"is_valid_format": true,
"mx_records": { "has_mx": true, "records": [...] },
"is_disposable": true,
"typo_check": { "is_typo": false, "suggestion": null },
"risk_score": 85,
"risk_level": "critical",
"message": "Email uses a disposable domain"
}
Response Fields
| Field | Type | Description |
|---|---|---|
| string | The email that was verified | |
| domain | string | Extracted domain from the email |
| is_valid_format | boolean | Whether the format is RFC-compliant |
| mx_records.has_mx | boolean | Whether the domain has MX records |
| mx_records.records | array | List of MX server hostnames |
| is_disposable | boolean | Whether the domain is a known disposable provider |
| typo_check.is_typo | boolean | Whether a likely typo was detected |
| typo_check.suggestion | string|null | Suggested correct email, or null |
| risk_score | integer | 0-100 risk score (higher = riskier) |
| risk_level | string | One of: low, medium, high, critical |
| message | string | Human-readable summary |
Risk Levels
| Level | Score Range | Description |
|---|---|---|
| low | 0β29 | Email looks safe. Valid format, real MX, not disposable. |
| medium | 30β59 | Minor concerns. May have unusual domain or missing records. |
| high | 60β79 | Significant risk. Possible typo, missing MX, or suspicious domain. |
| critical | 80β100 | Very risky. Disposable, invalid format, or multiple red flags. |
GET Health Check
Check the API's health status including database and Redis connectivity. No authentication required.
{
"status": "healthy",
"version": "2.0.0",
"database": "connected",
"redis": "connected",
"timestamp": "2025-01-15T12:00:00Z"
}
GET Status Dashboard
A live status dashboard showing system health, uptime, and service status. Returns HTML. Open Status Page β
Error Codes
| Code | Meaning | Description |
|---|---|---|
| 400 | Bad Request | Invalid or missing email in request body |
| 401 | Unauthorized | Missing or invalid API key / JWT token |
| 403 | Forbidden | API key deactivated or insufficient permissions |
| 409 | Conflict | Username or email already registered |
| 422 | Validation Error | Request body failed validation (e.g., weak password) |
| 429 | Too Many Requests | Rate limit exceeded. Retry after the window resets. |
| 500 | Internal Server Error | Server-side error. Contact support. |
| 503 | Service Unavailable | API in maintenance mode. Auth endpoints still work. |
Error Response Format
{
"detail": {
"message": "Invalid API key",
"code": "AUTH_FAILED"
}
}
Rate Limits
Rate limits are applied per API key and depend on your plan:
| Plan | Monthly Requests | Rate Limit |
|---|---|---|
| Basic (Free) | 100 | 10/min |
| Pro | 5,000 | 300/min |
| Ultra | 50,000 | 600/min |
| Mega | 500,000 | 1,000/min |
Rate Limit Headers
Every response includes these headers:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Max requests in the current window |
| X-RateLimit-Remaining | Requests remaining in the current window |
| X-RateLimit-Reset | Unix timestamp when the window resets |
| X-Request-ID | Unique request identifier for debugging |
Full Integration Example
Here's a complete example showing registration, login, and email verification flow:
import requests
BASE = "https://email-verification-api.nerot.me"
# Step 1: Register
reg = requests.post(f"{BASE}/api/v1/auth/register", json={
"username": "myapp",
"email": "dev@myapp.com",
"password": "SecureP@ss123"
})
api_key = reg.json()["user"]["api_key"]
print(f"API Key: {api_key}") # Save this!
# Step 2: Verify an email
result = requests.post(
f"{BASE}/api/v1/verify",
headers={"X-API-Key": api_key},
json={"email": "test@gmail.com"}
)
data = result.json()
print(f"Valid: {data['is_valid_format']}") # True
print(f"MX: {data['mx_records']['has_mx']}") # True
print(f"Disposable: {data['is_disposable']}") # False
print(f"Risk: {data['risk_score']}/100") # 5/100
# Step 3: Handle different cases
if data["is_disposable"]:
print("β Disposable email rejected")
elif data["typo_check"]["is_typo"]:
print(f"π‘ Did you mean {data['typo_check']['suggestion']}?")
elif data["risk_score"] > 60:
print("π΄ High risk email")
else:
print("β
Email is safe to use")