# Doctor API > **Prefix:** `/api/v1/doctor`, `/api/v1/doctors`, `/api/v1/clinic-pro/doctor-address*` --- ## POST `/api/v1/doctor` Create a doctor profile for the authenticated user. **Permission:** `AUTH` — any authenticated user ### Request Body (`application/json`) ```json { "title": "دکتر علی احمدی", "gender": "male", "medical_system_code": "12345", "degree": "متخصص", "info": "توضیحات درباره پزشک", "specialties": [1, 2], "doctor_services": [3, 4] } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `title` | string | ✅ | Full name with title | | `gender` | string | ❌ | `"male"` or `"female"` | | `medical_system_code` | string | ❌ | Nظام پزشکی code | | `degree` | string | ❌ | Academic degree | | `info` | string | ❌ | Bio/description | | `specialties` | integer[] | ❌ | Array of specialty IDs | | `doctor_services` | integer[] | ❌ | Array of doctor service IDs | ### Response `201` ```json { "success": true, "data": { "uuid": "550e8400-e29b-41d4-a716-446655440000", "title": "دکتر علی احمدی", "gender": "male", "medical_system_code": "12345", "degree": "متخصص", "info": "...", "doctor_rate": null, "active_doctor_appointment": false, "specialties": [], "doctor_services": [], "created_at": 1717000000 } } ``` ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Missing or invalid token | | `ERR_CONFLICT_001` | 409 | Doctor profile already exists for this user | | `ERR_VALIDATION_002` | 422 | Missing required field | --- ## GET `/api/v1/doctor/{uuid}` Get doctor detail with clinics. **Permission:** `PUBLIC` ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `uuid` | string (UUID) | Doctor UUID | ### Response `200` ```json { "success": true, "data": { "data": { "uuid": "550e8400-...", "name": "دکتر علی احمدی", "gender": "man", "medical_system_code": "12345", "degree": "specialist", "detail": "...", "img": [], "social_media": { "instagram": "https://instagram.com/dr.example", "telegram": "https://t.me/dr_example", "aparat": null, "youtube": null, "linkedin": null }, "satisfaction": "60", "point": "3.5", "free_turn": "دوشنبه 09:00–13:00", "hours_of_work": "شنبه: 09:00–13:00 و 14:00–18:00 | یکشنبه: 09:00–13:00", "active": true, "specialties": [{ "uuid": "...", "id": "1", "name": "قلب و عروق", "parent_id": null }], "expertise": [{ "uuid": "...", "id": "3", "name": "نوار قلب" }], "address": [], "state": [], "city": [], "clinics": [{ "uuid": "...", "name": "کلینیک الوند", "address": "...", "telephone": "..." }] } } } ``` > ⚠️ **Double-nested:** Frontend extracts with `data?.data?.data` ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_NOT_FOUND_001` | 404 | Doctor not found | --- ## GET `/api/v1/clinic/my-doctor/{doctorUuid}` Get doctor detail for clinic owner — only doctors who are members of the authenticated clinic. **Permission:** `ROLE_CLINIC` ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `doctorUuid` | string (UUID) | Doctor UUID | ### Response `200` ```json { "success": true, "data": { "data": { "uuid": "...", "title": "دکتر علی احمدی", "specialties": [...], "clinics": [{ "uuid": "...", "name": "کلینیک نور", "address": "...", "telephone": "..." }] } } } ``` > ⚠️ **Double-nested:** Frontend extracts with `data?.data?.data` > **Side note:** Returns only the authenticated clinic's data in the `clinics` array (not all clinics of the doctor). ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_VALIDATION_002` | 404 | Clinic or doctor not found | | `ERR_AUTH_006` | 403 | Doctor is not a member of this clinic | --- ### Schedule Fields Notes | Field | When schedule exists | When no schedule | |-------|---------------------|-----------------| | `free_turn` | نزدیک‌ترین روز/ساعت کاری از امروز (مثلاً «دوشنبه ۹:۰۰–۱۳:۰۰») | «نوبت آزادی موجود نیست» | | `hours_of_work` | خلاصه ساعت‌های روزهای فعال با `\|` جداشده | «برنامه کاری تنظیم نشده» | | `active` | `activeDoctorAppointment && has_active_sessions` | `false` — نوبت‌دهی غیرفعال | --- ## GET `/api/v1/doctors` List doctors with pagination and filters. **Permission:** `PUBLIC` ### Query Parameters | Param | Type | Required | Description | |-------|------|----------|-------------| | `page` | integer | ❌ | Default: 1 | | `limit` | integer | ❌ | Default: 20 | | `search` | string | ❌ | Search in title | | `specialty` | integer | ❌ | Filter by specialty ID | | `city` | integer | ❌ | Filter by city ID — شامل دکترهایی که مستقیم در آن شهر هستند (`doctor_cities`) یا از طریق کلینیکی که آدرس آن در آن شهر است (`doctor_addresses.clinic_id`) | | `state` | integer | ❌ | Filter by province ID | ### Response `200` ```json { "success": true, "data": [ { "uuid": "...", "name": "دکتر علی احمدی", "gender": "man", "degree": "specialist", "img": [], "specialties": [{ "uuid": "...", "id": "1", "name": "قلب و عروق" }], "satisfaction": "60", "point": "3.5", "free_turn": "دوشنبه 09:00–13:00", "hours_of_work": "شنبه: 09:00–13:00 و 14:00–18:00 | یکشنبه: 09:00–13:00", "active": true } ], "meta": { "totalRecords": 50, "totalPages": 3, "currentPage": 1 } } ``` --- ## PATCH `/api/v1/doctor/{uuid}` Update doctor profile. **Permission:** `AUTH` — must be the owner (or `ROLE_ADMIN`) ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `uuid` | string (UUID) | Doctor UUID | ### Request Body (`application/json`) Same fields as POST (all optional), plus: | Field | Type | Description | |-------|------|-------------| | `social_media` | object | Keys: `instagram`, `telegram`, `aparat`, `youtube`, `linkedin`. Each value must be a full valid URL or `null`. Any value that fails `FILTER_VALIDATE_URL` is silently stored as `null`. | ```json { "social_media": { "instagram": "https://instagram.com/dr.example", "telegram": "https://t.me/dr_example", "aparat": null, "youtube": null, "linkedin": null } } ``` ### Response `200` Updated doctor object (same structure as GET single). ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Missing token | | `ERR_FORBIDDEN_001` | 403 | Not the owner | | `ERR_NOT_FOUND_001` | 404 | Doctor not found | --- ## DELETE `/api/v1/doctor/{uuid}` Delete a doctor profile. **Permission:** `ROLE_ADMIN` ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `uuid` | string (UUID) | Doctor UUID | ### Response `200` ```json { "success": true, "data": { "message": "پزشک با موفقیت حذف شد" } } ``` ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Missing token | | `ERR_AUTH_006` | 403 | Not admin | | `ERR_NOT_FOUND_001` | 404 | Doctor not found | --- ## POST `/file/upload/clinic_pro/doctor/field_image` Upload doctor profile image. **Permission:** `AUTH` ### Request `Content-Type: multipart/form-data` | Field | Type | Required | Description | |-------|------|----------|-------------| | `file` | binary | ✅ | Image file (max 5MB) | ### Response `200` ```json { "success": true, "data": { "url": "https://clinic-pro.ddev.site/uploads/doctor/abc123.jpg", "uuid": "...", "filename": "abc123.jpg", "filemime": "image/jpeg", "filesize": 204800 } } ``` ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_FILE_001` | 422 | Invalid file type | | `ERR_AUTH_001` | 401 | Missing token | --- ## GET `/api/v1/clinic-pro/doctor-addresses/{doctorId}` Get all practice addresses for a doctor, including addresses of clinics the doctor is a member of. **Permission:** `PUBLIC` ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `doctorId` | integer | Doctor's numeric ID | ### Response `200` ```json { "success": true, "data": [ { "id": "1", "uuid": "...", "type": "personal", "clinic_id": null, "clinic_name": null, "name": "مطب تهران", "address": "تهران، خیابان...", "telephone": "02112345678", "map": { "latitude": "35.6892", "longitude": "51.3890" }, "city": { "id": "1", "name": "تهران" }, "province": { "id": "1", "name": "تهران" } }, { "id": "5", "uuid": "...", "type": "clinic", "clinic_id": 12, "clinic_name": "کلینیک الوند", "name": null, "address": "اصفهان، خیابان...", "telephone": "03112345678", "map": { "latitude": null, "longitude": null }, "city": { "id": "3", "name": "اصفهان" }, "province": { "id": "2", "name": "اصفهان" } } ] } ``` > **نکته:** آدرس‌های با `type: "clinic"` از کلینیک‌هایی که پزشک عضو آن‌هاست می‌آیند و `clinic_name` نام کلینیک را نشان می‌دهد. --- ## POST `/api/v1/clinic-pro/doctor-address` Add a new practice address. **Permission:** `AUTH` — must own the doctor profile ### Request Body ```json { "name": "مطب تهران", "address": "تهران، خیابان ولیعصر", "telephone": "02112345678", "province_id": 1, "city_id": 3, "latitude": 35.6892, "longitude": 51.3890 } ``` | Field | Type | Required | |-------|------|----------| | `name` | string | ❌ | | `address` | string | ✅ (frontend validation) | | `telephone` | string | ✅ (frontend validation) | | `province_id` | integer | ✅ (frontend validation) | | `city_id` | integer | ✅ (frontend validation) | | `latitude` | float | ❌ | | `longitude` | float | ❌ | ### Response `201` ```json { "success": true, "data": { "id": 1, "name": "مطب تهران", "address": "تهران، خیابان ولیعصر", "telephone": "02112345678", "latitude": 35.6892, "longitude": 51.3890 } } ``` ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Missing token | | `ERR_FORBIDDEN_001` | 403 | Not the doctor owner | | `ERR_NOT_FOUND_001` | 404 | Doctor not found | --- ## PATCH `/api/v1/clinic-pro/doctor-address/{id}` Update a practice address. **Permission:** `AUTH` — must own the doctor profile ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `id` | integer | Address ID | ### Request Body Same fields as POST — all optional. ### Response `200` Updated address object. ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Missing token | | `ERR_FORBIDDEN_001` | 403 | Not the owner | | `ERR_NOT_FOUND_001` | 404 | Address not found | --- ## DELETE `/api/v1/clinic-pro/doctor-address/{id}` Delete a practice address. **Permission:** `AUTH` — must own the doctor profile ### Response `200` ```json { "success": true, "data": { "message": "آدرس حذف شد" } } ``` ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Missing token | | `ERR_FORBIDDEN_001` | 403 | Not the owner | | `ERR_NOT_FOUND_001` | 404 | Address not found | --- ## POST `/api/v1/clinic-pro/doctor-address/from-clinic/{clinicUuid}` Create a doctor address automatically from a clinic's location. **Permission:** `AUTH` — must own the doctor profile and be associated with the clinic ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `clinicUuid` | string (UUID) | Clinic UUID | ### Response `201` Address object created from clinic data. ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_FORBIDDEN_001` | 403 | Not associated with this clinic | | `ERR_NOT_FOUND_001` | 404 | Clinic not found |