Revenue Defenders API

Programmatic access to your Revenue Defenders data. Available on the Premium tier.

Authentication

All API requests require a Bearer token in the Authorization header. Create API keys from Settings → API Keys in your dashboard.

Request Header

Authorization: Bearer rd_a1b2c3d4_e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6

Keys have the prefix format rd_XXXXXXXX_.... The prefix (first 12 chars) identifies the key. The full key is shown only once at creation time.

Scopes

Each key is issued with specific scopes that control access:

ScopeAccess
leads:readList and retrieve leads
leads:writeCreate leads
evidence:readList evidence items
disputes:readList and retrieve disputes
disputes:writeCreate disputes
customers:readList customers
transactions:readList transactions

Rate Limits

API keys are limited to 60 requests per minute. Exceeding this returns a 429 response. The limit resets every 60 seconds.

429 Response

{ "error": "Rate limit exceeded. Max 60 requests per minute." }

Endpoints

All endpoints are under /api/v1/ and are scoped to your tenant.

GET/api/v1/leadsScope: leads:read

List leads with cursor pagination.

ParamTypeDescription
businessIdstringFilter by business (optional — defaults to first business)
statusstringFilter by lead status (optional)
cursorstringPagination cursor (optional)
limitnumberResults per page, max 200 (default 50)

Response

{
  "items": [
    {
      "id": "clx...",
      "businessId": "clx...",
      "source": "WEB_FORM",
      "status": "NEW",
      "name": "John Doe",
      "email": "john@example.com",
      "phone": "+15551234567",
      "createdAt": "2026-05-25T12:00:00.000Z"
    }
  ],
  "nextCursor": "eyJpZCI6Ii..."
}
GET/api/v1/leads/:idScope: leads:read

Retrieve a single lead by ID.

POST/api/v1/leadsScope: leads:write

Create a new lead. The lead is scored and follow-up plans are generated automatically.

Request Body

{
  "businessId": "clx...",
  "source": "WEB_FORM",
  "name": "Jane Smith",
  "email": "jane@example.com",
  "phone": "+15559876543",
  "message": "I need a roof repair estimate",
  "serviceInterest": "Roof Repair"
}
GET/api/v1/disputesScope: disputes:read

List dispute cases with cursor pagination.

GET/api/v1/disputes/:idScope: disputes:read

Retrieve a single dispute case by ID.

POST/api/v1/disputesScope: disputes:write

Create a new dispute case.

Request Body

{
  "businessId": "clx...",
  "reason": "NOT_AS_DESCRIBED",
  "amountCents": 15000,
  "customerId": "clx...",
  "customerClaim": "Service was not completed as agreed"
}
GET/api/v1/evidenceScope: evidence:read

List evidence items for a business. Supports category filtering and cursor pagination.

GET/api/v1/customersScope: customers:read

List customers for a business.

GET/api/v1/transactionsScope: transactions:read

List transactions for a business.

Webhooks

Configure outbound webhooks from Settings → Webhooks to receive real-time event notifications.

Events

EventTrigger
lead.createdA new lead is created
lead.status_changedA lead status is updated
dispute.createdA new dispute case is opened
package.generatedAn evidence package is generated

Payload Format

Webhook Delivery

POST https://your-server.com/webhooks/rd
Content-Type: application/json
X-RevenueDefenders-Signature: sha256=abc123...
X-RevenueDefenders-Event: lead.created
X-RevenueDefenders-Delivery: clx_delivery_id

{
  "id": "clx...",
  "businessId": "clx...",
  "source": "WEB_FORM",
  "name": "John Doe",
  "createdAt": "2026-05-25T12:00:00.000Z"
}

Signature Verification

Each delivery includes an X-RevenueDefenders-Signature header containing an HMAC-SHA256 hex digest of the raw request body, using your webhook signing secret as the key.

Node.js Verification Example

import crypto from 'crypto';

function verifyWebhookSignature(body: string, signature: string, secret: string): boolean {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return signature === `sha256=${expected}`;
}

// Usage in your handler:
const rawBody = await request.text();
const sig = request.headers.get('X-RevenueDefenders-Signature');
if (!verifyWebhookSignature(rawBody, sig, process.env.WEBHOOK_SECRET)) {
  return new Response('Invalid signature', { status: 401 });
}
const payload = JSON.parse(rawBody);

Retry Policy

Failed deliveries (non-2xx responses or timeouts) are retried with exponential backoff: 5 minutes, 30 minutes, 2 hours, 12 hours, then 24 hours (max 5 attempts).

TypeScript SDK

The official TypeScript SDK wraps all /api/v1/ endpoints with full type safety, automatic retries, and cursor pagination helpers. Zero runtime dependencies — works in Node 18+, Bun, Deno, and edge runtimes.

Install

npm i @revenue-defenders/sdk

Quickstart (Node)

import { createClient } from '@revenue-defenders/sdk';

const rd = createClient({ apiKey: process.env.RD_API_KEY! });

// List leads
const { items } = await rd.leads.list({ businessId: 'biz_123', limit: 50 });

// Iterate all leads
for await (const lead of rd.leads.iterate({ businessId: 'biz_123' })) {
  console.log(lead.name, lead.status);
}

Webhook Verification

import { verifyWebhookSignature } from '@revenue-defenders/sdk';

const rawBody = await request.text();
const sig = request.headers.get('X-RevenueDefenders-Signature')!;
const valid = await verifyWebhookSignature({
  rawBody, signatureHeader: sig, secret: process.env.WEBHOOK_SECRET!,
});

Edge runtime support (Cloudflare Workers, Vercel Edge) works out of the box — the SDK uses Web Crypto for signature verification. Python SDK is on the roadmap.

View SDK source on GitHub

Error Responses

StatusMeaning
401Invalid, revoked, or missing API key
403Insufficient scope or tenant mismatch
404Resource not found
429Rate limit exceeded
500Internal server error