Email Validation

Bulk Verification

Submit up to 100,000 emails in a single request. The job runs asynchronously — poll for status or use a callback URL.

Submit a Bulk Job

bash
curl -X POST http://YOUR_SERVER/v1/bulk \
  -H "Content-Type: application/json" \
  -H "Cookie: auth_token=YOUR_SESSION" \
  -d '{
    "emails": ["user1@example.com", "user2@test.com"],
    "level": 2,
    "concurrency": 100,
    "store_results": true,
    "callback_url": "https://your-app.com/webhook/results",
    "callback_batch": 200
  }'

Parameters

FieldTypeDefaultDescription
emailsstring[]Array of email addresses (max 100,000)
levelinteger1Verification depth (1 or 2)
concurrencyinteger200Parallel workers for this job
store_resultsbooleantrueKeep results for later retrieval
callback_urlstringURL to POST results to in batches
callback_batchinteger200Results per callback POST

Response

json
{"id": "abc123-def456", "total": 5000}

Check Job Status

bash
curl http://YOUR_SERVER/v1/bulk/JOB_ID
json
{
  "job": {
    "id": "abc123-def456",
    "status": "running",
    "total": 5000,
    "done": 3200,
    "failed": 12,
    "level": 2
  }
}

Get Results (Paginated)

bash
curl "http://YOUR_SERVER/v1/bulk/JOB_ID/results?offset=0&limit=1000"

Download as CSV

bash
curl http://YOUR_SERVER/v1/bulk/JOB_ID/download -o results.csv

CSV columns: email, reachable, syntax_valid, disposable, role_account, free, has_mx_records, smtp_host_exists, smtp_catch_all, smtp_deliverable, and more.

CSV Upload

You can also submit a CSV file directly:

bash
curl -X POST http://YOUR_SERVER/v1/bulk?level=2 \
  -H "Content-Type: text/csv" \
  -H "Cookie: auth_token=YOUR_SESSION" \
  --data-binary @emails.csv

The CSV must have an email column header. If no header matches, the first column is used.

Callback webhooks

If callback_url is set, Cleanmails POSTs results in batches as they complete. This is useful for large jobs where you don't want to poll. The callback receives the same result format as the results endpoint.

Result TTL

Results are kept in memory for 15 minutes by default (configurable via RESULT_TTL). Download or fetch results before they expire.