Valid leads can go straight to your Smartlead or Instantly campaign.See integrations

API reference

Version 1. Base URL https://api.bouncebrake.com. Requests and responses are JSON with snake_case fields, timestamps are ISO-8601 UTC.

Authentication

Create a key in the dashboard under Settings → API keys (workspace admins). Keys look like bb_live_… and are shown once; we store only a hash. Send the key in the x-api-key header on every request.

A key belongs to one workspace. Everything it creates lives in that workspace, and credits come from the workspace’s account. Revoking a key in the dashboard takes effect immediately; a key stops working if its workspace is archived.

curl https://api.bouncebrake.com/v1/credits -H "x-api-key: $BOUNCEBRAKE_KEY"

Statuses and credits

  • pending: being verified. Most addresses start here; most lists finish within 24–48 hours.
  • valid: safe to send.
  • invalid: would bounce, or not a well-formed address.
  • risky: reserved for results from a connected pre-verifier.
  • unknown: no verdict within 7 days. Credits for these are returned to the balance when a file completes.

Each well-formed address costs 1 credit. Malformed addresses are returned as invalid immediately and cost nothing.

Verify an address

POST /v1/verify

FieldTypeNotes
emailstringRequired. Up to 320 characters.
callback_urlstringOptional. HTTPS only, up to 2,000 characters, must resolve to a public address.
identifierstringOptional. Your own reference, up to 300 characters, echoed back in results and callbacks.
{"id": 90211, "email": "maria.alvarez@harborline.co", "status": "pending", "identifier": "crm-48121"}

Returns 402 when the account is out of credits and 422 for a callback URL that isn’t HTTPS or points at a private host.

Verify in bulk

POST /v1/verify/bulk with {"emails": [...], "callback_url"?, "identifier"?}. Send 1 to 100 addresses; duplicates in one request are collapsed and charged once. More than 100 returns 413. The response is an array of {id, email, status, identifier}.

Look up results

  • GET /v1/verify/{id} returns {id, email, status, identifier, checked_at}, or 404 if the id isn’t in this workspace.
  • GET /v1/verify?email= returns the most recent result for that address in this workspace, or 404.

Files

POST /v1/files takes multipart/form-data:

  • file: a CSV up to 50 MB and 100,000 unique addresses.
  • email_column: 0-based index of the email column (default 0).
  • has_header: whether the first row is a header (default true).

The file is counted, charged and started in one step. Returns 201 with {id, file_name, status, unique_emails}, or 402 / 413.

curl https://api.bouncebrake.com/v1/files -H "x-api-key: $BOUNCEBRAKE_KEY" \
  -F file=@catch-all-leads.csv -F email_column=2

GET /v1/files/{id} returns progress: {id, file_name, status, total_rows, unique_emails, valid, invalid, risky, unknown, pending, completed_at}.

GET /v1/files/{id}/download?kind=all|valid|invalid returns {url}, a signed link valid for 60 seconds. It returns 409 until the file is completed. Result CSVs keep your original columns and add a BounceBrakeStatus column after the email.

Credits

GET /v1/credits returns {"credits": 4810}, the account balance shared by all workspaces.

Callbacks

When an address submitted with a callback_url reaches a final status, we POST to it. Final statuses are collected every 15 minutes.

  • Body: {"email", "status", "identifier"} as JSON, or form-encoded if you set the key’s callback format to form.
  • Signature: X-BounceBrake-Signature: sha256=<hex>, HMAC-SHA256 over the raw body. The key is the lowercase hex SHA-256 of your API key.
  • Delivery: HTTPS with a verified certificate, 10-second timeout, redirects not followed. Respond with any 2xx.
  • Retries: after 15, 30, 60 and 120 minutes, so up to 5 attempts in total.
// Node.js
import { createHash, createHmac, timingSafeEqual } from "node:crypto"

export function verified(rawBody, header, apiKey) {
  const key = createHash("sha256").update(apiKey).digest("hex")
  const want = "sha256=" + createHmac("sha256", key).update(rawBody).digest("hex")
  return want.length === header.length && timingSafeEqual(Buffer.from(want), Buffer.from(header))
}

Errors

Errors return {"error": "<message>", "code": "<code>"}.

HTTPCodeWhen
400bad_requestMalformed request
401unauthorizedMissing, unknown or revoked key
402insufficient_creditsNot enough credits; the body includes needed and balance
404not_foundThe resource isn’t in this workspace
409conflictFor example, downloading before a file completes
413too_largeMore than 100 emails, or a file over the limits
422invalidA field failed validation
429rate_limitedOver 10 requests per second

Limits

  • 10 requests per second per key.
  • 100 addresses per bulk call.
  • 50 MB and 100,000 unique addresses per file.

Questions about the API: support@bouncebrake.com.