Skip to main content

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

EndpointReturns
GET /api/v1/meBusiness name, tenant id, timezone — use as a connection test.
GET /api/v1/callsCalls, newest first: numbers, outcome, duration, AI summary.
GET /api/v1/appointmentsBooked jobs: schedule, customer, address, status.
GET /api/v1/leadsMissed-call leads: caller, service needed, urgency, status.
GET/POST/DELETE /api/v1/webhooksManage 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

EventFires when
call.completedA phone call ends (includes outcome, duration, and the AI summary when available).
call.missedA call is missed and the missed-call text-back flow starts a new lead.
appointment.createdA job is booked — by the AI during a call, or from the dashboard.
lead.capturedA 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.