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:

  1. Register β€” Create an account at the homepage or via the register endpoint.
  2. Save your API key β€” Displayed once at registration. Starts with nrt_.
  3. Make a request β€” Send a POST to /api/v1/verify with your API key and email.
Quick test
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

https://email-verification-api.nerot.me

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

/api/v1/auth/register

Create a new user account and receive an API key.

Request Body

FieldTypeRequiredDescription
usernamestringYes3-50 chars, alphanumeric + underscores
emailstringYesValid email address
passwordstringYesMin 8 chars, must include uppercase, lowercase, digit

Response

terminal
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"
  }'
register.py
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"])
register.js
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);
register.php
<?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

/api/v1/auth/login

Authenticate with username and password to receive a JWT token.

Request Body

FieldTypeRequiredDescription
usernamestringYesYour username
passwordstringYesYour password

Success Response (200)

{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "bearer",
  "user": {
    "id": "550e8400-...",
    "username": "johndoe",
    "email": "john@example.com",
    "plan": "basic"
  }
}

GET Current User

/api/v1/auth/me

Get the authenticated user's profile. Requires JWT Bearer token.

terminal
curl https://email-verification-api.nerot.me/api/v1/auth/me \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

POST Verify Email

/api/v1/verify

Validate an email address with comprehensive checks including format, MX records, disposable detection, typo suggestions, and risk scoring.

Headers

HeaderValueRequired
Content-Typeapplication/jsonYes
X-API-Keynrt_your_api_keyYes

Request Body

FieldTypeRequiredDescription
emailstringYesEmail address to verify

Code Examples

terminal
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"}'
verify.py
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']}?")
verify.js
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}?`);
}
verify.php
<?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)

200 OK β€” Valid email
{
  "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

200 OK β€” Typo detected
{
  "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

200 OK β€” Disposable
{
  "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

FieldTypeDescription
emailstringThe email that was verified
domainstringExtracted domain from the email
is_valid_formatbooleanWhether the format is RFC-compliant
mx_records.has_mxbooleanWhether the domain has MX records
mx_records.recordsarrayList of MX server hostnames
is_disposablebooleanWhether the domain is a known disposable provider
typo_check.is_typobooleanWhether a likely typo was detected
typo_check.suggestionstring|nullSuggested correct email, or null
risk_scoreinteger0-100 risk score (higher = riskier)
risk_levelstringOne of: low, medium, high, critical
messagestringHuman-readable summary

Risk Levels

LevelScore RangeDescription
low0–29Email looks safe. Valid format, real MX, not disposable.
medium30–59Minor concerns. May have unusual domain or missing records.
high60–79Significant risk. Possible typo, missing MX, or suspicious domain.
critical80–100Very risky. Disposable, invalid format, or multiple red flags.

GET Health Check

/health

Check the API's health status including database and Redis connectivity. No authentication required.

200 OK
{
  "status": "healthy",
  "version": "2.0.0",
  "database": "connected",
  "redis": "connected",
  "timestamp": "2025-01-15T12:00:00Z"
}

GET Status Dashboard

/status

A live status dashboard showing system health, uptime, and service status. Returns HTML. Open Status Page β†’

Error Codes

CodeMeaningDescription
400Bad RequestInvalid or missing email in request body
401UnauthorizedMissing or invalid API key / JWT token
403ForbiddenAPI key deactivated or insufficient permissions
409ConflictUsername or email already registered
422Validation ErrorRequest body failed validation (e.g., weak password)
429Too Many RequestsRate limit exceeded. Retry after the window resets.
500Internal Server ErrorServer-side error. Contact support.
503Service UnavailableAPI 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:

PlanMonthly RequestsRate Limit
Basic (Free)10010/min
Pro5,000300/min
Ultra50,000600/min
Mega500,0001,000/min

Rate Limit Headers

Every response includes these headers:

HeaderDescription
X-RateLimit-LimitMax requests in the current window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets
X-Request-IDUnique request identifier for debugging

Full Integration Example

Here's a complete example showing registration, login, and email verification flow:

full_example.py
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")