Bounce Protect
Clean your email lists before you send
API Documentation
Integrate Bounce Protect email validation into your app with our simple REST API. Each validation costs 1 credit.
Quickstart
Validate your first email in under 60 seconds. Get your API key from the dashboard.
curl -X POST https://bounceprotect.com/api/v1/validate/email \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "john.doe@company.com"}'{
"email": "john.doe@company.com",
"status": "valid",
"status_reason": "valid_domain_with_mx",
"status_explanation": "Domain mail servers detected",
"deliverability_score": 92,
"signals": {
"is_disposable": false,
"is_role_account": false,
"is_free_provider": false,
"is_possible_typo": false,
"suggested_domain": null,
"has_mx": true,
"has_spf": true,
"has_dmarc": true
},
"send_recommendation": "SEND",
"credits_remaining": 4999
}Authentication
All API requests must include your API key in the Authorization header using the Bearer scheme.
Authorization: Bearer bp_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxGenerate and manage your API keys in the API Keys dashboard. Never expose your API key in client-side code.
Validate email
/api/v1/validate/emailValidate a single email address. Costs 1 credit.
Request body
| Parameter | Type | Description |
|---|---|---|
emailrequired | string | The email address to validate. |
Example
curl -X POST https://bounceprotect.com/api/v1/validate/email \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "sarah@company.com"}'Node.js
const response = await fetch('https://bounceprotect.com/api/v1/validate/email', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({ email: 'sarah@company.com' }),
});
const result = await response.json();
console.log(result.status); // "valid" | "risky" | "invalid" | "unknown"Python
import requests
response = requests.post(
'https://bounceprotect.com/api/v1/validate/email',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
json={'email': 'sarah@company.com'}
)
result = response.json()
print(result['status']) # "valid" | "risky" | "invalid" | "unknown"PHP
$response = file_get_contents('https://bounceprotect.com/api/v1/validate/email', false,
stream_context_create(['http' => [
'method' => 'POST',
'header' => "Authorization: Bearer YOUR_API_KEY\r\nContent-Type: application/json\r\n",
'content' => json_encode(['email' => 'sarah@company.com']),
]])
);
$result = json_decode($response, true);
echo $result['status']; // "valid" | "risky" | "invalid" | "unknown"Validate bulk
/api/v1/validate/bulkValidate up to 100 emails in a single request. Costs 1 credit per email.
Request body
| Parameter | Type | Description |
|---|---|---|
emailsrequired | string[] | Array of email addresses to validate. Maximum 100 per request. |
Example
curl -X POST https://bounceprotect.com/api/v1/validate/bulk \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"emails": ["sarah@company.com", "noreply@brand.com", "test@gmail.com"]}'Response
{
"results": [
{
"email": "sarah@company.com",
"status": "valid",
"status_reason": "valid_domain_with_mx",
"deliverability_score": 92,
"send_recommendation": "SEND",
"signals": { "is_disposable": false, "is_role_account": false, "has_mx": true }
},
{
"email": "noreply@brand.com",
"status": "risky",
"status_reason": "role_address",
"deliverability_score": 35,
"send_recommendation": "DO_NOT_SEND",
"signals": { "is_disposable": false, "is_role_account": true, "has_mx": true }
}
],
"total": 2,
"credits_used": 2,
"credits_remaining": 4997
}Node.js
const response = await fetch('https://bounceprotect.com/api/v1/validate/bulk', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
emails: ['sarah@company.com', 'noreply@brand.com', 'test@gmail.com'],
}),
});
const { results, credits_remaining } = await response.json();
const safe = results.filter(r => r.send_recommendation === 'SEND');
console.log(`${safe.length} safe to send, ${credits_remaining} credits left`);Account balance
/api/v1/account/balanceReturns your current credit balance.
curl https://bounceprotect.com/api/v1/account/balance \
-H "Authorization: Bearer YOUR_API_KEY"{
"credits_remaining": 4999,
"dashboard_url": "https://bounceprotect.com/dashboard/usage"
}Response fields
| Field | Type | Description |
|---|---|---|
status | string | "valid" | "risky" | "invalid" | "unknown" |
status_reason | string | Machine-readable reason code e.g. free_email_provider, disposable_domain, invalid_syntax |
status_explanation | string | Plain-English explanation of the status. |
deliverability_score | number | 0-100 score. Higher is better. 90+ is safe to send, below 40 is high risk. |
signals.is_disposable | boolean | Temporary or disposable email provider detected. |
signals.is_role_account | boolean | Role-based address detected (info@, noreply@, etc). |
signals.is_free_provider | boolean | Free email provider detected (Gmail, Yahoo, etc). |
signals.is_possible_typo | boolean | Possible domain typo detected. |
signals.suggested_domain | string | null | Suggested corrected domain if a typo was detected. |
signals.has_mx | boolean | null | Domain has valid MX records. |
signals.has_spf | boolean | null | Domain has SPF record configured. |
signals.has_dmarc | boolean | null | Domain has DMARC record configured. |
send_recommendation | string | "SEND" | "SEND_WITH_CAUTION" | "REVIEW" | "DO_NOT_SEND" — our recommendation based on all signals combined. The fastest way to action results without building your own scoring logic. |
credits_remaining | number | Your remaining credit balance after this request. |
Error codes
| Status | Code | Meaning |
|---|---|---|
400 | Bad Request | Missing or invalid request body. Check that email is a valid string. |
401 | Unauthorized | Missing, invalid, or revoked API key. |
402 | Payment Required | Insufficient credits. Top up at bounceprotect.com/dashboard/usage. |
429 | Too Many Requests | Rate limit exceeded. Slow down your requests. |
500 | Server Error | Something went wrong on our end. Try again. |
Best practices
When to block vs allow at point of entry
When validating emails at signup or form submission, we recommend this approach:
| Status | Recommendation | Reason |
|---|---|---|
valid | Allow | Safe to proceed. Domain has mail servers and passed all checks. |
risky | Allow with caution | Review the signals. Free providers and catch-alls are often legitimate. Block disposable and role accounts if your use case requires it. |
invalid | Block | Email will bounce. Do not send to invalid addresses. |
unknown | Allow | Could not be verified. Treat as valid and monitor bounce rates. |
Deliverability score guide
| Score | Rating | Action |
|---|---|---|
90-100 | Excellent | Safe to send. High confidence this is a real, active inbox. |
70-89 | Good | Generally safe. May be a free provider or have minor signals. |
40-69 | Moderate | Review before sending. Catch-all, new domain, or role account. |
1-39 | High risk | Avoid sending. Disposable, invalid syntax, or no mail servers. |
0 | Invalid | Do not send. Email is definitively invalid. |
Rate limits
| Plan | Requests/second | Bulk limit |
|---|---|---|
Pro | 10 req/s | Up to 100 emails per bulk request. |
Agency | 50 req/s | Up to 100 emails per bulk request. |
Scale | 200 req/s | Up to 100 emails per bulk request. |
Rate limit headers are included in every response. If you exceed the limit you will receive a 429 response. Implement exponential backoff in your client.
Changelog
March 2026 — Initial release
- Single email validation endpoint
- Bulk validation up to 100 emails per request
- Account balance endpoint
- API key management dashboard
- Deliverability scoring (0-100)
- Multi-signal detection: disposable, role accounts, domain typos, SPF/DMARC