Batch Verification API
Validate large lists of emails efficiently with our batch processing API. The workflow involves three sequential steps: submitting your file, monitoring progress, and downloading results.
How it works
Batch verification is asynchronous to handle large files without timing out. You upload your file once, receive a task ID to track progress, and download the processed results when complete. This approach allows you to validate millions of emails.
The service accepts CSV, XLSX, and TSV files with an email column.
Deduplication
By default you have deduplicate=true setting enabled, so duplicate email addresses are removed before processing — only the last occurrence of each email is kept. This prevents from sending the email for the same address twice.
Invalid emails
Emails that fail format validation (e.g. plaintext, missing@tld, @nodomain.) are automatically marked with category: black and domain_type: invalid in the results file. You are not charged for invalid emails — only emails that pass format validation count toward your usage.
Step 1: Submit your file
Upload your email list and receive a task ID for tracking.
API Reference: POST /batch-check-emails
import requests, os
resp = requests.post(
"https://api.user.cleaning/v1/external-api-requests/batch-check-emails",
headers={"X-API-Key": os.environ["USER_CLEANING_API_KEY"]},
files={"file": open("emails.csv", "rb")},
data={"project_name": "my-list"}
)
task_id = resp.json()["task_id"]const form = new FormData()
form.append('file', fs.createReadStream('emails.csv'))
form.append('project_name', 'my-list')
const { task_id } = await fetch('https://api.user.cleaning/v1/external-api-requests/batch-check-emails', {
method: 'POST',
headers: { 'X-API-Key': process.env.USER_CLEANING_API_KEY, ...form.getHeaders() },
body: form
}).then(r => r.json())const form = new FormData()
form.append('file', fs.createReadStream('emails.csv'))
form.append('project_name', 'my-list')
const { task_id } = await fetch('https://api.user.cleaning/v1/external-api-requests/batch-check-emails', {
method: 'POST',
headers: { 'X-API-Key': process.env.USER_CLEANING_API_KEY!, ...form.getHeaders() },
body: form as any
}).then(r => r.json())Step 2: Monitor processing status
Poll the status endpoint until your task completes. The status transitions from processing to completed or failed.
API Reference: GET /batch-check-status/{task_id}
import time
while True:
status = requests.get(
f"https://api.user.cleaning/v1/external-api-requests/batch-check-status/{task_id}",
headers={"X-API-Key": os.environ["USER_CLEANING_API_KEY"]}
).json()["status"]
if status == "completed":
break
time.sleep(5)let done = false
while (!done) {
const { status } = await fetch(
`https://api.user.cleaning/v1/external-api-requests/batch-check-status/${task_id}`,
{ headers: { 'X-API-Key': process.env.USER_CLEANING_API_KEY } }
).then(r => r.json())
done = status === 'completed'
if (!done) await new Promise(r => setTimeout(r, 5000))
}let done = false
while (!done) {
const { status } = await fetch(
`https://api.user.cleaning/v1/external-api-requests/batch-check-status/${task_id}`,
{ headers: { 'X-API-Key': process.env.USER_CLEANING_API_KEY! } }
).then(r => r.json())
done = status === 'completed'
if (!done) await new Promise(r => setTimeout(r, 5000))
}Step 3: Download your results
Your account has a total storage limit of 5GB across all batch verification projects. All projects are auto-deleted in 30 days after submission. You can manually delete the project from batch verification dashboard.
Once processing completes, retrieve a temporary download URL for your validated results. The link expires in 1 hour, so download the file promptly after receiving it.
Results are returned in the same format as your input file, with two added columns: category (white/grey/black) and domain_type.
API Reference: GET /batch-task-download/{task_id}
url = requests.get(
f"https://api.user.cleaning/v1/external-api-requests/batch-task-download/{task_id}",
headers={"X-API-Key": os.environ["USER_CLEANING_API_KEY"]}
).json()["download_url"]
open("results.csv", "wb").write(requests.get(url).content)const { download_url } = await fetch(
`https://api.user.cleaning/v1/external-api-requests/batch-task-download/${task_id}`,
{ headers: { 'X-API-Key': process.env.USER_CLEANING_API_KEY } }
).then(r => r.json())
fs.writeFileSync('results.csv', Buffer.from(await fetch(download_url).then(r => r.arrayBuffer())))const { download_url } = await fetch(
`https://api.user.cleaning/v1/external-api-requests/batch-task-download/${task_id}`,
{ headers: { 'X-API-Key': process.env.USER_CLEANING_API_KEY! } }
).then(r => r.json())
fs.writeFileSync('results.csv', Buffer.from(await fetch(download_url).then(r => r.arrayBuffer())))