| Time | Patient | Doctor | Status | Reason | Actions |
|---|
| ID | Name | Phone | Date of Birth | Gender | Appointments |
|---|
Base URL: /api/v1 — Auth: Authorization: Bearer <key> or X-API-Key: <key>
/api/v1/specialties — List all specialties{
"specialties": [
{ "id": "spec_001", "name": "Cardiology", "description": "Heart and vascular system" },
{ "id": "spec_002", "name": "Dermatology", "description": "Skin, hair, and nail conditions" }
]
}/api/v1/doctors?specialty_id=&name=&available_on= — Search doctorsGET /api/v1/doctors?specialty_id=spec_001
// Response 200
{
"doctors": [
{
"id": "doc_001",
"name": "Dr. Sari Wijaya, Sp.JP",
"specialty": { "id": "spec_001", "name": "Cardiology" },
"hospital": { "id": "hosp_001", "name": "RS Mekari Sehat - Jakarta" },
"consultation_fee": 350000,
"bio": "Cardiologist with 15 years of experience...",
"languages": ["id", "en"],
"photo_url": "https://ui-avatars.com/api/?name=Dr.+Sari+Wijaya",
"next_available_slot": "2026-05-22T10:00:00+07:00"
}
]
}/api/v1/doctors/{doctor_id}/slots?from=&to=&status= — Get available slotsGET /api/v1/doctors/doc_001/slots?from=2026-05-22&to=2026-05-22
// Response 200
{
"doctor_id": "doc_001",
"slots": [
{ "id": "slot_0042", "doctor_id": "doc_001", "start_time": "2026-05-22T10:00:00+07:00", "end_time": "2026-05-22T10:30:00+07:00", "status": "available" },
{ "id": "slot_0043", "doctor_id": "doc_001", "start_time": "2026-05-22T10:30:00+07:00", "end_time": "2026-05-22T11:00:00+07:00", "status": "available" }
]
}/api/v1/patients — Register new patientPOST /api/v1/patients
Content-Type: application/json
{
"full_name": "Budi Santoso",
"phone": "+628123456789",
"date_of_birth": "1985-03-12",
"gender": "male",
"email": "budi@example.com"
}
// Response 201
{
"patient": {
"id": "pat_0004",
"full_name": "Budi Santoso",
"phone": "+628123456789",
"date_of_birth": "1985-03-12",
"gender": "male",
"email": "budi@example.com",
"created_at": "2026-05-19T14:33:00+07:00"
}
}
// Error 409 — phone already registered
{
"error": {
"code": "PATIENT_ALREADY_EXISTS",
"message": "A patient with this phone number is already registered",
"details": { "patient_id": "pat_0001" }
}
}/api/v1/patients/lookup?phone= — Look up patient by phoneGET /api/v1/patients/lookup?phone=%2B628123456789
// Response 200
{
"patient": {
"id": "pat_0001",
"full_name": "Budi Santoso",
"phone": "+628123456789",
"date_of_birth": "1985-03-12",
"gender": "male",
"email": "budi.santoso@email.com",
"created_at": "2026-05-19T14:00:00+07:00"
}
}
// Error 404 — not found
{
"error": { "code": "PATIENT_NOT_FOUND", "message": "No patient found with this phone number" }
}/api/v1/appointments — Book appointmentPOST /api/v1/appointments
Content-Type: application/json
{
"patient_id": "pat_0001",
"doctor_id": "doc_001",
"slot_id": "slot_0042",
"reason_for_visit": "Chest pain and shortness of breath for 2 weeks"
}
// Response 201
{
"appointment": {
"id": "appt_00003",
"patient": { "id": "pat_0001", "full_name": "Budi Santoso", "phone": "+628123456789" },
"doctor": { "id": "doc_001", "name": "Dr. Sari Wijaya, Sp.JP", "specialty": "Cardiology" },
"slot": { "id": "slot_0042", "start_time": "2026-05-22T10:00:00+07:00", "end_time": "2026-05-22T10:30:00+07:00" },
"status": "confirmed",
"reason_for_visit": "Chest pain and shortness of breath for 2 weeks",
"created_at": "2026-05-19T14:33:00+07:00",
"updated_at": "2026-05-19T14:33:00+07:00"
}
}
// Error 409 — slot taken
{ "error": { "code": "SLOT_UNAVAILABLE", "message": "Selected slot is no longer available" } }
// Error 409 — patient has overlapping appointment
{
"error": {
"code": "PATIENT_HAS_CONFLICT",
"message": "Patient already has an appointment at this time",
"details": { "conflicting_appointment": { "id": "appt_00001", "..." : "..." } }
}
}
// Error 400 — slot in the past
{ "error": { "code": "SLOT_IN_PAST", "message": "Cannot book a slot in the past" } }/api/v1/appointments?patient_id=&status=&from=&to= — List appointmentsGET /api/v1/appointments?patient_id=pat_0001&status=confirmed
// Response 200
{
"appointments": [
{
"id": "appt_00001",
"patient": { "id": "pat_0001", "full_name": "Budi Santoso", "phone": "+628123456789" },
"doctor": { "id": "doc_001", "name": "Dr. Sari Wijaya, Sp.JP", "specialty": "Cardiology" },
"slot": { "id": "slot_0001", "start_time": "2026-05-22T08:00:00+07:00", "end_time": "2026-05-22T08:30:00+07:00" },
"status": "confirmed",
"reason_for_visit": "Chest pain and shortness of breath for 2 weeks",
"created_at": "2026-05-19T14:00:00+07:00",
"updated_at": "2026-05-19T14:00:00+07:00"
}
]
}/api/v1/appointments/{id} — Get appointment detailGET /api/v1/appointments/appt_00001
// Response 200
{
"appointment": {
"id": "appt_00001",
"patient": { "id": "pat_0001", "full_name": "Budi Santoso", "phone": "+628123456789" },
"doctor": { "id": "doc_001", "name": "Dr. Sari Wijaya, Sp.JP", "specialty": "Cardiology" },
"slot": { "id": "slot_0001", "start_time": "2026-05-22T08:00:00+07:00", "end_time": "2026-05-22T08:30:00+07:00" },
"status": "confirmed",
"reason_for_visit": "Chest pain and shortness of breath for 2 weeks",
"cancellation_reason": null,
"created_at": "2026-05-19T14:00:00+07:00",
"updated_at": "2026-05-19T14:00:00+07:00"
}
}/api/v1/appointments/{id} — Reschedule (change slot)PATCH /api/v1/appointments/appt_00001
Content-Type: application/json
{
"slot_id": "slot_0055"
}
// Response 200
{
"appointment": {
"id": "appt_00001",
"patient": { "id": "pat_0001", "full_name": "Budi Santoso", "phone": "+628123456789" },
"doctor": { "id": "doc_001", "name": "Dr. Sari Wijaya, Sp.JP", "specialty": "Cardiology" },
"slot": { "id": "slot_0055", "start_time": "2026-05-26T09:00:00+07:00", "end_time": "2026-05-26T09:30:00+07:00" },
"status": "rescheduled",
"reason_for_visit": "Chest pain and shortness of breath for 2 weeks",
"created_at": "2026-05-19T14:00:00+07:00",
"updated_at": "2026-05-19T15:20:00+07:00"
}
}
// Error 409 — new slot not available
{ "error": { "code": "SLOT_UNAVAILABLE", "message": "Selected slot is no longer available" } }
// Error 400 — cannot reschedule cancelled appointment
{ "error": { "code": "CANNOT_RESCHEDULE_CANCELLED_APPOINTMENT", "message": "Cannot reschedule a cancelled appointment" } }
// Error 400 — appointment is in the past
{ "error": { "code": "CANNOT_RESCHEDULE_PAST_APPOINTMENT", "message": "Cannot reschedule a past appointment" } }/api/v1/appointments/{id} — Cancel appointmentDELETE /api/v1/appointments/appt_00001
Content-Type: application/json
{
"reason": "Patient feels better and no longer needs visit"
}
// Response 200
{
"appointment": {
"id": "appt_00001",
"patient": { "id": "pat_0001", "full_name": "Budi Santoso", "phone": "+628123456789" },
"doctor": { "id": "doc_001", "name": "Dr. Sari Wijaya, Sp.JP", "specialty": "Cardiology" },
"slot": { "id": "slot_0001", "start_time": "2026-05-22T08:00:00+07:00", "end_time": "2026-05-22T08:30:00+07:00" },
"status": "cancelled",
"reason_for_visit": "Chest pain and shortness of breath for 2 weeks",
"cancellation_reason": "Patient feels better and no longer needs visit",
"created_at": "2026-05-19T14:00:00+07:00",
"updated_at": "2026-05-19T16:00:00+07:00"
}
}/api/v1/reset — Reset demo dataPOST /api/v1/reset
// Response 200
{
"message": "Demo data reset successfully",
"summary": { "slots": 608, "patients": 3, "appointments": 2 }
}/api/v1/hospitals — Hospital infoGET /api/v1/hospitals
// Response 200
{
"hospitals": [
{
"id": "hosp_001",
"name": "RS Mekari Sehat - Jakarta",
"address": "Jl. Jend. Sudirman Kav. 52-53, Senayan, Jakarta Selatan 12190",
"phone": "+6221-5551234",
"operating_hours": {
"monday": "08:00-17:00", "tuesday": "08:00-17:00", "wednesday": "08:00-17:00",
"thursday": "08:00-17:00", "friday": "08:00-17:00", "saturday": "08:00-13:00",
"sunday": "Closed"
}
}
]
}/health — Health check (no auth)GET /health
// Response 200
{ "status": "ok", "auth_enabled": false }{
"error": {
"code": "SLOT_UNAVAILABLE",
"message": "Selected slot is no longer available",
"details": {}
}
}
Error codes: SLOT_UNAVAILABLE, SLOT_IN_PAST, PATIENT_ALREADY_EXISTS, PATIENT_NOT_FOUND, PATIENT_HAS_CONFLICT, CANNOT_RESCHEDULE_CANCELLED_APPOINTMENT, CANNOT_RESCHEDULE_PAST_APPOINTMENT, ALREADY_CANCELLED, VALIDATION_ERROR, UNAUTHORIZED