bouncyboobs
How it worksPricingIntegrations

Docs

Verify emails from your backend.

One endpoint covers the full pipeline. Authenticate with an API key from the dashboard. Each verification counts against your monthly plan quota.

Base URL

https://bouncyboobs.dev

Authentication

Pass your key in the Authorization header. Keys start with bb_live_ and are shown in plaintext exactly once when created.

Authorization: Bearer bb_live_xxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Revoked keys return 401. Unknown keys return 401. Valid keys on a lapsed subscription return 402.

POST /api/verify

Run one email through the full pipeline and get a verdict back. Send a list to verify many at once (up to 1,000 per request).

curl https://bouncyboobs.dev/api/verify \
  -H "Authorization: Bearer $BOUNCYBOOBS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"emails": ["alice@example.com"]}'

Response

{
  "results": [
    {
      "email": "alice@example.com",
      "verdict": "deliverable",
      "reason": "Mailbox exists and domain is healthy",
      "syntax_ok": true,
      "dns_ok": true,
      "disposable": false,
      "role_based": false,
      "smtp_ok": true,
      "suggestion": null,
      "confidence": 95,
      "insights": {
        "spf_pass": true,
        "dmarc_policy": "reject",
        "mx_provider": "Google Workspace"
      },
      "checked_at": "2026-04-16T19:12:04Z"
    }
  ],
  "summary": {
    "total": 1,
    "deliverable": 1,
    "undeliverable": 0,
    "risky": 0,
    "unknown": 0
  },
  "quota": {
    "thresholdsCrossed": { "eighty": false, "hundred": false }
  }
}

Verdicts

  • deliverable — active mailbox on a healthy domain.
  • risky — role address, catch-all, or provider with mixed deliverability.
  • undeliverable — typo, dead domain, disposable provider, or the mailbox does not exist.
  • unknown — the receiving server refused to confirm (greylisting, rate-limited, transient error).

Confidence score

Every result includes a confidence integer 0–100. Higher = safer to send. The score is anchored on the verdict and tuned by secondary signals (role-based, typo suggestion, anti-enumeration provider). Typical bands:

  • deliverable — 90–95
  • risky — 35–55 (role pulls up, typo pulls down)
  • unknown — 40–50
  • undeliverable — 0–15

Most CRMs wire this to a threshold: e.g. auto-send above 70, flag for review 40–70, drop below 40.

Domain insights

Every result also includes an insights object with domain-level reputation signals. Useful for risk-scoring above the mailbox level — a domain with no SPF + no DMARC is more likely to be spoofed or shut down than one with both configured.

  • spf_pass — true when the domain has a v=spf1 TXT record, false when missing, null when the lookup failed.
  • dmarc_policy — "none", "quarantine", or "reject" if the domain publishes a DMARC record; null if no DMARC is configured.
  • mx_provider — Recognised MX host provider when we can match it (Google Workspace, Microsoft 365, Proofpoint, Mimecast, SendGrid, etc.); null otherwise.

Status codes

  • 200 — success. Inspect summary and results.
  • 400 — malformed body or invalid email format.
  • 401 — missing, unknown, or revoked API key.
  • 402 — no active subscription, or monthly quota exhausted. Response body includes remaining and monthlyQuota.
  • 413 — too many emails (cap is 1,000 per request).
  • 429 — per-IP rate-limit. Retry after Retry-After seconds.

Webhooks

When a bulk job submitted via the dashboard finishes, we POST a signed event to your configured URL.

POST <your-url>
Content-Type: application/json
x-bouncyboobs-event: bulk_job.completed
x-bouncyboobs-signature: sha256=<hex>

{
  "type": "bulk_job.completed",
  "created_at": "2026-04-16T19:14:22Z",
  "data": {
    "job_id": "a77faa30-7046-4275-a09e-6e19f8827410",
    "label": "Q2 newsletter",
    "total": 4217,
    "deliverable": 3984,
    "undeliverable": 122,
    "risky": 71,
    "unknown": 40
  }
}

Verifying the signature (Node.js)

import crypto from "node:crypto";

export function verify(req, rawBody, secret) {
  const sig = req.headers["x-bouncyboobs-signature"] ?? "";
  const expected = "sha256=" + crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(sig),
    Buffer.from(expected),
  );
}

First attempt fires immediately with a 5-second timeout. If your endpoint returns non-2xx or times out, we retry on an exponential schedule (30s, 2m, 10m, 30m, 2h, 6h) — up to 6 attempts total before giving up. The parallel email notification always fires regardless.

Result caching

To save you money on repeat addresses, single-email verifications are cached per account for 7 days. A cached hit returns the original result in full and skips the quota debit — verifying the same address twice in the same week costs one credit, not two.

{
  "results": [{ "email": "lena@acme.co", "verdict": "deliverable", ... }],
  "summary": { "total": 1, "deliverable": 1, ... },
  "cached": true
}

The cached field is only present (and always true) when the response came from cache. Bulk jobs do not currently share this cache. Identical requests fired in the same millisecond (before either has written to the cache) will both hit the real verification path — this is a known cold-start race; debounce at your end if it matters.

Rate limits & quotas

  • Per-IP: 30 requests per hour for anonymous, 600 per hour for authenticated.
  • Per-request: 1,000 emails (single-request cap). Larger lists — use the dashboard bulk uploader.
  • Quota: every verification counts as 1, regardless of verdict. Usage resets on your billing period start.

Need something missing?

Email hello@bouncyboobs.dev.

bouncyboobs

Email verification built for deliverability — cleaner lists, fewer hard bounces, better inbox placement.

Permitted bounce categories — castles, rubber balls, misplaced optimism. Email campaigns remain excluded.

ProductHow it worksPricingDashboardHistorySupport
LegalTermsPrivacyCookies
© 2026 bouncyboobsStrictly necessary cookies only.