# Clinic Doctor Invitation API > **Prefix:** `/api/v1/admin/clinic/...` (admin) and `/api/v1/clinic-invitation/...` (public) Admins invite doctors to clinics via SMS. The doctor receives a secure 96-char token link valid for 72 hours. --- ## POST `/api/v1/admin/clinic/{uuid}/invite-doctor` Send an invitation to a doctor (by mobile number) to join a clinic. **Permission:** `ROLE_ADMIN` ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `uuid` | string (UUID) | Clinic UUID | ### Request Body (`application/json`) ```json { "mobile": "09123456789", "name": "دکتر علی احمدی", "specialty": "قلب و عروق" } ``` | Field | Type | Required | Validation | |-------|------|----------|------------| | `mobile` | string | ✅ | Format: `09XXXXXXXXX` | | `name` | string | ❌ | Doctor's display name | | `specialty` | string | ❌ | Specialty label for SMS | ### Response `201` ```json { "success": true, "data": { "uuid": "inv-uuid-...", "mobile": "09123456789", "invited_name": "دکتر علی احمدی", "invited_specialty": "قلب و عروق", "status": "pending", "invited_at": 1717000000, "expires_at": 1717259200, "token_used": false, "clinic": { "uuid": "...", "name": "کلینیک الوند" } } } ``` > SMS is dispatched **asynchronously** via Symfony Messenger → Redis queue. > SMS text: `"دکتر گرامی، کلینیک {name} شما را برای همکاری دعوت کرده است.\nبرای بررسی: {link}\nاین لینک تا ۷۲ ساعت معتبر است."` ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Missing or invalid token | | `ERR_AUTH_006` | 403 | Not admin | | `ERR_NOT_FOUND_001` | 404 | Clinic not found | | `ERR_VALIDATION_001` | 422 | Invalid mobile format | --- ## GET `/api/v1/admin/clinic/{uuid}/invitations` List all invitations for a clinic. **Permission:** `ROLE_ADMIN` ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `uuid` | string (UUID) | Clinic UUID | ### Query Parameters | Param | Type | Required | Default | |-------|------|----------|---------| | `page` | integer | ❌ | 1 | | `limit` | integer | ❌ | 50 | ### Response `200` ```json { "success": true, "data": [ { "uuid": "...", "mobile": "09123456789", "invited_name": "دکتر علی احمدی", "invited_specialty": "قلب و عروق", "status": "pending", "invited_at": 1717000000, "expires_at": 1717259200, "responded_at": null, "token_used": false, "doctor": null } ], "meta": { "totalRecords": 5, "totalPages": 1, "currentPage": 1 } } ``` **Invitation Status Values:** | Value | Description | |-------|-------------| | `pending` | Sent, awaiting response | | `accepted` | Doctor accepted | | `rejected` | Doctor rejected | | `suspended` | Suspended by admin | | `removed` | Removed | ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Missing token | | `ERR_AUTH_006` | 403 | Not admin | | `ERR_NOT_FOUND_001` | 404 | Clinic not found | --- ## POST `/api/v1/admin/clinic/invitation/{invUuid}/resend` Resend the invitation SMS with a fresh token and reset expiry to +72 hours. **Permission:** `ROLE_ADMIN` ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `invUuid` | string (UUID) | Invitation 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 | Invitation not found | --- ## PATCH `/api/v1/admin/clinic/invitation/{invUuid}/status` Change the status of an invitation (e.g., suspend or remove). **Permission:** `ROLE_ADMIN` ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `invUuid` | string (UUID) | Invitation UUID | ### Request Body ```json { "status": "suspended" } ``` | Field | Type | Required | Allowed Values | |-------|------|----------|----------------| | `status` | string | ✅ | `pending`, `suspended`, `removed` | ### Response `200` ```json { "success": true, "data": { "status": "suspended" } } ``` ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Missing token | | `ERR_AUTH_006` | 403 | Not admin | | `ERR_NOT_FOUND_001` | 404 | Invitation not found | | `ERR_VALIDATION_001` | 422 | Invalid status value | --- ## DELETE `/api/v1/admin/clinic/invitation/{invUuid}` Delete an invitation. **Permission:** `ROLE_ADMIN` ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `invUuid` | string (UUID) | Invitation UUID | ### Response `204` Empty body. ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Missing token | | `ERR_AUTH_006` | 403 | Not admin | | `ERR_NOT_FOUND_001` | 404 | Invitation not found | --- ## GET `/api/v1/clinic-invitation/{token}` View invitation details by token (used on the doctor-facing landing page). **Permission:** `PUBLIC` ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `token` | string | 96-char hex token from SMS link | ### Response `200` ```json { "success": true, "data": { "invitation": { "uuid": "...", "mobile": "09123456789", "invited_name": "دکتر علی احمدی", "invited_specialty": "قلب و عروق", "status": "pending", "expires_at": 1717259200 }, "clinic": { "uuid": "...", "name": "کلینیک الوند", "city": "تهران", "clinic_logo": "https://..." }, "is_usable": true } } ``` > `is_usable: false` when: token already used, expired, or status is not `pending` ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_NOT_FOUND_001` | 404 | Token not found | --- ## POST `/api/v1/clinic-invitation/{token}/accept` Doctor accepts the invitation. If a doctor profile exists for this mobile, they are automatically linked to the clinic. **Permission:** `PUBLIC` ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `token` | string | 96-char hex token | ### Response `200` ```json { "success": true, "data": { "message": "دعوتنامه پذیرفته شد" } } ``` ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_NOT_FOUND_001` | 404 | Token not found | | `ERR_VALIDATION_001` | 422 | Token expired or already used | --- ## POST `/api/v1/clinic-invitation/{token}/reject` Doctor rejects the invitation. **Permission:** `PUBLIC` ### Path Parameters | Param | Type | Description | |-------|------|-------------| | `token` | string | 96-char hex token | ### Response `200` ```json { "success": true, "data": { "message": "دعوتنامه رد شد" } } ``` ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_NOT_FOUND_001` | 404 | Token not found | | `ERR_VALIDATION_001` | 422 | Token expired or already used |