Files
clinicpro/docs/api/auth.md
T
hamed e7b90a6399 feat(api): add dashboard endpoints for clinic, doctor, and secretary roles
- Implemented GET /api/v1/dashboard/clinic to return clinic stats and today's schedule for clinic owners.
- Implemented GET /api/v1/dashboard/doctor to return doctor's stats and today's schedule for doctors.
- Implemented GET /api/v1/dashboard/secretary to return stats and conditional appointments for secretaries.

feat(migrations): create user_active_context and mobile_verification_otp tables

- Added migration to create user_active_context table for tracking active user sessions.
- Added migration to create mobile_verification_otp table for handling mobile number verification.

feat(migrations): create site_config table for application settings

- Added migration to create site_config table to store various site configuration settings.

feat(appointments): create MyAppointmentsController for user-specific appointments

- Added MyAppointmentsController to handle fetching user-specific appointments with pagination and filtering.

feat(auth): implement NotificationMobileController for mobile number verification

- Added NotificationMobileController to handle OTP requests and verification for mobile number changes.

feat(auth): create MobileVerificationOtp entity for OTP management

- Created MobileVerificationOtp entity to manage OTP records for mobile verification.

feat(auth): create UserActiveContext entity for user session management

- Created UserActiveContext entity to manage user active sessions.

feat(config): implement SiteConfigController for managing site settings

- Added SiteConfigController to handle fetching and updating site configuration settings.

feat(config): create SiteConfig entity and repository for configuration management

- Created SiteConfig entity and repository to manage site configuration data.
2026-06-11 12:20:12 +03:30

11 KiB

Authentication API

Prefix: /api/v1/user and /oauth
Permission: All endpoints in this module are PUBLIC (no JWT required) except userinfo and logout


POST /api/v1/user/send-code

Send OTP code to mobile number.

Permission: PUBLIC

Request Body

{
  "mobile": "09123456789"
}
Field Type Required Validation
mobile string Format: 09XXXXXXXXX (11 digits)

Response 200

{
  "success": true,
  "data": {
    "uuid": "550e8400-e29b-41d4-a716-446655440000",
    "message": "کد تأیید ارسال شد"
  }
}

Errors

Code HTTP Description
ERR_VALIDATION_001 422 Invalid mobile format
ERR_AUTH_004 429 OTP rate limit exceeded

POST /api/v1/user/verify-code

Verify OTP code. Returns whether this is a new or existing user.

Permission: PUBLIC

Request Body

{
  "uuid": "550e8400-e29b-41d4-a716-446655440000",
  "code": "123456"
}
Field Type Required Description
uuid string UUID returned from send-code
code string 6-digit OTP

Response 200

{
  "success": true,
  "data": {
    "message": "کد تأیید شد",
    "is_new_user": false,
    "uuid": "550e8400-e29b-41d4-a716-446655440000"
  }
}

Errors

Code HTTP Description
ERR_AUTH_002 401 Invalid OTP code
ERR_AUTH_003 401 OTP expired
ERR_VALIDATION_002 422 Missing required field

POST /api/v1/user/register

Complete registration for new users (called only when is_new_user: true).

Permission: PUBLIC

Request Body

{
  "uuid": "550e8400-e29b-41d4-a716-446655440000",
  "real_name": "علی احمدی"
}
Field Type Required Description
uuid string Verified UUID from verify-code
real_name string User's full name

Response 201

{
  "success": true,
  "data": {
    "message": "ثبت‌نام با موفقیت انجام شد",
    "uuid": "550e8400-e29b-41d4-a716-446655440000"
  }
}

Errors

Code HTTP Description
ERR_VALIDATION_002 422 Missing uuid
ERR_CONFLICT_001 409 User already registered

POST /api/v1/user/login

Login with mobile number and password (for users who set a password).

Permission: PUBLIC

Request Body

{
  "mobile_number": "09123456789",
  "password": "mypassword"
}
Field Type Required
mobile_number string
password string

Response 200

{
  "success": true,
  "data": {
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
    "refresh_token": "def50200..."
  }
}

Errors

Code HTTP Description
ERR_AUTH_005 401 Wrong credentials
ERR_AUTH_006 403 Account suspended
ERR_AUTH_004 429 Too many attempts

POST /oauth/token

Exchange verified UUID for JWT access token.

Permission: PUBLIC

Request Body

{
  "grant_type": "mobile",
  "uuid": "550e8400-e29b-41d4-a716-446655440000"
}
Field Type Required Description
grant_type string Must be "mobile"
uuid string UUID from verified OTP flow

Response 200

{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
  "refresh_token": "def50200..."
}

JWT payload: { username: mobile_number, roles: [...], iat, exp }
Access token TTL: 1 hour | Refresh token TTL: 30 days (stored in Redis)

Errors

Code HTTP Description
ERR_AUTH_002 400 Invalid or expired UUID

POST /oauth/token/refresh

Refresh expired JWT using refresh token.

Permission: PUBLIC

Request Body

{
  "refresh_token": "def50200..."
}

Response 200

{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
  "refresh_token": "def50200..."
}

Errors

Code HTTP Description
ERR_AUTH_001 401 Invalid or expired refresh token

GET /oauth/userinfo

Get authenticated user info — extended with multi-context support.

Permission: AUTH — requires valid JWT

Headers

Authorization: Bearer <token>

Response 200

{
  "success": true,
  "data": {
    "id": 4766,
    "uuid": "550e8400-e29b-41d4-a716-446655440000",
    "mobile_number": "09123456789",
    "realName": "دکتر وحید درویشی",
    "status": 1,
    "roles": ["ROLE_USER", "ROLE_DOCTOR"],
    "primary_role": "doctor",
    "db_uuid": "a6ef5d29-38b8-4e69-b1ef-27a304696966",
    "db_key": "hmac-sha256-hash...",
    "context": {
      "type": "doctor",
      "db_uuid": "a6ef5d29-38b8-4e69-b1ef-27a304696966",
      "name": "مطب شخصی دکتر وحید درویشی",
      "role": "doctor"
    },
    "available_contexts": [
      {
        "type": "doctor",
        "db_uuid": "a6ef5d29-38b8-4e69-b1ef-27a304696966",
        "name": "مطب شخصی دکتر وحید درویشی",
        "role": "doctor"
      },
      {
        "type": "clinic",
        "db_uuid": "clinic-uuid-...",
        "name": "کلینیک سلامت",
        "role": "doctor"
      }
    ]
  }
}
فیلد نوع توضیح
primary_role string نقش اصلی: admin | clinic | doctor | secretary | user
db_uuid string|null UUID موجودیت فعال (null = هنوز context انتخاب نشده)
db_key string|null HMAC-SHA256(db_uuid, APP_SECRET) برای اعتبارسنجی
context object|null context فعال انتخاب‌شده
available_contexts array همه محیط‌های کاری قابل انتخاب

قانون primary_role (اولویت‌بندی):

  • ROLE_ADMIN"admin"
  • ROLE_CLINIC"clinic"
  • ROLE_DOCTOR"doctor"
  • ROLE_SECRETARY"secretary"
  • بقیه → "user"

قانون db_uuid:

  • اگر یک context وجود دارد: خودکار فعال می‌شود
  • اگر چند context وجود دارد و کاربر هنوز انتخاب نکرده: null — frontend باید صفحه انتخاب نشان دهد
  • پس از POST /api/v1/auth/switch-context: برابر context انتخاب‌شده

Errors

Code HTTP Description
ERR_AUTH_001 401 Invalid or missing token

POST /api/v1/auth/switch-context

تغییر محیط کاری فعال — باید از لیست available_contexts انتخاب شود.

Permission: AUTH

Request Body

{
  "db_uuid": "clinic-uuid-..."
}
فیلد نوع Required توضیح
db_uuid string (UUID) UUID محیط کاری از لیست available_contexts

Response 200

{
  "success": true,
  "data": {
    "db_uuid": "clinic-uuid-...",
    "db_key": "new-hmac-hash...",
    "context": {
      "type": "clinic",
      "db_uuid": "clinic-uuid-...",
      "name": "کلینیک سلامت",
      "role": "doctor"
    }
  }
}

Errors

Code HTTP Description
ERR_AUTH_001 401 Missing or invalid token
ERR_AUTH_006 403 db_uuid در لیست context های این کاربر نیست
ERR_VALIDATION_001 422 db_uuid ارسال نشده

Notification Mobile (OTP)

Endpoints for setting/verifying a separate SMS notification number for doctors and clinics. This number receives appointment SMS notifications instead of the account login mobile.

Permission: All 4 endpoints require IS_AUTHENTICATED_FULLY (JWT).


POST /api/v1/notification-mobile/request-otp

Request an OTP code to verify a new notification mobile number.

Permission: AUTH

Request Body

{
  "target": "doctor",
  "new_mobile": "09123456789"
}
Field Type Required Validation
target string doctor or clinic
new_mobile string Format: 09XXXXXXXXX

Response 200

{
  "success": true,
  "data": {
    "message": "کد تأیید ارسال شد",
    "expires_in": 300
  }
}

Errors

Code HTTP Description
ERR_VALIDATION_001 422 Invalid target or mobile format
ERR_NOT_FOUND_001 404 No doctor/clinic profile found for this user

Notes

  • Previous unused OTPs for the entity are deleted before creating a new one
  • OTP is 6-digit, expires in 5 minutes
  • Sends via SMS asynchronously

POST /api/v1/notification-mobile/verify

Verify the OTP and save the notification mobile number.

Permission: AUTH

Request Body

{
  "target": "doctor",
  "otp_code": "123456"
}
Field Type Required
target string doctor or clinic
otp_code string 6-digit code

Response 200

{
  "success": true,
  "data": {
    "notification_mobile": "09123456789",
    "message": "شماره اعلان با موفقیت ذخیره شد"
  }
}

Errors

Code HTTP Description
ERR_VALIDATION_001 422 Invalid target / OTP expired / wrong code
ERR_NOT_FOUND_001 404 No OTP request found or profile not found

GET /api/v1/notification-mobile/{target}

Get the current notification mobile for the authenticated user.

Permission: AUTH
Path param: targetdoctor or clinic

Response 200

{
  "success": true,
  "data": {
    "notification_mobile": "09123456789"
  }
}
  • Returns null for notification_mobile if not set

Errors

Code HTTP Description
ERR_NOT_FOUND_001 404 No profile found for this user

DELETE /api/v1/notification-mobile/{target}

Remove the notification mobile number.

Permission: AUTH
Path param: targetdoctor or clinic

Response 200

{
  "success": true,
  "data": {
    "message": "شماره اعلان حذف شد"
  }
}

Errors

Code HTTP Description
ERR_NOT_FOUND_001 404 No profile found for this user

POST /oauth/logout

Invalidate the refresh token (stored in Redis).

Permission: AUTH

Request Body

{
  "refresh_token": "def50200..."
}
Field Type Required
refresh_token string

Response 200

{
  "success": true,
  "data": {
    "message": "با موفقیت خارج شدید"
  }
}