Onboarding EndUser
Base URL: https://api.fursahub.com/api/v1
Short Description: The Onboarding APIflow manages the complete user onboarding flowendpoints for Fursa Hub. ItGuides handlesnew users through phone verification via OTP, languageverification, preference selection, dynamic preference pages with multilingual support, progress tracking, and administrativeprofile pagecompletion. management.All Thecontent systemis usestranslated abased stateon machineuser's approachpreferredLanguage to ensure users complete all required steps before accessing the main platform.setting.
Hints:
- Onboarding
followsstepsamuststrictbesequence:completedPhoneinVerificationorder→-LanguageskippingPreferenceahead→returnsPreference412Pages → Profile Completion All preference pages are admin-configurable with multilingual support (EN, SW, FR, ZH)PRECONDITION_FAILED- Phone verification uses
internalOTPsystemsent viaTextify AfricaSMSgateway(supports TZ, KE, UG, RW, BI country codes) Progress endpoint provides weighted percentage completion across all stepsSkip is only allowed onPreference pagesmarkedareasdynamicadmin can add/remove/reorder without code changesisSkippable:-true- User's
Accept-Languageheader orpreferredLanguagedeterminesresponsetranslationlanguageof all onboarding content - Email verification is optional/skippable by default (Firebase handles actual verification)
Onboarding Flow Overview
Complete Onboarding Journey
Flow
┌─────────────────────────────────────────────────────────────────────────┐
│ COMPLETE ONBOARDING STATEFLOW MACHINE│
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ After POST /auth/firebase/authenticate: │
│ └── Check response.data.onboarding.currentStep │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ STEP 1: PENDING_EMAIL_VERIFICATION (Optional/Skippable) │ │
│ ├─────────────────────────────────────────────────────────────────┤ │
│ │ • Firebase handles actual email verification │ │
│ │ • Check: GET /onboarding/email-verification/status │ │
│ │ • Skip: POST /onboarding/email-verification/skip │ │
│ │ • Or wait for user to verify email in Firebase │ │
│ │ • Auto-transitions when Firebase reports email verified │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ STEP 2: PENDING_PHONE_VERIFICATION (Required) │ │
│ ├─────────────────────────────────────────────────────────────────┤ │
│ │ • POST /onboarding/auth-phone/request-otp │ │
│ │ └── User enters phone number (+255...) │ │
│ │ └── Backend sends OTP via SMS │ │
│ │ └── Returns token for verification │ │
│ │ • POST /onboarding/auth-phone/verify │ │
│ │ └── User enters 6-digit OTP │ │
│ │ └── On success: phone saved, transitions to next step │ │
│ │ • POST /onboarding/auth-phone/resend-otp (if needed) │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ STEP 3: PENDING_PREFERENCES (Required) │ │
│ ├─────────────────────────────────────────────────────────────────┤ │
│ │ • GET /onboarding/pages?current=true │ │
│ │ └── Get current preference page │ │
│ │ • Loop through pages: │ │
│ │ └── Display options (translated to user's language) │ │
│ │ └── User selects options │ │
│ │ └── POST /onboarding/pages/{pageId}/response │ │
│ │ └── Or POST /onboarding/pages/{pageId}/skip (if skippable) │ │
│ │ └── Move to next page until all complete │ │
│ │ • Auto-transitions when all pages completed │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ STEP 4: PENDING_PROFILE_COMPLETION (Required) │ │
│ ├─────────────────────────────────────────────────────────────────┤ │
│ │ • GET /profile │ │
│ │ └── Get current profile (some data from Firebase) │ │
│ │ • PUT /profile │ │
│ │ └── fullName (required) │ │
│ │ └── username (required, unique) │ │
│ │ └── bio (required) │ │
│ │ └── gender, link (optional) │ │
│ │ • On save: auto-completes onboarding │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ STEP 5: COMPLETED ✓ │ │
│ ├─────────────────────────────────────────────────────────────────┤ │
│ │ • Navigate to home screen │ │
│ │ • User can now access all app features │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ PENDING │ │ PENDING │ │ PENDING │ │ │
│ PHONE │────▶│ PREFERENCES │────▶│ PROFILE │────▶│ COMPLETED │
│ VERIFICATION │ │ │ │ COMPLETION │ │ │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
│ │ │ │
▼ ▼ ▼ ▼
Phone OTP Flow Preference Pages Profile Update Main App
(request/verify) (dynamic pages) (auto-complete) Access
Onboarding Status Values
| ||
| ||
| ||
|
Step Weight Distribution
Standard Response Format
All API responses follow a consistent structure using our Globe Response Builder pattern:
Success Response Structure
{
"success": true,
"httpStatus": "OK",
"message": "Operation completed successfully",
"action_time": "2025-01-02T10:30:45",
"data": {
// Actual response data goes here
}
}
Error Response Structure
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Error description",
"action_time": "2025-01-02T10:30:45",
"data": "Error description"
}
Phone Verification Endpoints
1. Request OTP
Purpose: RequestSend aOTP one-time passwordcode to be sent via SMS foruser's phone number for verification.
Endpoint: POST {base_url}/onboarding/auth-phone/request-otp
Access Level: 🔒 Protected (Requires valid access token)
Authentication: Bearer Token
Request HeadersPrerequisite:
| |||
|
Request JSON Sample:
{
"phoneNumber": "+255712345678"
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation | |
|---|---|---|---|---|---|
phoneNumber |
string | Yes | Phone number |
E.164 | format: 255XXXXXXXXX |
Supported Country Codes:
+255 | - Tanzania |
+254 | - Kenya |
+256 | - Uganda |
+250 | - Rwanda |
+257 | - Burundi |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "OTP sent successfully",
"action_time": "2025-01-02T10:05T10:30:45",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"phoneNumber": "+255****678",
"expiresInSeconds": 600,
"resendAvailableIn": 120
}
}
Success Response Fields:
| Field | Description |
|---|---|
token |
Temporary token for verify/resend endpoints |
| phoneNumber | Masked phone number for |
expiresInSeconds |
OTP validity period ( |
resendAvailableIn |
Seconds until resend |
Error Response JSON SamplesResponses:
Wrong Onboarding Step (412):
{
"success": false,
"httpStatus": "PRECONDITION_FAILED",
"message": "Onboarding step required",
"action_time": "2025-01-05T10:30:45",
"data": {
"message": "Complete email verification first",
"currentStep": "PENDING_EMAIL_VERIFICATION",
"requiredStep": "PENDING_EMAIL_VERIFICATION"
}
}
Rate Limit Exceeded (429):
{
"success": false,
"httpStatus": "TOO_MANY_REQUESTS",
"message": "Too many OTP requests. Try again in 10 minutes.",
"action_time": "2025-01-05T10:30:45",
"data": "Too many OTP requests. Try again in 10 minutes."
}
Phone Already Registered (409):
{
"success": false,
"httpStatus": "CONFLICT",
"message": "Phone number already registered",
"action_time": "2025-01-02T10:05T10:30:45",
"data": "Phone number already registered to another account"
}
Rate Limit Exceeded (429):
{
"success": false,
"httpStatus": "TOO_MANY_REQUESTS",
"message": "Too many OTP requests",
"action_time": "2025-01-02T10:30:45",
"data": "Too many OTP requests. Try again in 10 minutes."
}
Resend Cooldown Active (429):
{
"success": false,
"httpStatus": "TOO_MANY_REQUESTS",
"message": "Please wait before requesting another OTP",
"action_time": "2025-01-02T10:30:45",
"data": "Please wait 85 seconds before requesting another OTP"
}
Unsupported Country (400):
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Unsupported country code",
"action_time": "2025-01-02T10:30:45",
"data": "Supported country codes: +255, +254, +256, +250, +257"registered"
}
2. Verify OTP
Purpose: Verify the OTP code sentand to the user'scomplete phone number.verification.
Endpoint: POST {base_url}/onboarding/auth-phone/verify
Access Level: 🔒 Protected (Requires valid access token)
Authentication: Bearer Token
Request Headers:
| |||
|
Request JSON Sample:
{
"phoneNumber"token": "+255712345678"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"otp": "123456"
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
token |
string | Yes | ||
otp |
string | Yes | 6-digit OTP code | Exactly 6 digits |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Phone verified successfully",
"action_time": "2025-01-02T10:30:45"05T10:35:00",
"data": {
"verified": true,
"phoneNumber": "+255712345678"255****678",
"onboardingStatus": "PENDING_PREFERENCES",
"nextStep": "/api/v1/onboarding/preferences"pages"
}
}
Success Response Fields:
| |
| |
| |
|
Error Response JSON SamplesResponses:
Invalid OTP (403):
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Invalid OTP"OTP. 2 attempt(s) remaining.",
"action_time": "2025-01-02T10:30:45"05T10:35:00",
"data": "Invalid OTP. 2 attempt(s) remaining."
}
Expired OTP Expired (403):
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "OTP has expired"expired. Please request a new one.",
"action_time": "2025-01-02T10:30:45"05T10:35:00",
"data": "OTP has expired. Please request a new one."
}
Max Attempts Reached (403):
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Maximum attempts reached"reached. Please request a new OTP.",
"action_time": "2025-01-02T10:30:45"05T10:35:00",
"data": "Maximum attempts reached. Please request a new OTP."
}
No Active OTP (403):
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "No active OTP found",
"action_time": "2025-01-02T10:30:45",
"data": "No active OTP found. Please request a new one."
}
3. Resend OTP
Purpose: ResendRequest a new OTP tocode using the sameexisting phone number (subject to cooldown).token.
Endpoint: POST {base_url}/onboarding/auth-phone/resend-otp
Access Level: 🔒 Protected (Requires valid access token)
Authentication: Bearer Token
Request Headers:
| |||
|
Request JSON Sample:
{
"phoneNumber"token": "+255712345678"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
RequestSuccess Body ParametersResponse:
|
4. Get Email Verification Status
Purpose: Check email verification status and options.
Endpoint: GET {base_url}/onboarding/email-verification/status
Access Level: 🔒 Protected
Authentication: Bearer Token
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "OTPEmail resentverification successfully"status",
"action_time": "2025-01-02T10:30:45"05T10:00:00",
"data": {
"phoneNumber"verified": false,
"email": "+255*jo****678"@example.com",
"expiresInSeconds"required": 600,false,
"resendAvailableIn"canSkip": 120true,
"currentStep": "PENDING_EMAIL_VERIFICATION"
}
}
Same response format as Request OTP
Language5. PreferenceSkip Endpoint
Email 4. Set Language PreferenceVerification
Purpose: SetSkip user'semail preferredverification languagestep for(if theallowed platform.by config).
Endpoint: POST {base_url}/onboarding/language-preferenceemail-verification/skip
Access Level: 🔒 Protected (Requires valid access token)
Authentication: Bearer Token
Request Headers:
| |||
|
Request JSON Sample:
{
"code": "sw"
}
Request Body Parameters:
|
Supported Languages:
| ||
| ||
| ||
|
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "LanguageEmail preferenceverification updated"skipped",
"action_time": "2025-01-02T10:30:45"05T10:05:00",
"data": {
"code"verified": false,
"skipped": true,
"nextStep": "sw",
"name": "Swahili",
"nativeName": "Kiswahili"PENDING_PHONE_VERIFICATION"
}
}
Success
ResponsePreference
Fields:
| |
| |
|
Onboarding Progress Endpoint
5.6. Get Onboarding Progress
Purpose: Get detailedoverall onboarding progress information acrosswith all onboarding steps with weighted percentages.steps.
Endpoint: GET {base_url}/onboarding/progress
Access Level: 🔒 Protected (Requires valid access token)
Authentication: Bearer Token
Request Headers:
| |||
|
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Progress retrieved",
"action_time": "2025-01-02T10:30:45"05T10:40:00",
"data": {
"percentage": 55.45.0,
"currentStage": "PENDING_PREFERENCES",
"currentStageLabel": "Complete your preferences",
"steps": [
{
"key": "registration",
"label": "Registration",
"completed": true,
"weight": 15.0
},
{0,
"key"skippable": "email_verification",
"label": "Email Verification",
"completed": true,
"weight": 15.0false
},
{
"key": "phone_verification",
"label": "Phone Verification",
"completed": true,
"weight": 15.00,
"skippable": false
},
{
"key": "page_interests",
"label": "WhatYour are your interests?"Interests",
"completed": true,
"weight": 13.33
},
{33,
"key"skippable": "page_industries",
"label": "Select your industries",
"completed": false,
"weight": 13.33false
},
{
"key": "page_goals",
"label": "WhatYour are your goals?"Goals",
"completed": false,
"weight": 13.3433,
"skippable": true
},
{
"key": "page_experience",
"label": "Your Experience",
"completed": false,
"weight": 13.33,
"skippable": false
},
{
"key": "profile_completion",
"label": "Complete Profile",
"completed": false,
"weight": 15.00,
"skippable": false
}
],
"nextStep": {
"key": "page_industries"page_goals",
"label": "SelectYour your industries"Goals",
"endpoint": "/api/v1/onboarding/pages?page=2",
"skippable": true
}
}
}
Success Response Fields:
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
Onboarding Pages Endpoints
6.7. Get All Pages
Purpose: RetrieveGet all active onboarding preference pages with completion status.
Endpoint: GET {base_url}/onboarding/pages
Access Level: 🔒 Protected (Requires valid access token)
Authentication: Bearer Token
Request Headers:
| |||
|
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
all |
boolean | No | |
page |
integer | No | Get specific page by order |
category |
string | No | Get page by category key |
current |
boolean | No | |
Success Response JSON Sample (all=true):
{
"success": true,
"httpStatus": "OK",
"message": "All pages retrieved",
"action_time": "2025-01-02T10:30:45"05T10:45:00",
"data": {
"totalPages": 3,
"completedPages": 1,
"isOnboardingComplete": false,
"pages": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"pageOrder": 1,
"categoryKey": "interests",
"title": "WhatMaslahi are your interests?"Yako",
"description": "SelectChagua themambo areas you're most interested in exploring on Fursa Hub"yanayokuvutia",
"bannerImages": [
"https://cdn.fursahub.com/onboarding/interests-banner.interests.jpg"
],
"isSkippable": false,
"minSelections": 1,
"maxSelections": 5,
"options": [
{ "key": "technology"jobs", "label": "Technology"Kazi", "icon": "💻"briefcase" },
{ "key": "agriculture"funding", "label": "Agriculture"Ufadhili", "icon": "🌾"dollar" },
{ "key": "finance"events", "label": "Finance & Banking"Matukio", "icon": "💰"calendar" },
{ "key": "health"skills", "label": "Healthcare"Ujuzi", "icon": "🏥"book" },
{ "key": "education"networking", "label": "Education"Mitandao", "icon": "📚"users" }
],
"isCompleted": true
},
{
"id": "550e8400-e29b-41d4-a716-446655440002",
"pageOrder": 2,
"categoryKey": "industries",
"title": "Select your industries",
"description": "Choose the industries you work in or want to explore",
"bannerImages": [],
"isSkippable": true,
"minSelections": 0,
"maxSelections": 10,
"options": [
{
"key": "tech_startup",
"label": "Tech Startups",
"icon": "🚀"
},
{
"key": "manufacturing",
"label": "Manufacturing",
"icon": "🏭"
},
{
"key": "retail",
"label": "Retail & E-commerce",
"icon": "🛒"
}
],
"isCompleted": false
},
{
"id": "550e8400-e29b-41d4-a716-446655440003",
"pageOrder": 3,
"categoryKey": "goals",
"title": "WhatMalengo are your goals?"Yako",
"description": "TellUnataka uskufikia what you want to achieve on Fursa Hub",
nini?"bannerImages": [],
"isSkippable": false,true,
"minSelections": 1,
"maxSelections": 3,
"options": [
{ "key": "find_job", "label": "FindKupata a Job"kazi", "icon": "💼"search" },
{ "key": "find_funding"start_business", "label": "FindKuanzisha Funding"biashara", "icon": "💵"
},
{
"key": "network",
"label": "Networking",
"icon": "🤝"store" },
{ "key": "learn_skills", "label": "LearnKujifunza New Skills"ujuzi", "icon": "📖graduation" },
{ "key": "get_funding", "label": "Kupata ufadhili", "icon": "money" }
],
"isCompleted": false
}
]
}
}
Success Response Fields:
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
7.8. Get SingleCurrent Page
Purpose: RetrieveGet athe specificfirst onboardingincomplete pagepreference with progress context.page.
Endpoint: GET {base_url}/onboarding/pages?page={pageOrder}current=true
Access Level: 🔒 Protected (Requires valid access token)
Authentication: Bearer Token
Query Parameters:
|
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "PageCurrent page retrieved",
"action_time": "2025-01-02T10:30:45"05T10:50:00",
"data": {
"page": {
"id": "550e8400-e29b-41d4-a716-446655440002",
"pageOrder": 2,
"categoryKey": "industries"goals",
"title": "SelectMalengo your industries"Yako",
"description": "ChooseUnataka thekufikia industries you work in or want to explore",
nini?"bannerImages": [],
"isSkippable": true,
"minSelections": 0,1,
"maxSelections": 10,3,
"options": [
{
"key": "tech_startup",
"label": "Tech Startups",
"icon": "🚀"
},
{
"key": "manufacturing",
"label": "Manufacturing",
"icon": "🏭"
}
...],
"isCompleted": false
},
"progress": {
"current": 2,
"total": 3,
"nextPage": 3,
"isLast": false,
"isCompleted": false
}
}
}
Success Response Fields:
| |
| |
| |
| |
| |
|
8. Get Current Page
Purpose: Get the next incomplete onboarding page.
Endpoint: GET {base_url}/onboarding/pages?current=true
Access Level: 🔒 Protected (Requires valid access token)
Authentication: Bearer Token
Success Response JSON Sample (when pages remain):
{
"success": true,
"httpStatus": "OK",
"message": "Current page retrieved",
"action_time": "2025-01-02T10:30:45",
"data": {
"page": {
"id": "550e8400-e29b-41d4-a716-446655440002",
"pageOrder": 2,
"categoryKey": "industries",
"title": "Select your industries",
"description": "Choose the industries you work in",
"bannerImages": [],
"isSkippable": true,
"minSelections": 0,
"maxSelections": 10,
"options": [...],
"isCompleted": false
},
"progress": {
"current": 2,
"total": 3,
"nextPage": 3,
"isLast": false,
"isCompleted": false
}
}
}
Success Response JSON Sample (all pages completed):
{
"success": true,
"httpStatus": "OK",
"message": "Current page retrieved",
"action_time": "2025-01-02T10:30:45",
"data": {
"page": null,
"progress": {
"current": 3,
"total": 3,
"nextPage": null,
"isLast": true,
"isCompleted": true
}
}
}
9. Submit Page Response
Purpose: SubmitSave user's selected optionsselections for ana onboardingpreference page.
Endpoint: POST {base_url}/onboarding/pages/{pageId}/response
Access Level: 🔒 Protected (Requires valid access token)
Authentication: Bearer Token
Request Headers:
| |||
|
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
pageId |
UUID | Yes | Page identifier |
Request JSON Sample:
{
"selectedOptions": ["technology"find_job", "finance", "health"learn_skills"]
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
selectedOptions |
Yes | Array of selected option keys | Must |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Response saved",
"action_time": "2025-01-02T10:30:45"05T10:55:00",
"data": {
"saved": true,
"progress": {
"current": 1,2,
"total": 3,
"nextPage": 2,3,
"isLast": false,
"isCompleted": false
}
}
}
Success Response Fields:
| |
| |
| |
| |
| |
|
Error Response JSON SamplesResponses:
Too Few Selections (400):
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Minimum selections1 notselection(s) met"required",
"action_time": "2025-01-02T10:30:45"05T10:55:00",
"data": "Minimum 1 selection(s) required"
}
Too Many Selections (400):
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Maximum selections exceeded",
"action_time": "2025-01-02T10:30:45",
"data": "Maximum 5 selection(s) allowed"
}
Invalid Option (400):
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Invalid option"option: unknown_key",
"action_time": "2025-01-02T10:30:45"05T10:55:00",
"data": "Invalid option: unknown_key"
}
Page Not Found (404):
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Page not found",
"action_time": "2025-01-02T10:30:45",
"data": "Page not found"
}
10. Skip Page
Purpose: Skip ana optionalpreference onboardingpage page.(only if page is skippable).
Endpoint: POST {base_url}/onboarding/pages/{pageId}/skip
Access Level: 🔒 Protected (Requires valid access token)
Authentication: Bearer Token
Path Parameters:
|
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Page skipped",
"action_time": "2025-01-02T10:30:45"05T11:00:00",
"data": {
"saved": true,
"progress": {
"current": 2,
"total": 3,
"nextPage": 3,
"isLast": false,
"isCompleted": false
}
}
}
Error Response JSON Sample:
(Page Not Skippable (400)Skippable):
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "PageThis page cannot be skipped",
"action_time": "2025-01-02T10:30:45"05T11:00:00",
"data": "This page cannot be skipped"
}
AdminLanguage EndpointsPreference Endpoint
11. GetSet AllLanguage Pages (Admin)Preference
Purpose: RetrieveUpdate alluser's onboardinglanguage pagespreference including(can inactivebe onescalled foranytime adminduring management.onboarding).
Endpoint: GETPOST {base_url}/onboarding/pages/managelanguage-preference
Access Level: 🔒 Protected (Requires ROLE_MODERATOR, ROLE_ADMIN, or ROLE_SUPER_ADMIN)
Authentication: Bearer Token
Request JSON Sample:
{
"code": "sw"
}
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "PagesLanguage retrieved"preference updated",
"action_time": "2025-01-02T10:30:45",
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"pageOrder": 1,
"categoryKey": "interests",
"title": "What are your interests?",
"description": "Select the areas you're most interested in",
"bannerImages": [],
"isSkippable": false,
"minSelections": 1,
"maxSelections": 5,
"options": [...],
"isCompleted": false
}
]
}
12. Create Page (Admin)
Purpose: Create a new onboarding page with multilingual support.
Endpoint: POST {base_url}/onboarding/pages/manage
Access Level: 🔒 Protected (Requires ROLE_MODERATOR, ROLE_ADMIN, or ROLE_SUPER_ADMIN)
Authentication: Bearer Token
Request JSON Sample:
{
"pageOrder": 4,
"categoryKey": "experience_level",
"isSkippable": true,
"minSelections": 1,
"maxSelections": 1,
"translations": {
"en": {
"title": "What's your experience level?",
"description": "Help us understand your professional background"
},
"sw": {
"title": "Kiwango chako cha uzoefu ni kipi?",
"description": "Tusaidie kuelewa historia yako ya kitaaluma"
}
},
"bannerImages": [
"https://cdn.fursahub.com/onboarding/experience-banner.jpg"
],
"options": [
{
"key": "student",
"icon": "🎓",
"translations": {
"en": "Student",
"sw": "Mwanafunzi"
}
},
{
"key": "entry_level",
"icon": "🌱",
"translations": {
"en": "Entry Level (0-2 years)",
"sw": "Kiwango cha Mwanzo (miaka 0-2)"
}
},
{
"key": "mid_level",
"icon": "📈",
"translations": {
"en": "Mid Level (3-5 years)",
"sw": "Kiwango cha Kati (miaka 3-5)"
}
},
{
"key": "senior",
"icon": "⭐",
"translations": {
"en": "Senior (6+ years)",
"sw": "Mkuu (miaka 6+)"
}
}
]
}
Request Body Parameters:
| ||||
| ||||
| ||||
| ||||
| ||||
| | |||
| ||||
| ||||
| ||||
| ||||
| ||||
| ||||
| |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "CREATED",
"message": "Page created",
"action_time": "2025-01-02T10:30:45"05T11:05:00",
"data": {
"id"code": "550e8400-e29b-41d4-a716-446655440004"sw",
"pageOrder": 4,
"categoryKey"name": "experience_level"Swahili",
"title"nativeName": "What's your experience level?",
"description": "Help us understand your professional background",
"bannerImages": ["https://cdn.fursahub.com/onboarding/experience-banner.jpg"],
"isSkippable": true,
"minSelections": 1,
"maxSelections": 1,
"options": [
{"key": "student", "label": "Student", "icon": "🎓"},
{"key": "entry_level", "label": "Entry Level (0-2 years)", "icon": "🌱"},
{"key": "mid_level", "label": "Mid Level (3-5 years)", "icon": "📈"},
{"key": "senior", "label": "Senior (6+ years)", "icon": "⭐"}
],
"isCompleted": falseKiswahili"
}
}
13. Update Page (Admin)
Purpose: Update an existing onboarding page.
Endpoint: PUT {base_url}/onboarding/pages/manage/{pageId}
Access Level: 🔒 Protected (Requires ROLE_MODERATOR, ROLE_ADMIN, or ROLE_SUPER_ADMIN)
Authentication: Bearer Token
Path Parameters:
|
Request body same as Create Page
14. Delete Page (Admin)
Purpose: Delete an onboarding page.
Endpoint: DELETE {base_url}/onboarding/pages/manage/{pageId}
Access Level: 🔒 Protected (Requires ROLE_MODERATOR, ROLE_ADMIN, or ROLE_SUPER_ADMIN)
Authentication: Bearer Token
Path Parameters:
|
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Page deleted",
"action_time": "2025-01-02T10:30:45",
"data": null
}
15. Activate/Deactivate Page (Admin)
Purpose: Toggle page active status.
Endpoint (Activate): PATCH {base_url}/onboarding/pages/manage/{pageId}/activate
Endpoint (Deactivate): PATCH {base_url}/onboarding/pages/manage/{pageId}/deactivate
Access Level: 🔒 Protected (Requires ROLE_MODERATOR, ROLE_ADMIN, or ROLE_SUPER_ADMIN)
Authentication: Bearer Token
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Page activated",
"action_time": "2025-01-02T10:30:45",
"data": null
}
16. Reorder Pages (Admin)
Purpose: Change the display order of onboarding pages.
Endpoint: PATCH {base_url}/onboarding/pages/manage/reorder
Access Level: 🔒 Protected (Requires ROLE_MODERATOR, ROLE_ADMIN, or ROLE_SUPER_ADMIN)
Authentication: Bearer Token
Request JSON Sample:
{
"pageIds": [
"550e8400-e29b-41d4-a716-446655440003",
"550e8400-e29b-41d4-a716-446655440001",
"550e8400-e29b-41d4-a716-446655440002"
]
}
Request Body Parameters:
|
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Pages reordered",
"action_time": "2025-01-02T10:30:45",
"data": null
}
Standard Error Types
Application-Level Exceptions (400-499)
Server-Level Exceptions (500+)
Frontend Implementation Guide
CompletePhone OnboardingVerification FlowScreen
const1. completeOnboardingShow =phone asyncinput ()with =>country {code selector
2. On submit: POST /onboarding/auth-phone/request-otp
3. Save token from response
4. Navigate to OTP input screen
5. Show countdown for resendAvailableIn
6. On OTP submit: POST /onboarding/auth-phone/verify
Step7. 1:On Checksuccess: currentNavigate progressbased conston progress = await getProgress();
switch (progress.currentStage) {
case 'PENDING_PHONE_VERIFICATION':
navigation.navigate('PhoneVerification');
break;
case 'PENDING_PREFERENCES':
navigation.navigate('OnboardingPages');
break;
case 'PENDING_PROFILE_COMPLETION':
navigation.navigate('ProfileCompletion');
break;
case 'COMPLETED':
navigation.navigate('Home');
break;
}
};
Quick Reference
Onboarding Status Flow
PENDING_PHONE_VERIFICATION → PENDING_PREFERENCES → PENDING_PROFILE_COMPLETION → COMPLETEDnextStep
OTPPreference ConfigurationPages Loop
SupportedProgress LanguagesIndicator
| ||
| ||
| ||
|
Admin Rolespercentage for Pageprogress Management
bar
|
|
| |
| |
|