api reference
Batch checks
POST /v1/check/batch checks up to 100 emails, domains or website URLs in one request. Each item counts toward your quota. Limits, response and retry advice.
POST https://api.isbusinessemail.com/v1/check/batch
Checks up to 100 items in one request. Use it for imports, CRM clean-ups and back-filling verdicts on existing users. For a live signup form, use the single /v1/check: it’s faster for one address.
Secret keys only.
Request
{
"items": [
"jane@acme.io",
"bob@gmail.com",
"contoso.com"
],
"policy": "b2b"
}
| Field | Required | Notes |
|---|---|---|
items |
yes | Array of 1–100 strings. Each is an email address (has @), a website URL (has https:// or a path, like acme.io/about) or a bare domain. |
policy |
no | b2b (default), strict or lenient. Applies to every item. |
Limits:
- More than 100 items:
413 batch_too_large. Split into chunks of 100. - Request body over 256 KB:
413 payload_too_large. - Every item counts as one check toward your per-second and daily limits. Duplicates in the same batch are still counted, so de-duplicate first.
Response
The response contains one result per item, in the same order as items. Each result has the same shape as a single /v1/check response.
{
"results": [
{ "email": "jane@acme.io", "domain": "acme.io", "category": "business", "recommendation": "allow", "…": "…" },
{ "email": "bob@gmail.com", "domain": "gmail.com", "category": "personal", "recommendation": "block", "…": "…" },
{ "email": null, "domain": "contoso.com", "category": "business", "recommendation": "allow", "…": "…" }
]
}
An item that isn’t a valid address or domain doesn’t fail the batch. It comes back with category: "invalid" and a reason such as invalid_syntax.
Example: check a CSV column in chunks
import { readFile } from 'node:fs/promises';
const emails = [...new Set(
(await readFile('signups.csv', 'utf8'))
.split('\n').slice(1) // skip header
.map((line) => line.split(',')[0]?.trim().toLowerCase())
.filter(Boolean),
)];
const results = [];
for (let i = 0; i < emails.length; i += 100) {
const res = await fetch('https://api.isbusinessemail.com/v1/check/batch', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.IBE_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ items: emails.slice(i, i + 100) }),
});
if (res.status === 429) {
const wait = Number(res.headers.get('Retry-After') ?? 1);
await new Promise((r) => setTimeout(r, wait * 1000));
i -= 100; // retry this chunk
continue;
}
if (!res.ok) throw new Error(`batch failed: ${res.status}`);
const { results: chunk } = await res.json();
results.push(...chunk);
}
console.table(results.map((r) => ({ email: r.email, category: r.category, recommendation: r.recommendation })));
Tips
- Mind your daily quota. A tier 0 account has 100 checks a day, which is one full batch. Need a one-off import above that? Ask for higher limits.
- Respect
Retry-Afteron429 rate_limitedand back off;429 quota_exceededmeans the daily quota is used up until 00:00 UTC. - Prefer domains for CRM data. If you only care about the company, de-duplicate to domains first. 10,000 contacts often collapse to a few hundred domains.
- No code? The bulk CSV checker does the same from a CSV upload.