Skip to content

Developers

Enrichment API

Enrich companies and contacts programmatically. Bearer-authenticated, rate-limited, metered with prepaid credits, and compliance-enforced — opted-out and do-not-contact records never appear in a response.

Authentication

Create a key in Settings → API keys (shown once). Send it as a bearer token on every request. Keys are hashed at rest and can be revoked anytime.

Authorization: Bearer de_live_xxxxxxxxxxxxxxxx

POST /api/v1/enrich

Enrich a company or contact. Live providers apply when your workspace is on a paid plan with provider keys configured; otherwise the response is mock-safe.

curl -X POST https://leadsbite.com/api/v1/enrich \
  -H "Authorization: Bearer $DE_API_KEY" \
  -H "content-type: application/json" \
  -d '{ "type": "company", "input": { "domain": "intercom.com" } }'
{
  "ok": true,
  "data": {
    "jobId": "…",
    "company": { "name": "Intercom", "domain": "intercom.com", "industry": "software" },
    "contacts": [ { "fullName": "…", "title": "…", "email": "…", "grade": "B" } ],
    "contactsSuppressed": 0,
    "grade": "B", "riskClass": "YELLOW", "complianceAllowed": true
  }
}

contactsSuppressed reports how many results were withheld for compliance (opt-out / DNC / restricted source).

POST /api/v1/capture

Enrich a single company by its public domain. Domain only; social / login-walled hosts are rejected.

curl -X POST https://leadsbite.com/api/v1/capture \
  -H "Authorization: Bearer $DE_API_KEY" \
  -H "content-type: application/json" \
  -d '{ "domain": "intercom.com" }'

Limits & credits

Each key is limited to 60 requests/minute (HTTP 429 with Retry-After when exceeded). Successful responses include X-RateLimit-Limit and X-RateLimit-Remaining so you can self-throttle. Every call is metered, and one prepaid credit is debited when a balance is available. Buy credit packs in Billing → API credits.

Webhooks

Subscribe an https endpoint in Settings → Webhooks to receive events (enrichment.completed, export.created, crm_sync.completed). Each delivery is signed with HMAC-SHA256 using your endpoint secret. Verify the X-DataEnrich-Signature-V2 header before trusting the payload: it signs the time of the attempt and the delivery id along with the body, so a stale or replayed request fails. Failed deliveries are retried with backoff — each retry is re-signed with a fresh time — so your handler should be idempotent. The older body-only X-DataEnrich-Signature header is still sent, unchanged, for existing receivers.

// headers: X-DataEnrich-Signature-V2: t=<unix seconds>,v2=<hex>   <- verify this one
//          X-DataEnrich-Delivery:     <delivery id>   (covered by the v2 signature)
//          X-DataEnrich-Signature:    sha256=<hex>    (legacy: body only, still sent)
import crypto from "node:crypto";

const parts = Object.fromEntries(
  String(req.headers["x-dataenrich-signature-v2"] ?? "")
    .split(",")
    .map((kv) => kv.split("=", 2)),
);
const t = Number(parts.t);
const deliveryId = String(req.headers["x-dataenrich-delivery"] ?? "");

const expected = crypto
  .createHmac("sha256", endpointSecret)
  .update(t + "." + deliveryId + "." + rawRequestBody) // the RAW body, before JSON parsing
  .digest("hex");

// Compare lengths first: timingSafeEqual THROWS on a mismatch, so a malformed
// header would crash the handler instead of being rejected.
const sig = Buffer.from(parts.v2 ?? "");
const exp = Buffer.from(expected);
if (sig.length !== exp.length || !crypto.timingSafeEqual(sig, exp)) return reject();

// t is when THIS attempt was sent (a retry is re-signed), so a 5-minute window
// accepts every retry and rejects a replayed capture. Do not judge freshness on
// the body's createdAt: that is when the EVENT happened, and a retry keeps it.
if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > 5 * 60) return reject();

// The delivery id is signed and retries reuse it: dedupe on it to stay idempotent.
if (await alreadyProcessed(deliveryId)) return ok();

This is also the substrate for Zapier / Make / n8n — point a webhook at your automation's catch hook.

Errors

401 invalid_api_key      missing / invalid / revoked / expired key
403 insufficient_scope   the key lacks the scope this route needs
422 validation_error     bad body, or Idempotency-Key reused with a different request
429 rate_limited         too many requests (see Retry-After)
402 arrears_cap_reached  prepaid credits exhausted past the daily arrears limit

Scopes & idempotency

Keys are least-privilege and can carry an expiry. Grant only what an integration needs: enrich:read (verify, score), enrich:write (enrich, extract, capture), export:write (build exports).

Send an Idempotency-Key header on credit-charging calls — a retry replays the original response without re-charging, and comes back with Idempotency-Replayed: true.

curl -X POST https://leadsbite.com/api/v1/enrich \
  -H "Authorization: Bearer de_live_..." \
  -H "Idempotency-Key: order-4417" \
  -H "Content-Type: application/json" \
  -d '{"type":"company","input":{"domain":"acme.com"}}'

OpenAPI 3.1

The full contract is machine-readable — generate a typed client, import it into Postman/Insomnia, or hand it to an AI agent.

# The spec
https://leadsbite.com/api/v1/openapi.json

# Generate a typed TypeScript client
npx openapi-typescript https://leadsbite.com/api/v1/openapi.json -o leadsbite.d.ts

View the raw spec →

MCP connector (for AI agents)

The same capabilities are exposed to AI agents over the Model Context Protocol — so an assistant can enrich, verify, score, discover, and build compliance-safe exports on your behalf. Discovery returns labelled sample data only; no live discovery source is connected. Streamable HTTP with a bundled OAuth 2.1 authorization server (dynamic client registration, PKCE), scope-gated per tool.

Endpoint   https://leadsbite.com/api/mcp
Transport  Streamable HTTP (spec 2025-11-25)
Auth       OAuth 2.1 (DCR + PKCE) — or a de_live_ key as a static bearer
Tools      enrich_company · enrich_contact · discover_companies
           verify_email · score_trust · build_export

Tools are registered only when the caller's scopes cover them, and workspace RBAC still applies — a read-only member can never export through an agent.

Compliance guarantee

Every response runs through the same eligibility filter as exports and CRM sync. Records that are opted-out, on a do-not-contact list, blocked, or from a restricted source are removed before the API returns — so a data-subject request honored in the app is honored in the API on the very next call.

Ready to build? Create a free workspace and issue your first key in under a minute.