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
| Field | Type | Notes |
|---|---|---|
email | string | Required. Up to 320 characters. |
callback_url | string | Optional. HTTPS only, up to 2,000 characters, must resolve to a public address. |
identifier | string | Optional. 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}, or404if the id isn’t in this workspace.GET /v1/verify?email=returns the most recent result for that address in this workspace, or404.
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=2GET /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>"}.
| HTTP | Code | When |
|---|---|---|
| 400 | bad_request | Malformed request |
| 401 | unauthorized | Missing, unknown or revoked key |
| 402 | insufficient_credits | Not enough credits; the body includes needed and balance |
| 404 | not_found | The resource isn’t in this workspace |
| 409 | conflict | For example, downloading before a file completes |
| 413 | too_large | More than 100 emails, or a file over the limits |
| 422 | invalid | A field failed validation |
| 429 | rate_limited | Over 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.