← Help centre / Handbook · chapter 11 of 19

The API

Everything a screen in Clinidiary can do arrives through an API first — the screens themselves are clients of it. A key lets your own software, or an AI agent working for the practice, walk through the same doors with the same rules: every request is scoped to your practice, every write is audited, and nothing is reachable that the key was not explicitly given.

This page is written to be handed over whole. If a developer is integrating for you, send them the link. If an AI agent is doing the work, paste this page into its instructions — it contains everything the agent needs to behave.

Getting a key

Settings → Integrations → New key. Three decisions, made on that screen:

  1. Name it after the job — "Reminder sync", "Clini — bookings". The name is what you will read in six months when deciding whether to revoke it.
  2. Read only, or read and write. A read-only key is refused every write at the door, whatever else it holds. Start read-only, watch what the software asks for, and mint a writing key once it behaves.
  3. Tick what it may do. Sections match the areas below. A key should hold the permissions its job needs and nothing else — you can always mint another key for another job.

The key is shown once, at creation. Only a hash is stored, so nobody — including us — can read it back later. Lost means revoked and re-made. Revoking takes effect on the very next request.

You are only offered what your practice actually runs. A physiotherapy practice is not offered hospital wards; a practice without claiming is not offered claims. If a section named below is missing from your screen, your Clinidiary does not have that area switched on.

Calling it

Base URL: https://clinidiary.com for Australian practices, https://clinidiary.in for Indian practices — always the country your practice signed up in; records never cross that line.

Every request carries the key as a bearer token:

GET /api/patients?search=chen HTTP/1.1
Host: clinidiary.com
Authorization: Bearer clinidiary_sk_…

Conventions, everywhere and without exception:

  • JSON in, JSON out. Send Content-Type: application/json on writes.
  • Money is whole cents, integers, in the practice's own currency. Totals and tax are computed by the server; a client never sends a total.
  • Times are ISO 8601 with timezone. The practice's own timezone governs what "today" means.
  • IDs are UUIDs, issued by the server.
  • Everything is scoped to your practice. There is no parameter that reaches another organisation's records, and an ID from outside your practice answers 404 as if it did not exist.

Errors are one shape: { "error": "a plain sentence" } with the usual status codes — 401 for a missing, revoked or expired key, 403 for a permission the key does not hold (or any write on a read-only key), 404 for a record that does not exist in your practice, 409 for a rule the request would break (the sentence says which), and 400 with field details when the body does not validate.

The endpoints

Each area below names the permission that unlocks it — the same names as the tick-boxes on the key screen. GET needs the read permission; writes need the write permission named beside them.

Patients — clients.view, writes clients.create / clients.edit

GET /api/patients
List and search. ?search= matches name, mobile, email and patient number.
GET /api/patients/:id
One patient in full.
POST /api/patients
Create. Name and mobile are enough; the country decides the address and phone shapes.
PATCH /api/patients/:id
Edit details.
POST /api/patients/:id/archive
Archive, never delete — clinical history stays.

Diary — diary.view, writes diary.book

GET /api/scheduling/practitioners
Who works here, and their columns.
GET /api/scheduling/appointment-types
The bookable types, their lengths and prices.
GET /api/scheduling/locations
Rooms and places.
GET /api/scheduling/appointments?from=&to=
The book between two dates.
GET /api/scheduling/slots
Free, bookable times — the same answer online booking uses.
POST /api/scheduling/appointments
Book.
PATCH /api/scheduling/appointments/:id
Move, retype, or edit.
DELETE /api/scheduling/appointments/:id
Delete a booking made in error; refused once a note, invoice or pack credit hangs off it. To cancel, PATCH with status: "cancelled".
POST /api/scheduling/appointments/:id/clear
Take a cancelled appointment off the diary (diary.cancel). Hidden, not deleted; …/restore puts it back.

Waiting list — diary.view, writes diary.book

GET /api/waiting-list
Who is waiting, for what.
POST /api/waiting-list
Add somebody.
POST /api/waiting-list/:id/offered
Record that a time was offered.

Money — billing.view, payments billing.payment, invoicing billing.invoice

GET /api/billing/invoices
List, filterable by status. Newest 100 unless limit says otherwise (1-200, or all); total is how many match.
GET /api/billing/invoices/:id
One invoice with its lines and payments.
GET /api/billing/uninvoiced
Completed work not yet billed.
GET /api/billing/patients/:id/account
A patient's account — owed, held, history.
POST /api/billing/invoices
Raise an invoice. The server prices and totals it.
POST /api/billing/invoices/:id/issue
Issue it — after this the total never moves.
POST /api/billing/payments
Take a payment against an invoice.

A key can read money and take payments. It can never void, refund or discount — those belong to a person who can be asked why.

Messages — comms.send (where messaging is switched on)

POST /api/messaging/send
Send an SMS to a patient. Consent and quiet hours are enforced by the server, not by the caller's good manners.

Tasks — tasks.use

GET /api/tasks
The list.
POST /api/tasks
Add one.
POST /api/tasks/:id/done
Done.

Directory — directory.view

GET /api/directory
GPs, specialists, insurers — everyone outside the practice.
GET /api/directory/:id
One entry.

Reports — reports.operational and friends

GET /api/reports/catalogue
Every report this practice can run, and what each needs.
GET /api/reports/run/:key?from=&to=
Run one over a date range.

Wards — hospitals only — ward.view, writes ward.admit / ward.transfer

Practices running inpatient care also see the Inpatients section on the key screen: wards, beds, admissions, transfers and ward charges. Discharge is never offered to a key — ending a stay can record a death, and that belongs to a named person.

For an AI agent, specifically

  • Start with a read-only key. Do the job in reads until the practice has watched you do it; ask for a writing key only for the writes the job needs.
  • Ask what the key holds before you try. GET /api/auth/me answers for a key as it does for a person: permissions is exactly what this key may do, and readOnly says whether it may write at all. A key cannot be changed after it is made; if it lacks something, ask for a new one.
  • Read before you write. Book into GET /api/scheduling/slots answers, not into times you computed yourself.
  • Do not retry a 409. It is not a transient failure; it is a rule. Show the sentence to a human.
  • Never store the key in what you produce — not in logs, not in output, not in a file a person might share.
  • Everything you do is written to the practice's activity log under the key's name. Behave as if the owner reads it, because they do.

What a key can never do

However it is made, whoever makes it: a key cannot write or sign clinical notes, cannot void, refund or discount money, cannot manage users, permissions or other keys, cannot message the team as a colleague, cannot merge patient records, and cannot discharge a patient from a ward. Those acts belong to signed-in people. The server refuses them to every key — this is not a setting.