Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BounceZero — Node.js

Real-time & bulk email verification with a 5-stage intelligence pipeline

npm version node License: MIT Docs Status

Documentation · Dashboard · API Status · Support


The official Node.js client for the BounceZero email verification API. Zero dependencies, Node 18+, with TypeScript definitions included and a small, predictable, Promise-based surface built for production — from a signup form that validates one address in real time to a nightly job that cleans millions.

const BounceZero = require("bouncezero");

const client = new BounceZero("bz_live_...");
const result = await client.verify("someone@example.com");

console.log(result.classification, result.score);   // → verified 98

Why BounceZero

Every address is scored across 40+ signals through a five-stage pipeline — syntax, DNS/MX, SMTP mailbox probing, disposable & role detection, and a Bayesian + ML confidence model — so you catch invalid, risky, and low-value addresses before they cost you deliverability.

  • Real-time single verification in ~500 ms–2 s, or async bulk for large lists
  • 🎯 Six clear verdicts (verified / invalid / catch_all / disposable / risky / unknown) plus threat flags
  • 🔁 Idempotent bulk submits — a network retry can never double-charge you
  • 🧪 Sandbox keys to build & test without spending credits
  • 🔒 Signed webhooks with a one-line verifier
  • 📦 Zero dependencies, typed errors, automatic retries with backoff, first-class TypeScript

Installation

npm install bouncezero

Requires Node.js 18+ (uses the built-in fetch). No transitive dependencies.

Authentication

Grab your API key from the dashboard and pass it to the client. Keep live keys server-side — never ship them in client code.

const BounceZero = require("bouncezero");
// or: import BounceZero from "bouncezero";

const client = new BounceZero("bz_live_...");

Quick start

// 1 — Verify a single address
const result = await client.verify("jane@example.com");
if (result.classification === "verified") addToMailingList(result.email);

// 2 — Batch up to 100 synchronously
const report = await client.verifyBatch(["a@example.com", "b@example.com"]);
console.log(report.summary);           // { verified: 1, invalid: 1, ... }

// 3 — Async bulk for large lists (idempotency-safe)
const job   = await client.verifyBulk(emails, { idempotencyKey: "import-2026-07-11" });
const final = await client.waitForBulk(job.job_id);
const csv   = await client.bulkDownload(job.job_id);

Verification result

verify() resolves to an object with the full signal breakdown. The fields you'll use most:

Field Type Description
email string The address that was checked
classification string One of the six verdicts below
score number Confidence 0–100
is_deliverable boolean | null true/false, or null when inconclusive
risk_level string low · medium · high
recommendation string Human-readable guidance

Classifications

Verdict Meaning Safe to send?
verified Mailbox exists and accepts mail
invalid Mailbox does not exist — will hard bounce
catch_all Domain accepts everything; mailbox unconfirmable ⚠️
disposable Temporary/throwaway provider ⚠️
risky Concrete negative signals (full mailbox, poor reputation…) ⚠️
unknown Mail server blocked/greylisted the probe — retry later

Two rare threat verdicts — complainer and spamtrap — may also appear; remove those addresses immediately (details in threat_type).

API reference

Method Description
verify(email, depth = "standard") Verify one address. depth: standard · deep · ultra
verifyBatch(emails) Verify up to 100 addresses synchronously
verifyBulk(emails, { idempotencyKey }) Submit an async bulk job
bulkStatus(jobId) Poll job progress
bulkResults(jobId, { limit, offset }) Paginated results
bulkDownload(jobId) Download completed results as a CSV string
waitForBulk(jobId, { pollInterval, timeout }) Await until a job finishes
domain(domain) Domain-level intelligence (MX, provider, catch-all…)
analyzeList(emails) Free list-quality analysis — no verification, no credits
BounceZero.verifyWebhookSignature(body, header, secret) Validate a webhook signature

Bulk verification

Bulk jobs run asynchronously. Submit, then either await or poll:

const job = await client.verifyBulk(emails, { idempotencyKey: "crm-sync-42" });

// Option A — await until done
const final = await client.waitForBulk(job.job_id, { pollInterval: 10000 });

// Option B — poll yourself
const status = await client.bulkStatus(job.job_id);
console.log(`${status.completed} / ${status.total}`);

// Fetch results (paginated) or download the full CSV
const page = await client.bulkResults(job.job_id, { limit: 1000, offset: 0 });
const csv  = await client.bulkDownload(job.job_id);

Idempotency — pass an idempotencyKey (any unique string). Replaying the same key returns the original job instead of creating and charging for a duplicate, so retries after a timeout are always safe.

Error handling

Every failure throws a subclass of BounceZeroError, each carrying .statusCode and .payload:

const {
  BounceZero, AuthenticationError, InsufficientCreditsError,
  RateLimitError, NotFoundError, BounceZeroError,
} = require("bouncezero");

try {
  const result = await client.verify("someone@example.com");
} catch (e) {
  if (e instanceof InsufficientCreditsError) topUpCredits();
  else if (e instanceof RateLimitError) await sleep((e.retryAfter || 60) * 1000);
  else if (e instanceof AuthenticationError) alert("Check your API key");
  else throw e;
}
Error HTTP When
AuthenticationError 401 / 403 Missing, invalid, disabled, or IP-restricted key
InsufficientCreditsError 402 Not enough credits
NotFoundError 404 Unknown job or resource
RateLimitError 429 Plan rate limit exceeded (see .retryAfter)
BounceZeroError other Any other API/transport error

Requests automatically retry on 429 and 5xx with exponential backoff (honoring Retry-After); tune with maxRetries.

Rate limits

Limits are per API key, per minute, by plan. Responses include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset.

Plan Requests / min
Free 30
Starter · Growth 100
Professional · Business · Scale 300
Ultimate · Enterprise 1000

Sandbox / testing

Create a sandbox key (bz_test_ prefix) in the dashboard. It returns deterministic mock results, never spends credits, and never performs a real probe — the local part of the address picks the verdict:

const sandbox = new BounceZero("bz_test_...");
(await sandbox.verify("verified@example.com")).classification;  // → "verified"
(await sandbox.verify("risky@example.com")).classification;     // → "risky"

Supported on verify(). See the sandbox docs.

Webhooks

BounceZero signs every webhook with X-BounceZero-Signature (HMAC-SHA256). Always verify against the raw request body before parsing:

const BounceZero = require("bouncezero");

app.post("/webhooks/bouncezero", express.raw({ type: "application/json" }), (req, res) => {
  const ok = BounceZero.verifyWebhookSignature(
    req.body,                                  // raw Buffer
    req.headers["x-bouncezero-signature"],
    signingSecret,                             // from Dashboard → Webhooks
  );
  if (!ok) return res.status(400).end();
  const event = JSON.parse(req.body);
  // ...
  res.status(200).end();
});

Configuration

const client = new BounceZero("bz_live_...", {
  baseUrl: "https://app.bouncezero.io",  // override for a dedicated region
  timeout: 60000,                        // milliseconds
  maxRetries: 2,                         // retries on 429 / 5xx
});

TypeScript

Types ship with the package — no @types install needed.

import BounceZero, { VerifyResult, RateLimitError } from "bouncezero";

const client = new BounceZero(process.env.BOUNCEZERO_API_KEY!);
const result: VerifyResult = await client.verify("someone@example.com");

Support

License

MIT © BounceZero Ltd

About

Official Node.js client for the BounceZero email verification API

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages