Developers
Callbook API
Pull your calls, appointments, and leads into any system — or receive them in real time via signed webhooks. This is the same API our Zapier integration is built on.
Authentication
Create an API key in your Callbook dashboard under Settings → Developers. Keys are shown once at creation and can be revoked at any time. Pass the key as a bearer token on every request:
curl https://getcallbook.com/api/v1/me \
-H "Authorization: Bearer cbk_live_..."Rate limit: 120 requests per minute per key. All endpoints return JSON; errors are{ "error": "message" }with a conventional HTTP status.
REST endpoints
| Endpoint | Returns |
|---|---|
| GET /api/v1/me | Business name, tenant id, timezone — use as a connection test. |
| GET /api/v1/calls | Calls, newest first: numbers, outcome, duration, AI summary. |
| GET /api/v1/appointments | Booked jobs: schedule, customer, address, status. |
| GET /api/v1/leads | Missed-call leads: caller, service needed, urgency, status. |
| GET/POST/DELETE /api/v1/webhooks | Manage webhook subscriptions (see below). |
List endpoints support ?limit= (max 100) and cursor pagination — pass the previous response's nextCursor as ?cursor=.
Webhooks
Subscribe an HTTPS endpoint to events and Callbook POSTs each event as it happens. Deliveries are retried up to 5 times with exponential backoff; an endpoint that fails 20 consecutive times is disabled automatically (re-enable it from the dashboard).
curl -X POST https://getcallbook.com/api/v1/webhooks \
-H "Authorization: Bearer cbk_live_..." \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/hooks/callbook",
"events": ["call.completed", "appointment.created"]}'
# → { "id": "...", "secret": "whsec_..." } (secret is shown once — store it)Events
| Event | Fires when |
|---|---|
| call.completed | A phone call ends (includes outcome, duration, and the AI summary when available). |
| call.missed | A call is missed and the missed-call text-back flow starts a new lead. |
| appointment.created | A job is booked — by the AI during a call, or from the dashboard. |
| lead.captured | A lead becomes qualified (name/service captured, or a booking). |
Payload envelope
{
"id": "evt_appointment_created_cmxyz...", // stable per event — safe to dedupe on
"type": "appointment.created",
"createdAt": "2026-07-26T14:03:07.412Z",
"data": {
"jobId": "cmxyz...",
"title": "Water heater replacement",
"scheduledDate": "2026-07-28",
"scheduledStartTime": "09:00",
"customerName": "Jane Doe",
"customerPhone": "+19045551234",
"source": "ai-call"
}
}Verifying signatures
Every delivery is signed with your endpoint's secret using the industry-standard Svix scheme, via the webhook-id, webhook-timestamp, and webhook-signature headers — any Svix-compatible library verifies it, or do it manually:
import { createHmac, timingSafeEqual } from "crypto";
function verify(req, rawBody, secret) {
const id = req.headers["webhook-id"];
const ts = req.headers["webhook-timestamp"];
const expected = createHmac("sha256", secret)
.update(`${id}.${ts}.${rawBody}`)
.digest("base64");
return req.headers["webhook-signature"]
.split(" ")
.some((part) => {
const [version, sig] = part.split(",");
if (version !== "v1" || !sig) return false;
const a = Buffer.from(sig), b = Buffer.from(expected);
return a.length === b.length && timingSafeEqual(a, b);
});
}Deliveries are at-least-once: rare duplicates carry the same event id, so treat it as an idempotency key. Reject timestamps older than 5 minutes to prevent replays.
Questions?
Email support@getcallbook.com — we answer developer questions directly. No Callbook account yet? Get started.
