Booking an Appointment
Booking an Appointment
This guide walks you through the complete appointment booking flow: searching for available slots, creating an appointment, and managing it through its lifecycle.
Overview
The DELPHOS scheduling system uses a stateful appointment lifecycle that tracks every appointment from initial request through completion. Each appointment transitions through well-defined states, ensuring full auditability and conflict prevention.
Appointment Lifecycle
requested → confirmed → checked_in → in_progress → completed │ │ │ └───────────┴────────────┴──→ cancelled │ │ └───────────┴──→ no_show │ └──→ rescheduledBooking Sources
Appointments can originate from multiple channels:
| Source | Description |
|---|---|
web | Patient self-service portal |
phone | Phone call booking |
whatsapp | WhatsApp conversation |
api | Direct API integration |
walk_in | Walk-in patient |
chatbot | DELPHOS conversational assistant |
Step 1: Search Available Slots
Before creating an appointment, search for available time slots that match the patient’s needs.
Request
curl -X GET "https://your-instance.delphos.app/v1/scheduling/slots?\date_from=2026-04-15&\date_to=2026-04-18&\appointment_type_id=550e8400-e29b-41d4-a716-446655440003&\provider_id=550e8400-e29b-41d4-a716-446655440001&\location_id=550e8400-e29b-41d4-a716-446655440004&\duration_minutes=30&\limit=10" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json"import httpx
response = httpx.get( "https://your-instance.delphos.app/v1/scheduling/slots", headers={"x-api-key": "YOUR_API_KEY"}, params={ "date_from": "2026-04-15", "date_to": "2026-04-18", "appointment_type_id": "550e8400-e29b-41d4-a716-446655440003", "provider_id": "550e8400-e29b-41d4-a716-446655440001", "location_id": "550e8400-e29b-41d4-a716-446655440004", "duration_minutes": 30, "limit": 10, },)
slots = response.json()print(f"Found {len(slots['slots'])} available slots")Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
date_from | date | Yes | Start of search range (YYYY-MM-DD) |
date_to | date | Yes | End of search range (YYYY-MM-DD) |
appointment_type_id | uuid | Yes | Type of appointment |
provider_id | uuid | No | Specific provider (omit for cross-provider search) |
specialty | string | No | Filter by specialty (used with cross-provider search) |
location_id | uuid | No | Specific location |
duration_minutes | integer | No | Desired duration in minutes |
limit | integer | No | Max results (default: 50, max: 200) |
cursor | string | No | Pagination cursor from previous response |
Response
{ "slots": [ { "provider_profile_id": "550e8400-e29b-41d4-a716-446655440001", "location_id": "550e8400-e29b-41d4-a716-446655440004", "start_time": "2026-04-15T09:00:00Z", "end_time": "2026-04-15T09:30:00Z", "duration_minutes": 30, "score": 1.0 }, { "provider_profile_id": "550e8400-e29b-41d4-a716-446655440001", "location_id": "550e8400-e29b-41d4-a716-446655440004", "start_time": "2026-04-15T10:00:00Z", "end_time": "2026-04-15T10:30:00Z", "duration_minutes": 30, "score": 1.0 } ], "next_cursor": "eyJzdGFydCI6IjIwMjYtMDQtMTVUMTE6MDAifQ==", "has_more": true}Step 2: Create the Appointment
Once you have identified a suitable slot, create the appointment.
Request
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-04-15T09:00:00Z", "end_time": "2026-04-15T09:30:00Z", "source": "web", "notes": "Follow-up consultation for blood pressure monitoring" }'import httpx
response = httpx.post( "https://your-instance.delphos.app/v1/scheduling/appointments", headers={"x-api-key": "YOUR_API_KEY"}, json={ "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-04-15T09:00:00Z", "end_time": "2026-04-15T09:30:00Z", "source": "web", "notes": "Follow-up consultation for blood pressure monitoring", },)
appointment = response.json()print(f"Appointment created: {appointment['id']}")print(f"Status: {appointment['status']}")Request Body
| Field | Type | Required | Description |
|---|---|---|---|
provider_profile_id | uuid | Yes | Provider conducting the appointment |
patient_id | uuid | Yes | Patient being seen |
appointment_type_id | uuid | Yes | Type of appointment (consultation, exam, etc.) |
location_id | uuid | Yes | Physical location |
start_time | datetime | Yes | Start time in UTC (ISO 8601) |
end_time | datetime | Yes | End time in UTC (ISO 8601) |
room_id | uuid | No | Specific room assignment |
source | string | No | Booking channel (default: api) |
notes | string | No | Patient-visible notes |
internal_notes | string | No | Staff-only notes |
external_reference | string | No | External system reference (max 255 chars) |
metadata | object | No | Additional key-value data |
Response (201 Created)
{ "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "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", "room_id": null, "start_time": "2026-04-15T09:00:00Z", "end_time": "2026-04-15T09:30:00Z", "status": "requested", "source": "web", "notes": "Follow-up consultation for blood pressure monitoring", "internal_notes": null, "external_reference": null, "metadata": {}, "version": 1, "created_at": "2026-04-14T18:30:00Z", "updated_at": "2026-04-14T18:30:00Z"}Conflict Detection
DELPHOS automatically detects scheduling conflicts. If the requested time slot
overlaps with an existing appointment for the same provider and location, you
will receive a 409 Conflict response:
{ "detail": "Appointment conflicts with existing appointment at the requested time"}Step 3: Confirm the Appointment
New appointments start in requested status. Confirm them to signal
the provider has accepted:
curl -X POST "https://your-instance.delphos.app/v1/scheduling/appointments/\a1b2c3d4-e5f6-7890-abcd-ef1234567890/confirm" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"confirmed_by": "Dr. Silva"}'response = httpx.post( f"https://your-instance.delphos.app/v1/scheduling/appointments/{appointment_id}/confirm", headers={"x-api-key": "YOUR_API_KEY"}, json={"confirmed_by": "Dr. Silva"},)
confirmed = response.json()print(f"Status: {confirmed['status']}") # "confirmed"Step 4: Day-of-Visit Lifecycle
On the day of the appointment, move through the remaining states:
Check-In
curl -X POST "https://your-instance.delphos.app/v1/scheduling/appointments/\{appointment_id}/check-in" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"checked_in_by": "Reception Desk 1"}'response = httpx.post( f"https://your-instance.delphos.app/v1/scheduling/appointments/{appointment_id}/check-in", headers={"x-api-key": "YOUR_API_KEY"}, json={"checked_in_by": "Reception Desk 1"},)Start Appointment
curl -X POST "https://your-instance.delphos.app/v1/scheduling/appointments/\{appointment_id}/start" \ -H "x-api-key: YOUR_API_KEY"Complete Appointment
curl -X POST "https://your-instance.delphos.app/v1/scheduling/appointments/\{appointment_id}/complete" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"notes": "Blood pressure stable at 120/80. Continue current medication."}'response = httpx.post( f"https://your-instance.delphos.app/v1/scheduling/appointments/{appointment_id}/complete", headers={"x-api-key": "YOUR_API_KEY"}, json={"notes": "Blood pressure stable at 120/80. Continue current medication."},)Rescheduling
Rescheduling atomically cancels the existing appointment and creates a new one
in a single transaction. The original appointment transitions to rescheduled
status, and a new appointment is created with the updated time.
curl -X POST "https://your-instance.delphos.app/v1/scheduling/appointments/\{appointment_id}/reschedule" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "new_start_time": "2026-04-16T14:00:00Z", "new_end_time": "2026-04-16T14:30:00Z" }'response = httpx.post( f"https://your-instance.delphos.app/v1/scheduling/appointments/{appointment_id}/reschedule", headers={"x-api-key": "YOUR_API_KEY"}, json={ "new_start_time": "2026-04-16T14:00:00Z", "new_end_time": "2026-04-16T14:30:00Z", },)
# Returns 201 with the NEW appointmentnew_appointment = response.json()print(f"New appointment: {new_appointment['id']}")Cancellation
Cancel an appointment with an optional reason. DELPHOS supports configurable cancellation policies per tenant. A typical configuration might be:
- 24+ hours before: No restrictions
- 1-24 hours before: Late cancellation fee may apply
- Less than 1 hour: Cancellation may be restricted
The exact policy is tenant-configurable via the Configuration API.
curl -X POST "https://your-instance.delphos.app/v1/scheduling/appointments/\{appointment_id}/cancel" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "reason": "Patient requested reschedule due to travel", "cancelled_by": "Patient via phone" }'response = httpx.post( f"https://your-instance.delphos.app/v1/scheduling/appointments/{appointment_id}/cancel", headers={"x-api-key": "YOUR_API_KEY"}, json={ "reason": "Patient requested reschedule due to travel", "cancelled_by": "Patient via phone", },)Marking No-Shows
When a patient does not attend a confirmed or checked-in appointment:
curl -X POST "https://your-instance.delphos.app/v1/scheduling/appointments/\{appointment_id}/no-show" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"notes": "Patient did not respond to confirmation calls"}'Retrieving Appointments
List Appointments
curl -X GET "https://your-instance.delphos.app/v1/scheduling/appointments?\provider_id=550e8400-e29b-41d4-a716-446655440001&\status=confirmed&\date_from=2026-04-15&\date_to=2026-04-20&\limit=25" \ -H "x-api-key: YOUR_API_KEY"response = httpx.get( "https://your-instance.delphos.app/v1/scheduling/appointments", headers={"x-api-key": "YOUR_API_KEY"}, params={ "provider_id": "550e8400-e29b-41d4-a716-446655440001", "status": "confirmed", "date_from": "2026-04-15", "date_to": "2026-04-20", "limit": 25, },)
data = response.json()for apt in data["items"]: print(f"{apt['start_time']} - {apt['status']}")List Query Parameters
| Parameter | Type | Description |
|---|---|---|
provider_id | uuid | Filter by provider |
patient_id | uuid | Filter by patient |
location_id | uuid | Filter by location |
status | string | Filter by status |
date_from | date | Start of date range |
date_to | date | End of date range |
limit | integer | Results per page |
cursor | string | Pagination cursor |
Get Single Appointment
Retrieve a single appointment with its full status change history:
curl -X GET "https://your-instance.delphos.app/v1/scheduling/appointments/\a1b2c3d4-e5f6-7890-abcd-ef1234567890" \ -H "x-api-key: YOUR_API_KEY"The detail response includes a status_history array showing every
state transition with timestamps and actors.
Updating Appointments
Update notes, metadata, or room assignment on existing appointments.
Updates use optimistic locking — you must provide the current version
number to prevent conflicting changes.
curl -X PUT "https://your-instance.delphos.app/v1/scheduling/appointments/\a1b2c3d4-e5f6-7890-abcd-ef1234567890" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "version": 2, "notes": "Patient needs wheelchair access", "internal_notes": "Insurance pre-auth required", "room_id": "550e8400-e29b-41d4-a716-446655440099" }'response = httpx.put( f"https://your-instance.delphos.app/v1/scheduling/appointments/{appointment_id}", headers={"x-api-key": "YOUR_API_KEY"}, json={ "version": 2, "notes": "Patient needs wheelchair access", "internal_notes": "Insurance pre-auth required", "room_id": "550e8400-e29b-41d4-a716-446655440099", },)Multi-Location Support
Providers who work at multiple locations have their schedules managed per-location. DELPHOS automatically detects cross-location conflicts:
curl -X GET "https://your-instance.delphos.app/v1/scheduling/providers/\{provider_id}/cross-location-conflicts?\date_from=2026-04-15&date_to=2026-04-20" \ -H "x-api-key: YOUR_API_KEY"Response:
{ "conflicts": [ { "date": "2026-04-16", "location_a": "Clinic Downtown", "location_b": "Hospital North", "overlap_start": "14:00", "overlap_end": "15:00" } ], "has_conflicts": true}Error Handling
| Status Code | Error | Description |
|---|---|---|
404 | Not Found | Appointment does not exist |
409 | Conflict | Time slot already occupied, or optimistic lock version mismatch |
422 | Validation Error | Invalid request body (e.g., start_time after end_time) |
Next Steps
- Calendar Management — Set up provider schedules and templates
- Patient Communication — Configure reminders and webhooks
- Scheduling API Reference — Complete endpoint reference