REST API · v1

Email Verification API Documentation

Real-time single and bulk email validation. Webhooks, job history, detailed results. Works with Python, PHP, Node.js, and any HTTP client.

Base URL

https://bounceguard.net/api/v1

All endpoints are relative to this base URL. Requests and responses use JSON (except file upload which uses multipart/form-data).

Authentication

All requests must include your API key in the Authorization header:

Authorization: Bearer YOUR_API_KEY
  1. Log in to your BounceGuard account
  2. Go to the Integration page
  3. Click "Generate New API Key" and copy it
Keep your API key private. Never commit it to public repositories.

Possible Results

Valid

Mailbox exists and accepts email.

✓ Safe to send

Catch-all

Domain accepts all emails — specific mailbox unconfirmed.

⚠ Risky — may bounce

Bad

Mailbox does not exist or address is invalid.

✗ Do not send

Domain Issue

No MX records or DNS problem with the domain.

✗ Invalid domain

Rate Limits & Credits

  • Each email validation costs 1 credit — single or bulk
  • Credits never expire — buy once, use anytime
  • Bulk jobs deduct credits when the job completes
  • Use GET /api/v1/credits to monitor your balance anytime

Single Email Validation

Validate one email address in real-time. Returns result immediately. Each call costs 1 credit.

POST
/validate-email
Validates a single email address synchronously.
curl -X POST https://bounceguard.net/api/v1/validate-email \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "username@example.com"}'

Response

{
  "status": "success",
  "email": "username@example.com",
  "result": "Valid",
  "reason": "Mailbox confirmed to exist",
  "remaining_credits": 4999
}

Error Responses

// 401 — Invalid or missing API key
{"status": "error", "message": "Invalid API key"}

// 402 — Insufficient credits
{"error": "insufficient_credits", "message": "Not enough credits. You have 0 remaining."}

// 400 — Invalid email format
{"error": "validation_error", "message": "Invalid email format"}

// 404 — File not found
{"error": "not_found", "message": "File not found or unauthorized"}

Bulk Email Validation

Bulk validation is asynchronous — upload CSV → get file_id → poll status → download results. Or use webhooks to skip polling entirely.

How it works

1
Upload CSV → get file_id
POST your CSV to /bulk-validate. Response has file_id and URLs.
2
Poll status (or use webhook)
GET /bulk-validate/status/{file_id} every 3–5s until "status": "complete".
3
Download results
GET /bulk-validate/download/{file_id} for the validated CSV.

1. Upload CSV

CSV must have a column named Email or Emails (case-insensitive).
curl -X POST https://bounceguard.net/api/v1/bulk-validate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@emails.csv"

Response

{
  "status": "queued",
  "file_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "total_emails": 500,
  "urls": {
    "status":   "https://bounceguard.net/api/v1/bulk-validate/status/a1b2c3d4-...",
    "results":  "https://bounceguard.net/api/v1/bulk-validate/results/a1b2c3d4-...",
    "download": null
  },
  "webhook": "will fire when complete",
  "message": "Validation queued."
}

2. Check Status

curl https://bounceguard.net/api/v1/bulk-validate/status/YOUR_FILE_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "status": "complete",
  "file_id": "a1b2c3d4-...",
  "processed": 500,
  "total": 500,
  "results": { "valid": 420, "bad": 55, "catch_all": 20, "domain_invalid": 5 },
  "download_url": "https://bounceguard.net/api/v1/bulk-validate/download/a1b2c3d4-..."
}

3. Download Results

curl https://bounceguard.net/api/v1/bulk-validate/download/YOUR_FILE_ID \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -o validated_results.csv

Bulk API — Code Examples

Python

import requests, time

API_KEY = "YOUR_API_KEY"
BASE    = "https://bounceguard.net/api/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

# 1. Upload
with open("emails.csv", "rb") as f:
    res = requests.post(f"{BASE}/bulk-validate", headers=HEADERS, files={"file": f})
file_id = res.json()["file_id"]
print(f"Queued: {file_id}")

# 2. Poll
while True:
    s = requests.get(f"{BASE}/bulk-validate/status/{file_id}", headers=HEADERS).json()
    print(f"Progress: {s['processed']}/{s['total']}")
    if s["status"] == "complete":
        print("Results:", s["results"])
        break
    time.sleep(4)

# 3. Download
csv = requests.get(f"{BASE}/bulk-validate/download/{file_id}", headers=HEADERS)
open("validated_results.csv", "wb").write(csv.content)
print("Saved!")

Node.js

const fs = require('fs');
const FormData = require('form-data');

const API_KEY = 'YOUR_API_KEY';
const BASE    = 'https://bounceguard.net/api/v1';
const HEADERS = { 'Authorization': `Bearer ${API_KEY}` };

async function bulkValidate(csvPath) {
  const form = new FormData();
  form.append('file', fs.createReadStream(csvPath));
  const { file_id } = await (await fetch(`${BASE}/bulk-validate`, {
    method: 'POST', headers: { ...HEADERS, ...form.getHeaders() }, body: form
  })).json();
  console.log('Queued:', file_id);

  while (true) {
    await new Promise(r => setTimeout(r, 4000));
    const s = await (await fetch(`${BASE}/bulk-validate/status/${file_id}`, { headers: HEADERS })).json();
    console.log(`${s.processed}/${s.total}`);
    if (s.status === 'complete') { console.log('Results:', s.results); break; }
  }

  const csv = await (await fetch(`${BASE}/bulk-validate/download/${file_id}`, { headers: HEADERS })).text();
  fs.writeFileSync('validated_results.csv', csv);
  console.log('Saved!');
}
bulkValidate('emails.csv');

PHP

<?php
$API_KEY = 'YOUR_API_KEY';
$BASE    = 'https://bounceguard.net/api/v1';
$HEADERS = ["Authorization: Bearer $API_KEY"];

// Upload
$ch = curl_init("$BASE/bulk-validate");
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_POST=>true,
    CURLOPT_HTTPHEADER=>$HEADERS, CURLOPT_POSTFIELDS=>['file'=>new CURLFile('emails.csv')]]);
$data = json_decode(curl_exec($ch), true);
$file_id = $data['file_id'];

// Poll
while (true) {
    sleep(4);
    $ch = curl_init("$BASE/bulk-validate/status/$file_id");
    curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_HTTPHEADER=>$HEADERS]);
    $s = json_decode(curl_exec($ch), true);
    echo "{$s['processed']}/{$s['total']}\n";
    if ($s['status'] === 'complete') { print_r($s['results']); break; }
}

// Download
$ch = curl_init("$BASE/bulk-validate/download/$file_id");
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_HTTPHEADER=>$HEADERS]);
file_put_contents('validated_results.csv', curl_exec($ch));

Webhooks NEW

Configure a webhook URL to receive automatic notifications when bulk validation completes. No polling required.

Recommended for production. Set up once — your server receives results the instant validation finishes.
POST
/webhook
Set webhook URL. A test ping is sent immediately.
GET
/webhook
Get current webhook URL and status.
DEL
/webhook
Remove webhook URL.

Set Webhook

curl -X POST https://bounceguard.net/api/v1/webhook \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://yourserver.com/webhook"}'
{
  "message":     "Webhook configured successfully",
  "webhook_url": "https://yourserver.com/webhook",
  "ping_status": 200,
  "note":        "A test ping was sent to your webhook URL"
}

Webhook Payload

{
  "event":    "validation.complete",
  "file_id":  "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "filename": "emails.csv",
  "total":    500,
  "results": {
    "valid": 420, "invalid": 55, "catch_all": 20, "domain_invalid": 5
  },
  "download_url": "https://bounceguard.net/api/v1/bulk-validate/download/a1b2c3d4-...",
  "timestamp": "2026-04-29T17:29:55.571395Z"
}

Python — Zero Polling Flow

import requests

API_KEY = "YOUR_API_KEY"
BASE    = "https://bounceguard.net/api/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

# Set webhook once
requests.post(f"{BASE}/webhook", headers=HEADERS, json={"url": "https://yourserver.com/webhook"})

# Upload — webhook fires automatically when done. No polling needed!
with open("emails.csv", "rb") as f:
    res = requests.post(f"{BASE}/bulk-validate", headers=HEADERS, files={"file": f})
print("Queued:", res.json()["file_id"])

Credits & Usage NEW

GET
/credits
Get credit balance, usage stats, and plan info.
curl https://bounceguard.net/api/v1/credits \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "credits": { "total": 10000, "used": 1500, "remaining": 8500 },
  "plan": "free",
  "user": { "email": "you@example.com", "username": "yourname" }
}

Job History NEW

Retrieve all past bulk validation jobs with stats, progress, and download URLs. Paginated.

GET
/history?page=1&limit=20
Paginated list of past validation jobs.
curl "https://bounceguard.net/api/v1/history?page=1&limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "jobs": [
    {
      "file_id":    "a1b2c3d4-...",
      "filename":   "emails.csv",
      "status":     "complete",
      "total":      500,
      "processed":  500,
      "progress_pct": 100.0,
      "results": { "valid": 420, "bad": 55, "catch_all": 20, "domain_invalid": 5, "valid_pct": 84.0 },
      "download_url":        "https://bounceguard.net/api/v1/bulk-validate/download/a1b2c3d4-...",
      "created_at":          "2026-04-29T17:22:15Z",
      "processing_time_sec": 191
    }
  ],
  "pagination": {
    "page": 1, "limit": 10, "total_jobs": 24, "total_pages": 3,
    "has_next": true, "has_prev": false
  }
}

Detailed Results NEW

Get individual email results for a completed job. Filter by status and paginate through large datasets.

GET
/bulk-validate/results/{file_id}?status=valid&page=1&limit=100
Filter: valid, invalid, catch_all, domain_invalid, all
# Get only valid emails
curl "https://bounceguard.net/api/v1/bulk-validate/results/YOUR_FILE_ID?status=valid" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "file_id": "a1b2c3d4-...", "filename": "emails.csv", "filter": "valid",
  "emails": [
    { "email": "john@example.com",  "status": "valid",     "status_text": "Valid" },
    { "email": "info@catchall.com", "status": "catch_all", "status_text": "Catch-all" }
  ],
  "summary": { "total": 500, "valid": 420, "invalid": 55, "catch_all": 20, "domain_invalid": 5, "valid_pct": 84.0 },
  "pagination": { "page": 1, "limit": 100, "total_items": 420, "total_pages": 5, "has_next": true },
  "download_url": "https://bounceguard.net/api/v1/bulk-validate/download/a1b2c3d4-..."
}

Auto Validate & Download EASY

The simplest way to use BounceGuard API — one script does everything automatically: uploads your file, waits for validation to complete, and saves the results to your Downloads folder. No manual steps, no file IDs to track.

Perfect for beginners. Just change your API key and CSV file path — the script handles everything else automatically.

Python — One Script Does Everything

Install Python requests library first (only needed once):

pip3 install requests

Then run this script — change only API_KEY and csv_path:

import requests, time, os

API_KEY     = "YOUR_API_KEY"           # Get from Integration page
BASE        = "https://bounceguard.net/api/v1"
HEADERS     = {"Authorization": f"Bearer {API_KEY}"}
SAVE_FOLDER = os.path.expanduser("~/Downloads")  # Change if needed

def validate_and_download(csv_path):
    # Step 1: Upload file
    print("📤 Uploading file...")
    with open(csv_path, "rb") as f:
        res = requests.post(f"{BASE}/bulk-validate", headers=HEADERS, files={"file": f})
    data = res.json()

    if data.get("status") != "queued":
        print("❌ Upload failed:", data.get("message"))
        return

    file_id = data["file_id"]
    total   = data["total_emails"]
    print(f"✅ Uploaded! {total} emails queued (file_id: {file_id})")

    # Step 2: Auto poll until complete
    print("⏳ Validating emails...")
    while True:
        status = requests.get(
            f"{BASE}/bulk-validate/status/{file_id}", headers=HEADERS
        ).json()

        processed = status.get("processed", 0)
        print(f"   {processed}/{total} processed...")

        if status.get("status") == "complete":
            print(f"✅ Validation complete!")
            print(f"   Valid: {status['results']['valid']}")
            print(f"   Bad:   {status['results']['bad']}")
            print(f"   Catch-all: {status['results']['catch_all']}")
            break

        time.sleep(5)  # Check every 5 seconds

    # Step 3: Auto download
    print("📥 Downloading results...")
    download_url = status.get("download_url")
    if not download_url:
        print("❌ Download URL not ready. Try again in a moment.")
        return

    csv_res  = requests.get(download_url, headers=HEADERS)
    filename = os.path.join(SAVE_FOLDER, f"results_{file_id[:8]}.csv")
    open(filename, "wb").write(csv_res.content)
    print(f"✅ Saved to: {filename}")

# ── Run it ──
validate_and_download("/Users/yourname/Downloads/emails.csv")  # Change this path

What the output looks like

📤 Uploading file...
✅ Uploaded! 500 emails queued (file_id: abc12345-...)
⏳ Validating emails...
   0/500 processed...
   100/500 processed...
   300/500 processed...
   500/500 processed...
✅ Validation complete!
   Valid: 420
   Bad:   55
   Catch-all: 20
📥 Downloading results...
✅ Saved to: /Users/yourname/Downloads/results_abc12345.csv
Output CSV format: The downloaded file contains two columns — Email and Status.
Status values: Valid, Bad, Catch-all, Domain Issue

Single Email — Code Examples

Python

import requests
response = requests.post(
    "https://bounceguard.net/api/v1/validate-email",
    headers={"Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json"},
    json={"email": "username@example.com"}
)
print(response.json())

Node.js

fetch('https://bounceguard.net/api/v1/validate-email', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'username@example.com' })
}).then(r => r.json()).then(console.log);

PHP

<?php
$ch = curl_init('https://bounceguard.net/api/v1/validate-email');
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_POST=>true,
    CURLOPT_HTTPHEADER=>['Authorization: Bearer YOUR_API_KEY','Content-Type: application/json'],
    CURLOPT_POSTFIELDS=>json_encode(['email'=>'username@example.com'])]);
echo curl_exec($ch);

Common Use Cases

Prevent Fake Signups

Validate emails in real-time during registration. Fast responses for seamless UX.

Clean Email Lists at Scale

Upload entire CRM exports as CSV. Bulk API processes thousands in background. Configure webhook — get notified automatically when done.

CRM Integration

Export from HubSpot/Salesforce → validate → re-import only valid emails. Use /history to track all past jobs and /bulk-validate/results/{id}?status=valid to extract clean emails programmatically.

Best Practices

  • For lists over 100 emails — always use Bulk API, not single validation in a loop
  • Use webhooks in production — eliminates polling overhead entirely
  • Store file_id from uploads — results re-downloadable anytime via /history
  • Monitor credits via GET /credits — top up before running out
  • Regenerate API key immediately if you suspect it's compromised

Support

Need help? Reach out at support@bounceguard.net — we respond within 24 hours on business days.

Happy validating! 🚀