Zapier, Make and n8n (REST hooks)
ReadyBuyerFinder supports REST hooks: a tool subscribes a URL to an event, and ReadyBuyerFinder posts to that URL each time the event happens.
Zapier app listing: pending. A Zapier app definition exists, but it is not in Zapier's directory yet. Today, use Webhooks by Zapier → Catch Hook and subscribe its URL as shown below. Make (Custom webhook) and n8n (Webhook node) work the same way.
Events
| Event | When |
|---|---|
lead.created | An agent finds a new lead |
lead.approved | A lead is approved (by you, auto mode or the MCP server) |
reply.received | A reply comes back from OutreachSender or ReachDak, with its label |
Test the connection
curl -H "Authorization: Bearer $KEY" https://readybuyerfinder.com/api/v1/me
Returns { "workspace_id", "name", "plan" }.
Subscribe
curl -X POST https://readybuyerfinder.com/api/v1/hooks \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"target_url":"https://hooks.zapier.com/hooks/catch/123/abc/","event":"lead.approved"}'
Returns 201 { "id", "event", "target_url", "secret" }. Keep the secret: it signs every post. Up to 50 subscriptions per workspace.
List and unsubscribe
curl -H "Authorization: Bearer $KEY" https://readybuyerfinder.com/api/v1/hooks
curl -X DELETE -H "Authorization: Bearer $KEY" https://readybuyerfinder.com/api/v1/hooks/HOOK_ID
DELETE returns 204. If your URL answers 410 Gone, ReadyBuyerFinder removes the subscription by itself.
What we post
{ "type": "lead.approved", "created_at": "2026-10-24T05:30:00.000Z", "data": { "...": "the lead, as in the webhook payload" } }
Headers: Idempotency-Key and X-Surge-Signature: t=<unix>,v1=<hex>, where v1 is the HMAC-SHA256 of t + "." + body, keyed with the subscription's secret. Failed posts are retried like every other delivery.
Verify the signature (Node)
import { createHmac, timingSafeEqual } from "node:crypto";
export function verifyReadyBuyerFinder(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false; // older than 5 minutes
const expected = createHmac("sha256", secret).update(t + "." + rawBody).digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(parts.v1 || "");
return a.length === b.length && timingSafeEqual(a, b);
}
Use the raw request body, exactly as received, not a re-serialised object.