Programmatic access to your Revenue Defenders data. Available on the Premium tier.
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_e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6Keys have the prefix format rd_XXXXXXXX_.... The prefix (first 12 chars) identifies the key. The full key is shown only once at creation time.
Each key is issued with specific scopes that control access:
| Scope | Access |
|---|---|
leads:read | List and retrieve leads |
leads:write | Create leads |
evidence:read | List evidence items |
disputes:read | List and retrieve disputes |
disputes:write | Create disputes |
customers:read | List customers |
transactions:read | List transactions |
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." }All endpoints are under /api/v1/ and are scoped to your tenant.
/api/v1/leadsScope: leads:readList leads with cursor pagination.
| Param | Type | Description |
|---|---|---|
| businessId | string | Filter by business (optional — defaults to first business) |
| status | string | Filter by lead status (optional) |
| cursor | string | Pagination cursor (optional) |
| limit | number | Results 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..."
}/api/v1/leads/:idScope: leads:readRetrieve a single lead by ID.
/api/v1/leadsScope: leads:writeCreate 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"
}/api/v1/disputesScope: disputes:readList dispute cases with cursor pagination.
/api/v1/disputes/:idScope: disputes:readRetrieve a single dispute case by ID.
/api/v1/disputesScope: disputes:writeCreate a new dispute case.
Request Body
{
"businessId": "clx...",
"reason": "NOT_AS_DESCRIBED",
"amountCents": 15000,
"customerId": "clx...",
"customerClaim": "Service was not completed as agreed"
}/api/v1/evidenceScope: evidence:readList evidence items for a business. Supports category filtering and cursor pagination.
/api/v1/customersScope: customers:readList customers for a business.
/api/v1/transactionsScope: transactions:readList transactions for a business.
Configure outbound webhooks from Settings → Webhooks to receive real-time event notifications.
| Event | Trigger |
|---|---|
lead.created | A new lead is created |
lead.status_changed | A lead status is updated |
dispute.created | A new dispute case is opened |
package.generated | An evidence package is generated |
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"
}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);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).
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.
npm i @revenue-defenders/sdkimport { 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);
}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.
| Status | Meaning |
|---|---|
| 401 | Invalid, revoked, or missing API key |
| 403 | Insufficient scope or tenant mismatch |
| 404 | Resource not found |
| 429 | Rate limit exceeded |
| 500 | Internal server error |