Email Verification API
Verify email addresses in milliseconds. REST API, JSON responses, free tier included.
Authentication
All requests require an API key passed in the X-API-Key header. Your key is generated automatically when you sign up — find it in your dashboard under Account Settings.
X-API-Key: pj_your_api_key_here
Base URL
All API endpoints are relative to:
https://prospectjet.polsia.app/api/v1
Response Format
All responses are JSON. Successful responses include "success": true. Error responses include "success": false and an "error" code string.
POST /verify
Verify a single email address. Runs four detection layers: syntax, disposable domain, MX record lookup, and role-based detection. Consumes 1 verification credit.
POST /api/v1/verify
Request body:
| Field | Type | Description |
|---|---|---|
| email required | string | The email address to verify |
curl -X POST https://prospectjet.polsia.app/api/v1/verify \ -H "Content-Type: application/json" \ -H "X-API-Key: pj_your_api_key_here" \ -d '{"email": "john@example.com"}'
const response = await fetch('https://prospectjet.polsia.app/api/v1/verify', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': 'pj_your_api_key_here' }, body: JSON.stringify({ email: 'john@example.com' }) }); const data = await response.json(); console.log(data.result); // "valid" | "invalid" | "risky" | "unknown"
import requests response = requests.post( 'https://prospectjet.polsia.app/api/v1/verify', json={'email': 'john@example.com'}, headers={'X-API-Key': 'pj_your_api_key_here'} ) data = response.json() print(data['result']) # "valid" | "invalid" | "risky" | "unknown"
Response:
{
"success": true,
"email": "john@example.com",
"result": "valid", // "valid" | "invalid" | "risky" | "unknown"
"confidence": "high", // "high" | "medium" | "low"
"reason": "passed_all_checks",
"usage": {
"used": 1,
"remaining": 99,
"monthly_limit": 100
}
}
POST /verify/bulk
Verify up to 100 email addresses in a single request. Consumes N credits (one per email). The entire batch must fit within your remaining quota — if not, a 402 is returned before any processing begins.
POST /api/v1/verify/bulk
Request body:
| Field | Type | Description |
|---|---|---|
| emails required | string[] | Array of email addresses. Max 100 per request. |
curl -X POST https://prospectjet.polsia.app/api/v1/verify/bulk \ -H "Content-Type: application/json" \ -H "X-API-Key: pj_your_api_key_here" \ -d '{"emails": ["john@example.com", "info@other.com", "test@mailinator.com"]}'
const response = await fetch('https://prospectjet.polsia.app/api/v1/verify/bulk', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': 'pj_your_api_key_here' }, body: JSON.stringify({ emails: ['john@example.com', 'info@other.com', 'test@mailinator.com'] }) }); const data = await response.json(); // data.results is an array of individual verification results data.results.forEach(r => console.log(r.email, r.result));
import requests response = requests.post( 'https://prospectjet.polsia.app/api/v1/verify/bulk', json={'emails': ['john@example.com', 'info@other.com']}, headers={'X-API-Key': 'pj_your_api_key_here'} ) data = response.json() for r in data['results']: print(r['email'], r['result'])
Response:
{
"success": true,
"results": [
{ "email": "john@example.com", "result": "valid", "confidence": "high", "reason": "passed_all_checks" },
{ "email": "info@other.com", "result": "risky", "confidence": "high", "reason": "role_based" },
{ "email": "test@mailinator.com", "result": "invalid", "confidence": "high", "reason": "disposable_domain" }
],
"usage": {
"used": 3,
"remaining": 97,
"monthly_limit": 100
}
}
GET /usage
Check your current quota usage. Useful for monitoring and pre-flight checks before bulk operations.
GET /api/v1/usage
curl https://prospectjet.polsia.app/api/v1/usage \ -H "X-API-Key: pj_your_api_key_here"
{
"success": true,
"api_key": "pj_your_api_...",
"tier": "free",
"usage": {
"used": 3,
"remaining": 97,
"monthly_limit": 100,
"reset_date": "2026-06-01T00:00:00.000Z"
}
}
Result Values
Every verification returns a result and a confidence level.
| Result | Meaning | Recommended action |
|---|---|---|
| valid | string | Passed all checks. Safe to send. |
| invalid | string | Failed a hard check (bad syntax, disposable domain, no MX). Do not send. |
| risky | string | Role-based address (info@, admin@). Email exists but likely low engagement. |
| unknown | string | DNS inconclusive. Proceed with caution. |
Common reason values: passed_all_checks, invalid_syntax, disposable_domain, no_mx_record, role_based, dns_timeout
Rate Limits
| Tier | Monthly quota | Rate limit |
|---|---|---|
| Free | 100 verifications | 100 requests/minute |
| Starter ($29/mo) | 5,000 verifications | 1,000 requests/minute |
| Growth ($79/mo) | 25,000 verifications | 1,000 requests/minute |
| Scale ($199/mo) | 100,000 verifications | 1,000 requests/minute |
402 Payment Required when your monthly quota is used up. Usage resets on the first of each month.
Error Codes
| HTTP | error field | Description |
|---|---|---|
| 400 | missing_email | Request body missing the email field |
| 400 | missing_emails | Bulk request missing or empty emails array |
| 400 | too_many_emails | Bulk request contains more than 100 emails |
| 401 | invalid_api_key | Missing or unrecognized X-API-Key header |
| 402 | quota_exceeded | Monthly quota exhausted. Upgrade to continue. |
| 402 | quota_insufficient | Bulk batch requires more credits than remaining quota |
| 429 | rate_limited | Exceeded per-minute request rate limit |
| 500 | internal_error | Server error. Safe to retry with exponential backoff. |
Full Integration Example
A complete example that verifies a list of emails, filters results, and handles quota errors:
const API_KEY = 'pj_your_api_key_here'; const BASE = 'https://prospectjet.polsia.app/api/v1'; async function verifyEmails(emails) { // Check quota first const usage = await fetch(`${BASE}/usage`, { headers: { 'X-API-Key': API_KEY } }).then(r => r.json()); if (usage.usage.remaining < emails.length) { throw new Error(`Insufficient quota: ${usage.usage.remaining} remaining`); } // Verify in batches of 100 const results = []; for (let i = 0; i < emails.length; i += 100) { const batch = emails.slice(i, i + 100); const res = await fetch(`${BASE}/verify/bulk`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': API_KEY }, body: JSON.stringify({ emails: batch }) }); const data = await res.json(); results.push(...data.results); } // Filter to deliverable only return results.filter(r => r.result === 'valid'); } const valid = await verifyEmails([ 'alice@company.com', 'bob@example.com', 'noreply@spam.com' ]); console.log(`${valid.length} deliverable emails`);
import requests API_KEY = 'pj_your_api_key_here' BASE = 'https://prospectjet.polsia.app/api/v1' HEADERS = {'X-API-Key': API_KEY} def verify_emails(emails): # Check quota first usage = requests.get(f'{BASE}/usage', headers=HEADERS).json() if usage['usage']['remaining'] < len(emails): raise ValueError(f"Insufficient quota") # Verify in batches of 100 results = [] for i in range(0, len(emails), 100): batch = emails[i:i+100] r = requests.post( f'{BASE}/verify/bulk', json={'emails': batch}, headers=HEADERS ).json() results.extend(r['results']) # Return deliverable only return [r for r in results if r['result'] == 'valid'] valid = verify_emails(['alice@company.com', 'bob@example.com']) print(f'{len(valid)} deliverable emails')