The Email Verification API Built for Scale

Verify single emails in real-time or process millions in bulk. Clean JSON responses, credits-based pricing, and 99.9% uptime — so you can focus on building.

POST /api/v1/verify
# Single email verification — real-time SMTP check curl -X POST https://zuhal.io/api/v1/verify \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com"}' # Response { "status": "success", "request_id": "550e8400-e29b-41d4-a716", "email_status": "valid", "credits_used": 1, "remaining_credits": 4999 }
99.9%
API Uptime
<3s
Avg Response Time
5
Verification Statuses
30d
Result Retention
Capabilities

Everything You Need in One API

From quick single-email spot checks to processing multi-million-row lists, the Zuhal API has you covered.

Real-Time Single Verification

Verify any email address instantly via full SMTP handshake — syntax, DNS, MX, and mailbox existence all checked in one call.

Bulk CSV Processing

Upload a CSV file of up to 500 000 rows, and we'll verify every address asynchronously. Poll status and download results when ready.

Disposable & Catch-All Detection

Automatically flag throwaway addresses and accept-all domains so you never waste credits or credits on unverifiable emails.

Credits-Based Pricing

Pay only for what you use. Credits never expire — buy once and consume at your own pace. No monthly minimums or seat fees.

30-Day Result History

Every verification result is stored for 30 days. Re-fetch any single or bulk result by its request_id without re-verifying.

REST + JSON

Standard HTTP verbs, clean JSON responses, meaningful HTTP status codes, and predictable error objects — no SDK required.

Quick Start

Up and Running in Minutes

Get your API key, make your first request, and start verifying emails — no SDK or complex setup required.

1
Get your free API key

Create an account at zuhal.io and navigate to Dashboard → API Keys → Generate. Your key is ready to use immediately with 100 free starter credits.

Create Free Account →
2
Set the base URL
BASE https://zuhal.io/api/v1
3
Authenticate via Authorization header

Pass your API key as a Bearer token in every request header. No OAuth flow required.

Authorization: Bearer YOUR_API_KEY
4
Make your first verification

Send a POST request with the email to verify. That's it — you'll receive a result in under 3 seconds.

First Request Example
curl -X POST https://zuhal.io/api/v1/verify \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "email": "hello@yourcompany.com" }'
🔑
Security Note

API keys are prefixed sk_live_. Never expose them in client-side JavaScript or public repositories. Use environment variables or a secrets manager.

Reference

API Endpoints

Five focused endpoints — single email verification, bulk upload, status polling, result download, and deletion.

POST /api/v1/verify Verify a single email address in real time
Request Parameters
ParameterTypeRequiredDescription
email string Required The email address to verify.
Response Fields
FieldTypeDescription
request_iduuidUnique ID for this verification. Store it to re-fetch within 30 days.
emailstringThe verified email address.
email_statusstringResult: valid, invalid, catch-all, disposable, or unknown.
credits_usedintegerAlways 1 for single verification.
remaining_creditsintegerYour balance after this request.
Request
{
  "email": "john.doe@acme.com"
}
200 Success Response
{
  "status":            "success",
  "message":           "Email verified successfully.",
  "request_id":        "550e8400-e29b-41d4-a716-446655440000",
  "email":             "john.doe@acme.com",
  "email_status":      "valid",
  "credits_used":      1,
  "remaining_credits": 4999
}
POST /api/v1/bulk/upload Upload a CSV for async bulk verification
Request Parameters (multipart/form-data)
ParameterTypeRequiredDescription
filefileRequiredCSV or TXT file. One email per line or in first column. Max 10 MB.
namestringOptionalFriendly label for this job, e.g. "Q1 leads".
Rate Gate

Maximum 10 active bulk jobs per API key at one time. Submit a new job only after an existing one reaches completed or failed status.

202 Accepted Response
{
  "status":      "success",
  "message":     "Bulk job queued successfully.",
  "uuid":        "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "total_emails": 25000,
  "credits_reserved": 25000,
  "status":      "processing"
}

Save the uuid — you'll use it to poll status and download results.

GET /api/v1/bulk/status/{uuid} Check job progress or single verification result
Path Parameters
ParameterTypeDescription
uuiduuidThe uuid from a bulk upload or the request_id from a single verification.
Bulk Job Status Values
pending processing completed failed
200 Response (bulk job)
{
  "status":     "success",
  "uuid":       "f47ac10b-58cc-4372-a567-...",
  "job_status": "completed",
  "total":      25000,
  "valid":      18420,
  "invalid":    4230,
  "catch_all":  1890,
  "unknown":    460,
  "download_url": "/api/v1/bulk/download/f47ac10b"
}
GET /api/v1/bulk/download/{uuid} Get signed download link for completed job results
Notes
  • Only available when job status = completed.
  • Returns a signed URL valid for streaming the result CSV.
  • The CSV includes original email, status, and score columns.
  • Results are retained for 30 days after job completion.
200 Response
{
  "status":       "success",
  "uuid":         "f47ac10b-58cc-...",
  "download_url": "https://zuhal.io/api/v1/bulk/download/f47ac10b/file",
  "expires_at":   "2026-06-26T18:00:00Z"
}
DELETE /api/v1/bulk/delete/{uuid} Permanently delete a bulk job and its results
Notes
  • Irreversible — deletes the job record and result CSV from storage.
  • Cannot delete a job that is currently processing.
  • Use this to free up your active-jobs quota or clean up sensitive data before the 30-day auto-purge.
200 Response
{
  "status":  "success",
  "message": "Bulk job and results deleted.",
  "uuid":    "f47ac10b-58cc-..."
}
Integration

Code Examples

Copy-paste ready snippets for the most common languages and tools.

# ── Single email verification ──────────────────────────────
curl -X POST https://zuhal.io/api/v1/verify \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "user@domain.com"}'

# ── Upload a bulk CSV ──────────────────────────────────────
curl -X POST https://zuhal.io/api/v1/bulk/upload \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@/path/to/emails.csv" \
  -F "name=My List"

# ── Poll bulk job status ───────────────────────────────────
curl https://zuhal.io/api/v1/bulk/status/JOB_UUID \
  -H "Authorization: Bearer YOUR_API_KEY"

# ── Get result download link ──────────────────────────────
curl https://zuhal.io/api/v1/bulk/download/JOB_UUID \
  -H "Authorization: Bearer YOUR_API_KEY"
Verification Statuses

What Each Status Means

Every email address resolves to one of five statuses. Here's exactly what each one tells you.

valid
Valid

The email address exists, the domain has active MX records, and the mailbox accepted our SMTP probe. Safe to send — highest deliverability confidence.

invalid
Invalid

The address is unreachable — bad syntax, non-existent domain, or the mailbox was explicitly rejected by the receiving server. Remove immediately.

catch-all
Catch-All

The domain accepts email to any address, so individual mailbox existence cannot be confirmed. Use with caution — treat as risky in high-reputation campaigns.

disposable
Disposable

A temporary or throwaway address from a known disposable email provider. These addresses expire quickly and are associated with low-intent users. Always remove.

unknown
Unknown

Verification was inconclusive — typically due to a temporary server timeout, greylisting, or an unresponsive mail server. Retry later for a definitive result.

Recommendation

For the best sender reputation: send only to valid. Suppress invalid and disposable. Decide based on domain quality for catch-all. Retry unknown before suppressing.

API Workflow

How the Bulk API Flow Works

Four simple steps from CSV upload to clean, downloadable results.

1
Upload CSV

POST your file to /bulk/upload. Receive a UUID immediately.

2
Job Queued

Credits are reserved. Verification begins across our distributed server cluster.

3
Poll Status

GET /bulk/status/{uuid} every 10–30 seconds until completed.

4
Download Results

GET /bulk/download/{uuid} for a signed CSV link. Retain for up to 30 days.

Error Handling

Error Responses

All errors return a consistent JSON envelope with a status: "error" field and a human-readable message.

Standard Error Envelope
{
  "status":  "error",
  "message": "Insufficient credits to process this request.",
  "code":    "ERR_INSUFFICIENT_CREDITS"
}
HTTPCodeWhen it fires
400ERR_VALIDATIONMissing or malformed email parameter.
401ERR_UNAUTHORIZEDMissing, invalid, or revoked API key.
402ERR_INSUFFICIENT_CREDITSAccount balance too low for the requested operation.
404ERR_NOT_FOUNDUUID not found or doesn't belong to this key.
405Wrong HTTP method for this endpoint.
422ERR_UNPROCESSABLEFile type not accepted or CSV has no valid emails.
429ERR_RATE_LIMITEDRequest rate or active-job limit exceeded. See Retry-After header.
500ERR_SERVERUnexpected server error. Retry with exponential backoff.
Rate Limits

Request Limits Per Endpoint

Limits are enforced per API key per minute. Exceeding a limit returns HTTP 429 with a Retry-After header.

POST
100
req / min
/verify
POST
25
req / min
/bulk/upload
GET
100
req / min
/bulk/status
GET
100
req / min
/bulk/download
DEL
100
req / min
/bulk/delete
ℹ️
Active Bulk Job Limit

A maximum of 10 bulk jobs can be in processing state simultaneously per API key. Additional upload attempts will return 429 until a slot frees up.

Credits System

Pay Only for What You Verify

Credits are the currency of the Zuhal API. Purchase a pack once and use it at any pace — there are no monthly fees and credits never expire.

Single Email Verification

One real-time SMTP verification via /verify

1 credit
📦
Bulk Email (per address)

Each unique email in a CSV uploaded to /bulk/upload

1 credit
🔁
Status / Download / Delete

Polling, downloading, or deleting jobs costs nothing

0 credits
🎁
Free Starter Credits

Every new account receives 100 free credits on sign-up

FREE
View Credit Packs & Pricing →
Request IDs & Data Retention

30-Day Result History

Every API response includes a unique request_id (for single verifications) or uuid (for bulk jobs). You can re-fetch any result within 30 days without spending additional credits.

🆔
What is a Request ID?

A UUID-v4 string returned in every single verification response. Use it with GET /bulk/status/{request_id} to look up the result later without re-running the verification.

🗓️
30-Day Retention Policy

Both single verification logs and bulk job results (including downloadable CSVs) are automatically purged after 30 days from the verification date. Export any data you need to keep before this window closes.

🗑️
Early Deletion

You can delete any bulk job before the 30-day window using DELETE /bulk/delete/{uuid} — useful for GDPR compliance or freeing up your active-job quota.

Trust & Security

Built for Production

Enterprise-grade security and reliability so you can integrate with confidence.

🔒
TLS Everywhere

All API traffic is encrypted in transit via TLS 1.3. No plaintext communication, ever.

🔑
Bearer Token Auth

Simple API key authentication — no OAuth flows or rotating secrets required. Revoke keys instantly from the dashboard.

🛡️
Per-Endpoint Rate Limiting

Independent rate buckets per endpoint prevent a single heavy endpoint from affecting the others. You always get 100 req/min for status polling even if verify is busy.

🌍
Multi-Server Verification

Verifications are load-balanced across a pool of distributed SMTP servers, each with its own IP and HELO hostname to maximize deliverability and avoid blacklisting.

📋
GDPR-Friendly

Results auto-purge after 30 days. Early deletion available via API. No data is sold or shared with third parties.

99.9% Uptime SLA

Redundant infrastructure with automatic failover. API health is monitored continuously and incidents are communicated transparently.

FAQ

Frequently Asked Questions

No. Sign up for free and receive 100 starter credits instantly — no credit card required. You only need to add payment when you want to buy more credits.

Most verifications complete in 2–5 seconds. Well-known providers (Gmail, Outlook, Yahoo) are typically faster. Slower servers or greylisting can extend this to 10–15 seconds in rare cases.

Yes. Role-based addresses are verified via the same SMTP flow. The result will indicate valid or invalid just like any other address.

Catch-all means the domain accepts mail for any address, so we cannot confirm whether the specific inbox exists. We recommend treating catch-all emails as medium-risk — suppress them in cold campaigns but keep them for transactional mail where you have prior engagement.

Any CSV or TXT file with one email address per line, or emails in the first column of a CSV with or without a header row. Max file size is 10 MB. Duplicate addresses within a single upload are automatically deduplicated.

Yes — use the request_id from the original verification with GET /bulk/status/{request_id} to retrieve the cached result at no cost, within 30 days of the original verification.

Credits are still consumed for unknown results — the SMTP handshake was performed and server resources were used. You may retry the same address later for free using the cached request_id.

There is no dedicated sandbox. Your 100 free starter credits serve as the test environment. Use a real but disposable email address (such as one you control) for integration testing.

Start Verifying Emails Today

Get your free API key in seconds. 100 starter credits included — no credit card required.