Realβtime email verification with syntax, domain, and SMTP checks. Built for developers who want transparency, not black boxes.
Base URL: https://parheliaweb.com
All requests must include an API key in the x-api-key header. Responses are in JSON.
All prices are listed in Euros (EUR). Your card will be charged in your local currency at the prevailing exchange rate. We use Stripe for secure payment processing, which supports 135+ currencies and local payment methods including iDEAL, Bancontact, and SEPA Direct Debit.
Pass your secret API key as an HTTP header on every request:
x-api-key: YOUR_API_KEY
If the key is missing or invalid, you'll receive a 401 Unauthorized or 403 Forbidden.
| Plan | Price | Rate Limit | Monthly Quota | Verification Depth | Support |
|---|---|---|---|---|---|
| Loading pricing... | |||||
When you exceed the limit, the API returns 429 Too Many Requests.
POST /v1/email/validate
Validates a single email address through our multi-phase verification pipeline. Currently monitoring β blacklisted domains with dynamic pattern detection for emerging spam techniques.
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | The email address to validate |
# Validate a single email address
curl -X POST https://parheliaweb.com/v1/email/validate \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_KEY" \
-d '{"email": "user@example.com"}'
# Validate a known disposable domain
curl -X POST https://parheliaweb.com/v1/email/validate \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_KEY" \
-d '{"email": "test@mailinator.com"}'
{
"status": "ok",
"result": {
"email": "user@example.com",
"status": "valid",
"confidence": 90,
"cached": false,
"first_seen": "2026-06-15 21:45:00",
"syntax_valid": true,
"domain_check": {
"passed": true,
"whitelisted": false,
"blacklisted": false,
"blacklist_match": null,
"dynamic_match": null,
"no_probe": false,
"checks_performed": [
"blacklist_clean",
"numeric_prefix_clean",
"double_tld_clean"
]
},
"mx_valid": true,
"mx_servers": ["mail.example.com"],
"smtp_check": {
"performed": true,
"result": true,
"code": 250,
"message": "Mailbox accepted (code 250)"
},
"risk_factors": [],
"performance_ms": {
"total": 1847.32,
"phases": {
"syntax": 0.03,
"domain_check": 1.48,
"dns": 45.12,
"smtp": 1800.69
}
}
}
}
{
"status": "ok",
"result": {
"email": "info@company.com",
"status": "risky",
"confidence": 45,
"cached": false,
"first_seen": "2026-06-15 21:45:00",
"syntax_valid": true,
"domain_check": {
"passed": true,
"whitelisted": false,
"blacklisted": false,
"blacklist_match": null,
"dynamic_match": null,
"no_probe": false,
"checks_performed": [
"blacklist_clean",
"numeric_prefix_clean",
"double_tld_clean"
]
},
"mx_valid": true,
"mx_servers": ["mail.company.com"],
"smtp_check": {
"performed": true,
"result": true,
"code": 250,
"message": "Mailbox accepted (code 250)"
},
"catch_all": {
"detected": true,
"message": "Domain accepts all 2 test addresses β likely catch-all"
},
"risk_factors": [
{"factor": "catch_all_domain", "severity": "medium"}
],
"performance_ms": {
"total": 3215.67,
"phases": {
"syntax": 0.02,
"domain_check": 1.52,
"dns": 38.41,
"smtp": 2847.33,
"catch_all": 328.39
}
}
}
}
{
"status": "ok",
"result": {
"email": "spam@mailinator.com",
"status": "invalid",
"confidence": 95,
"cached": false,
"first_seen": "2026-06-15 21:45:00",
"syntax_valid": true,
"domain_check": {
"passed": false,
"whitelisted": false,
"blacklisted": true,
"blacklist_match": {
"type": "static_domain",
"domain": "mailinator.com",
"reason": "Disposable email service",
"category": "disposable",
"severity": 10
},
"dynamic_match": null,
"no_probe": false,
"checks_performed": ["blacklist_hit"]
},
"mx_valid": false,
"mx_servers": [],
"smtp_check": {
"performed": false,
"result": null,
"code": null,
"message": "Skipped: domain rejected"
},
"risk_factors": [
{
"factor": "domain_rejected",
"severity": "critical",
"detail": {
"type": "static_domain",
"domain": "mailinator.com",
"reason": "Disposable email service",
"category": "disposable",
"severity": 10
}
}
],
"performance_ms": {
"total": 1.54,
"phases": {
"syntax": 0.02,
"domain_check": 1.48
}
}
}
}
| Field | Type | Description |
|---|---|---|
email | string | The email address that was validated |
status | string | Overall assessment: valid, invalid, risky, or unknown |
confidence | integer |
Confidence score 0β100. Meaning depends on the status:For valid: 90 = mailbox confirmed by SMTP server. Always high confidence when valid. For invalid: Indicates which phase caught the problem: β’ 100 = Syntax invalid (missing @, consecutive dots) β’ 95 = Domain rejected (blacklisted or dynamic pattern match) β’ 90 = No MX records (domain has no mail server) β’ 0 = SMTP server explicitly rejected the mailbox (code 550) For risky: Higher = less risky. 60 = minor issue (temporary failure), 55 = catch-all domain, 45β50 = multiple concerns, 35 = high risk. For unknown: Always 30 = could not obtain any answer (domain blocks probes, rate-limited, network issues). |
cached | boolean | True if the result was served from cache (instant), false if a fresh SMTP verification was performed |
X-Cache (HTTP header) | string | HIT if the result was served from cache, MISS if fresh verification was performed. Check this header to determine cache status without parsing the JSON body. |
first_seen | string|null | ISO 8601 timestamp of when this email hash was first encountered by our system. null on the first validation |
syntax_valid | boolean | Whether the email passes RFC 5322 syntax validation |
domain_check.passed | boolean | Whether the domain passed all blacklist and pattern checks |
domain_check.whitelisted | boolean | True if the email or domain is on the trusted whitelist |
domain_check.blacklisted | boolean | True if the domain is on the static blacklist (disposable, spam, etc.) |
domain_check.blacklist_match | object|null | Details about the blacklist match if applicable |
domain_check.dynamic_match | object|null | Details about dynamic pattern match (numeric prefix, double TLD, etc.) |
domain_check.no_probe | boolean | True if the domain is known to reject SMTP probes |
domain_check.checks_performed | array | List of all domain-level checks executed and their outcomes |
mx_valid | boolean | Whether the domain has valid MX records |
mx_servers | array | List of MX server hostnames (up to 5, sorted by priority) |
smtp_check.performed | boolean | Whether SMTP verification was attempted |
smtp_check.result | boolean|null | True = mailbox accepted, False = rejected, null = could not determine |
smtp_check.code | integer|null | SMTP response code (250, 550, etc.) |
smtp_check.message | string | Human-readable explanation of the SMTP result |
catch_all.detected | boolean|null | Pro tier: Whether the domain appears to be a catch-all |
catch_all.message | string | Pro tier: Details about catch-all detection |
risk_factors | array | List of risk factors with severity levels (critical, high, medium) |
performance_ms.total | float | Total validation time in milliseconds |
performance_ms.phases | object | Per-phase timing breakdown (syntax, domain_check, dns, smtp, catch_all) |
| Status | Meaning | Recommended Action |
|---|---|---|
| valid | Email syntax is correct, domain exists, and SMTP server confirmed the mailbox | Safe to send |
| invalid | Email failed syntax, domain, or SMTP checks with high confidence | Do not send β will bounce |
| risky | Email could not be fully verified (catch-all domain, greylisting, suspicious patterns) | Send with caution for marketing; avoid for transactional email |
| unknown | Could not determine (rate-limited by provider, domain blocks probes, network issues) | Retry later or verify through other means |
X-Priority header on your requests:
If no header is set, balanced mode is used automatically.
performance_ms so you can see
exactly where the time was spent.
POST /v1/email/validate/batch
Validate up to 100 email addresses in a single request. Batches of 6 or more emails are processed asynchronously β you'll receive an immediate response with a batch_id and can poll for results. Small batches (5 or fewer) are processed synchronously and return results immediately. Each batch is assigned a unique batch_id tracked in your validation logs. Batch validation uses connection pooling β emails to the same domain share a single SMTP connection, significantly reducing verification time for large lists with repeated domains.
batch_id immediately, and poll the status endpoint to retrieve
results when complete. Cached results return instantly, making repeat batches
significantly faster.
| Field | Type | Required | Description |
|---|---|---|---|
emails | array of strings | Yes | List of email addresses to validate (max 100) |
curl -X POST https://parheliaweb.com/v1/email/validate/batch \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_KEY" \
-d '{
"emails": [
"user@example.com",
"spam@mailinator.com",
"info@catchall-domain.com"
]
}'
{
"status": "ok",
"result": {
"batch_id": "dbb2b6bc8cc9",
"total_emails": 3,
"total_ms": 28.37,
"results": [
{
"email": "user@example.com",
"status": "valid",
"confidence": 90,
"cached": false,
"first_seen": "2026-06-15 21:45:00"
},
{
"email": "spam@mailinator.com",
"status": "invalid",
"confidence": 95,
"cached": false,
"first_seen": "2026-06-15 21:45:01"
},
{
"email": "info@catchall-domain.com",
"status": "risky",
"confidence": 45,
"cached": false,
"first_seen": "2026-06-15 21:45:02"
}
]
}
}
{
"status": "ok",
"result": {
"batch_id": "23f6e6244854",
"total_emails": 20,
"status": "processing",
"message": "Batch queued for processing. Poll GET /v1/email/validate/batch/23f6e6244854 for results."
}
}
GET /v1/email/validate/batch/{batch_id}
Poll for the results of an asynchronously processed batch. Returns the batch status and, when complete, the full results array.
curl -H "x-api-key: YOUR_KEY" https://parheliaweb.com/v1/email/validate/batch/23f6e6244854
{
"status": "ok",
"result": {
"batch_id": "23f6e6244854",
"total_emails": 20,
"completed_emails": 0,
"status": "processing",
"total_ms": null
}
}
{
"status": "ok",
"result": {
"batch_id": "23f6e6244854",
"total_emails": 20,
"completed_emails": 20,
"status": "completed",
"total_ms": 45230.67,
"results": [
{
"email": "user@example.com",
"status": "valid",
"confidence": 90,
"cached": false,
"first_seen": "2026-06-15 21:45:00"
},
{
"email": "spam@mailinator.com",
"status": "invalid",
"confidence": 95,
"cached": false,
"first_seen": "2026-06-15 21:45:01"
}
]
}
}
import requests
headers = {
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY"
}
data = {"email": "user@example.com"}
resp = requests.post("https://parheliaweb.com/v1/email/validate", headers=headers, json=data)
result = resp.json()["result"]
print(f"Status: {result['status']}, Confidence: {result['confidence']}%")
fetch("https://parheliaweb.com/v1/email/validate", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": "YOUR_API_KEY"
},
body: JSON.stringify({ email: "user@example.com" })
})
.then(res => res.json())
.then(data => console.log(data.result.status));
curl -X POST https://parheliaweb.com/v1/email/validate \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{"email": "user@example.com"}'
If you run into any issues or have feature suggestions, email us at info@parheliaweb.com.
Email Validator API by ParheliaWeb Β· Built in the Netherlands Β· Terms Β· Privacy Β· Contact
AI verification powered by DeepSeek