MailLandDocs

Batch Validation

Validate up to 100 email addresses in a single request

Authentication

Include your API key in the X-API-Key header:

X-API-Key: ml_pv_Ab3Kx9mN2pQ7rT4wL8yD...

The credential must be a Validation product credential with the Api channel enabled.

Validate a Batch

POST https://api.mail.land/v1/validation/batch
Batch validation request
{
  "emails": [
    "[email protected]",
    "[email protected]",
    "invalid@",
    "[email protected]",
    "[email protected]"
  ],
  "verify_smtp": true
}
FieldTypeDefaultDescription
emailsarray-Email addresses to validate (required, max 100)
verify_smtpbooltruePerform SMTP mailbox verification
Batch validate
curl -X POST https://api.mail.land/v1/validation/batch \
  -H "X-API-Key: ml_pv_Ab3Kx9mN2pQ7rT4wL8yD..." \
  -H "Content-Type: application/json" \
  -d '{
    "emails": ["[email protected]", "[email protected]", "[email protected]"],
    "verify_smtp": true
  }'

Response

Batch validation response
{
  "total_count": 5,
  "processed_count": 5,
  "successful_count": 5,
  "credits_consumed": 4,
  "free_validations": 1,
  "results": [
    {
      "email": "[email protected]",
      "result": "Deliverable",
      "score": 95,
      "syntax": { "is_valid": true, "has_typo": false },
      "disposable": { "is_disposable": false },
      "role": { "is_role_account": false },
      "mx": { "has_mx": true, "records": ["mx.example.com"], "accepts_mail": true },
      "smtp": { "can_connect": true, "is_deliverable": true, "is_catch_all": false, "reachability": "safe" },
      "provider": { "name": "Unknown", "type": "unknown" },
      "cached": false,
      "verified_at": "2026-02-17T12:34:56Z"
    },
    {
      "email": "[email protected]",
      "result": "Deliverable",
      "score": 95,
      "syntax": { "is_valid": true, "has_typo": false },
      "disposable": { "is_disposable": false },
      "role": { "is_role_account": false },
      "mx": { "has_mx": true, "records": ["gmail-smtp-in.l.google.com"], "accepts_mail": true },
      "smtp": { "can_connect": true, "is_deliverable": true, "is_catch_all": false, "reachability": "safe" },
      "provider": { "name": "Gmail", "type": "consumer" },
      "cached": false,
      "verified_at": "2026-02-17T12:34:56Z"
    },
    {
      "email": "invalid@",
      "result": "Undeliverable",
      "score": 0,
      "syntax": { "is_valid": false, "has_typo": false },
      "disposable": { "is_disposable": false },
      "role": { "is_role_account": false },
      "mx": { "has_mx": false, "records": [], "accepts_mail": false },
      "smtp": null,
      "provider": { "name": "Unknown", "type": "unknown" },
      "cached": false,
      "verified_at": "2026-02-17T12:34:56Z"
    },
    {
      "email": "[email protected]",
      "result": "Undeliverable",
      "score": 10,
      "syntax": { "is_valid": true, "has_typo": false },
      "disposable": { "is_disposable": true },
      "role": { "is_role_account": false },
      "mx": { "has_mx": true, "records": ["mx.tempmail.org"], "accepts_mail": true },
      "smtp": null,
      "provider": { "name": "Unknown", "type": "unknown" },
      "cached": false,
      "verified_at": "2026-02-17T12:34:56Z"
    },
    {
      "email": "[email protected]",
      "result": "Deliverable",
      "score": 85,
      "syntax": { "is_valid": true, "has_typo": false },
      "disposable": { "is_disposable": false },
      "role": { "is_role_account": true },
      "mx": { "has_mx": true, "records": ["mx.company.com"], "accepts_mail": true },
      "smtp": { "can_connect": true, "is_deliverable": true, "is_catch_all": false, "reachability": "safe" },
      "provider": { "name": "Unknown", "type": "unknown" },
      "cached": false,
      "verified_at": "2026-02-17T12:34:56Z"
    }
  ]
}

Response Fields

FieldTypeDescription
total_countintUnique addresses in the request. Exact, case-sensitive duplicates are deduplicated before processing and validated once, so this can be lower than the number of emails you sent.
processed_countintEmails that were processed
successful_countintValidations that completed without error
credits_consumedintCredits deducted (paid validations)
free_validationsintFree validations (disposable, typos, SMTP errors)
resultsarrayOne entry per unique address, in first-occurrence order. Match results to your input on the email field, not on position: duplicates in your request will not have a corresponding entry.

Each item in results has the same structure as a single validation response.

Credit Consumption

Credits are checked before processing the batch. If you don't have enough credits for the entire batch, the request is rejected with 402.

Within the batch, free validations apply per the same rules as single validation:

  • Disposable domains: free
  • High-confidence typos (90%+): free
  • SMTP connection errors: free

The response shows the exact breakdown: credits_consumed (billed) + free_validations (not billed) = processed_count.

Concurrency

Batch validations run up to 10 emails concurrently within a single request. This balances throughput against SMTP server rate limits. Results are returned in the same order as the input array regardless of processing order.

For lists larger than 100 emails, split them into multiple batch requests. The concurrency limit applies per request: you can run multiple batch requests in parallel from your server.

Validation History

All validations (single and batch) are recorded in your validation history:

GET https://api.mail.land/v1/validation/history
ParameterTypeDefaultDescription
cursorstring-Opaque cursor from the previous page's nextCursor. Omit for the first page.
limitint20Items per page (max 100)
resultstring-Filter: Deliverable, Risky, Unknown, Undeliverable, Invalid
fromdatetime-Start date
todatetime-End date
searchstring-Search by email address
Validation history response
{
  "items": [
    {
      "email": "u***@example.com",
      "result": "Deliverable",
      "score": 95,
      "is_disposable": false,
      "is_role_account": false,
      "has_valid_mx": true,
      "smtp_deliverable": true,
      "provider": "Unknown",
      "was_cached": false,
      "smtp_verified": true,
      "credit_consumed": true,
      "verified_at": "2026-02-17T12:34:56Z"
    }
  ],
  "nextCursor": "eyJ2IjoxLCJzIjoidmFsaWRhdGlvbjp2ZXJpZmllZGF0OmRlc2MiLCJrIjoi...",
  "hasMore": true
}

Email addresses in history are partially masked for privacy (e.g., u***@example.com).

Validation Statistics

Get aggregate statistics for your validation usage:

GET https://api.mail.land/v1/validation/stats
ParameterTypeDefaultDescription
fromdatetime-Start date
todatetime-End date
Validation stats response
{
  "total_validations": 450,
  "deliverable": 320,
  "risky": 65,
  "undeliverable": 50,
  "unknown": 15,
  "deliverable_rate": 71.11,
  "risky_rate": 14.44,
  "undeliverable_rate": 11.11,
  "unknown_rate": 3.33,
  "credits_consumed": 380,
  "free_validations": 70
}

Limits

LimitValue
Max emails per batch100
Concurrent validations per batch10
SMTP timeout per email30 seconds
Max email length320 characters

Error Responses

StatusCodeDescription
400INVALID_REQUESTAt least one email is required
400CONTENT_TOO_LARGEBatch exceeds 100 emails
402INSUFFICIENT_CREDITSNot enough credits for the batch

Best Practices

  • Validate before importing: run batch validation on new subscriber lists before importing them to avoid bounce spikes.
  • Filter by result: only import Deliverable emails. Treat Risky emails with caution and avoid Undeliverable entirely.
  • Check typo suggestions: when syntax.has_typo is true, present the syntax.suggestion to the user for confirmation before sending.
  • Use during signup: validate emails in your registration flow with single validation to prevent bad addresses from entering your system.
  • Monitor credit usage: check /validation/credits to track consumption and plan upgrades before hitting your quota limit.

Next Steps

On this page