CareFlux API

A small REST API for building on top of a clinic running CareFlux — booking widgets, reporting tools, and integrations with whatever else the practice already uses.

This page documents what exists today. It is version 1, and it is deliberately narrow: six endpoints we can support properly rather than thirty we cannot.

Authentication

A clinic administrator creates a key under Settings → API keys. The raw key is shown once and never again — we store only its SHA-256 hash, so a leaked database backup does not leak working credentials.

curl https://your-careflux-domain/api/v1/me \
  -H "Authorization: Bearer mfl_xxxxxxxxxxxxxxxx"

Every key belongs to exactly one clinic. There is no cross-clinic key, and no endpoint takes an organisation id — the key is the tenant.

Scopes

A key holds an explicit list of scopes and can do nothing outside them. Scopes marked patient data expose identifying health information — grant them only to systems that genuinely need them, and only for as long as they do.

Endpoints

GET/api/v1/me

Which clinic this key belongs to and what it can do.

Start here. Needs no scope — holding the key is the point.

Scope: none required

GET/api/v1/providers

The clinic's doctors and nurses.

Scope: api:read:providers

GET/api/v1/services

Services offered, with prices in minor units.

price_minor is an integer — 150000 with currency PKR is Rs 1,500.00. Never a float.

Scope: api:read:services

GET/api/v1/appointmentspatient data

Appointments in a date range.

?from=&to= as ISO timestamps. Defaults to the next 7 days. 92 days maximum per call.

Scope: api:read:appointments

POST/api/v1/appointmentspatient data

Book an appointment for an existing patient.

Send client_reference to make the call safe to retry — the same reference always returns the same appointment instead of booking twice.

Scope: api:write:appointments

GET/api/v1/patientspatient data

Find a patient by MRN, national ID or full name.

Exact match only, and one of those three is required. There is no endpoint that lists every patient.

Scope: api:read:patients

Booking, safely

A booking request that times out is not necessarily a booking that failed. Send a client_reference you generate, and retry with the same value: the second call returns the appointment the first one created, with idempotent_replay: true.

curl -X POST https://your-careflux-domain/api/v1/appointments \
  -H "Authorization: Bearer mfl_..." \
  -H "Content-Type: application/json" \
  -d '{
    "patient_id": "019f...",
    "provider_id": "019f...",
    "starts_at": "2026-08-14T09:30:00Z",
    "duration_minutes": 20,
    "client_reference": "booking-4417"
  }'

If the provider is already busy at that time you get 409 slot_unavailable. That check is a database constraint, not application logic, so two simultaneous bookings for the same slot cannot both win.

Errors

Every failure has the same shape:

{ "error": { "code": "insufficient_scope", "message": "..." } }
StatusCodeMeans
401missing_keyNo Authorization header, or the scheme was not Bearer.
401invalid_keyUnknown, revoked, or wrong key.
401key_expiredThe key is past its expiry date.
403ip_not_allowedThe key has an IP allowlist and you are not on it.
403insufficient_scopeThe key does not hold the scope this endpoint needs.
429rate_limitedToo many requests this minute. Default is 120 per key.
400missing_fieldA required field was absent.
404patient_not_foundNo such patient in this clinic.
409slot_unavailableThat provider is already booked at that time.

Rate limits

120 requests per minute per key by default, in fixed one-minute windows. Over the limit you get 429 rate_limited. A clinic can raise the limit on a specific key if an integration genuinely needs more.

What we log

Every request — successful, refused, and unauthenticated — is recorded with the method, path, status, duration, IP and whether the endpoint returns patient data. The clinic can read that log.

We do not log request or response bodies. A body on a patient endpoint is patient data, and a log table is the last place it should accumulate.

Not in v1

Creating patients, clinical records, prescriptions, and billing are all absent, and that is a decision rather than a backlog item.

Patient creation in particular is where duplicate records come from — that is why bulk import goes through a staged review rather than a straight write. A booking integration that can silently mint patients will mint duplicates, and the clinic will find out months later.

If you need something that is not here, ask — a v1 that exposes everything is a v1 that can never change.