Docs

The endpoints you actually call.

One key, two endpoints: verify an address, or verify a list.

01Auth

One key, sent as a bearer token.

Every request carries your API key. Keys are created in the dashboard and carry the verify and bulk scopes.

Authorization: Bearer bi_live_…
Content-Type: application/json

Keys are shown once at creation and never again; we store only the prefix. If one leaks, revoke it and mint another; the rest keep working.

02Single / real time

Verify one address.

A synchronous check: syntax, DNS, MX, then an SMTP conversation with the receiving server. One credit.

POSThttps://api.bounceintel.com/v1/check_email

Verify an address

Returns the full scored report. Median latency is under 500 ms; allow 30 s for a slow receiving server.

verify.sh
curl -sS -X POST 'https://api.bounceintel.com/v1/check_email' \
  -H "Authorization: Bearer $BOUNCEINTEL_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "[email protected]"
}'
Response200
{
  "input": "[email protected]",
  "is_reachable": "safe",
  "provider": "google_workspace",
  "provider_confidence": "high",
  "score": {
    "score": 100,
    "category": "valid",
    "sub_reason": "deliverable",
    "safe_to_send": true,
    "confidence": 95,
    "confidence_level": "high",
    "reason_codes": ["provider_reputation"],
    "signals": {
      "valid_syntax": true,
      "has_mx_records": true,
      "smtp_can_connect": true,
      "smtp_is_deliverable": true,
      "smtp_is_catch_all": false
    }
  },
  "syntax": { "username": "ada", "domain": "stripe.com", "is_valid_syntax": true },
  "mx": { "accepts_mail": true, "records": ["aspmx.l.google.com."] },
  "smtp": {
    "can_connect_smtp": true,
    "is_deliverable": true,
    "is_catch_all": false,
    "has_full_inbox": false,
    "is_disabled": false
  },
  "misc": { "is_disposable": false, "is_role_account": false, "is_b2c": false },
  "bounce_risk": { "score": 8, "category": "low", "action": "send", "confidence": 0.71 }
}
mx, smtp and misc are unions: each is either its detail object or an error object for a stage that could not complete. Narrow before reading.

03Bulk / asynchronous

Verify a list.

Submit the whole list in one request, poll for progress, then page through the results. One credit per address, charged at submission.

POSThttps://api.bounceintel.com/v1/bulk

Submit a list

Send every address as a JSON array. The response is a job id; verification runs in the background. The playground also accepts a CSV or TXT: it reads the file, then submits the same JSON.

bulk.sh
curl -sS -X POST 'https://api.bounceintel.com/v1/bulk' \
  -H "Authorization: Bearer $BOUNCEINTEL_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "input": [
    "[email protected]",
    "[email protected]",
    "[email protected]"
  ]
}'
Response200
{
  "job_id": 8
}
Credits are charged for the whole batch at submission, atomically, so two concurrent jobs cannot both spend the same balance. If the batch exceeds your remaining credits the whole request is refused; nothing is partially charged. Drop a .csv or .txt in the playground below; the API itself still takes a JSON input array.
GEThttps://api.bounceintel.com/v1/bulk/{job_id}

Check progress

Poll while the job runs. finished_at stays null until every address has been processed. job_status is Running or Completed.

status.sh
curl -sS -X GET 'https://api.bounceintel.com/v1/bulk/{job_id}' \
  -H "Authorization: Bearer $BOUNCEINTEL_KEY" \
  -H "Accept: application/json"
Response200
{
  "job_id": 8,
  "created_at": "2026-09-02T15:16:15.447365Z",
  "finished_at": null,
  "total_records": 4,
  "total_processed": 2,
  "summary": {
    "total_safe": 1,
    "total_risky": 0,
    "total_invalid": 1,
    "total_unknown": 0
  },
  "job_status": "Running"
}
Poll every few seconds, not in a tight loop. The summary counts are live and update as the job progresses.
GEThttps://api.bounceintel.com/v1/bulk/{job_id}/results?format=json&limit=1000&offset=0

Fetch results

Page through the finished results. Each row is the same shape a single check returns.

results.sh
curl -sS -X GET 'https://api.bounceintel.com/v1/bulk/{job_id}/results?format=json&limit=1000&offset=0' \
  -H "Authorization: Bearer $BOUNCEINTEL_KEY" \
  -H "Accept: application/json"
Response200
{
  "results": [
    {
      "input": "[email protected]",
      "is_reachable": "safe",
      "provider": "google_workspace",
      "score": {
        "score": 100,
        "category": "valid",
        "safe_to_send": true,
        "sub_reason": "deliverable",
        "reason_codes": ["provider_reputation"]
      },
      "syntax": { "username": "ada", "domain": "stripe.com", "is_valid_syntax": true },
      "mx": { "accepts_mail": true, "records": ["aspmx.l.google.com."] },
      "smtp": { "can_connect_smtp": true, "is_deliverable": true, "is_catch_all": false },
      "misc": { "is_disposable": false, "is_role_account": false },
      "bounce_risk": { "score": 8, "category": "low", "action": "send" }
    }
  ]
}
limit defaults to 50 for JSON. Pass it explicitly, up to 1000, and page with offset. Use format=csv to stream the whole set as a file instead.

04AI assistants

Verify from your AI assistant.

BounceIntel runs an MCP server at https://api.bounceintel.com/mcp. Connect Claude Code, Cursor, VS Code or any client that speaks MCP over HTTP, and the assistant can check addresses and lists for you with the same API key and the same credits.

terminal
claude mcp add --transport http bounceintel https://api.bounceintel.com/mcp \
  --header "Authorization: Bearer $BOUNCEINTEL_KEY"

Send your API key as a bearer token, exactly as you would to the REST API. The snippets read it from BOUNCEINTEL_KEY, so the key stays out of files you might commit.

ToolKey scopeWhat it does
verify_emailverifyChecks one address and returns the verdict, score and reason. One credit.
verify_email_listbulkStarts a bulk job for a list and returns its job id. One credit per unique address.
get_bulk_jobbulkReports a job's progress and how many addresses have each verdict. No credits.
get_bulk_resultsbulkReturns a finished job's verdicts a page at a time, filtered by verdict if you want. No credits.
get_accountany keyShows the plan, the credits left and when they reset. No credits.

Bulk jobs run in the background, so the assistant starts the job, checks on it, then reads the results. Tools a key is not allowed to use are hidden from the assistant.

05Errors

What can come back.

Every failure is a JSON body with an error field. These are the ones worth branching on.

StatusErrorWhat to do
400invalid_requestThe body was malformed or the address was unusable. Fix and resend.
401unauthorizedThe key is missing, wrong or revoked.
403forbiddenThe key is valid but lacks the scope for this endpoint.
429rate_limitedToo many requests. Back off and retry.
429quota_exceededOut of credits. Buying more is the only way forward; retrying will not help.
503unavailableWe could not establish your quota. Transient: retry shortly.

06Playground

Try it with your own key.

Runs a real verification against your account and spends credits. Single uses one credit; bulk uses one per address, charged when the job is submitted.

Paste your own API key to try it. The key is sent to our website backend, used once, and not stored. Guest checks do not use your key.

Base URL: https://api.bounceintel.com

POST https://api.bounceintel.com/v1/check_email

verify.sh
curl -sS -X POST 'https://api.bounceintel.com/v1/check_email' \
  -H "Authorization: Bearer $BOUNCEINTEL_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "[email protected]"
}'

Copied snippets use $BOUNCEINTEL_KEY, never the key you typed.