Skip to main content

Profile

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

Base URL: https://api.fursahub.com/api/v1

Short Description: Profile management endpoints for Fursa Hub. Allows users to view and update their profile information, manage photos, change theme and language preferences. Profile completion is the final step of onboarding.

Hints:

  • All profile endpoints require authentication (Bearer token)
  • Username must be unique and can only contain letters, numbers, and underscores
  • Profile photos should be uploaded via Files API first, then URLs added here
  • Completing profile (fullName + username + bio) auto-completes onboarding if at final step
  • Theme changes take effect immediately on client side

Profile in Onboarding Context

┌─────────────────────────────────────────────────────────────────────────┐
│                     PROFILE & ONBOARDING RELATIONSHIP                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  Profile data comes from multiple sources:                               │
│                                                                          │
│  1. FIREBASE (auto-filled at registration)                              │
│     └── fullName (from Google/Apple account)                            │
│     └── profilePhotoUrl (from social account)                           │
│     └── email (from auth provider)                                      │
│                                                                          │
│  2. REGISTRATION (user choice)                                          │
│     └── preferredLanguage                                               │
│     └── theme                                                           │
│                                                                          │
│  3. ONBOARDING (user completes)                                         │
│     └── phoneNumber (verified via OTP)                                  │
│     └── preferences (from onboarding pages)                             │
│                                                                          │
│  4. PROFILE COMPLETION (final step)                                     │
│     └── username (required, unique)                                     │
│     └── bio (required)                                                  │
│     └── fullName (can edit Firebase default)                            │
│     └── gender, link (optional)                                         │
│                                                                          │
│  When user completes: fullName + username + bio                         │
│  └── Onboarding auto-completes if at PENDING_PROFILE_COMPLETION         │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

Endpoints


1. Get Profile

Purpose: Retrieve current user's complete profile information.

Endpoint: GET {base_url}/profile

Access Level: 🔒 Protected

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer {accessToken}

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Profile retrieved",
  "action_time": "2025-01-05T10:30:45",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "username": "johndoe",
    "phoneNumber": "+255712345678",
    "fullName": "John Doe",
    "bio": "Software developer passionate about tech",
    "gender": "MALE",
    "link": "https://johndoe.com",
    "profilePhotoUrls": [
      "https://files.fursahub.com/bucket/profile/photo1.jpg",
      "https://files.fursahub.com/bucket/profile/photo2.jpg"
    ],
    "primaryPhotoUrl": "https://files.fursahub.com/bucket/profile/photo1.jpg",
    "isPhoneVerified": true,
    "isEmailVerified": true,
    "preferredLanguage": "sw",
    "theme": "DARK",
    "authProvider": "GOOGLE",
    "role": "ROLE_USER",
    "onboardingStatus": "COMPLETED",
    "isOnboardingComplete": true,
    "createdAt": "2025-01-01T08:00:00",
    "updatedAt": "2025-01-05T10:30:00"
  }
}

Success Response Fields:

Field Description
id Unique user identifier (UUID)
email User's email address
username Unique username (lowercase)
phoneNumber Verified phone number in E.164 format
fullName Display name
bio User biography/description
gender MALE or FEMALE
link Personal website or social link
profilePhotoUrls Array of all profile photo URLs
primaryPhotoUrl First photo URL (main profile picture)
isPhoneVerified Phone verification status
isEmailVerified Email verification status
preferredLanguage Language code (en, sw, fr, zh)
theme LIGHT, DARK, or SYSTEM
authProvider GOOGLE, APPLE, or EMAIL
role User role (ROLE_USER, ROLE_ADMIN, etc.)
onboardingStatus Current onboarding step
isOnboardingComplete true if onboarding finished

2. Update Profile

Purpose: Update user profile information. Only provided fields are updated.

Endpoint: PUT {base_url}/profile

Access Level: 🔒 Protected

Authentication: Bearer Token

Request Headers:

Header Type Required Description
Authorization string Yes Bearer {accessToken}
Content-Type string Yes application/json

Request JSON Sample:

{
  "fullName": "John Doe Updated",
  "username": "johndoe_new",
  "bio": "Building the future of opportunity in East Africa",
  "gender": "MALE",
  "link": "https://linkedin.com/in/johndoe",
  "profilePhotoUrls": [
    "https://files.fursahub.com/bucket/profile/new-photo.jpg"
  ],
  "theme": "LIGHT",
  "preferredLanguage": "en"
}

Request Body Parameters:

Parameter Type Required Description Validation
fullName string No Display name Min: 2, Max: 100 chars
username string No Unique username Min: 3, Max: 30 chars, alphanumeric + underscore only
bio string No User biography Max: 500 chars
gender string No User gender enum: MALE, FEMALE
link string No Personal/social link Must be valid URL (https://...)
profilePhotoUrls array No List of photo URLs Array of strings
theme string No UI theme preference enum: LIGHT, DARK, SYSTEM
preferredLanguage string No Language preference Must be active language code

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Profile updated",
  "action_time": "2025-01-05T10:35:00",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "username": "johndoe_new",
    "fullName": "John Doe Updated",
    "bio": "Building the future of opportunity in East Africa",
    "theme": "LIGHT",
    "preferredLanguage": "en",
    "onboardingStatus": "COMPLETED",
    "isOnboardingComplete": true
  }
}

Error Responses:

Username Already Taken (409):

{
  "success": false,
  "httpStatus": "CONFLICT",
  "message": "Username already taken",
  "action_time": "2025-01-05T10:35:00",
  "data": "Username already taken"
}

Invalid Language Code (400):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Invalid or inactive language code: xx",
  "action_time": "2025-01-05T10:35:00",
  "data": "Invalid or inactive language code: xx"
}

Validation Error (422):

{
  "success": false,
  "httpStatus": "UNPROCESSABLE_ENTITY",
  "message": "Validation failed",
  "action_time": "2025-01-05T10:35:00",
  "data": {
    "username": "Username can only contain letters, numbers, and underscores",
    "fullName": "Name must be 2-100 characters"
  }
}

3. Update Theme (Quick Toggle)

Purpose: Quick endpoint to change theme without full profile update.

Endpoint: PATCH {base_url}/profile/theme

Access Level: 🔒 Protected

Authentication: Bearer Token

Request JSON Sample:

{
  "theme": "DARK"
}

Request Body Parameters:

Parameter Type Required Description Validation
theme string Yes Theme preference enum: LIGHT, DARK, SYSTEM

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Theme updated",
  "action_time": "2025-01-05T10:40:00",
  "data": {
    "theme": "DARK"
  }
}

4. Check Username Availability

Purpose: Check if a username is available before updating profile.

Endpoint: GET {base_url}/profile/username/check

Access Level: 🔒 Protected

Authentication: Bearer Token

Query Parameters:

Parameter Type Required Description Validation
username string Yes Username to check Min: 3 chars

Success Response JSON Sample (Available):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Username available",
  "action_time": "2025-01-05T10:45:00",
  "data": {
    "username": "newusername",
    "available": true
  }
}

Success Response JSON Sample (Taken):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Username taken",
  "action_time": "2025-01-05T10:45:00",
  "data": {
    "username": "existinguser",
    "available": false
  }
}

5. Add Profile Photo

Purpose: Add a new photo to user's profile photos array.

Endpoint: POST {base_url}/profile/photo

Access Level: 🔒 Protected

Authentication: Bearer Token

Request JSON Sample:

{
  "photoUrl": "https://files.fursahub.com/bucket/profile/new-photo.jpg"
}

Request Body Parameters:

Parameter Type Required Description Validation
photoUrl string Yes URL of uploaded photo Must be valid URL

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Photo added",
  "action_time": "2025-01-05T10:50:00",
  "data": {
    "profilePhotoUrls": [
      "https://files.fursahub.com/bucket/profile/photo1.jpg",
      "https://files.fursahub.com/bucket/profile/new-photo.jpg"
    ],
    "primaryPhotoUrl": "https://files.fursahub.com/bucket/profile/photo1.jpg"
  }
}

6. Remove Profile Photo

Purpose: Remove a photo from user's profile photos array.

Endpoint: DELETE {base_url}/profile/photo

Access Level: 🔒 Protected

Authentication: Bearer Token

Query Parameters:

Parameter Type Required Description
photoUrl string Yes URL of photo to remove

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Photo removed",
  "action_time": "2025-01-05T10:55:00",
  "data": {
    "profilePhotoUrls": [
      "https://files.fursahub.com/bucket/profile/photo1.jpg"
    ],
    "primaryPhotoUrl": "https://files.fursahub.com/bucket/profile/photo1.jpg"
  }
}

Frontend Implementation Guide

Profile Completion Screen

When onboardingStatus = "PENDING_PROFILE_COMPLETION":

1. GET /profile to fetch current data
2. Show form with:
   ├── fullName (pre-filled from Firebase)
   ├── username (auto-generated, editable)
   │   └── On change: GET /profile/username/check
   ├── bio (required)
   ├── gender (optional)
   └── link (optional)
3. PUT /profile with form data
4. If isOnboardingComplete = true → Navigate to home

Settings Screen

Theme Toggle:
└── PATCH /profile/theme with selected theme
└── Apply theme immediately on client

Language Change:
└── PUT /profile with preferredLanguage
└── Reload UI with new language strings

Profile Edit:
└── PUT /profile with changed fields only

Photo Management

Adding Photo:
1. Upload via Files API (POST /files/upload-single)
2. Get permanentUrl from response
3. POST /profile/photo with photoUrl

Removing Photo:
1. DELETE /profile/photo?photoUrl=...
2. Optionally delete from Files API