Skip to main content

User Profile Management Service

Author: Josh S. Sakweli, Backend Lead Team
Last Updated: 2025-09-232026-05-19
Version: v1.0

Base URL: {base_url}/api/v1/profile

Short Description: The UserProfile API manages a user's social presence β€” what others see when they visit your page. This includes viewing your own full profile, looking up other users by ID or username, and updating your display information such as name, bio, location, and profile pictures.

Why Account and Profile ManagementAre ServiceSeparate:

handles
user

Profile = how you appear to others (display name, bio, location, picture, social stats). Account = who you are in the system (credentials, security, identity verification).

Profile operations are social in nature β€” some endpoints (/id/{userId}, /u/{username}) are intentionally viewable by any authenticated user, not just the owner. Account operations carry security implications and are always strictly private. By separating the two, we can apply the right access rules to each: profile updates,data securitycan settings,be shared, account verification,data passwordcannot. changes,Anything andthat accounttouches managementcredentials for(password, 2FA, email, phone) belongs in the NextGateAccount socialAPI, commercenot platform.here.

This service provides comprehensive profile management with security controls, two-factor authentication, and account verification capabilities.

Hints:

  • AllGET endpoints/me requirerequires JWTauthentication; Bearerit tokenreturns authenticationprivate fields like email, phoneNumber, and securityStrength only visible to the account owner
  • PasswordGET changes trigger automatic logout/id/{userId} and requireGET re-authentication/u/{username} work for both authenticated and unauthenticated callers β€” authenticated callers additionally receive relationship info (isFollowing, isBlocked, etc.)
  • UsernamePUT changes/update requireonly immediateaccepts re-loginsocial/display withfields newβ€” credentials
  • to
  • Email/change username use POST /api/v1/account/username/change; to change email or phone updatesuse requirethe OTPAccount verificationLinking for securityAPI
  • Profile picture URLs must be validpublicly HTTPSaccessible https:// image URLs (maxending in .jpg, .jpeg, .png, .gif, or .webp
  • Maximum 5 pictures)
  • profile
  • Securitypicture strength is calculated based on verification status and 2FA
  • Account deactivation locks the account instead of deleting data
  • Rate limiting applies to OTP verification requests (5URLs per 10-minute window)account

EndpointsStandard Response Format

1.

Success Get Current User Profile

Purpose: Retrieve complete profile information for the authenticated user

Endpoint: GET https://apinexgate.glueauth.com/api/v1/profile/me

Access Level: πŸ”’ Protected (Requires JWT Bearer token)

Authentication: Bearer Token (JWT access token required)

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer {access_token}
Content-TypestringYesMust be "application/json"

Response JSON Sample:

Structure
{
  "success": true,
  "httpStatus": "OK",
  "message": "ProfileOperation retrievedcompleted successfully",
  "action_time": "2025-09-23T10:30:00"45",
  "data": {}
}

Error Response Structure

{
  "id": "123e4567-e89b-12d3-a456-426614174000",
    "userName": "johndoe-a1B2c3D",
    "firstName": "John",
    "lastName": "Doe",
    "middleName": "Michael",
    "email": "john.doe@example.com",
    "phoneNumber": "+255712345678",
    "isVerified": true,
    "isEmailVerified": true,
    "isPhoneVerified"success": false,
  "isTwoFactorEnabled": false,
    "isAccountLocked": false,
    "createdAt"httpStatus": "2025-09-23T10:00:00"BAD_REQUEST",
  "editedAt"message": "Error description",
  "action_time": "2025-09-23T10:30:00"45",
  "roles": ["ROLE_NORMAL_USER"],
    "profilePictureUrls": [
      "https://files.nextgate.com/bucket-uuid/profile/avatar1.jpg",
      "https://files.nextgate.com/bucket-uuid/profile/avatar2.jpg"
    ],
    "securityStrength": {
      "score": 65,
      "level"data": "MEDIUM",Error "description": "Your account security is good but can be improved",
      "recommendations": [
        "Verify your phone number",
        "Enable two-factor authentication"
      ]
    }
  }
}

Standard Response Fields:

indicating onsuccess,errordetails
FieldType Description
success Booleanboolean true operationfor successsuccessful operations, false for errors
httpStatusstring HTTP status codename as(OK, stringBAD_REQUEST, NOT_FOUND, etc.)
message SuccessstringHuman-readable message describing the result
action_timestring ISO 8601 timestamp of when the response generationwas generated
data.iddata Unique user identifier (UUID)
data.userNameobject/string User'sResponse uniquepayload username
data.firstName User'son first name
data.lastNameUser's last name
data.middleNameUser's middle name
data.emailUser's email address
data.phoneNumberUser's phone number in international format
data.isVerifiedOverall account verification status
data.isEmailVerifiedEmail verification status
data.isPhoneVerifiedPhone number verification status
data.isTwoFactorEnabledTwo-factor authentication status
data.isAccountLockedAccount lock status
data.createdAtAccount creation timestamp
data.editedAtLast profile modification timestamp
data.rolesArray of user roles/permissions
data.profilePictureUrlsArray of profile picture URLs (max 5)
data.securityStrength.scoreSecurity score from 0-100
data.securityStrength.levelSecurity level (WEAK, MEDIUM, STRONG, VERY_WEAK)
data.securityStrength.descriptionHuman-readable security assessment
data.securityStrength.recommendationsArray of security improvement suggestionsfailure

Standard Error Responses:

Types

  • 401400 UnauthorizedBAD_REQUEST: MissingInvalid request data or business rule violation
  • 401 UNAUTHORIZED: Missing, expired, or invalid JWT token
  • 404 Not FoundNOT_FOUND: User account not found
  • 500422 Internal Server ErrorUNPROCESSABLE_ENTITY: Server-side processingValidation errors with field-level detail
  • 500 INTERNAL_SERVER_ERROR: Unexpected server error

2.Endpoints

Update

1. BasicGet My Profile Information

Purpose: UpdateReturns user'sthe basicfull profile informationof the currently authenticated user, including username,private names,fields (email, phone, and profile pictures

Endpoint: PUT https://apinexgate.glueauth.com/api/v1/profile/update-basic-info

Access Level: πŸ”’ Protected (Requires JWT Bearer token) ⚠️ Username changes require re-authentication

Authentication: Bearer Token (JWT access token required)

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer {access_token}
Content-TypestringYesMust be "application/json"

Request JSON Sample:

{
  "userName": "johnsmith",
  "firstName": "John",
  "lastName": "Smith",
  "middleName": "Michael",
  "email": "john.smith@example.com",
  "phoneNumber": "+255723456789",
  "profilePictureUrls": [
    "https://files.nextgate.com/bucket-uuid/profile/new-avatar.jpg",
    "https://files.nextgate.com/bucket-uuid/profile/banner.jpg"
  ]
}

Request Body Parameters:

ParameterTypeRequiredDescriptionValidation
userNamestringNoNew username (triggers re-authentication if changed)3-30 chars, start with letter, alphanumeric + underscore/hyphen only
firstNamestringNoUser's first name1-30 characters
lastNamestringNoUser's last name1-30 characters
middleNamestringNoUser's middle nameMax 30 characters
emailstringNoUser's email address (requires re-verification if changed)Valid email format
phoneNumberstringNoPhone number (requires re-verification if changed)E.164 international format (+1234567890)
profilePictureUrlsarrayNoArray of profile picture URLsMax 5 URLs, valid HTTPS image URLs only

Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Username changed successfully! You will be logged out automatically. Please login again with your new username.",
  "action_time": "2025-09-23T10:35:00",
  "data": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "userName": "johnsmith",
    "firstName": "John",
    "lastName": "Smith",
    "middleName": "Michael",
    "email": "john.smith@example.com",
    "phoneNumber": "+255723456789",
    "isVerified": true,
    "isEmailVerified": false,
    "isPhoneVerified": false,
    "isTwoFactorEnabled": false,
    "isAccountLocked": false,
    "createdAt": "2025-09-23T10:00:00",
    "editedAt": "2025-09-23T10:35:00",
    "roles": ["ROLE_NORMAL_USER"],
    "profilePictureUrls": [
      "https://files.nextgate.com/bucket-uuid/profile/new-avatar.jpg",
      "https://files.nextgate.com/bucket-uuid/profile/banner.jpg"
    ],
    "securityStrength": {
      "score": 40,
      "level": "WEAK",
      "description": "Your accountstatus, security needs improvement",
      "recommendations": [
        "Verify your email address",
        "Verify your phone number",
        "Enable two-factor authentication"
      ]
    }
  }
}

Response Fields:

FieldDescription
successBoolean indicating operation success
httpStatusHTTP status code as string
messageSuccess message (special message if username changed)
action_timeISO 8601 timestamp of response generation
dataUpdated UserProfileResponse object with complete profile data

Error Responses:

  • 400 Bad Request: Invalid input data or validation errors
  • 401 Unauthorized: Missing or invalid JWT token
  • 409 Conflict: Username or email already taken
  • 422 Unprocessable Entity: Validation errors (reserved username, invalid format)
  • 500 Internal Server Error: Server-side processing errors

3. Change Password

Purpose: Change user's password with current password verificationstrength) and strengthsocial validation

Endpoint: PUT https://apinexgate.glueauth.com/api/v1/profile/change-password

Access Level: πŸ”’ Protectedstats (Requiresfollowers, JWTposts, Bearershops, token) ⚠️ Triggers automatic logout

Authentication: Bearer Token (JWT access token required)

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer {access_token}
Content-TypestringYesMust be "application/json"

Request JSON Sample:

{
  "currentPassword": "OldPassword123!",
  "newPassword": "NewSecurePass456@",
  "confirmPassword": "NewSecurePass456@"
}

Request Body Parameters:

ParameterTypeRequiredDescriptionValidation
currentPasswordstringYesUser's current passwordMust match current password
newPasswordstringYesNew passwordMin 8 chars, uppercase, lowercase, digit, special character
confirmPasswordstringYesConfirmation of new passwordMust match newPassword exactly

Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Password changed successfully",
  "action_time": "2025-09-23T10:40:00",
  "data": null
}

Response Fields:

FieldDescription
successBoolean indicating operation success
httpStatusHTTP status code as string
messageSuccess message confirming password change
action_timeISO 8601 timestamp of response generation
dataAlways null for password change operations

Error Responses:

  • 400 Bad Request: Invalid password format or passwords don't match
  • 401 Unauthorized: Missing or invalid JWT token or incorrect current password
  • 422 Unprocessable Entity: Password strength requirements not met
  • 500 Internal Server Error: Server-side processing errors

4. Validate Username Availability

Purpose: Check if a username is available and valid, with suggestions if taken

Endpoint: GET https://apinexgate.glueauth.com/api/v1/profile/validate-username/{username}

Access Level: πŸ”’ Protected (Requires JWT Bearer token)

Authentication: Bearer Token (JWT access token required)

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer {access_token}
Content-TypestringYesMust be "application/json"

Path Parameters:

ParameterTypeRequiredDescriptionValidation
usernamestringYesUsername to validate3-30 characters, alphanumeric + underscore/hyphen

Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Username validation completed",
  "action_time": "2025-09-23T10:45:00",
  "data": {
    "available": false,
    "valid": true,
    "message": "This username is already taken",
    "suggestions": [
      "johnsmith1",
      "johnsmith2",
      "johnsmithuser",
      "johnsmith2024",
      "johnsmithpro"
    ],
    "details": {
      "correctLength": true,
      "validFormat": true,
      "notReserved": true,
      "notTaken": false,
      "formatRequirement": "Username must start with a letter and be 3-30 characters long"
    }
  }
}

Response Fields:

FieldDescription
successBoolean indicating operation success
httpStatusHTTP status code as string
messageSuccess message
action_timeISO 8601 timestamp of response generation
data.availableBoolean indicating if username is available for use
data.validBoolean indicating if username format is valid
data.messageDetailed validation message
data.suggestionsArray of alternative username suggestions (if taken)
data.details.correctLengthBoolean indicating if length requirements are met
data.details.validFormatBoolean indicating if format requirements are met
data.details.notReservedBoolean indicating if username is not reserved
data.details.notTakenBoolean indicating if username is not already taken
data.details.formatRequirementString describing format requirements

Error Responses:

  • 400 Bad Request: Invalid username parameter
  • 401 Unauthorized: Missing or invalid JWT token
  • 500 Internal Server Error: Server-side processing errors

5. Request Email Verification

Purpose: Send OTP to user's email for email verification

Endpoint: POST https://apinexgate.glueauth.com/api/v1/profile/request-email-verification

Access Level: πŸ”’ Protected (Requires JWT Bearer token)

Authentication: Bearer Token (JWT access token required)

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer {access_token}
Content-TypestringYesMust be "application/json"

Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Email verification OTP sent successfully",
  "action_time": "2025-09-23T10:50:00",
  "data": {
    "tempToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.events)..",
    "message": "Verification email sent successfully",
    "expireAt": "2025-09-23T11:00:00",
    "email": "jo***@example.com"
  }
}

Response Fields:

FieldDescription
successBoolean indicating operation success
httpStatusHTTP status code as string
messageSuccess message
action_timeISO 8601 timestamp of response generation
data.tempTokenJWT temporary token for OTP verification
data.messageSpecific message about email sending
data.expireAtISO 8601 timestamp when temp token expires
data.emailMasked email address for privacy

Error Responses:

  • 400 Bad Request: Email already verified
  • 401 Unauthorized: Missing or invalid JWT token
  • 429 Too Many Requests: Rate limit exceeded for OTP requests
  • 500 Internal Server Error: Email sending or server errors

6. Verify Email

Purpose: Complete email verification using OTP code

Endpoint: POST https://apinexgate.glueauth.com/api/v1/profile/verify-email

Access Level: πŸ”’ Protected (Requires JWT Bearer token)

Authentication: Bearer Token (JWT access token required)

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer {access_token}
Content-TypestringYesMust be "application/json"

Request JSON Sample:

{
  "tempToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "otpCode": "123456"
}

Request Body Parameters:

ParameterTypeRequiredDescriptionValidation
tempTokenstringYesTemporary token from email verification requestMust be valid non-expired temp token
otpCodestringYes6-digit OTP code from emailMust be exactly 6 digits (\d{6})

Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Email verified successfully",
  "action_time": "2025-09-23T10:55:00",
  "data": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "userName": "johndoe-a1B2c3D",
    "firstName": "John",
    "lastName": "Doe",
    "middleName": "Michael",
    "email": "john.doe@example.com",
    "phoneNumber": "+255712345678",
    "isVerified": true,
    "isEmailVerified": true,
    "isPhoneVerified": false,
    "isTwoFactorEnabled": false,
    "isAccountLocked": false,
    "createdAt": "2025-09-23T10:00:00",
    "editedAt": "2025-09-23T10:55:00",
    "roles": ["ROLE_NORMAL_USER"],
    "profilePictureUrls": [],
    "securityStrength": {
      "score": 75,
      "level": "MEDIUM",
      "description": "Your account security is good but can be improved",
      "recommendations": [
        "Verify your phone number",
        "Enable two-factor authentication"
      ]
    }
  }
}

Response Fields:

FieldDescription
successBoolean indicating operation success
httpStatusHTTP status code as string
messageSuccess message confirming email verification
action_timeISO 8601 timestamp of response generation
dataUpdated UserProfileResponse object with email verification status

Error Responses:

  • 400 Bad Request: Invalid OTP format or missing required fields
  • 401 Unauthorized: Missing or invalid JWT token or temp token
  • 422 Unprocessable Entity: OTP verification failed or token expired
  • 500 Internal Server Error: Server-side processing errors

7. Get Security Information

Purpose: Retrieve detailed security settings and account security strength

Endpoint: GET https://apinexgate.glueauth.com/api/v1/profile/security-info

Access Level: πŸ”’ Protected (Requires JWT Bearer token)

Authentication: Bearer Token (JWT access token required)

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer {access_token}
Content-TypestringYesMust be "application/json"

Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Security information retrieved successfully",
  "action_time": "2025-09-23T11:00:00",
  "data": {
    "isEmailVerified": true,
    "isPhoneVerified": false,
    "isTwoFactorEnabled": false,
    "isAccountLocked": false,
    "lastPasswordChange": "2025-09-23T10:40:00",
    "accountCreatedAt": "2025-09-23T10:00:00",
    "roles": ["ROLE_NORMAL_USER"],
    "securityStrength": {
      "score": 75,
      "level": "MEDIUM",
      "description": "Your account security is good but can be improved",
      "recommendations": [
        "Verify your phone number",
        "Enable two-factor authentication"
      ]
    }
  }
}

Response Fields:

FieldDescription
successBoolean indicating operation success
httpStatusHTTP status code as string
messageSuccess message
action_timeISO 8601 timestamp of response generation
data.isEmailVerifiedEmail verification status
data.isPhoneVerifiedPhone verification status
data.isTwoFactorEnabledTwo-factor authentication status
data.isAccountLockedAccount lock status
data.lastPasswordChangeTimestamp of last password change
data.accountCreatedAtAccount creation timestamp
data.rolesArray of user roles/permissions
data.securityStrengthDetailed security strength analysis

Error Responses:

  • 401 Unauthorized: Missing or invalid JWT token
  • 404 Not Found: User account not found
  • 500 Internal Server Error: Server-side processing errors

8. Enable Two-Factor Authentication

Purpose: Enable two-factor authentication for enhanced account security

Endpoint: POST https://apinexgate.glueauth.com/api/v1/profile/enable-2fa

Access Level: πŸ”’ Protected (Requires JWT Bearer token)

Authentication: Bearer Token (JWT access token required)

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer {access_token}
Content-TypestringYesMust be "application/json"

Request JSON Sample:

{
  "password": "CurrentPassword123!"
}

Request Body Parameters:

ParameterTypeRequiredDescriptionValidation
passwordstringYesUser's current password for verificationMust match current password

Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Two-factor authentication enabled successfully",
  "action_time": "2025-09-23T11:05:00",
  "data": null
}

Response Fields:

FieldDescription
successBoolean indicating operation success
httpStatusHTTP status code as string
messageSuccess message confirming 2FA enablement
action_timeISO 8601 timestamp of response generation
dataAlways null for 2FA operations

Error Responses:

  • 400 Bad Request: Missing password or 2FA already enabled
  • 401 Unauthorized: Missing or invalid JWT token or incorrect password
  • 422 Unprocessable Entity: Invalid password verification
  • 500 Internal Server Error: Server-side processing errors

9. Disable Two-Factor Authentication

Purpose: Disable two-factor authentication with password verification

Endpoint: POST https://apinexgate.glueauth.com/api/v1/profile/disable-2fa

Access Level: πŸ”’ Protected (Requires JWT Bearer token)

Authentication: Bearer Token (JWT access token required)

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer {access_token}
Content-TypestringYesMust be "application/json"

Request JSON Sample:

{
  "password": "CurrentPassword123!"
}

Request Body Parameters:

ParameterTypeRequiredDescriptionValidation
passwordstringYesUser's current password for verificationMust match current password

Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Two-factor authentication disabled successfully",
  "action_time": "2025-09-23T11:10:00",
  "data": null
}

Response Fields:

FieldDescription
successBoolean indicating operation success
httpStatusHTTP status code as string
messageSuccess message confirming 2FA disablement
action_timeISO 8601 timestamp of response generation
dataAlways null for 2FA operations

Error Responses:

  • 400 Bad Request: Missing password or 2FA not enabled
  • 401 Unauthorized: Missing or invalid JWT token or incorrect password
  • 422 Unprocessable Entity: Invalid password verification
  • 500 Internal Server Error: Server-side processing errors

10. Deactivate Account

Purpose: Deactivate (soft delete) user account with password verification

Endpoint: DELETE https://apinexgate.glueauth.com/api/v1/profile/deactivate

Access Level: πŸ”’ Protected (Requires JWT Bearer token) ⚠️ Irreversible action

Authentication: Bearer Token (JWT access token required)

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer {access_token}
Content-TypestringYesMust be "application/json"

Request JSON Sample:

{
  "password": "CurrentPassword123!",
  "reason": "No longer using the platform"
}

Request Body Parameters:

ParameterTypeRequiredDescriptionValidation
passwordstringYesUser's current password for verificationMust match current password
reasonstringNoOptional reason for deactivationMax 500 characters

Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Account deactivated successfully",
  "action_time": "2025-09-23T11:15:00",
  "data": null
}

Response Fields:

FieldDescription
successBoolean indicating operation success
httpStatusHTTP status code as string
messageSuccess message confirming account deactivation
action_timeISO 8601 timestamp of response generation
dataAlways null for deactivation operations

Error Responses:

  • 400 Bad Request: Missing password or invalid reason length
  • 401 Unauthorized: Missing or invalid JWT token or incorrect password
  • 422 Unprocessable Entity: Invalid password verification
  • 500 Internal Server Error: Server-side processing errors

11. Get My Profile Summary (Modified from Get Current User Profile)

Purpose: Retrieve the authenticated user's profile summary with stats

Endpoint: GET {base_url}/api/v1/profile/me

Access Level: πŸ”’ Protected (Requires Authentication)valid JWT β€” own profile only)

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer token for authentication<jwt_token>

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Profile retrieved successfully",
  "action_time": "2026-05-19T10:30:45",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "userName": "john_doe",
    "firstName": "John",
    "lastName": "Doe",
    "middleName": null,
    "email": "john@example.com",
    "phoneNumber": "+254712345678",
    "bio": "Building cool things.",
    "location": "Nairobi, Kenya",
    "profilePictureUrls": [
      "https://cdn.example.com/profiles/john_main.jpg"
    ],
    "isVerified": true,
    "isEmailVerified": true,
    "isPhoneVerified": true,
    "isTwoFactorEnabled": false,
    "isAccountLocked": false,
    "followersCount": 1420,
    "followingCount": 310,
    "postsCount": 42,
    "shopsCount": 1,
    "eventsCount": 3,
    "createdAt": "2025-12-29T17:01T14:00:00",
    "editedAt": "2026-05-10T08:22:00",
    "roles": ["ROLE_USER"],
    "securityStrength": {
      "score": 50,
      "level": "MEDIUM",
      "description": "Your account security is good but can be improved",
      "recommendations": ["Enable two-factor authentication"]
    }
  }
}

Success Response Fields:

FieldDescription
idAccount UUID
userNamePublic username
firstNameFirst name
lastNameLast name
middleNameMiddle name (may be null)
emailLinked email address (private β€” only visible to owner)
phoneNumberLinked phone number (private β€” only visible to owner)
bioProfile bio text
locationLocation string
profilePictureUrlsArray of profile picture URLs (first is primary)
isVerifiedWhether the account has been verified
isEmailVerifiedWhether the email has been verified
isPhoneVerifiedWhether the phone has been verified
isTwoFactorEnabledWhether 2FA is active
isAccountLockedWhether the account is deactivated or locked
followersCountNumber of accepted followers
followingCountNumber of accounts the user is following
postsCountNumber of published posts
shopsCountNumber of active shops
eventsCountNumber of published events
createdAtISO 8601 account creation timestamp
editedAtISO 8601 last profile update timestamp
rolesArray of assigned role strings
securityStrength.scoreSecurity health score 0–100
securityStrength.levelVERY_WEAK, WEAK, MEDIUM, or STRONG
securityStrength.recommendationsActionable steps to improve security score

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Token has expired",
  "action_time": "2026-05-19T10:30:45",
  "data": "Token has expired"
}

2. Get Profile by User ID

Purpose: Returns the public profile summary of any user by their UUID. Authenticated callers additionally receive relationship context (isFollowing, isBlocked, etc.).

Endpoint: GET {base_url}/api/v1/profile/id/{userId}

Access Level: 🌐 Public (Relationship info available when authenticated)

Authentication: Bearer Token (optional)

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringNoBearer <jwt_token> β€” include to get relationship data

Path Parameters:

ParameterTypeRequiredDescriptionValidation
userIdUUIDYesThe UUID of the user whose profile to fetchValid UUID format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Profile retrieved successfully",
  "action_time": "2026-05-19T10:30:45",
  "data": {
    "userId": "550e8400-e29b-41d4-a716-446655440000",
    "userName": "john_doe",
    "firstName": "John",
    "lastName": "Doe",
    "profilePictureUrl": "https://storage.cdn.example.com/profiles/john.john_main.jpg",
    "bio": "TechBuilding enthusiastcool | Entrepreneur | Dar es Salaam"things.",
    "location": "DarNairobi, es Salaam, Tanzania"Kenya",
    "isVerified": true,
    "followersCount": 1250,1420,
    "followingCount": 340,310,
    "postsCount": 85,
    "shopsCount": 2,
    "eventsCount": 5,
    "createdAt": "2024-03-15T08:00:00",
    "isOwnProfile": true,
    "relationship": null
  }
}

Success Response Fields:

FieldDescription
userIdUnique identifier of the user
userNameUsername handle
firstNameUser's first name
lastNameUser's last name
profilePictureUrlURL to profile picture
bioUser's bio/description
locationUser's location
isVerifiedWhether user is verified
followersCountNumber of followers
followingCountNumber of users following
postsCountNumber of published posts
shopsCountNumber of active shops owned
eventsCountNumber of published events created
createdAtAccount creation date
isOwnProfileAlways true for this endpoint
relationshipAlways null for own profile

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "User not authenticated",
  "action_time": "2025-12-29T17:00:00",
  "data": null
}

Standard Error Types:

  • 401 UNAUTHORIZED: Missing or invalid authentication token

12. Get User Profile by ID

Purpose: Retrieve a user's profile summary by their unique ID

Endpoint: GET {base_url}/api/v1/profile/id/{userId}

Access Level: πŸ”’ Protected (Requires Authentication)

Authentication: Bearer Token

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringYesBearer token for authentication

Path Parameters:

ParameterTypeRequiredDescriptionValidation
userIdUUIDYesUnique identifier of the userValid UUID format

Success Response JSON Sample (Viewing Other User):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Profile retrieved successfully",
  "action_time": "2025-12-29T17:00:00",
  "data": {
    "userId": "660e8400-e29b-41d4-a716-446655440001",
    "userName": "jane_smith",
    "firstName": "Jane",
    "lastName": "Smith",
    "profilePictureUrl": "https://storage.example.com/profiles/jane.jpg",
    "bio": "Fashion designer | Shop owner | Arusha",
    "location": "Arusha, Tanzania",
    "isVerified": true,
    "followersCount": 5420,
    "followingCount": 180,
    "postsCount": 320,42,
    "shopsCount": 1,
    "eventsCount": 12,3,
    "createdAt": "2023-08-20T10:2025-12-01T14:00:00",
    "isOwnProfile": false,
    "relationship": {
      "isFollowing": true,
      "isFollowedBy": false,
      "isBlocked": false,
      "isBlockedBy": false
    }
  }
}

Success Response Fields:

FieldDescription
userIdAccount UUID
userNamePublic username
firstNameFirst name
lastNameLast name
profilePictureUrlPrimary profile picture URL (first in the list, may be null)
bioProfile bio
locationLocation string
isVerifiedWhether the account has been platform-verified
followersCountNumber of accepted followers
followingCountNumber of accounts the user follows
postsCountNumber of published posts
shopsCountNumber of active shops
eventsCountNumber of published events
createdAtISO 8601 account creation timestamp
isOwnProfiletrue if the authenticated caller is viewing their own profile
relationshipPresent only when the caller is authenticated and viewing someone else's profile
relationship.isFollowingtrue if the caller follows this user
relationship.isFollowedBytrue if this user follows the caller
relationship.isBlockedtrue if the caller has blocked this user
relationship.isBlockedBytrue if this user has blocked the caller

Error Response JSON Sample:

(Viewing
{
  Own"success": false,
  "httpStatus": "NOT_FOUND",
  "message": "User not found",
  "action_time": "2026-05-19T10:30:45",
  "data": "User not found"
}

3. Get Profile by ID)Username

Purpose: Returns the public profile summary of any user by their username. Authenticated callers additionally receive relationship context. Functionally identical to endpoint 2 but accessed via username instead of UUID.

Endpoint: GET {base_url}/api/v1/profile/u/{username}

Access Level: 🌐 Public (Relationship info available when authenticated)

Authentication: Bearer Token (optional)

Request Headers:

HeaderTypeRequiredDescription
AuthorizationstringNoBearer <jwt_token> β€” include to get relationship data

Path Parameters:

ParameterTypeRequiredDescriptionValidation
usernamestringYesThe public username to look upSupports @username format

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Profile retrieved successfully",
  "action_time": "2025-12-29T17:00:00"2026-05-19T10:30:45",
  "data": {
    "userId": "550e8400-e29b-41d4-a716-446655440000",
    "userName": "john_doe",
    "firstName": "John",
    "lastName": "Doe",
    "profilePictureUrl": "https://storage.cdn.example.com/profiles/john.john_main.jpg",
    "bio": "TechBuilding enthusiastcool | Entrepreneur | Dar es Salaam"things.",
    "location": "DarNairobi, es Salaam, Tanzania"Kenya",
    "isVerified": true,
    "followersCount": 1250,1420,
    "followingCount": 340,310,
    "postsCount": 85,42,
    "shopsCount": 2,1,
    "eventsCount": 5,3,
    "createdAt": "2024-03-15T08:2025-12-01T14:00:00",
    "isOwnProfile": true,false,
    "relationship": null{
      "isFollowing": false,
      "isFollowedBy": false,
      "isBlocked": false,
      "isBlockedBy": false
    }
  }
}

Success Response Fields: Same as endpoint 2 β€” see Get Profile by User ID.

FieldDescription
userIdUnique identifier of the user
userNameUsername handle
firstNameUser's first name
lastNameUser's last name
profilePictureUrlURL to profile picture
bioUser's bio/description
locationUser's location
isVerifiedWhether user is verified
followersCountNumber of followers
followingCountNumber of users following
postsCountNumber of published posts
shopsCountNumber of active shops owned
eventsCountNumber of published events created
createdAtAccount creation date
isOwnProfiletrue if viewing own profile, false otherwise
relationshipRelationship info (null if isOwnProfile is true)

Relationship Object Fields:

FieldDescription
isFollowingWhether viewer follows this user
isFollowedByWhether this user follows viewer
isBlockedWhether viewer has blocked this user
isBlockedByWhether this user has blocked viewer

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "BAD_REQUEST"NOT_FOUND",
  "message": "User not found",
  "action_time": "2025-12-29T17:00:00"2026-05-19T10:30:45",
  "data": null"User not found"
}

Standard Error Types:

  • 400 BAD_REQUEST: User not found
  • 401 UNAUTHORIZED: Missing or invalid authentication token

13.4. Get UserUpdate Profile by Username

Purpose: RetrieveUpdates athe authenticated user's profilesocial/display summaryinformation. Only accepts social fields β€” username changes, email changes, and phone changes are handled by theirthe usernameAccount API. All fields are optional; only fields provided will be updated.

Endpoint: GETPUT {base_url}/api/v1/profile/u/{username}update

Access Level: πŸ”’ Protected (Requires Authentication)valid JWT β€” own profile only)

Authentication: Bearer Token

Request Headers:

forauthentication
Header Type Required Description
Authorization string Yes Bearer token<jwt_token>
Content-TypestringYesapplication/json

PathRequest JSON Sample:

{
  "firstName": "John",
  "lastName": "Doe",
  "middleName": "K",
  "bio": "Building cool things one commit at a time.",
  "location": "Nairobi, Kenya",
  "profilePictureUrls": [
    "https://cdn.example.com/profiles/john_main.jpg",
    "https://cdn.example.com/profiles/john_alt.jpg"
  ]
}

Request Body Parameters:

username
Parameter Type Required Description Validation
usernamefirstName string YesNo UsernameFirst name1–30 characters
lastNamestringNoLast name1–30 characters
middleNamestringNoMiddle nameMax 30 characters
biostringNoShort bio shown on profileNo length constraint enforced here
locationstringNoLocation string shown on profileNo length constraint enforced here
profilePictureUrlsarray of the userstrings ValidNo Ordered formatlist of image URLsMax 5 items; each URL must be a valid https:// image URL ending in .jpg, .jpeg, .png, .gif, or .webp; max 500 characters per URL

Note: To change your username, use POST /api/v1/account/username/change. To change your email or phone number, use the Account Linking API (/api/v1/account/link).

Success Response JSON Sample (Viewing Other User):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Profile retrievedupdated successfully",
  "action_time": "2025-12-29T17:00:00"2026-05-19T10:30:45",
  "data": {
    "userId": "660e8400-e29b-41d4-a716-446655440001",
    "userName": "jane_smith",
    "firstName": "Jane",
    "lastName": "Smith",
    "profilePictureUrl": "https://storage.example.com/profiles/jane.jpg",
    "bio": "Fashion designer | Shop owner | Arusha",
    "location": "Arusha, Tanzania",
    "isVerified": true,
    "followersCount": 5420,
    "followingCount": 180,
    "postsCount": 320,
    "shopsCount": 1,
    "eventsCount": 12,
    "createdAt": "2023-08-20T10:00:00",
    "isOwnProfile": false,
    "relationship": {
      "isFollowing": true,
      "isFollowedBy": true,
      "isBlocked": false,
      "isBlockedBy": false
    }
  }
}

Success Response JSON Sample (Viewing Own Profile by Username):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Profile retrieved successfully",
  "action_time": "2025-12-29T17:00:00",
  "data": {
    "userId"id": "550e8400-e29b-41d4-a716-446655440000",
    "userName": "john_doe",
    "firstName": "John",
    "lastName": "Doe",
    "profilePictureUrl"middleName": "https://storage.example.com/profiles/john.jpg"K",
    "email": "john@example.com",
    "phoneNumber": "+254712345678",
    "bio": "TechBuilding enthusiastcool |things Entrepreneurone |commit Darat esa Salaam"time.",
    "location": "DarNairobi, esKenya",
    Salaam,"profilePictureUrls": Tanzania"[
      "https://cdn.example.com/profiles/john_main.jpg",
      "https://cdn.example.com/profiles/john_alt.jpg"
    ],
    "isVerified": true,
    "followersCount"isEmailVerified": 1250,true,
    "followingCount"isPhoneVerified": 340,true,
    "postsCount"isTwoFactorEnabled": 85,false,
    "shopsCount"isAccountLocked": 2,
    "eventsCount": 5,false,
    "createdAt": "2024-03-15T08:2025-12-01T14:00:00",
    "isOwnProfile"editedAt": true,"2026-05-19T10:30:45",
    "relationship"roles": null["ROLE_USER"],
    "securityStrength": {
      "score": 50,
      "level": "MEDIUM",
      "description": "Your account security is good but can be improved",
      "recommendations": ["Enable two-factor authentication"]
    }
  }
}

Success Response Fields:

Field Description
userIdid UniqueAccount identifier of the userUUID
userName UsernamePublic handleusername (unchanged by this endpoint)
firstName User'sUpdated first name
lastName User'sUpdated last name
profilePictureUrlmiddleName URLUpdated tomiddle profilename picture(may be null)
bioemail User'sCurrent bio/descriptionemail (unchanged by this endpoint)
locationphoneNumber User'sCurrent phone number (unchanged by this endpoint)
bioUpdated bio
locationUpdated location
isVerifiedprofilePictureUrls WhetherUpdated userlist isof verifiedprofile picture URLs
followersCountisVerified NumberAccount ofverification followersstatus
followingCountisEmailVerified NumberEmail ofverification users followingstatus
postsCountisPhoneVerified NumberPhone ofverification published postsstatus
shopsCountisTwoFactorEnabled Number2FA of active shops ownedstatus
eventsCountisAccountLocked NumberAccount oflock published events createdstatus
createdAt Account creation datetimestamp
isOwnProfileeditedAt trueUpdated iftimestamp viewingreflecting ownthis profile, false otherwisechange
relationshiproles RelationshipAssigned inforole (null if isOwnProfile is true)

Relationship Object Fields:

FieldDescription
isFollowingWhether viewer follows this userstrings
isFollowedBysecurityStrength WhetherCurrent thissecurity userscore followsand viewer
isBlockedWhether viewer has blocked this user
isBlockedByWhether this user has blocked viewerrecommendations

Error Response JSON Sample:

{
  "success": false,
  "httpStatus": "BAD_REQUEST"UNPROCESSABLE_ENTITY",
  "message": "UserValidation not found"failed",
  "action_time": "2025-12-29T17:00:00"2026-05-19T10:30:45",
  "data": null{
    "firstName": "First name must be between 1 and 30 characters",
    "profilePictureUrls": "Maximum 5 profile pictures allowed"
  }
}

Standard Error Types:

  • 400 BAD_REQUEST: User not found
  • 401 UNAUTHORIZED: Missing or invalid authentication token

Quick Reference β€” All Profile Endpoints Summary

profile if own usernameifprofile
#MethodEndpoint PurposeAuth isOwnProfilerelationshipDescription
1GETGET /api/v1/profile/me GetπŸ”’ my profileRequired AlwaysFull true Alwaysβ€” nullown account only
2GETGET /api/v1/profile/id/{userId} Get🌐 OptionalPublic profile by IDtrue if own IDnull if own profileUUID
3GETGET /api/v1/profile/u/{username} Get🌐 OptionalPublic profile by username
true4 PUT null/profile/update πŸ”’ ownRequired Update display info

RelationshipWhat FieldBelongs Logicin Profile vs Account

GETPUT isFollowedBy,isBlocked,isBlockedBy
ScenarioI want to… isOwnProfilerelationshipUse
ViewingView ownmy full profile via /me true null/profile/me
ViewingView ownsomeone else's profile via /id/{myId} trueGET /profile/u/{username} or nullGET /profile/id/{id}
ViewingUpdate ownmy profilename, viabio, /u/{myUsername}location, or picture true null/profile/update
ViewingChange othermy user's profileusername falsePOST /api/v1/account/username/change
Change my email address {POST isFollowing,/api/v1/account/link/email/initiate
Change }my phone numberPhone OTP verification flow
Change my passwordPOST /api/v1/account/password/change
Enable or disable 2FAPOST /api/v1/account/2fa/enable or /disable
Verify my emailPOST /api/v1/account/email/request-verification β†’ /email/verify
View my security statusGET /api/v1/account/security-info
Deactivate my accountDELETE /api/v1/account/deactivate

Frontend Usage Example

const profile = response.data;

if (profile.isOwnProfile) {
    // Show edit profile button
    // Hide follow/block buttons
    showEditProfileButton();
} else {
    // Show follow button based on relationship
    if (profile.relationship.isFollowing) {
        showUnfollowButton();
    } else {
        showFollowButton();
    }
    
    // Show "Follows you" badge
    if (profile.relationship.isFollowedBy) {
        showFollowsYouBadge();
    }
    
    // Handle blocked state
    if (profile.relationship.isBlockedBy) {
        showLimitedProfile();
        disableInteractions();
    }
}

Quick Reference Guide

Security Strength Scoring

  • Email Verification: 25 points
  • Phone Verification: 25 points
  • Two-Factor Authentication: 35 points
  • Recent Password Change: 15 points (within 6 months)

Security Levels

  • STRONG (80-100): Excellent security
  • MEDIUM (60-79): Good security, can be improved
  • WEAK (40-59): Needs improvement
  • VERY_WEAK (0-39): Poor security, immediate attention needed

Profile Picture Requirements

  • Format: HTTPS URLs only
  • File Types: JPG, JPEG, PNG, GIF, WebP
  • Limit: Maximum 5 profile pictures
  • Size: No specific limit (handled by file service)
  • Security: SSRF protection implemented

Common HTTP Status Codes

  • 200 OK: Successful GET/PUT request
  • 204 No Content: Successful DELETE request
  • 400 Bad Request: Invalid request data
  • 401 Unauthorized: Authentication required/failed
  • 403 Forbidden: Insufficient permissions
  • 404 Not Found: Resource not found
  • 409 Conflict: Username/email already taken
  • 422 Unprocessable Entity: Validation errors
  • 429 Too Many Requests: Rate limit exceeded
  • 500 Internal Server Error: Server error

Authentication Types

  • Bearer Token: Include Authorization: Bearer your_access_token in headers
  • Password Verification: Required for sensitive operations (password change, 2FA, deactivation)
  • OTP Verification: Required for email/phone verification
  • Re-authentication: Required after username changes

Data Format Standards

  • Dates: Use ISO 8601 format (2025-09-23T10:30:00Z)
  • Phone Numbers: E.164 international format (+1234567890)
  • UUIDs: Standard UUID format for all identifiers
  • URLs: Full HTTPS URLs for profile pictures
  • Passwords: Min 8 chars, uppercase, lowercase, digit, special character