Developers
Connect Reach-book.com to the tools you already use
Find companies and the people who work there, add prospects from your own systems, record sales outcomes, and get a signed webhook the moment a prospect replies or a deal is won. No code needed with Zapier or Make.
- Base URL
- https://reach-book.com/api/v1
- Authentication
- Bearer token (rbk_…)
- Format
- JSON requests and responses
- Rate limit
- 60 requests per minute
Step 1
Create an API token
Tokens belong to one workspace and only carry the abilities you choose. Workspace admins create them.
- 1Open Workspace settings → Automation & API and choose Create token.
- 2Pick only the abilities it needs, such as
prospects:readorleads:search; each endpoint below names the one it requires. Give it an expiry date up to one year away. - 3Copy the token right away. It starts with
rbk_and is shown only once; revoke it there when it is no longer needed.
Step 2
Call the API
Send the token in the Authorization header. Lists return data, links and meta for paging.
Every field, response and error is in the API reference. Step-by-step guides are in the developer docs.
curl https://reach-book.com/api/v1/prospects?search=dental \
-H "Authorization: Bearer rbk_YOUR_TOKEN" \
-H "Accept: application/json"curl -X POST https://reach-book.com/api/v1/prospects \
-H "Authorization: Bearer rbk_YOUR_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"company":"Acme Dental","domain":"acmedental.example","contact_name":"Dana Reyes","contact_email":"[email protected]"}'- GET
/tokenany tokenShow the workspace, abilities and expiry of the token. Works with any valid token. - GET
/prospectsprospects:readList prospects, newest first. Filter with search, tag or group_id; page through with page and per_page (up to 100). - GET
/prospects/{id}prospects:readRead one prospect by its id. - POST
/prospectsprospects:writeCreate a prospect. Only company is required; domain, website, location, contact, notes, tags and owner_id are optional. - PATCH
/prospects/{id}prospects:writeUpdate the fields you send. tags replaces the tags; owner_id moves the prospect to another member. - DELETE
/prospects/{id}prospects:deleteDelete a prospect permanently. - POST
/prospects/{id}/outcomesoutcomes:writeRecord the sales outcome, meeting time and opportunity value for a prospect. - GET
/groupsprospects:readList prospect groups with how many prospects each holds. - POST
/groups/{id}/prospectsprospects:writeAdd up to 500 prospects to a group. - DELETE
/groups/{id}/prospectsprospects:writeRemove prospects from a group without deleting them. - GET
/campaignscampaigns:readList the token creator's campaigns. Filter with status: draft, active, paused or completed. - GET
/campaigns/{id}campaigns:readRead a campaign with its results: enrolled, contacted, emails sent, replies, bounces and opt-outs. - POST
/campaigns/{id}/prospectscampaigns:writeAdd up to 500 prospects to a draft campaign. Launching stays a reviewed step in the app. - POST
/campaigns/{id}/pausecampaigns:writePause an active campaign. - POST
/campaigns/{id}/resumecampaigns:writeResume a paused campaign. - GET
/do-not-contactdnc:readList blocked email addresses and domains. - POST
/do-not-contactdnc:writeBlock up to 500 email addresses or domains. - DELETE
/do-not-contact/{id}dnc:writeRemove an entry. People who unsubscribed stay blocked. - GET
/membersmembers:readList members with their role, for use as a prospect owner_id. - GET
/creditsany tokenShow the credit balance for each service in the current billing period. Works with any valid token. - GET
/lead-search/optionsleads:searchList the values the search filters accept: industries, technologies, sizes, seniorities, departments and more. - POST
/companies/searchleads:searchFind companies by description, industry, size, location, technology, funding, open roles or similarity to a domain. 1 credit per call. - POST
/companies/enrichleads:searchLook up a company by its domain. 1 credit, free if it was looked up in the last 30 days. - POST
/people/searchleads:searchFind people by job title, seniority or department at up to 10 companies. 1 credit per company. - POST
/people/enrichleads:searchLook up a person by their email address: name, job title, company and profiles. 1 credit. - POST
/email-lookupsleads:searchFind an email address from a name and company, a LinkedIn profile, or a department at a company. Runs in the background. - GET
/email-lookups/{id}leads:searchRead an email lookup and the addresses it found once completed. - POST
/email-verificationsleads:searchCheck whether an email address can receive mail. At most 1 credit.
Errors and limits
Errors are JSON with a message. The limit is 60 requests per minute per address.
- 401
- The token is missing, invalid, expired or revoked.
- 403
- The token does not include the ability this endpoint needs.
- 404
- Nothing with that id in this workspace.
- 422
- Validation failed. errors lists the problem for each field.
- 429
- Too many requests. Wait for the seconds in the Retry-After header.
Webhooks
Get events as they happen
Add a webhook in Automation & API and choose its events. Each event is a signed JSON POST to your HTTPS address.
Respond with any 2xx status within 10 seconds. Timeouts, 408, 429 and 5xx responses are retried after 1 minute, 5 minutes, 30 minutes and 2 hours (5 attempts in all). An event can arrive more than once, so use its id to skip duplicates.
The address must use HTTPS on port 443 without a query string; redirects are not followed.
prospect.createdA prospect is added in the app, by import or through the API.
data: prospect_id, company, contact_email
inbox.reply.receivedA prospect replies to an email you sent.
data: prospect_id, company, contact_email
conversation.assignedA conversation is assigned to a teammate or unassigned.
data: prospect_id, assignee_id
prospect.outcome.updatedA sales outcome, meeting or value is recorded for a prospect.
data: prospect_id, outcome, meeting_at, value_minor, currency
opportunity.updatedSent alongside prospect.outcome.updated for CRM-style tools.
data: prospect_id, outcome, meeting_at, value_minor, currency
meeting.bookedA meeting time is set or the outcome becomes Meeting booked.
data: prospect_id, outcome, meeting_at, value_minor, currency
opportunity.wonThe outcome changes to Won.
data: prospect_id, outcome, meeting_at, value_minor, currency
Example event
{
"id": "01JB7Q3M5K8V2X9N4R6T0Y1ZWC",
"event": "prospect.created",
"workspace_id": "01J9T2D6F8H3K5M7N9P1Q3R5S7",
"occurred_at": "2026-10-02T09:30:00+00:00",
"data": {
"prospect_id": "01JB7Q3M2C4E6G8J0L2N4Q6S8U",
"company": "Acme Dental",
"contact_email": "[email protected]"
}
}Headers: Reachbook-Event-ID, Reachbook-Event, Reachbook-Timestamp and Reachbook-Signature.
Security
Verify every webhook
The signature is v1= followed by the hexadecimal HMAC-SHA256 of the timestamp, a dot and the raw body, keyed with the webhook's signing secret (it starts with whk_). Compare in constant time and reject timestamps older than five minutes.
import crypto from 'node:crypto';
// Use the raw body, e.g. express.raw({ type: 'application/json' }).
export function verifyReachbook(rawBody, headers, secret) {
const timestamp = headers['reachbook-timestamp'] ?? '';
const signature = headers['reachbook-signature'] ?? '';
const expected = 'v1=' + crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) < 300;
return fresh
&& signature.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}<?php
$payload = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_REACHBOOK_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_REACHBOOK_SIGNATURE'] ?? '';
$expected = 'v1='.hash_hmac('sha256', $timestamp.'.'.$payload, $secret);
$fresh = abs(time() - (int) $timestamp) < 300;
if (! $fresh || ! hash_equals($expected, $signature)) {
http_response_code(401);
exit;
}
$event = json_decode($payload, true);import hashlib
import hmac
import time
def verify_reachbook(raw_body: bytes, headers, secret: str) -> bool:
timestamp = headers.get("Reachbook-Timestamp", "")
signature = headers.get("Reachbook-Signature", "")
expected = "v1=" + hmac.new(
secret.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256
).hexdigest()
fresh = timestamp.isdigit() and abs(time.time() - int(timestamp)) < 300
return fresh and hmac.compare_digest(expected, signature)No code
Zapier and Make
Both work with their built-in webhook and HTTP modules, so you don't need a dedicated app. Use the same steps for n8n, Pipedream or your own server.
Zapier: start a Zap from a Reach-book.com event
- 1Create a Zap with the trigger Webhooks by Zapier → Catch Raw Hook (or Catch Hook if you don't need to verify signatures) and copy its URL.
- 2In Automation & API, add a webhook with that URL and choose events such as
inbox.reply.received. - 3Cause the event once (for example add a test prospect for
prospect.created), then choose Test trigger in Zapier. - 4Map fields from
datainto your next steps, such as a Slack message or a CRM update.
Zapier: add prospects from another app
- 1Add the action Webhooks by Zapier → POST.
- 2URL
https://reach-book.com/api/v1/prospects, payload type JSON, and data fieldscompany,contact_name,contact_emailmapped from your trigger. - 3Headers
Authorization:Bearer rbk_YOUR_TOKENandAccept:application/json. The token needsprospects:write.
Make: watch events
- 1Start a scenario with Webhooks → Custom webhook, create a webhook and copy its address.
- 2Add that address as a webhook in Automation & API with the events you want.
- 3Choose Redetermine data structure in Make, then cause the event once so Make learns the fields.
Make: call the API
- 1Add HTTP → Make a request with URL
https://reach-book.com/api/v1/prospectsand method POST (or GET to read). - 2Add the headers
Authorization:Bearer rbk_YOUR_TOKENandAccept:application/json. - 3Body type Raw, content type JSON (application/json), and turn on Parse response so later modules can use the prospect's
id.