Integration Overview
Use this API to discover package-scoped booking options, list open clinics and departments, check availability, and create bookings on behalf of people in your organisation.
All operations are organisation-scoped and require an access token from your approved integration client.
The patient-communication.raised.v1 webhook is a generic pointer. If it identifies a clinical communication, retrieve its persisted content with GET /external/v1/organisation-booking/clinical-communications/{notificationId}. This requires organisation.booking.read and current full clinical-record-sharing access; non-clinical notifications are not available from that endpoint.
Step-by-Step Booking Flow
- Get access token from
/connect/tokenusing client credentials. GET /external/v1/organisation-booking/employeesto find the person to book for. UseemployeeIdandpatientIdfrom the result. If the person is not yet on DocTap and your integration is enabled for it,POST /external/v1/organisation-booking/employees.GET /external/v1/organisation-booking/booking/packagesto find thepackageIdthat funds the booking.GET /external/v1/organisation-booking/booking/booking-types?employeeId=…(orpackageId, optionallypatientId). Theidof the chosen item is thebookingTypeIdfor booking and theConsultationTypeIdfor availability. Note the optional investigation panel ids.GET /external/v1/organisation-booking/booking/clinics. UseidasClinicIdandlocation.idasLocationId.- Availability —
/external/v1/organisation-booking/availability/clinicsand/availability/cliniciansneedConsultationTypeId,PackageId,LocationId;/availability/timesneedsConsultationTypeId,PackageId;/availability/slotsneedsConsultationTypeId,PackageId,ClinicId,FromDateTime,ToDateTime. PassEmployeeIdandPatientIdwhere you have them. POST /external/v1/organisation-booking/bookingscreates the basket, booking and invoice in one call. On success you getbasketId,bookingIdand the invoice summary.- If the response reports the invoice step failed (
failedStepin the problem details), retry withPOST /external/v1/organisation-booking/baskets/{basketId}/invoice. - Afterwards:
GET /external/v1/organisation-booking/appointments/{id}, preview and confirm cancellation, and the patient-records endpoints.
Reference data: list open clinics' departments via GET /external/v1/organisation-booking/booking/departments. Nothing in the booking flow above consumes a department id.
Omit patientId to browse the general catalogue. Supply an authorised patientId to remove optional panels that are unsuitable for that patient before checking availability. Investigation IDs represent bookable panels, not constituent tests or analytes; pass selected optional panel IDs to the existing additionalInvestigations fields.
A catalogue item with type: product remains discoverable, but this metadata does not establish an external product availability or checkout workflow.
Each catalogue item can also carry priceFrom and totalDurationMinutes for listing pages. priceFrom is the same “from” price DocTap's own booking pages show: the lowest standard price over the next 10 days, excluding optional investigations, refreshed every few hours. It is null when nothing is bookable in that window or DocTap does not show a “from” price for the service. totalDurationMinutes is the most time the patient should set aside for the standard service, including the longest waits between stages; it is null for products. Availability prices and durations for a specific time are authoritative: /availability/slots and /availability/times results carry the actual totalDurationMinutes for that time, including selected optional investigations, and prices can be higher than priceFrom, for example at weekends.
Use idempotent retries for transient failures and rotate secrets immediately if exposure is suspected.
Authentication (OAuth2 Client Credentials)
Request a token from /connect/token then send Authorization: Bearer <access_token>.
The token endpoint supports client credentials in either request body (client_secret_post) or Authorization: Basic header (client_secret_basic).
IMPORTANT: keep client_secret on your backend only. Never expose it in browser/mobile code, logs, screenshots, or public repositories.
The HTTP Bearer option in this page's "Authorize" dialog is for interactive testing only — paste a token you already obtained. It is not a substitute for the client-credentials flow below.
organisation.integration— required for all external organisation endpoints.organisation.booking.read— required for read operations.organisation.booking.write— required for write operations.organisation.booking.cancel— required to confirm an appointment cancellation.organisation.webhook.manage— required for the webhook management endpoints.
POSIX shell / macOS / Linux:
curl -X POST "/connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=<client_id>" \
-d "client_secret=<client_secret>" \
-d "scope=organisation.integration organisation.booking.read"
Windows cmd:
curl -X POST "/connect/token" ^
-H "Content-Type: application/x-www-form-urlencoded" ^
-d "grant_type=client_credentials" ^
-d "client_id=<client_id>" ^
-d "client_secret=<client_secret>" ^
-d "scope=organisation.integration organisation.booking.read"
Using HTTP Basic auth instead of a client_secret body parameter (POSIX shell):
curl -X POST "/connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Authorization: Basic <base64(client_id:client_secret)>" \
-d "grant_type=client_credentials" \
-d "scope=organisation.integration organisation.booking.read"