# 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 ```json { "mobile": "09123456789" } ``` | Field | Type | Required | Validation | |-------|------|----------|------------| | `mobile` | string | ✅ | Format: `09XXXXXXXXX` (11 digits) | ### Response `200` ```json { "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 ```json { "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` ```json { "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 ```json { "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` ```json { "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 ```json { "mobile_number": "09123456789", "password": "mypassword" } ``` | Field | Type | Required | |-------|------|----------| | `mobile_number` | string | ✅ | | `password` | string | ✅ | ### Response `200` ```json { "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 ```json { "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` ```json { "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 ```json { "refresh_token": "def50200..." } ``` ### Response `200` ```json { "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. **Permission:** `AUTH` — requires valid JWT ### Headers ``` Authorization: Bearer ``` ### Response `200` ```json { "success": true, "data": { "uuid": "550e8400-e29b-41d4-a716-446655440000", "mobile_number": "09123456789", "real_name": "علی احمدی", "roles": ["ROLE_USER"], "status": "active", "created_at": 1717000000 } } ``` ### Errors | Code | HTTP | Description | |------|------|-------------| | `ERR_AUTH_001` | 401 | Invalid or missing token | --- ## POST `/oauth/logout` Invalidate the refresh token (stored in Redis). **Permission:** `AUTH` ### Request Body ```json { "refresh_token": "def50200..." } ``` | Field | Type | Required | |-------|------|----------| | `refresh_token` | string | ❌ | ### Response `200` ```json { "success": true, "data": { "message": "با موفقیت خارج شدید" } } ```