Skip to content

Booking an Appointment

Booking an Appointment

The DELPHOS scheduling API provides a full appointment lifecycle from creation through completion or cancellation. Appointments follow a defined status machine with explicit transition endpoints.

Appointment Lifecycle

requested → confirmed → checked_in → in_progress → completed
│ │ │
│ └───────────┴──────────────────→ no_show
└──────────────────────────────────────────→ cancelled
StatusDescription
requestedAppointment created, awaiting confirmation
confirmedConfirmed by staff or provider
checked_inPatient has arrived and checked in
in_progressAppointment session is active
completedAppointment finished successfully
no_showPatient did not appear (from confirmed or checked_in)
cancelledAppointment cancelled (from requested, confirmed, or checked_in)

Create an Appointment

POST /v1/scheduling/appointments

Request body

FieldTypeRequiredDefaultDescription
provider_profile_idUUIDYesUUID of the provider profile
patient_idUUIDYesUUID of the patient
appointment_type_idUUIDYesUUID of the appointment type
location_idUUIDYesUUID of the location
start_timedatetimeYesAppointment start time (UTC)
end_timedatetimeYesAppointment end time (UTC); must be after start_time
room_idUUIDNonullOptional room assignment
sourcestringNo"api"Booking channel: web, phone, whatsapp, api, walk_in, chatbot
notesstringNonullPatient-visible notes
internal_notesstringNonullStaff-only internal notes
external_referencestringNonullExternal system reference (max 255 chars)
metadataobjectNo{}Additional metadata

Status codes

CodeMeaning
201Appointment created successfully
409Scheduling conflict — provider already has an appointment in this slot
422Validation error (e.g. end_time before start_time, invalid source)
Terminal window
curl -X POST "https://your-instance.delphos.app/v1/scheduling/appointments" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"provider_profile_id": "550e8400-e29b-41d4-a716-446655440001",
"patient_id": "550e8400-e29b-41d4-a716-446655440002",
"appointment_type_id": "550e8400-e29b-41d4-a716-446655440003",
"location_id": "550e8400-e29b-41d4-a716-446655440004",
"start_time": "2026-05-15T09:00:00Z",
"end_time": "2026-05-15T09:30:00Z",
"source": "web",
"notes": "Follow-up for hypertension management"
}'

Response fields (AppointmentResponse)

FieldTypeDescription
idUUIDAppointment UUID
provider_profile_idUUIDProvider profile UUID
patient_idUUIDPatient UUID
appointment_type_idUUIDAppointment type UUID
location_idUUIDLocation UUID
room_idUUID or nullRoom UUID
series_idUUID or nullSeries UUID (for recurring appointments)
start_timedatetimeStart time (UTC)
end_timedatetimeEnd time (UTC)
statusstringCurrent appointment status
sourcestringBooking channel
notesstring or nullPatient-visible notes
internal_notesstring or nullStaff-only notes
external_referencestring or nullExternal system reference
metadataobjectAdditional metadata
versionintegerOptimistic locking version
created_atdatetimeCreation timestamp (UTC)
updated_atdatetimeLast update timestamp (UTC)
cancellation_reasonstring or nullReason provided when appointment was cancelled
cancellation_policy_appliedstring or nullCancellation policy that was applied (e.g., late cancellation fee)

Lifecycle Transitions

Each lifecycle action is a dedicated POST endpoint on the appointment.

Confirm

POST /v1/scheduling/appointments/{appointment_id}/confirm

Valid transition: requestedconfirmed.

FieldTypeRequiredDescription
confirmed_bystringNoIdentifier of who confirmed

Check in

POST /v1/scheduling/appointments/{appointment_id}/check-in

Valid transition: confirmedchecked_in.

FieldTypeRequiredDescription
checked_in_bystringNoIdentifier of who checked the patient in

Start

POST /v1/scheduling/appointments/{appointment_id}/start

Valid transition: checked_inin_progress. No request body required.

Complete

POST /v1/scheduling/appointments/{appointment_id}/complete

Valid transition: in_progresscompleted.

FieldTypeRequiredDescription
notesstringNoCompletion notes

Mark as no-show

POST /v1/scheduling/appointments/{appointment_id}/no-show

Valid transitions: confirmedno_show, checked_inno_show.

FieldTypeRequiredDescription
notesstringNoNo-show notes

Cancel

POST /v1/scheduling/appointments/{appointment_id}/cancel

Valid transitions: requestedcancelled, confirmedcancelled, checked_incancelled.

FieldTypeRequiredDescription
reasonstringNoCancellation reason text
cancelled_bystringNoWho cancelled: "patient", "provider", or "system"

Cancellation policy:

TimingPolicy
More than 24h before startFree cancellation
1h–24h before startLate fee flag applied
Less than 1h before startNot allowed (422) unless cancelled_by = "system"

Reschedule

POST /v1/scheduling/appointments/{appointment_id}/reschedule

Atomic operation: cancels the original appointment and creates a new one in a single transaction.

FieldTypeRequiredDescription
new_start_timedatetimeYesNew start time (UTC)
new_end_timedatetimeYesNew end time (UTC); must be after new_start_time
new_location_idUUIDNoNew location (keeps original if omitted)
new_room_idUUIDNoNew room assignment
reasonstringNoReschedule reason
Terminal window
curl -X POST "https://your-instance.delphos.app/v1/scheduling/appointments/APPOINTMENT_ID/confirm" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"confirmed_by": "receptionist-001"}'

All lifecycle endpoints return 200 with the updated AppointmentResponse on success, 404 if the appointment is not found, and 422 if the transition is invalid for the current status.


List and Retrieve Appointments

List appointments

GET /v1/scheduling/appointments

Uses cursor-based pagination. Returns AppointmentListResponse with items, next_cursor, and has_more.

Get appointment detail

GET /v1/scheduling/appointments/{appointment_id}

Returns AppointmentDetailResponse, which extends AppointmentResponse with a status_history array of status change entries:

FieldDescription
previous_statusStatus before the change (null for creation)
new_statusStatus after the change
changed_byWho triggered the change
reasonReason for the change
created_atTimestamp of the change (UTC)

Update an Appointment

PUT /v1/scheduling/appointments/{appointment_id}

Supports partial updates for notes, internal_notes, metadata, and room_id. Requires the current version for optimistic locking.

FieldTypeRequiredDescription
versionintegerYesCurrent version (prevents lost updates)
notesstringNoUpdated patient-visible notes
internal_notesstringNoUpdated staff-only notes
metadataobjectNoUpdated metadata
room_idUUIDNoUpdated room assignment

Returns 409 if the version does not match (optimistic lock conflict).


Complete Booking Workflow

  1. Find available slotsGET /v1/scheduling/slots to search availability (see Calendar Management).

  2. Create appointmentPOST /v1/scheduling/appointments with the chosen slot times.

  3. ConfirmPOST /v1/scheduling/appointments/{id}/confirm when the patient confirms.

  4. Check inPOST /v1/scheduling/appointments/{id}/check-in when the patient arrives.

  5. StartPOST /v1/scheduling/appointments/{id}/start when the consultation begins.

  6. CompletePOST /v1/scheduling/appointments/{id}/complete when finished.