# AuthHex API Documentation Base route: `api` All endpoints are `[AllowAnonymous]` at the HTTP layer, but individual functions may require a Bearer JWT (read via `HttpContext` claims) — noted per function below. ## Common envelope **Request** (`ApiRequest`) ```json { "functionName": "string (required, ignored for dedicated routes below)", "payload": { "...": "function-specific object" }, "reference": "string (required, can be empty)" } ``` **Response** (`ApiResponse`) ```json { "statusCode": 200, "success": true, "message": "success", "data": { "...": "function-specific object" } } ``` Errors: `404` unknown function, `400` (`KeyNotFoundException`/`InvalidOperationException`), `500` (`ArgumentException`). --- ## Routes | Route | Method | Dispatches to | FunctionName | |---|---|---|---| | `/api/status` | GET | — | — (health check) | | `/api/user` | POST | UserManager | from body | | `/api/recovery` | POST | RecoveryManager | from body | | `/api/registerUser` | POST | UserManager | forced `registerUser` | | `/api/loginUser` | POST | UserManager | forced `loginUser` | | `/api/forgotPassword` | POST | RecoveryManager | forced `forgotPassword` | | `/api/alt` | POST | AltOptionManager | from body | ### GET /api/status Response: ```json { "status": "API is running", "timestamp": "2026-07-03T00:00:00Z" } ``` --- ## /api/user — UserManager functions ### registerUser Payload: ```json { "userId": "guid (required)", "fullname": "string?", "userName": "string?", "nic": "string?", "email": "string?", "mobileNumber": "string?", "deviceName": "string? (default 'Unknown Device')", "roleId": "guid (required)", "userTypeId": "guid (required)", "chkUser": "bool? (if true, checks for existing conflicting user)", "password": "string? (auto-generated if empty)" } ``` Data: ```json { "accessToken": "jwt", "refreshToken": "string", "expiresIn": 3600, "user": { "id": "guid", "fullName": "", "userName": "", "email": "", "mobileNumber": "", "emailVerified": false, "mobileNumberVerified": false, "isMfaEnabled": false, "roleId": "guid", "userTypeId": "guid" } } ``` ### loginUser Payload: ```json { "identifier": "string (required)", "password": "string?", "userTypeId": "guid?", "deviceName": "string? (default 'Unknown Device')" } ``` Data: same shape as `registerUser` data. ### VerifyOtpForLogin Payload: ```json { "referenceNumber": "string (required)", "otpCode": "string (required)", "deviceName": "string?" } ``` Data: ```json { "success": true, "message": "OTP verified successfully.", "data": { "referenceNumber": "", "userId": "guid", "verified": true, "accessToken": "jwt", "refreshToken": "", "expiresIn": 3600, "user": { "...": "as above" } } } ``` ### refreshToken Payload: ```json { "refreshToken": "string (required)", "deviceName": "string?" } ``` Data: same shape as `registerUser` data (rotates session). ### getUserDetails Payload: ```json { "userId": "guid (required)" } ``` Data: ```json { "id": "guid", "fullName": "", "userName": "", "email": "", "nic": "", "mobileNumber": "", "emailVerified": false, "mobileNumberVerified": false, "isMfaEnabled": false, "isActive": true, "isLocked": false, "createdAt": "", "role": { "roleId": "", "code": "", "name": "" }, "userType": { "userTypeId": "", "code": "", "description": "" } } ``` ### getUserSessions _Requires auth (userId from claims). No payload needed._ Data: array of ```json { "sessionId": "", "deviceName": "", "browser": "", "os": "", "ipAddress": "", "createdAt": "", "expiresAt": "", "revokedAt": "", "isActive": true } ``` ### ChangeUserStatus _Requires auth._ Payload: ```json { "isActive": "bool (required)" } ``` Data: `{ "id", "fullName", "userName", "email", "mobileNumber", "isActive" }` ### LockUserAccount _Requires auth._ Payload: ```json { "isLocked": "bool (required)" } ``` Data: `{ "id", "fullName", "userName", "email", "mobileNumber", "isLocked", "deletedAt" }` (Also invalidates all user sessions.) ### ChangeUserPassword _Requires auth._ Payload: ```json { "currentPassword": "string (required)", "newPassword": "string (required)" } ``` Data: `{ "message": "Password changed successfully" }` ### LogoutUser Payload: ```json { "userId": "guid (required)" } ``` Data: `{ "message": "User logged out successfully" }` ### UpdateUser _Requires auth._ Payload (all optional, at least one required): ```json { "fullName": "string?", "userName": "string?", "nic": "string?", "address": "string?", "optional1": "string?", "optional2": "string?", "email": "string|null", "mobileNumber": "string|null", "currentPassword": "string? (required if newPassword set and existing password set)", "newPassword": "string?" } ``` Data: ```json { "message": "User updated successfully", "user": { "id", "fullName", "userName", "nic", "address", "optional1", "optional2", "email", "emailVerified", "mobileNumber", "mobileNumberVerified" } } ``` ### 2FA — initiateTwoFASetup _Requires auth. No payload._ Data: third-party-service-defined setup result (QR/secret info). ### 2FA — completeTwoFASetup _Requires auth._ Payload: ```json { "secretKey": "string (required)", "verificationCode": "string (required)" } ``` Data: ```json { "message": "2FA setup completed successfully", "backupCodes": ["..."], "user": { "id", "fullName", "userName", "email", "isMfaEnabled" } } ``` ### 2FA — verifyTwoFA _Requires auth._ Payload: ```json { "verificationCode": "string (required)" } ``` Data: raw third-party verification result object. ### 2FA — disableTwoFA _Requires auth._ Payload: ```json { "verificationCode": "string (required)" } ``` Data: ```json { "message": "2FA has been disabled successfully", "user": { "id", "fullName", "userName", "email", "isMfaEnabled" } } ``` ### 2FA — getTwoFAStatus _Requires auth. No payload._ Data: ```json { "isMfaEnabled": false, "isVerified": false, "lastUsedAt": null, "verifiedAt": null, "hasBackupCodes": false } ``` --- ## /api/recovery — RecoveryManager functions ### forgotPassword Payload: ```json { "identifier": "string (required)", "useResetLink": "bool? (default false)", "numberOfDigits": "int? (default 6)" } ``` Data (useResetLink = true): ```json { "success": true, "message": "Password reset link sent to your email.", "data": { "referenceNumber": "", "expiresAt": "", "recoveryType": "ResetLink" } } ``` Data (useResetLink = false, OTP flow): ```json { "success": true, "message": "OTP sent successfully.", "data": { "referenceNumber": "", "expiresAt": "", "recoveryType": "OTP" } } ``` ### verifyOTP Payload: ```json { "referenceNumber": "string (required)", "otpCode": "string (required)" } ``` Data: ```json { "success": true, "message": "OTP verified successfully. You can now reset your password.", "data": { "referenceNumber": "", "userId": "guid", "verified": true } } ``` ### resetPasswordWithToken Payload: ```json { "resetToken": "string (required)", "newPassword": "string (required, min 8 chars)", "confirmPassword": "string (required, must match)" } ``` Data: ```json { "success": true, "message": "Password reset successful. Please login with your new password.", "data": { "userId": "guid", "email": "", "resetAt": "" } } ``` ### resetPassword Payload: ```json { "referenceNumber": "string (required)", "newPassword": "string (required, min 8 chars)", "confirmPassword": "string (required, must match)" } ``` (Requires recovery status = "Verified" via prior `verifyOTP` call.) Data: same shape as `resetPasswordWithToken`. --- ## /api/alt — AltOptionManager functions ### IsAvailable Payload: ```json { "Identifier": "string?", "Recovery": "string? (any non-null value flags recovery-mode)" } ``` Data (available): `{ "isAvailable": true, "message": "Identifier is available" }` Data (taken, no Recovery): `{ "isAvailable": false, "message": "Identifier already in use" }` Data (taken, Recovery set): `{ "existingUsers": [...] }` ### sendOtp Payload: ```json { "identifier": "string (required, email or mobile)", "numberOfDigits": "int? (default 4)", "newUser": "bool? (default false)" } ``` Data (newUser = true): ```json { "success": true, "message": "OTP sent successfully for new user.", "data": { "referenceNumber": "", "expiresAt": "", "recoveryType": "OTP FOR NEW USER" } } ``` Data (existing user): ```json { "success": true, "message": "OTP sent successfully.", "data": { "referenceNumber": "", "expiresAt": "", "recoveryType": "OTP FOR LOGIN" } } ``` ### VerifyOTP (alt) Payload: ```json { "userId": "guid?", "referenceNumber": "string (required)", "otpCode": "string (required)", "newUser": "bool? (default false)", "identifier": "string? (email/mobile/other — marks it verified on user)", "deviceName": "string? (default 'Unknown Device')" } ``` Data: ```json { "success": true, "message": "OTP verified successfully.", "data": { "referenceNumber": "", "userId": "guid", "verified": true, "accessToken": "jwt", "refreshToken": "", "expiresIn": 3600, "user": { "id", "fullName", "userName", "email", "mobileNumber", "emailVerified", "mobileNumberVerified", "isMfaEnabled", "roleId", "userTypeId" } } } ``` --- ## Notes - All timestamps are UTC. - `deviceName`, `Browser`, `OS`, `IPAddress` are captured per session from request headers for session tracking (`getUserSessions`). - Password login validation (`PasswordHasher.Verify`) is currently commented out in `loginUser` — passwords are not checked on login as of this version. - JWT access tokens issued with `expiresIn: 3600` (1 hour); refresh tokens/sessions expire after 30 days.