Developers

Changelog

Every change to the API, dated. Version 1 only grows.

Every change to the Daobook API, dated, newest first. Version 1 only grows: a new endpoint, parameter, field, event type, enumerated value or error code may appear at any time and is noted here; nothing in version 1 is renamed, removed or changes meaning without at least twelve months' notice.

  • Someone who signed in more than ten minutes before now confirms it's them on the consent screen itself, in a part above Allow, instead of being sent to a separate password page first. They answer with their passkey, a code from their authenticator app or their password. Nothing changes for your app: the same GET /oauth/authorize, the same redirect back with code or error. Cancel needs no answer.
  • The consent screen says what an app may do in the person's terms: "your locations", and Make bookings names moving, cancelling and confirming the upcoming client bookings the person manages, as such an app has been able to since 26 October.
  • The guide gains Connecting an assistant: the address, the steps in Claude and Claude Code, and every tool with its scope.

26 October 2026 — An app acting as a person changes the diary as the person

  • Under appointments:book, an app acting as a person (an access token, dbk_access_…) now reaches, beside the bookings the API made, every upcoming client booking at the locations where the person's role manages the calendar, whoever made it, and POST /v1/appointments/{id}/reschedule, …/cancel and …/confirm act on it as the person would in the calendar: the staff rules apply, not the client's self-service rules; the person is recorded as who moved or cancelled; the client is told as their own preference says and the practitioner as by a colleague. Until now such an app could list a front-desk booking yet was answered 404 when asked to move it. A key is unchanged.
  • A new optional field on POST /v1/appointments/{id}/cancel, cancelled_by (client or clinic), for an app acting as a person: whose cancellation it is, as the calendar's cancel window asks; left out, it stays unknown. A key may not send it (400 invalid_parameter).
  • For an app acting as a person, 422 cancellation_not_allowed and 422 reschedule_not_allowed carry details.reason (cancelled, completed, paid, status) in place of details.outcome.
  • GET /v1/appointments and GET /v1/appointments/{id} under appointments:book list and show, for an app acting as a person, the bookings it may change as well; each such read is written on the client's record as the person through the app.
  • The MCP tools list_appointments, reschedule_appointment, cancel_appointment and confirm_appointment describe the same.

26 October 2026 — The MCP server

  • POST https://api.daobook.com.au/mcp: a stateless Model Context Protocol server over Streamable HTTP, answering JSON, for an assistant a practitioner uses (Claude, Claude Code, ChatGPT) or a business's own agent. The bearer is a person's access token or a key, as on /v1; without one the answer is 401 with WWW-Authenticate: Bearer … resource_metadata="https://api.daobook.com.au/.well-known/oauth-protected-resource/mcp", which is how a client starts sign-in. The tools offered are the credential's scopes': the catalogue and free times under availability:read; the diary under appointments:read or appointments:book; booking, moving, cancelling and confirming under appointments:book; the waiting list under waiting_list:write; finding, reading, adding and updating clients under clients:read and clients:write. Each tool call is the documented /v1 request made under the same credential, so it is logged (the request log names the tool), limited and written on the client's record as that request would be. No tool reaches anything clinical.
  • The authorization response now carries iss (RFC 9207) on every redirect back to the app, and authorization_response_iss_parameter_supported: true is advertised in the authorization server metadata.

26 October 2026 — Clients

  • Two new scopes, clients:read (ticked as Read client names and contact details) and clients:write (Add and update clients, which carries the read), the second and third staff-level scopes. A person may grant both to a connected app where their role schedules.
  • Under clients:read: GET /v1/clients (most recently changed first with updated_since; filtered by location_id and status; or a lookup by exact email, mobile digits, name or external_reference=system:reference, at most 20 matches) and GET /v1/clients/{id}, reaching what a receptionist at the key's locations would see: a location keeping a private client list only when it is on the key. The client carries identity, contact details and address, occupation, the home location and practitioner, status, contact (ok, declined, opted_out, undeliverable), reminders, marketing, external_references and the first and last visit, never anything clinical. Every client read is written on the client's record as a line by the key.
  • expand=client on GET /v1/appointments and GET /v1/appointments/{id} puts the client on each appointment, under clients:read as well. A new field, client, on every appointment: the client when expanded, null otherwise.
  • Under clients:write: POST /v1/clients with Idempotency-Key adds a client as the booking page adds one, matched to the existing clients by the booking floor's rule, a match answered 409 duplicate_client (with details.client and details.matched_on) or, with on_duplicate: "return", as the client; PATCH /v1/clients/{id} changes name and contact details, null clearing an optional field, an archived client refused with 422 client_archived. Setting a marketing channel on records the consent as asserted through the API.
  • Events client.created, client.updated, client.archived, client.restored, client.deleted and client.merged (with data.merged_into), carrying the client's id, status, location and practitioner and never a name, recorded once a key or a connected app of the business reads clients; GET /v1/events lists them under clients:read, and a webhook endpoint hears of them when the owner ticks Client changes on it.
  • New error codes: duplicate_client (409), client_archived (422).

26 October 2026 — Apps acting as a person

  • An app a practitioner uses themselves connects as that person with OAuth 2.1 (authorization code with PKCE S256, refresh tokens that rotate), under the guide's Acting as a person. The person allows it on a consent screen at www.daobook.com.au/oauth/authorize in Daobook's own words, within what their role allows at their locations; what the token reaches follows their current role at each request.
  • New endpoints on the API host: POST /oauth/register (RFC 7591, public clients only, or a Client ID Metadata Document as the client id), POST /oauth/token, POST /oauth/revoke, and the discovery documents GET /.well-known/oauth-authorization-server (RFC 8414) and GET /.well-known/oauth-protected-resource (RFC 9728). Every 401 now carries WWW-Authenticate: Bearer resource_metadata=…, and a 403 insufficient_scope names the scope in it.
  • Access tokens (dbk_access_…) are accepted wherever a key is. GET /v1/account gains practitioner_id, app_id and app_name (null for a key); for a token key_id is null.
  • Scopes a person may grant: availability:read, appointments:read, appointments:book, waiting_list:write, and offline_access for a refresh token; callers:verify stays a business key's alone.
  • The person sees and ends their connected apps under Settings → Security → Connected apps; an owner or admin sees every member's. Connecting and disconnecting are lines in the Activity Log, and a record an app reads for the person is shown on Who Opened This Record as the person, through the app.
  • The API is on for every business. The account owner accepts the terms of use once under Settings → Integrations → Developer API and makes keys there; nothing is switched on by request any more.

26 October 2026 — The diary read

  • A new scope, appointments:read, ticked as Read the diary when a key is made: the first staff-level scope. Under it, GET /v1/appointments and GET /v1/appointments/{id} reach every appointment at the key's locations, whoever made it, classes included. Nothing may be changed under it: POST /v1/appointments and the cancel, reschedule and confirm actions keep appointments:book and reach only the bookings the API made (and a verified caller's own). Every record read under the scope is written on the client's record as a line by the key, shown to the clinic on Who Opened This Record and in its Activity Log.
  • New parameters on GET /v1/appointments: a diary window, from and to (dates in each location's own zone, at most 31 days), listing soonest first on its own cursor, given instead of updated_since; practitioner_id; client_id (needs appointments:read); kind.
  • Two new fields on every appointment, in responses and in events: kind (booking, class_session, class_place) and class_session_id (for a place, its session). A class session has client_id: null. A booking made through the API is always a booking.
  • Events: once a business holds a live key with appointments:read, every appointment's change is recorded, not only the API's own; GET /v1/events lists them under appointments:read, and a key with appointments:book alone still hears only of the bookings the API made. A webhook endpoint hears of the API's own bookings unless the owner chooses Every booking in the diary for it in Settings.
  • The source of an appointment the API did not make reads staff or online, as it did for a verified caller's.

21 October 2026 — The caller check

  • A new scope, callers:verify, ticked as Check who is calling and reach their bookings when a key is made. For phone receptionists: a caller's other bookings are reached through a check on who is calling, never a patient list or a search.
  • Under it: POST /v1/caller_lookups answers whether the number a caller rang from is one patient's and their first name, for the greeting; POST /v1/caller_verifications checks a date of birth against that number or the caller's full name and answers a verification (vrf_…) that lasts fifteen minutes, or 404 verification_failed; GET /v1/caller_verifications/{id}/appointments lists the verified caller's upcoming bookings, however they were made. Every check is written to the patient's record as a line by the key.
  • A new header, Caller-Verification, on GET /v1/appointments, GET /v1/appointments/{id}, …/cancel, …/reschedule and …/confirm: with a live verification, those endpoints reach the verified caller's own bookings too, under the same patient rules. source on an appointment may now read staff or online for such a booking.
  • A new endpoint, POST /v1/appointments/{id}/confirm, the client's "yes, I'll be there", for API-made bookings and for a verified caller's own.
  • New error codes: verification_failed (404), too_many_attempts (429, with Retry-After and details.retry_after), confirmation_not_allowed (422).

19 October 2026 — The waiting list

  • A new scope, waiting_list:write, ticked as Add to the waiting list when a key is made.
  • Under it: POST /v1/waiting_list_entries with Idempotency-Key puts a caller on a location's waiting list with what they are waiting for (a client who already has an open entry made through the API there gets it back with 200); GET /v1/waiting_list_entries and GET /v1/waiting_list_entries/{id} read the entries the business made through the API; POST /v1/waiting_list_entries/{id}/remove takes the caller off. Daobook offers freed times to the list; the key never sees who else is waiting.
  • Events waiting_list_entry.created, waiting_list_entry.offered (with data.offer, the time sent), waiting_list_entry.booked and waiting_list_entry.removed, on the feed and to webhook endpoints. GET /v1/events now takes either appointments:book or waiting_list:write, and a key hears only about the records its scopes reach.
  • A new error code, entry_closed (422): the entry is already booked.

19 October 2026 — Held times

  • A clinic can hold a freed time for the people on its waiting list it was offered to (Messages → Automatic messages → Waiting list). While the hold lasts, up to two hours, the time is not in GET /v1/availability, and POST /v1/appointments or …/reschedule into it is 409 slot_unavailable, as for any taken time. Nothing in the API books through a hold; only the link the clinic sent does. No request or response changed shape.

14 October 2026 — Version 1

The first release: the booking module, for a clinic's own website or app.

  • GET /v1/account: the business and the key the request came in with.
  • Under availability:read: GET /v1/locations, GET /v1/practitioners, GET /v1/appointment_types and GET /v1/availability, the same catalogue and free times the clinic's booking page offers.
  • Under appointments:book: POST /v1/appointments with Idempotency-Key, GET /v1/appointments and GET /v1/appointments/{id} for the bookings the business made through the API, POST /v1/appointments/{id}/cancel and POST /v1/appointments/{id}/reschedule under the clinic's rules for a client's own changes, and the event feed GET /v1/events and GET /v1/events/{id}.
  • Events appointment.created, appointment.rescheduled, appointment.cancelled, appointment.updated, appointment.deleted and test.sent, pushed to webhook endpoints signed to Standard Webhooks 1.0.0 and kept for 30 days on the feed.
  • Keys, scopes, locations and webhook endpoints are managed by the account owner in Settings → Integrations → Developer API. Access was by request until 26 October 2026, when the API was switched on for every business.