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.
From quick single-email spot checks to processing multi-million-row lists, the Zuhal API has you covered.
Verify any email address instantly via full SMTP handshake — syntax, DNS, MX, and mailbox existence all checked in one call.
Upload a CSV file of up to 500 000 rows, and we'll verify every address asynchronously. Poll status and download results when ready.
Automatically flag throwaway addresses and accept-all domains so you never waste credits or credits on unverifiable emails.
Pay only for what you use. Credits never expire — buy once and consume at your own pace. No monthly minimums or seat fees.
Every verification result is stored for 30 days. Re-fetch any single or bulk result by its request_id without re-verifying.
Standard HTTP verbs, clean JSON responses, meaningful HTTP status codes, and predictable error objects — no SDK required.
Get your API key, make your first request, and start verifying emails — no SDK or complex setup required.
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 →https://zuhal.io/api/v1
Pass your API key as a Bearer token in every request header. No OAuth flow required.
Authorization: Bearer YOUR_API_KEY
Send a POST request with the email to verify. That's it — you'll receive a result in under 3 seconds.
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" }'
API keys are prefixed sk_live_. Never expose them in client-side JavaScript or public repositories. Use environment variables or a secrets manager.
Five focused endpoints — single email verification, bulk upload, status polling, result download, and deletion.
| Parameter | Type | Required | Description |
|---|---|---|---|
| string | Required | The email address to verify. |
| Field | Type | Description |
|---|---|---|
| request_id | uuid | Unique ID for this verification. Store it to re-fetch within 30 days. |
| string | The verified email address. | |
| email_status | string | Result: valid, invalid, catch-all, disposable, or unknown. |
| credits_used | integer | Always 1 for single verification. |
| remaining_credits | integer | Your balance after this request. |
{ "email": "john.doe@acme.com" }
{ "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 }
| Parameter | Type | Required | Description |
|---|---|---|---|
| file | file | Required | CSV or TXT file. One email per line or in first column. Max 10 MB. |
| name | string | Optional | Friendly label for this job, e.g. "Q1 leads". |
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.
{ "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.
| Parameter | Type | Description |
|---|---|---|
| uuid | uuid | The uuid from a bulk upload or the request_id from a single verification. |
{ "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" }
status = completed.{ "status": "success", "uuid": "f47ac10b-58cc-...", "download_url": "https://zuhal.io/api/v1/bulk/download/f47ac10b/file", "expires_at": "2026-06-26T18:00:00Z" }
processing.{ "status": "success", "message": "Bulk job and results deleted.", "uuid": "f47ac10b-58cc-..." }
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"
Every email address resolves to one of five statuses. Here's exactly what each one tells you.
The email address exists, the domain has active MX records, and the mailbox accepted our SMTP probe. Safe to send — highest deliverability confidence.
The address is unreachable — bad syntax, non-existent domain, or the mailbox was explicitly rejected by the receiving server. Remove immediately.
The domain accepts email to any address, so individual mailbox existence cannot be confirmed. Use with caution — treat as risky in high-reputation campaigns.
A temporary or throwaway address from a known disposable email provider. These addresses expire quickly and are associated with low-intent users. Always remove.
Verification was inconclusive — typically due to a temporary server timeout, greylisting, or an unresponsive mail server. Retry later for a definitive result.
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.
Four simple steps from CSV upload to clean, downloadable results.
POST your file to /bulk/upload. Receive a UUID immediately.
Credits are reserved. Verification begins across our distributed server cluster.
GET /bulk/status/{uuid} every 10–30 seconds until completed.
GET /bulk/download/{uuid} for a signed CSV link. Retain for up to 30 days.
All errors return a consistent JSON envelope with a status: "error" field and a human-readable message.
{ "status": "error", "message": "Insufficient credits to process this request.", "code": "ERR_INSUFFICIENT_CREDITS" }
Limits are enforced per API key per minute. Exceeding a limit returns HTTP 429 with a Retry-After header.
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 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.
One real-time SMTP verification via /verify
Each unique email in a CSV uploaded to /bulk/upload
Polling, downloading, or deleting jobs costs nothing
Every new account receives 100 free credits on sign-up
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.
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.
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.
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.
Enterprise-grade security and reliability so you can integrate with confidence.
All API traffic is encrypted in transit via TLS 1.3. No plaintext communication, ever.
Simple API key authentication — no OAuth flows or rotating secrets required. Revoke keys instantly from the dashboard.
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.
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.
Results auto-purge after 30 days. Early deletion available via API. No data is sold or shared with third parties.
Redundant infrastructure with automatic failover. API health is monitored continuously and incidents are communicated transparently.
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.
Get your free API key in seconds. 100 starter credits included — no credit card required.