# Appointment API > **Prefix:** `/api/v1/appointment*` --- ## GET `/api/v1/appointment-slots` Get all appointment slots (available and booked) for a doctor on a specific date. **Permission:** `PUBLIC` ### Query Parameters | Param | Type | Required | Description | |-------|------|----------|-------------| | `doctor_uuid` | string (UUID) | ✅ | Doctor UUID | | `date` | string | ✅ | Date in `Y-m-d` format (e.g. `2024-06-15`) | ### Response `200` ```json { "success": true, "data": { "doctor_uuid": "550e8400-...", "date": "2024-06-15", "sessions": [ { "start_time": "09:00", "end_time": "13:00", "slots": [ { "start": 1718438400, "end": 1718439600, "start_time": "09:00", "end_time": "09:20", "location_id": null, "is_available": true }, { "start": 1718439600, "end": 1718440800, "start_time": "09:20", "end_time": "09:40", "location_id": null, "is_available": false } ] }, { "start_time": "15:00", "end_time": "17:00", "slots": [...] } ] } } ``` > Returns **all** slots grouped by work shift. `is_available: false` means the slot has an active (pending/confirmed) appointment. Session boundaries match the doctor's `WeeklySchedule` or date override config. ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_NOT_FOUND_001` | 404 | Doctor not found | | `ERR_VALIDATION_001` | 422 | Missing or invalid date/doctor_uuid | --- ## POST `/api/v1/appointment` Book an appointment slot. **Permission:** `AUTH` — any authenticated user ### Request Body (`application/json`) ```json { "doctor_uuid": "550e8400-e29b-41d4-a716-446655440000", "slot_start": 1718438400, "slot_end": 1718439600, "note": "لطفاً سریع ویزیت شوم" } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `doctor_uuid` | string (UUID) | ✅ | Doctor UUID | | `slot_start` | integer | ✅ | Slot start (Unix timestamp) | | `slot_end` | integer | ✅ | Slot end (Unix timestamp) | | `note` | string | ❌ | Patient note | ### Response `201` ```json { "success": true, "data": { "uuid": "appt-uuid-...", "doctor": { "uuid": "...", "title": "دکتر علی احمدی" }, "user": { "uuid": "...", "real_name": "..." }, "slot_start": 1718438400, "slot_end": 1718439600, "status": "pending", "note": "...", "price": 500000, "created_at": 1717000000 } } ``` **Appointment Status Values:** | Value | Description | |-------|-------------| | `pending` | Awaiting payment | | `confirmed` | Paid and confirmed | | `cancelled` | Cancelled | | `completed` | Visit completed | | `no_show` | Patient did not show | ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Missing token | | `ERR_NOT_FOUND_001` | 404 | Doctor not found | | `ERR_CONFLICT_001` | 409 | Slot already booked | | `ERR_VALIDATION_001` | 422 | Invalid slot times | --- ## GET `/api/v1/appointment/{uuid}` Get appointment detail. **Permission:** `AUTH` — must be the patient, the doctor, or `ROLE_ADMIN` ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `uuid` | string (UUID) | Appointment UUID | ### Response `200` ```json { "success": true, "data": { "uuid": "appt-uuid-...", "doctor": { "uuid": "...", "title": "دکتر علی احمدی", "image": "https://..." }, "user": { "uuid": "...", "real_name": "کاربر", "mobile_number": "09..." }, "slot_start": 1718438400, "slot_end": 1718439600, "status": "confirmed", "note": "...", "price": 500000, "payment_uuid": "pay-uuid-...", "created_at": 1717000000 } } ``` ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Missing token | | `ERR_FORBIDDEN_001` | 403 | Not the patient/doctor/admin | | `ERR_NOT_FOUND_001` | 404 | Appointment not found | --- ## GET `/api/v1/appointments/doctor/{doctorUuid}` Get all appointments for a specific doctor. **Permission:** `AUTH` — must be the doctor, their secretary, or `ROLE_ADMIN` ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `doctorUuid` | string (UUID) | Doctor UUID | ### Query Parameters | Param | Type | Required | Description | |-------|------|----------|-------------| | `status` | string | ❌ | Filter: `pending`, `confirmed`, `cancelled`, `completed`, `no_show` | ### Response `200` ```json { "success": true, "data": [ { "uuid": "...", "user": { "uuid": "...", "real_name": "..." }, "slot_start": 1718438400, "slot_end": 1718439600, "status": "confirmed", "price": 500000 } ] } ``` ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Missing token | | `ERR_FORBIDDEN_001` | 403 | Not authorized to view this doctor's appointments | | `ERR_NOT_FOUND_001` | 404 | Doctor not found | --- ## GET `/api/v1/appointments/user` Get all appointments for the authenticated user. **Permission:** `AUTH` ### Query Parameters | Param | Type | Required | Description | |-------|------|----------|-------------| | `status` | string | ❌ | Filter by status | ### Response `200` ```json { "success": true, "data": [ { "uuid": "...", "doctor": { "uuid": "...", "title": "دکتر علی احمدی" }, "slot_start": 1718438400, "slot_end": 1718439600, "status": "confirmed", "price": 500000 } ] } ``` ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Missing token | --- ## PATCH `/api/v1/appointment/{uuid}/status` Change appointment status. **Permission:** `AUTH` — patient can cancel; doctor/secretary can confirm/complete/no_show; admin can do all ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `uuid` | string (UUID) | Appointment UUID | ### Request Body ```json { "status": "cancelled", "version": 3 } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `status` | string | ✅ | New status value | | `version` | integer | ❌ | Optimistic lock version (prevents double-submit) | **Allowed Transitions by Role:** | Actor | Allowed transitions | |-------|---------------------| | Patient | `pending → cancelled` | | Doctor / Secretary | `pending → confirmed`, `confirmed → completed`, `confirmed → no_show` | | Admin | Any transition | ### Response `200` Updated appointment object. ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Missing token | | `ERR_FORBIDDEN_001` | 403 | Not authorized for this transition | | `ERR_NOT_FOUND_001` | 404 | Appointment not found | | `ERR_CONFLICT_001` | 409 | Version mismatch (optimistic lock) | | `ERR_VALIDATION_001` | 422 | Invalid status value | --- ## POST `/api/v1/my/appointment` Create a new appointment for a patient. Used by doctor/clinic/secretary to book appointments on behalf of patients. If no user exists with the given mobile, a new user account is created automatically. **Auth:** `IS_AUTHENTICATED_FULLY` — Roles: `ROLE_DOCTOR`, `ROLE_CLINIC`, `ROLE_SECRETARY`, `ROLE_ADMIN` ### Request Body ```json { "doctor_uuid": "doctor-uuid", "slot_start": 1718438400, "slot_end": 1718439600, "patient_mobile": "09123456789", "patient_name": "علی محمدی", "note": "optional note" } ``` > اگر کاربری با این شماره موبایل وجود نداشته باشد، یک کاربر جدید با نقش `ROLE_USER` ساخته می‌شود. ### Response `201` ```json { "success": true, "data": { "uuid": "appt-uuid", "slot_start": 1718438400, "slot_end": 1718439600, "status": "pending" } } ``` ### Error Responses | Code | HTTP | Description | |------|------|-------------| | `FORBIDDEN` | 403 | Role not allowed | | `VALIDATION` | 422 | Missing required fields | | `DOCTOR_NOT_FOUND` | 404 | Doctor UUID not found | | `SLOT_TAKEN` | 409 | Slot already booked | --- ## GET /api/v1/my/appointments Role-aware paginated list of appointments. Returns only what the authenticated user is authorized to see. **Auth:** `IS_AUTHENTICATED_FULLY` (any role) **Role behavior:** | Role | Scope | |------|-------| | `ROLE_ADMIN` | All appointments | | `ROLE_CLINIC` | Appointments for doctors in this clinic | | `ROLE_DOCTOR` | Appointments for this doctor | | `ROLE_SECRETARY` | Appointments for the linked doctor (empty if `appointments.view` permission is false) | ### Query Parameters | Param | Type | Default | Description | |-------|------|---------|-------------| | `page` | int | 1 | Page number | | `limit` | int | 15 | Items per page (max 100) | | `search` | string | — | Search by mobile, real name, or doctor name | | `status` | string | — | Filter by appointment status | | `date` | string | — | Filter by date in `Y-m-d` format | ### Response `200` ```json { "success": true, "data": [ { "uuid": "string", "patient_name": "string", "patient_mobile": "string", "doctor_name": "string", "clinic_name": "string | null", "appointment_date": "2026-07-25", "appointment_time": "14:30", "slot_start": 1700000000, "status": "reserved", "amount": 0, "created_at": "ISO 8601 string" } ], "meta": { "totalRecords": 8000, "totalPages": 533, "currentPage": 1 } }