Docs · API quickstart

API quickstart

Call Cadence from your own backend with an organization key, or from the browser with the keyless public surface. Times are UTC ISO-8601 instants — render them in the customer's timezone.

Base URL & auth

Base URL

https://cadence.abhix-ai.com/api/v1

Auth header

Authorization: Bearer ck_…

Get a key in the dashboard under Settings → API keys (sign up first if needed). Cadence stores only a hash, so the key is shown once at creation. Keep it server-side — never embed it in a browser or the booking widget.

Keep your key on the server

The ck_… key can read and write everything in your org. Put it in a backend environment variable and proxy requests through your own route handlers, as in the example below. For browser apps, use the public surface instead.

List services

Every booking starts with a service id. List the active services for your org:

Request

bash
curl https://cadence.abhix-ai.com/api/v1/services \
  -H "Authorization: Bearer ck_live_…"

Then fetch open slots for one (practitioner_id is optional — omit it for "any available"):

Availability

bash
curl "https://cadence.abhix-ai.com/api/v1/availability?service_id=svc_123" \
  -H "Authorization: Bearer ck_live_…"

Create a booking

Post a booking against an open slot. Omit practitioner_id and Cadence picks a free, least-loaded practitioner. Send an Idempotency-Key header so retries are safe — a replay returns the existing booking with 200.

Request

bash
curl -X POST https://cadence.abhix-ai.com/api/v1/bookings \
  -H "Authorization: Bearer ck_live_…" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: visit-42" \
  -d '{
    "service_id": "svc_123",
    "start": "2026-06-01T13:00:00Z",
    "customer": { "name": "Pat Patient", "email": "pat@example.com" }
  }'

Responses: 201 created · 200 idempotent replay · 404 unknown service/practitioner · 422 not an open slot · 409 the slot was taken by a concurrent booking. The no-double-booking guarantee is enforced in Postgres.

To manage a booking later: GET /bookings/{id}, POST /bookings/{id}/reschedule (body { "start": "…" }), and POST /bookings/{id}/cancel.

Keep the key server-side

The pattern: your frontend calls your own route handler, which adds the key and forwards to Cadence. The secret never reaches the browser.

Next.js route handler

ts
// app/api/bookings/route.ts — the key never reaches the browser.
export async function POST(req: Request) {
  const body = await req.json();

  const res = await fetch("https://cadence.abhix-ai.com/api/v1/bookings", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.CADENCE_ORG_API_KEY}`,
      "Content-Type": "application/json",
      "Idempotency-Key": body.idem,
    },
    body: JSON.stringify(body),
  });

  return Response.json(await res.json(), { status: res.status });
}

Public surface (browser-safe, no key)

For client-side widgets and pages, the publishable surface resolves a tenant by slug and needs no API key. It exposes only the booking surface; abuse is bounded by the platform rate limiter.

  • GET /api/v1/public/orgs/{slug} → org id, name, timezone, branding
  • GET /api/v1/public/orgs/{slug}/services · /practitioners
  • GET /api/v1/public/orgs/{slug}/availability?service_id=&from=&to=
  • POST /api/v1/public/orgs/{slug}/bookings — same semantics as POST /bookings

No-key example

bash
# No key — resolve a tenant by slug. Safe to call from the browser.
curl https://cadence.abhix-ai.com/api/v1/public/orgs/movela/services

curl -X POST https://cadence.abhix-ai.com/api/v1/public/orgs/movela/bookings \
  -H "Content-Type: application/json" \
  -d '{
    "service_id": "svc_123",
    "start": "2026-06-01T13:00:00Z",
    "customer": { "name": "Pat", "phone": "+1…" }
  }'

Webhooks

Register an endpoint to receive a signed POST when bookings change, so your systems stay in sync without polling. Events: booking.created, booking.cancelled, booking.rescheduled. The signing secret is returned once at creation (add an endpoint in Settings).

Delivery headers

http
X-Cadence-Event: booking.created
X-Cadence-Signature: sha256=<hex hmac of the raw body>

Verify every delivery. The signature is an HMAC-SHA256 of the raw request body, keyed by your endpoint's signing secret. Recompute it and compare in constant time before trusting the payload:

Verify (Python)

python
from cadence_client import verify_signature

if not verify_signature(secret, raw_request_body, request.headers["X-Cadence-Signature"]):
    raise HTTPException(401)

SDKs

Prefer a typed client? Both wrap the same API and throw a typed error on non-2xx (409 taken · 422 not open).

TypeScript / JavaScript

bash
npm install @cadence/client
ts
import { CadenceClient } from "@cadence/client";

// Server-side, full API — the ck_… key is a server secret.
const cadence = new CadenceClient({ apiKey: process.env.CADENCE_ORG_API_KEY! });

const services = await cadence.listServices();
const avail = await cadence.getAvailability({ serviceId: services[0].id });

const booking = await cadence.createBooking({
  serviceId: services[0].id,
  start: avail.slots[0].start,        // omit practitionerId → any available
  customer: { name: "Pat", email: "pat@example.com" },
  idempotencyKey: "visit-42",         // safe retries
});

Python

bash
pip install cadence-client
python
from cadence_client import CadenceClient

async with CadenceClient("https://cadence.abhix-ai.com", api_key="ck_live_…") as cad:
    services = await cad.list_services()
    avail = await cad.get_availability(service_id=services[0].id)
    booking = await cad.create_booking(
        service_id=services[0].id,
        start=avail.slots[0].start,          # any available practitioner
        customer={"name": "Pat", "email": "pat@example.com"},
        idempotency_key="visit-42",
    )

There's also a browser-safe CadencePublicClient (TS) for the keyless public surface — see the prebuilt UI guide for the React components built on it.

Full reference

Every endpoint, query parameter, and response shape — generated from the live OpenAPI schema, with try-it-in-the-browser requests — lives at cadence.abhix-ai.com/api/docs. The raw schema is at /api/openapi.json.