> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mailbreeze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Batch Verify

> Verify multiple email addresses

Submit a batch of email addresses for verification. For large batches, results are processed asynchronously - use the verification ID to poll for results.

## Request Body

<ParamField body="emails" type="string[]" required>
  Array of email addresses to verify. Maximum 1000 emails per batch.
</ParamField>

## Examples

<CodeGroup>
  ```typescript JavaScript theme={null}
  import { MailBreeze } from "mailbreeze";

  const mailbreeze = new MailBreeze({ apiKey: "sk_live_xxx" });

  // Submit batch for verification
  const batch = await mailbreeze.verification.batch({
    emails: [
      "user1@example.com",
      "user2@example.com",
      "user3@example.com",
    ],
  });

  console.log(`Batch ID: ${batch.verificationId}`);
  console.log(`Status: ${batch.status}`);
  console.log(`Credits deducted: ${batch.creditsDeducted}`);

  // If all emails were cached, results are immediate
  if (batch.results) {
    console.log("All results from cache:");
    for (const result of batch.results) {
      console.log(`${result.email}: ${result.result}`);
    }
  } else {
    // Poll for results
    let status = await mailbreeze.verification.get(batch.verificationId);

    while (status.status === "processing") {
      await new Promise(r => setTimeout(r, 2000)); // Wait 2 seconds
      status = await mailbreeze.verification.get(batch.verificationId);
      console.log(`Progress: ${status.processedEmails}/${status.totalEmails}`);
    }

    console.log("Results:", status.results);
    console.log("Analytics:", status.analytics);
  }
  ```

  ```python Python theme={null}
  import asyncio
  from mailbreeze import MailBreeze

  client = MailBreeze(api_key="sk_live_xxx")

  # Submit batch for verification
  batch = await client.verification.batch(
      emails=[
          "user1@example.com",
          "user2@example.com",
          "user3@example.com",
      ]
  )

  print(f"Batch ID: {batch.verification_id}")
  print(f"Status: {batch.status}")
  print(f"Credits deducted: {batch.credits_deducted}")

  # If all emails were cached, results are immediate
  if batch.results:
      print("All results from cache:")
      for result in batch.results:
          print(f"{result.email}: {result.result}")
  else:
      # Poll for results
      status = await client.verification.get(batch.verification_id)

      while status.status == "processing":
          await asyncio.sleep(2)  # Wait 2 seconds
          status = await client.verification.get(batch.verification_id)
          print(f"Progress: {status.processed_emails}/{status.total_emails}")

      print("Results:", status.results)
      print("Analytics:", status.analytics)
  ```

  ```go Go theme={null}
  client := mailbreeze.NewClient("sk_live_xxx")

  // Submit batch for verification
  batch, err := client.Verification.Batch(ctx, &mailbreeze.BatchVerifyParams{
      Emails: []string{
          "user1@example.com",
          "user2@example.com",
          "user3@example.com",
      },
  })
  if err != nil {
      log.Fatal(err)
  }

  fmt.Printf("Batch ID: %s\n", batch.VerificationID)
  fmt.Printf("Status: %s\n", batch.Status)
  fmt.Printf("Credits deducted: %d\n", batch.CreditsDeducted)

  // If all emails were cached, results are immediate
  if batch.Results != nil {
      fmt.Println("All results from cache:")
      for _, result := range batch.Results {
          fmt.Printf("%s: %s\n", result.Email, result.Result)
      }
  } else {
      // Poll for results
      for {
          status, _ := client.Verification.Get(ctx, batch.VerificationID)
          if status.Status != "processing" {
              fmt.Println("Results:", status.Results)
              break
          }
          fmt.Printf("Progress: %d/%d\n", status.ProcessedEmails, status.TotalEmails)
          time.Sleep(2 * time.Second)
      }
  }
  ```

  ```php PHP theme={null}
  $mailbreeze = new MailBreeze('sk_live_xxx');

  // Submit batch for verification
  $response = $mailbreeze->verification->batch([
      'emails' => [
          'user1@example.com',
          'user2@example.com',
          'user3@example.com',
      ],
  ]);
  $batch = $response['data'];

  echo "Batch ID: " . $batch['verificationId'] . "\n";
  echo "Status: " . $batch['status'] . "\n";
  echo "Credits deducted: " . $batch['creditsDeducted'] . "\n";

  // If all emails were cached, results are immediate
  if (isset($batch['results'])) {
      echo "All results from cache:\n";
      foreach ($batch['results'] as $result) {
          echo $result['email'] . ": " . $result['result'] . "\n";
      }
  } else {
      // Poll for results
      do {
          sleep(2);
          $statusResponse = $mailbreeze->verification->get($batch['verificationId']);
          $status = $statusResponse['data'];
          echo "Progress: " . $status['processedEmails'] . "/" . $status['totalEmails'] . "\n";
      } while ($status['status'] === 'processing');

      print_r($status['results']);
  }
  ```

  ```rust Rust theme={null}
  let client = Client::new("sk_live_xxx");

  // Submit batch for verification
  let batch = client.verification().batch(BatchVerifyParams {
      emails: vec![
          "user1@example.com".to_string(),
          "user2@example.com".to_string(),
          "user3@example.com".to_string(),
      ],
  }).await?;

  println!("Batch ID: {}", batch.verification_id);
  println!("Status: {}", batch.status);
  println!("Credits deducted: {}", batch.credits_deducted);

  // If all emails were cached, results are immediate
  if let Some(results) = batch.results {
      println!("All results from cache:");
      for result in results {
          println!("{}: {}", result.email, result.result);
      }
  } else {
      // Poll for results
      loop {
          let status = client.verification().get(&batch.verification_id).await?;
          if status.status != "processing" {
              println!("Results: {:?}", status.results);
              break;
          }
          println!("Progress: {}/{}", status.processed_emails, status.total_emails);
          tokio::time::sleep(Duration::from_secs(2)).await;
      }
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.mailbreeze.com/api/v1/email-verification/batch \
    -H "Authorization: Bearer sk_live_xxx" \
    -H "Content-Type: application/json" \
    -d '{
      "emails": [
        "user1@example.com",
        "user2@example.com",
        "user3@example.com"
      ]
    }'
  ```
</CodeGroup>

## Response

<ResponseField name="verificationId" type="string">
  Unique ID for polling batch status.
</ResponseField>

<ResponseField name="totalEmails" type="integer">
  Total number of emails in the batch.
</ResponseField>

<ResponseField name="creditsDeducted" type="integer">
  Number of credits deducted (cached emails are free).
</ResponseField>

<ResponseField name="status" type="string">
  Current batch status:

  * `pending` - Batch submitted, not yet started
  * `processing` - Verification in progress
  * `completed` - All emails verified
  * `failed` - Batch verification failed
</ResponseField>

<ResponseField name="results" type="array">
  Only populated when all emails were cached. Contains array of verification results.
</ResponseField>

```json Example Response theme={null}
{
  "success": true,
  "data": {
    "totalEmails": 2,
    "creditsDeducted": 4,
    "status": "completed",
    "analytics": {
      "cleanCount": 0,
      "dirtyCount": 2,
      "unknownCount": 0,
      "cleanPercentage": 0
    },
    "results": {
      "clean": [],
      "dirty": [
        "test1@example.com",
        "test2@example.com"
      ],
      "unknown": []
    }
  },
  "meta": {
    "timestamp": "2025-12-27T13:39:38.819Z",
    "requestId": "5e1686a9-05dd-4693-bc5d-fd596fb16bdf",
    "path": "/api/v1/email-verification/batch"
  }
}
```

<Note>
  The response is wrapped in an envelope with `success`, `data`, and `meta` fields. SDKs automatically extract the `data` object.
</Note>

## Limits

| Limit                  | Value                   |
| ---------------------- | ----------------------- |
| Max emails per batch   | 1,000                   |
| Max concurrent batches | 5                       |
| Processing time        | \~1-2 seconds per email |

## Credits

* **New emails**: 1 credit per email
* **Cached emails**: 0 credits (cached 24 hours)
* Credits are deducted upfront when batch is submitted

## Errors

| Code                   | HTTP Status | Description                    |
| ---------------------- | ----------- | ------------------------------ |
| `BATCH_TOO_LARGE`      | 400         | More than 1000 emails in batch |
| `INSUFFICIENT_CREDITS` | 402         | Not enough credits for batch   |
| `TOO_MANY_BATCHES`     | 429         | Too many concurrent batches    |
| `VALIDATION_ERROR`     | 400         | Invalid email format in batch  |
