Useless Call Form API
Last Updated: 2026-02-11
Version: v1.0
Base URL: https://api.fursahub.com/api/v1
Short Description: The Useless Call Form API manages application forms for calls/opportunities posted on the FursaHub platform. It handles the complete lifecycle of application forms from creation through submission to review and approval/rejection. This API enables users to apply to calls by filling out detailed application forms and allows call owners to manage and review submitted applications.
Hints:
- All endpoints require authentication via Bearer token unless specified otherwise
- Form submissions cannot be edited after the status changes from DRAFT to SUBMITTED
- Call owners can only view forms with status SUBMITTED, UNDER_REVIEW, APPROVED, or REJECTED
- Applicants can save forms multiple times while in DRAFT status
- One user can only have one application per call (duplicate prevention)
- Page numbers start from 1 (not 0)
- Default pagination size is 20 items per page
- All timestamps are in ISO 8601 format
- File uploads (documents, certificates) should be handled separately and only URLs are stored in the form
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": "2026-02-11T10:30:45",
"data": {
// Actual response data goes here
}
}
Error Response Structure
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Error description",
"action_time": "2026-02-11T10:30:45",
"data": "Error description"
}
Standard Response Fields
| Field | Type | Description |
|---|---|---|
success |
boolean | Always true for successful operations, false for errors |
httpStatus |
string | HTTP status name (OK, BAD_REQUEST, NOT_FOUND, etc.) |
message |
string | Human-readable message describing the operation result |
action_time |
string | ISO 8601 timestamp of when the response was generated |
data |
object/string | Response payload for success, error details for failures |
HTTP Method Badge Standards
For better visual clarity, all endpoints use colored badges for HTTP methods with the following standard colors:
- GET - GET - Green (Safe, read-only operations)
- POST - POST - Blue (Create new resources)
- PUT - PUT - Yellow (Update/replace entire resource)
- PATCH - PATCH - Orange (Partial updates)
- DELETE - DELETE - Red (Remove resources)
Endpoints
1. Start Application Form
Purpose: Initialize a new application form for a specific call application in DRAFT status
Endpoint: POST {base_url}/useless-forms/applications/{applicationId}/start
Access Level: 🔒 Protected (Requires Bearer Token - Must be the application owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token for authentication |
| Content-Type | string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
| applicationId | UUID | Yes | Unique identifier of the call application | Must be valid UUID format |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form started successfully",
"action_time": "2026-02-11T10:30:45",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"applicationId": "660e8400-e29b-41d4-a716-446655440001",
"callId": "770e8400-e29b-41d4-a716-446655440002",
"userId": "880e8400-e29b-41d4-a716-446655440003",
"applicationStatus": "DRAFT",
"createdAt": "2026-02-11T10:30:45",
"updatedAt": "2026-02-11T10:30:45"
}
}
Success Response Fields:
| Field | Description |
|---|---|
| id | Unique identifier of the form |
| applicationId | Reference to the call application |
| callId | Reference to the call this form belongs to |
| userId | ID of the user who created the form |
| applicationStatus | Current status of the form (always DRAFT when starting) |
| createdAt | Timestamp when the form was created |
| updatedAt | Timestamp when the form was last updated |
Error Response Examples:
{
"success": false,
"httpStatus": "UNAUTHORIZED",
"message": "User not authenticated",
"action_time": "2026-02-11T10:30:45",
"data": "User not authenticated"
}
Forbidden (403):
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Not authorized",
"action_time": "2026-02-11T10:30:45",
"data": "Not authorized"
}
Not Found (404):
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Application not found",
"action_time": "2026-02-11T10:30:45",
"data": "Application not found"
}
2. Save Form Draft
Purpose: Save or update form data while keeping it in DRAFT status (can be called multiple times)
Endpoint: PUT {base_url}/useless-forms/applications/{applicationId}/draft
Access Level: 🔒 Protected (Requires Bearer Token - Must be the form owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token for authentication |
| Content-Type | string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
| applicationId | UUID | Yes | Unique identifier of the call application | Must be valid UUID format |
Request JSON Sample:
{
"whoIsApplying": "MYSELF",
"fullName": "John Doe",
"username": "johndoe",
"email": "john.doe@example.com",
"phoneNumber": "+255712345678",
"countryCode": "+255",
"nationality": "Tanzanian",
"preferredContactMethod": "EMAIL",
"profilePictureUrl": "https://storage.example.com/profiles/john.jpg",
"employmentStatus": "EMPLOYED",
"employerName": "Tech Solutions Ltd",
"jobTitle": "Software Engineer",
"employmentType": "FULL_TIME",
"dateOfBirth": "1990-05-15",
"placeOfBirth": "Dar es Salaam",
"sex": "MALE",
"maritalStatus": "SINGLE",
"ethnicity": "African",
"idType": "NIDA",
"idNumber": "19900515-12345-67890-12",
"nameOnId": "John Doe",
"idPhotoUrl": "https://storage.example.com/ids/john_id.jpg",
"primaryAddress": "123 Main Street",
"city": "Dar es Salaam",
"country": "Tanzania",
"region": "Dar es Salaam",
"district": "Kinondoni",
"zipCode": "12345",
"ownsBusiness": true,
"hasBusinessLicense": true,
"businessName": "JD Tech Solutions",
"businessEmail": "info@jdtech.com",
"businessPhoneNumber": "+255712345679",
"businessTinNumber": "123-456-789",
"businessIndustry": "TECHNOLOGY",
"businessWebsite": "https://jdtech.com",
"businessAddress": "456 Business Avenue",
"businessLicenseCertificateUrl": "https://storage.example.com/licenses/business_license.pdf",
"businessTinCertificateUrl": "https://storage.example.com/certificates/tin.pdf",
"loanApplicationLetterUrl": "https://storage.example.com/letters/loan_application.pdf",
"boardResolutionUrl": "https://storage.example.com/resolutions/board_resolution.pdf",
"businessLicenseEvidenceUrl": "https://storage.example.com/evidence/license_evidence.pdf",
"taxClearanceCertificateUrl": "https://storage.example.com/certificates/tax_clearance.pdf",
"taxpayerTin": "987-654-321",
"taxpayerIdType": "NIDA",
"taxpayerIdNumber": "19900515-12345-67890-12",
"taxpayerNameOnId": "John Doe",
"certificateOfRegistrationUrl": "https://storage.example.com/certificates/registration.pdf",
"bankStatementUrl": "https://storage.example.com/statements/bank_statement.pdf",
"allPurposeSupportingDocsUrl": "https://storage.example.com/docs/supporting_docs.pdf",
"brelaSearchReturnsUrl": "https://storage.example.com/brela/search_returns.pdf",
"callNotes": "Applying for business expansion loan"
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
| whoIsApplying | string | No | Who is submitting the application | enum: MYSELF, SOMEONE_ELSE |
| fullName | string | No | Full legal name of the applicant | Max: 200 characters |
| username | string | No | Username of the applicant | Max: 100 characters |
| string | No | Email address | Must be valid email format | |
| phoneNumber | string | No | Phone number with country code | Max: 20 characters |
| countryCode | string | No | International dialing code | Max: 10 characters |
| nationality | string | No | Nationality of the applicant | Max: 100 characters |
| preferredContactMethod | string | No | Preferred way to be contacted | enum: EMAIL, SMS, PHONE_CALL |
| profilePictureUrl | string | No | URL to profile picture | Valid URL format |
| employmentStatus | string | No | Current employment situation | enum: EMPLOYED, SELF_EMPLOYED, UNEMPLOYED, STUDENT, RETIRED |
| employerName | string | No | Name of current employer | Max: 200 characters |
| jobTitle | string | No | Current job title | Max: 200 characters |
| employmentType | string | No | Type of employment | enum: FULL_TIME, PART_TIME, CONTRACT, FREELANCE, INTERNSHIP |
| dateOfBirth | date | No | Date of birth | ISO 8601 date format (YYYY-MM-DD) |
| placeOfBirth | string | No | Place where applicant was born | Max: 200 characters |
| sex | string | No | Biological sex | enum: MALE, FEMALE, OTHER, PREFER_NOT_TO_SAY |
| maritalStatus | string | No | Current marital status | enum: SINGLE, MARRIED, DIVORCED, WIDOWED, SEPARATED |
| ethnicity | string | No | Ethnic background | Max: 100 characters |
| idType | string | No | Type of identification document | enum: NATIONAL_ID, PASSPORT, DRIVERS_LICENSE, VOTERS_ID, NIDA |
| idNumber | string | No | Identification document number | Max: 100 characters |
| nameOnId | string | No | Name as it appears on ID | Max: 200 characters |
| idPhotoUrl | string | No | URL to ID document photo | Valid URL format |
| primaryAddress | string | No | Primary residential address | Max: 500 characters |
| city | string | No | City of residence | Max: 100 characters |
| country | string | No | Country of residence | Max: 100 characters |
| region | string | No | Region/State of residence | Max: 100 characters |
| district | string | No | District of residence | Max: 100 characters |
| zipCode | string | No | Postal/ZIP code | Max: 20 characters |
| ownsBusiness | boolean | No | Whether applicant owns a business | true or false |
| hasBusinessLicense | boolean | No | Whether business has a valid license | true or false |
| businessName | string | No | Registered business name | Max: 200 characters |
| businessEmail | string | No | Business email address | Must be valid email format |
| businessPhoneNumber | string | No | Business contact number | Max: 20 characters |
| businessTinNumber | string | No | Business Tax Identification Number | Max: 100 characters |
| businessIndustry | string | No | Industry/sector of business | enum: AGRICULTURE, MANUFACTURING, RETAIL, TECHNOLOGY, HEALTHCARE, EDUCATION, FINANCE, CONSTRUCTION, HOSPITALITY, TRANSPORTATION, REAL_ESTATE, PROFESSIONAL_SERVICES, ENTERTAINMENT, MARKETING, OTHER |
| businessWebsite | string | No | Business website URL | Valid URL format |
| businessAddress | string | No | Physical business address | Max: 500 characters |
| businessLicenseCertificateUrl | string | No | URL to business license document | Valid URL format |
| businessTinCertificateUrl | string | No | URL to TIN certificate | Valid URL format |
| loanApplicationLetterUrl | string | No | URL to loan application letter | Valid URL format |
| boardResolutionUrl | string | No | URL to board resolution document | Valid URL format |
| businessLicenseEvidenceUrl | string | No | URL to business license evidence | Valid URL format |
| taxClearanceCertificateUrl | string | No | URL to tax clearance certificate | Valid URL format |
| taxpayerTin | string | No | Personal Tax Identification Number | Max: 100 characters |
| taxpayerIdType | string | No | Type of taxpayer ID | enum: NATIONAL_ID, PASSPORT, DRIVERS_LICENSE, VOTERS_ID, NIDA |
| taxpayerIdNumber | string | No | Taxpayer ID number | Max: 100 characters |
| taxpayerNameOnId | string | No | Name as appears on taxpayer ID | Max: 200 characters |
| certificateOfRegistrationUrl | string | No | URL to certificate of registration | Valid URL format |
| bankStatementUrl | string | No | URL to bank statement | Valid URL format |
| allPurposeSupportingDocsUrl | string | No | URL to general supporting documents | Valid URL format |
| brelaSearchReturnsUrl | string | No | URL to BRELA search returns | Valid URL format |
| llcFundApplicationLetterUrl | string | No | URL to LLC fund application letter | Valid URL format |
| llcMemartUrl | string | No | URL to LLC MEMART document | Valid URL format |
| llcCertificateOfIncorporationUrl | string | No | URL to LLC certificate of incorporation | Valid URL format |
| partnershipDeedUrl | string | No | URL to partnership deed | Valid URL format |
| partnershipCertificateRegistrationUrl | string | No | URL to partnership certificate | Valid URL format |
| partnershipMemartUrl | string | No | URL to partnership MEMART | Valid URL format |
| partnershipCertificateIncorporationUrl | string | No | URL to partnership incorporation cert | Valid URL format |
| generalBrelaSearchUrl | string | No | URL to general BRELA search | Valid URL format |
| generalFundApplicationUrl | string | No | URL to general fund application | Valid URL format |
| generalMemartUrl | string | No | URL to general MEMART | Valid URL format |
| generalCertificateIncorporationUrl | string | No | URL to general certificate of incorporation | Valid URL format |
| callNotes | string | No | Additional notes about the application | Max: 5000 characters |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Draft saved successfully",
"action_time": "2026-02-11T10:35:20",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"applicationId": "660e8400-e29b-41d4-a716-446655440001",
"callId": "770e8400-e29b-41d4-a716-446655440002",
"userId": "880e8400-e29b-41d4-a716-446655440003",
"whoIsApplying": "MYSELF",
"fullName": "John Doe",
"email": "john.doe@example.com",
"phoneNumber": "+255712345678",
"applicationStatus": "DRAFT",
"createdAt": "2026-02-11T10:30:45",
"updatedAt": "2026-02-11T10:35:20"
}
}
Error Response Examples:
Not Found (404):
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Form not found",
"action_time": "2026-02-11T10:35:20",
"data": "Form not found"
}
Forbidden (403):
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Not authorized",
"action_time": "2026-02-11T10:35:20",
"data": "Not authorized"
}
3. Submit Application Form
Purpose: Submit a draft form for review (changes status from DRAFT to SUBMITTED)
Endpoint: POST {base_url}/useless-forms/applications/{applicationId}/submit
Access Level: 🔒 Protected (Requires Bearer Token - Must be the form owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token for authentication |
| Content-Type | string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
| applicationId | UUID | Yes | Unique identifier of the call application | Must be valid UUID format |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form submitted successfully",
"action_time": "2026-02-11T11:00:00",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"applicationId": "660e8400-e29b-41d4-a716-446655440001",
"callId": "770e8400-e29b-41d4-a716-446655440002",
"userId": "880e8400-e29b-41d4-a716-446655440003",
"fullName": "John Doe",
"email": "john.doe@example.com",
"applicationStatus": "SUBMITTED",
"submittedAt": "2026-02-11T11:00:00",
"createdAt": "2026-02-11T10:30:45",
"updatedAt": "2026-02-11T11:00:00"
}
}
Success Response Fields:
| Field | Description |
|---|---|
| submittedAt | Timestamp when the form was submitted |
| applicationStatus | Changed to SUBMITTED status |
Error Response Examples:
Bad Request (400):
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Form already submitted",
"action_time": "2026-02-11T11:00:00",
"data": "Form already submitted"
}
Not Found (404):
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Form not found",
"action_time": "2026-02-11T11:00:00",
"data": "Form not found"
}
4. Get Form by Application ID
Purpose: Retrieve a specific form using the application ID
Endpoint: GET {base_url}/useless-forms/applications/{applicationId}
Access Level: 🔒 Protected (Requires Bearer Token - Must be form owner or call owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token for authentication |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
| applicationId | UUID | Yes | Unique identifier of the call application | Must be valid UUID format |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form retrieved successfully",
"action_time": "2026-02-11T11:15:00",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"applicationId": "660e8400-e29b-41d4-a716-446655440001",
"callId": "770e8400-e29b-41d4-a716-446655440002",
"userId": "880e8400-e29b-41d4-a716-446655440003",
"whoIsApplying": "MYSELF",
"fullName": "John Doe",
"username": "johndoe",
"email": "john.doe@example.com",
"phoneNumber": "+255712345678",
"countryCode": "+255",
"nationality": "Tanzanian",
"preferredContactMethod": "EMAIL",
"profilePictureUrl": "https://storage.example.com/profiles/john.jpg",
"employmentStatus": "EMPLOYED",
"employerName": "Tech Solutions Ltd",
"jobTitle": "Software Engineer",
"employmentType": "FULL_TIME",
"dateOfBirth": "1990-05-15",
"placeOfBirth": "Dar es Salaam",
"sex": "MALE",
"maritalStatus": "SINGLE",
"ethnicity": "African",
"idType": "NIDA",
"idNumber": "19900515-12345-67890-12",
"nameOnId": "John Doe",
"idPhotoUrl": "https://storage.example.com/ids/john_id.jpg",
"primaryAddress": "123 Main Street",
"city": "Dar es Salaam",
"country": "Tanzania",
"region": "Dar es Salaam",
"district": "Kinondoni",
"zipCode": "12345",
"ownsBusiness": true,
"hasBusinessLicense": true,
"businessName": "JD Tech Solutions",
"businessEmail": "info@jdtech.com",
"businessPhoneNumber": "+255712345679",
"businessTinNumber": "123-456-789",
"businessIndustry": "TECHNOLOGY",
"businessWebsite": "https://jdtech.com",
"businessAddress": "456 Business Avenue",
"applicationStatus": "SUBMITTED",
"submittedAt": "2026-02-11T11:00:00",
"createdAt": "2026-02-11T10:30:45",
"updatedAt": "2026-02-11T11:00:00"
}
}
Error Response Examples:
Not Found (404):
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Form not found",
"action_time": "2026-02-11T11:15:00",
"data": "Form not found"
}
Forbidden (403):
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Not authorized",
"action_time": "2026-02-11T11:15:00",
"data": "Not authorized"
}
5. Get Form by Form ID
Purpose: Retrieve a specific form using the form's unique ID
Endpoint: GET {base_url}/useless-forms/{formId}
Access Level: 🔒 Protected (Requires Bearer Token - Must be form owner or call owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token for authentication |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
| formId | UUID | Yes | Unique identifier of the form | Must be valid UUID format |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form retrieved successfully",
"action_time": "2026-02-11T11:20:00",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"applicationId": "660e8400-e29b-41d4-a716-446655440001",
"callId": "770e8400-e29b-41d4-a716-446655440002",
"userId": "880e8400-e29b-41d4-a716-446655440003",
"fullName": "John Doe",
"email": "john.doe@example.com",
"applicationStatus": "SUBMITTED",
"submittedAt": "2026-02-11T11:00:00",
"createdAt": "2026-02-11T10:30:45",
"updatedAt": "2026-02-11T11:00:00"
}
}
Error Response Examples:
Not Found (404):
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Form not found",
"action_time": "2026-02-11T11:20:00",
"data": "Form not found"
}
6. Get All Forms for a Call
Purpose: Retrieve all application forms submitted for a specific call with optional status filtering
Endpoint: GET {base_url}/useless-forms/calls/{callId}/forms
Access Level: 🔒 Protected (Requires Bearer Token - Must be call owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token for authentication |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
| callId | UUID | Yes | Unique identifier of the call | Must be valid UUID format |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
| status | string | No | Filter forms by application status | enum: DRAFT, SUBMITTED, UNDER_REVIEW, APPROVED, REJECTED, WITHDRAWN | null (all statuses) |
| page | integer | No | Page number for pagination | Min: 1 | 1 |
| size | integer | No | Number of items per page | Min: 1, Max: 100 | 20 |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Forms retrieved successfully",
"action_time": "2026-02-11T11:25:00",
"data": {
"content": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"applicationId": "660e8400-e29b-41d4-a716-446655440001",
"callId": "770e8400-e29b-41d4-a716-446655440002",
"callTitle": "SME Business Loan 2026",
"fullName": "John Doe",
"email": "john.doe@example.com",
"applicationStatus": "SUBMITTED",
"submittedAt": "2026-02-11T11:00:00",
"createdAt": "2026-02-11T10:30:45"
},
{
"id": "550e8400-e29b-41d4-a716-446655440004",
"applicationId": "660e8400-e29b-41d4-a716-446655440005",
"callId": "770e8400-e29b-41d4-a716-446655440002",
"callTitle": "SME Business Loan 2026",
"fullName": "Jane Smith",
"email": "jane.smith@example.com",
"applicationStatus": "APPROVED",
"submittedAt": "2026-02-10T14:30:00",
"createdAt": "2026-02-10T09:15:00"
}
],
"pageable": {
"pageNumber": 0,
"pageSize": 20,
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"offset": 0,
"paged": true,
"unpaged": false
},
"totalElements": 2,
"totalPages": 1,
"last": true,
"size": 20,
"number": 0,
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"numberOfElements": 2,
"first": true,
"empty": false
}
}
Success Response Fields:
| Field | Description |
|---|---|
| content | Array of form summaries |
| content[].id | Unique identifier of the form |
| content[].applicationId | Reference to the call application |
| content[].callId | Reference to the call |
| content[].callTitle | Title of the call |
| content[].fullName | Applicant's full name |
| content[].email | Applicant's email |
| content[].applicationStatus | Current status of the application |
| content[].submittedAt | When the form was submitted |
| content[].createdAt | When the form was created |
| totalElements | Total number of forms across all pages |
| totalPages | Total number of pages |
| size | Number of items per page |
| number | Current page number (0-indexed) |
| first | Whether this is the first page |
| last | Whether this is the last page |
7. Get My Forms
Purpose: Retrieve all forms created by the authenticated user
Endpoint: GET {base_url}/useless-forms/my-forms
Access Level: 🔒 Protected (Requires Bearer Token)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token for authentication |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
| page | integer | No | Page number for pagination | Min: 1 | 1 |
| size | integer | No | Number of items per page | Min: 1, Max: 100 | 20 |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Your forms retrieved successfully",
"action_time": "2026-02-11T11:30:00",
"data": {
"content": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"applicationId": "660e8400-e29b-41d4-a716-446655440001",
"callId": "770e8400-e29b-41d4-a716-446655440002",
"callTitle": "SME Business Loan 2026",
"fullName": "John Doe",
"email": "john.doe@example.com",
"applicationStatus": "SUBMITTED",
"submittedAt": "2026-02-11T11:00:00",
"createdAt": "2026-02-11T10:30:45"
},
{
"id": "550e8400-e29b-41d4-a716-446655440006",
"applicationId": "660e8400-e29b-41d4-a716-446655440007",
"callId": "770e8400-e29b-41d4-a716-446655440008",
"callTitle": "Youth Startup Grant 2026",
"fullName": "John Doe",
"email": "john.doe@example.com",
"applicationStatus": "DRAFT",
"submittedAt": null,
"createdAt": "2026-02-09T08:20:00"
}
],
"totalElements": 2,
"totalPages": 1,
"size": 20,
"number": 0,
"first": true,
"last": true,
"empty": false
}
}
8. Review Application Form
Purpose: Review and update the status of a submitted form (approve, reject, etc.)
Endpoint: POST {base_url}/useless-forms/{formId}/review
Access Level: 🔒 Protected (Requires Bearer Token - Must be call owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token for authentication |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
| formId | UUID | Yes | Unique identifier of the form to review | Must be valid UUID format |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
| status | string | Yes | New status for the application | enum: SUBMITTED, UNDER_REVIEW, APPROVED, REJECTED, WITHDRAWN | null |
| notes | string | No | Review notes or feedback for the applicant | Max: 5000 characters | null |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form reviewed successfully",
"action_time": "2026-02-11T11:45:00",
"data": null
}
Error Response Examples:
Not Found (404):
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Form not found",
"action_time": "2026-02-11T11:45:00",
"data": "Form not found"
}
Forbidden (403):
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Not authorized",
"action_time": "2026-02-11T11:45:00",
"data": "Not authorized"
}
9. Get Form Statistics for Call
Purpose: Get aggregated statistics of forms by status for a specific call
Endpoint: GET {base_url}/useless-forms/calls/{callId}/stats
Access Level: 🔒 Protected (Requires Bearer Token - Must be call owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token for authentication |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
| callId | UUID | Yes | Unique identifier of the call | Must be valid UUID format |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Stats retrieved successfully",
"action_time": "2026-02-11T11:50:00",
"data": {
"submitted": 45,
"approved": 12,
"rejected": 8,
"draft": 23,
"total": 88
}
}
Success Response Fields:
| Field | Description |
|---|---|
| submitted | Number of forms in SUBMITTED status |
| approved | Number of forms in APPROVED status |
| rejected | Number of forms in REJECTED status |
| draft | Number of forms in DRAFT status |
| total | Total number of all forms for this call |
10. Get User's Form for Specific Call
Purpose: Retrieve a specific user's form for a particular call
Endpoint: GET {base_url}/useless-forms/calls/{callId}/users/{userId}
Access Level: 🔒 Protected (Requires Bearer Token - Must be the user themselves or call owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token for authentication |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
| callId | UUID | Yes | Unique identifier of the call | Must be valid UUID format |
| userId | UUID | Yes | Unique identifier of the user | Must be valid UUID format |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form retrieved successfully",
"action_time": "2026-02-11T12:00:00",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"applicationId": "660e8400-e29b-41d4-a716-446655440001",
"callId": "770e8400-e29b-41d4-a716-446655440002",
"userId": "880e8400-e29b-41d4-a716-446655440003",
"fullName": "John Doe",
"email": "john.doe@example.com",
"applicationStatus": "APPROVED",
"submittedAt": "2026-02-11T11:00:00",
"createdAt": "2026-02-11T10:30:45",
"updatedAt": "2026-02-11T11:45:00"
}
}
Error Response Examples:
Not Found (404):
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Form not found",
"action_time": "2026-02-11T12:00:00",
"data": "Form not found"
}
Forbidden (403):
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Cannot view form at this stage",
"action_time": "2026-02-11T12:00:00",
"data": "Cannot view form at this stage"
}
11. Get Total Applicants Count
Purpose: Get the total number of applicants for a specific call
Endpoint: GET {base_url}/useless-forms/calls/{callId}/applicants/count
Access Level: 🔒 Protected (Requires Bearer Token)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token for authentication |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
| callId | UUID | Yes | Unique identifier of the call | Must be valid UUID format |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Applicant count retrieved successfully",
"action_time": "2026-02-11T12:05:00",
"data": {
"totalApplicants": 88
}
}
Success Response Fields:
| Field | Description |
|---|---|
| totalApplicants | Total number of unique applicants for this call |
12. Get My Status in Call
Purpose: Get the authenticated user's application status for a specific call
Endpoint: GET {base_url}/useless-forms/calls/{callId}/my-status
Access Level: 🔒 Protected (Requires Bearer Token)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token for authentication |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
| callId | UUID | Yes | Unique identifier of the call | Must be valid UUID format |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Your status retrieved successfully",
"action_time": "2026-02-11T12:10:00",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"applicationId": "660e8400-e29b-41d4-a716-446655440001",
"callId": "770e8400-e29b-41d4-a716-446655440002",
"userId": "880e8400-e29b-41d4-a716-446655440003",
"fullName": "John Doe",
"email": "john.doe@example.com",
"applicationStatus": "UNDER_REVIEW",
"submittedAt": "2026-02-11T11:00:00",
"createdAt": "2026-02-11T10:30:45",
"updatedAt": "2026-02-11T11:45:00"
}
}
Error Response Examples:
Not Found (404):
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "You have not applied to this call",
"action_time": "2026-02-11T12:10:00",
"data": "You have not applied to this call"
}
13. Check If User Has Applied
Purpose: Check whether the authenticated user has already applied to a specific call
Endpoint: GET {base_url}/useless-forms/calls/{callId}/check-applied
Access Level: 🔒 Protected (Requires Bearer Token)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token for authentication |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
| callId | UUID | Yes | Unique identifier of the call | Must be valid UUID format |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Check completed",
"action_time": "2026-02-11T12:15:00",
"data": {
"hasApplied": true
}
}
Success Response Fields:
| Field | Description |
|---|---|
| hasApplied | Boolean indicating whether the user has applied (true) or not (false) |
14. Get Applicants for Call (With Filters)
Purpose: Retrieve a paginated list of applicants for a specific call with optional filtering by status and search term
Endpoint: GET {base_url}/useless-forms/calls/{callId}/applicants
Access Level: 🔒 Protected (Requires Bearer Token - Must be call owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token for authentication |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
| callId | UUID | Yes | Unique identifier of the call | Must be valid UUID format |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
| status | string | No | Filter applicants by application status | enum: DRAFT, SUBMITTED, UNDER_REVIEW, APPROVED, REJECTED, WITHDRAWN | null (all statuses) |
| search | string | No | Search term to filter by name, email, or phone number | Max: 200 characters | null |
| page | integer | No | Page number for pagination | Min: 1 | 1 |
| size | integer | No | Number of items per page | Min: 1, Max: 100 | 20 |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Applicants retrieved successfully",
"action_time": "2026-02-11T12:20:00",
"data": {
"content": [
{
"userId": "880e8400-e29b-41d4-a716-446655440003",
"fullName": "John Doe",
"email": "john.doe@example.com",
"phoneNumber": "+255712345678",
"applicationStatus": "SUBMITTED",
"submittedAt": "2026-02-11T11:00:00",
"createdAt": "2026-02-11T10:30:45"
},
{
"userId": "880e8400-e29b-41d4-a716-446655440009",
"fullName": "Jane Smith",
"email": "jane.smith@example.com",
"phoneNumber": "+255723456789",
"applicationStatus": "APPROVED",
"submittedAt": "2026-02-10T14:30:00",
"createdAt": "2026-02-10T09:15:00"
}
],
"totalElements": 45,
"totalPages": 3,
"size": 20,
"number": 0,
"first": true,
"last": false,
"empty": false
}
}
Success Response Fields:
| Field | Description |
|---|---|
| content | Array of applicant summaries |
| content[].userId | Unique identifier of the user/applicant |
| content[].fullName | Applicant's full name |
| content[].email | Applicant's email address |
| content[].phoneNumber | Applicant's phone number |
| content[].applicationStatus | Current status of the application |
| content[].submittedAt | When the application was submitted |
| content[].createdAt | When the application was created |
| totalElements | Total number of applicants across all pages |
| totalPages | Total number of pages |
| size | Number of items per page |
| number | Current page number (0-indexed) |
| first | Whether this is the first page |
| last | Whether this is the last page |
Error Response Examples:
Forbidden (403):
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Not authorized to view applicants for this call",
"action_time": "2026-02-11T12:20:00",
"data": "Not authorized to view applicants for this call"
}
Not Found (404):
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Call not found",
"action_time": "2026-02-11T12:20:00",
"data": "Call not found"
}
Quick Reference Guide
Application Status Flow
DRAFT → SUBMITTED → UNDER_REVIEW → APPROVED/REJECTED
↘ WITHDRAWN (optional)
Status Descriptions
- DRAFT: Form is being filled out, can be edited multiple times
- SUBMITTED: Form has been submitted for review, cannot be edited
- UNDER_REVIEW: Call owner is actively reviewing the application
- APPROVED: Application has been approved
- REJECTED: Application has been rejected
- WITHDRAWN: Applicant has withdrawn their application
Authorization Rules
| Role | Can Start Form | Can Save Draft | Can Submit | Can Review | Can View All Forms |
|---|---|---|---|---|---|
| Applicant (Form Owner) | ✅ | ✅ | ✅ | ❌ | ❌ |
| Call Owner | ❌ | ❌ | ❌ | ✅ | ✅ |
| Other Users | ❌ | ❌ | ❌ | ❌ | ❌ |
Common Use Cases
Use Case 1: User Applies to a Call
POST /applications/{applicationId}/start- Start formPUT /applications/{applicationId}/draft- Save progress (can repeat)POST /applications/{applicationId}/submit- Submit form
Use Case 2: User Checks Their Application Status
GET /calls/{callId}/check-applied- Check if already appliedGET /calls/{callId}/my-status- View current status
Use Case 3: Call Owner Reviews Applications
GET /calls/{callId}/applicants?status=SUBMITTED- Get submitted applicationsGET /calls/{callId}/users/{userId}- View specific applicationPOST /{formId}/review?status=APPROVED¬es=Great candidate- Approve/Reject
Use Case 4: Call Owner Views Statistics
GET /calls/{callId}/stats- View aggregated statisticsGET /calls/{callId}/applicants/count- Get total applicant count
Pagination Best Practices
- Default page size is 20, maximum is 100
- Page numbers start from 1
- Use
totalPagesandlastto determine if more pages exist - Consider the response payload size when setting page size
Common HTTP Status Codes
200 OK: Successful GET/PUT/POST request400 Bad Request: Invalid request data or form already submitted401 Unauthorized: Missing or invalid authentication token403 Forbidden: Insufficient permissions or not authorized404 Not Found: Resource not found (form, call, or user)500 Internal Server Error: Unexpected server error
Data Format Standards
- Dates: Use ISO 8601 format (YYYY-MM-DD) for date fields
- Timestamps: Use ISO 8601 format with timezone (2026-02-11T10:30:45)
- UUIDs: Standard UUID v4 format (550e8400-e29b-41d4-a716-446655440000)
- Phone Numbers: Include country code (e.g., +255712345678)
- URLs: Must be valid HTTP/HTTPS URLs for document storage
Additional Notes
Document Upload Strategy
- The API stores URLs to documents, not the documents themselves
- Files should be uploaded to a separate file storage service (e.g., AWS S3, Azure Blob Storage)
- After upload, include the returned URL in the form draft
- Supported document types: Business licenses, tax certificates, ID photos, bank statements, etc.
Form Validation
- All fields are optional in draft mode to allow progressive completion
- Validation occurs on the client side before submission
- Call owners may define required fields based on call requirements
Performance Considerations
- Use pagination for large result sets
- Filter by status to reduce payload size
- Consider implementing caching for frequently accessed data
- Use search parameters to narrow down results
Security Notes
- All endpoints require authentication except where explicitly noted
- Users can only access their own forms unless they are the call owner
- Call owners have read-only access to submitted forms
- Sensitive data (ID numbers, financial info) should be encrypted at rest
- Implement rate limiting to prevent abuse
End of Documentation
For questions or support, please contact the FursaHub Backend Team.
No comments to display
No comments to display