Calls_service
Calls Service
Base URL: https://your-api-domain.com/api/v1
Short Description: The Calls Service API provides a comprehensive platform for managing opportunity calls (job postings, internships, grants, competitions, etc.) with integrated application forms and applicant management. Organizations can create calls, attach custom application forms, and manage the entire application lifecycle from submission to review.
Hints:
- All endpoints require authentication via Bearer token except where explicitly marked as public
- Phone verification is required to perform write operations (create, update, delete)
- Calls must have an application form before they can be published
- The service integrates with the Form Builder API for dynamic application forms
- Pagination uses 1-based indexing (page=1 is the first page)
- Soft deletion is implemented - deleted items have
deletedAttimestamp - Call owners have full control over their calls and can manage applications
- Applicants can only submit applications if the call is PUBLISHED and within the application period
- Multiple applications are controlled by the
allowMultipleApplicationsflag per call - Rate limiting: 100 requests per hour per authenticated user
User Journey Flow
┌─────────────────────────────────────────────────────────────────────────────┐
│ CALL CREATOR JOURNEY │
└─────────────────────────────────────────────────────────────────────────────┘
1. CREATE CALL (DRAFT)
│
├──> POST /api/v1/calls
│ └── Status: DRAFT, isActive: false
│
2. CREATE APPLICATION FORM
│
├──> POST /api/v1/calls/{callId}/form
│ └── Auto-creates first page
│
3. BUILD FORM STRUCTURE
│
├──> POST /api/v1/calls/{callId}/form/pages
│ └── Add additional pages
│
├──> POST /api/v1/calls/{callId}/form/pages/{pageId}/fields
│ └── Add fields to each page
│
4. REVIEW & UPDATE CALL
│
├──> GET /api/v1/calls/{callId}
│ └── Preview call details
│
├──> PUT /api/v1/calls/{callId}
│ └── Update call information
│
5. PUBLISH CALL
│
├──> POST /api/v1/calls/{callId}/publish
│ └── Status: PUBLISHED, isActive: true
│ └── Applications open
│
6. MANAGE APPLICATIONS
│
├──> GET /api/v1/calls/{callId}/applications
│ └── View all applications
│
├──> GET /api/v1/calls/{callId}/applicants
│ └── Get unique applicants
│
├──> GET /api/v1/calls/{callId}/analytics
│ └── View form analytics
│
├──> POST /api/v1/calls/applications/{applicationId}/review
│ └── Accept/Reject applications
│
7. CLOSE CALL
│
└──> POST /api/v1/calls/{callId}/close
└── Status: CLOSED, isActive: false
└── No new applications accepted
┌─────────────────────────────────────────────────────────────────────────────┐
│ APPLICANT JOURNEY │
└─────────────────────────────────────────────────────────────────────────────┘
1. BROWSE CALLS
│
├──> GET /api/v1/calls
│ └── View active/published calls
│
2. VIEW CALL DETAILS
│
├──> GET /api/v1/calls/{callId}
│ └── See full call information
│
├──> GET /api/v1/calls/{callId}/form
│ └── Preview application form
│
3. START APPLICATION
│
├──> POST /api/v1/calls/{callId}/apply
│ └── Creates DRAFT application
│ └── Returns applicationId & responseId
│
4. FILL APPLICATION (PAGE BY PAGE)
│
├──> POST /api/v1/calls/applications/{applicationId}/pages/{pageId}
│ ├── Save draft: moveToNextPage: false
│ └── Complete page: moveToNextPage: true
│
├──> Repeat for each page
│
5. SUBMIT APPLICATION
│
├──> POST /api/v1/calls/applications/{applicationId}/submit
│ └── Status: SUBMITTED
│ └── Validates all required fields
│
6. TRACK APPLICATION
│
├──> GET /api/v1/calls/applications/{applicationId}
│ └── Check application status
│
├──> GET /api/v1/calls/my-applications
│ └── View all your applications
│
7. WITHDRAW (OPTIONAL)
│
└──> POST /api/v1/calls/applications/{applicationId}/withdraw
└── Status: WITHDRAWN
└── Soft delete
┌─────────────────────────────────────────────────────────────────────────────┐
│ STATUS FLOW DIAGRAM │
└─────────────────────────────────────────────────────────────────────────────┘
CALL STATUSES:
DRAFT ──[publish]──> PUBLISHED ──[close]──> CLOSED
│ │
└────────────[delete]────> DELETED <─────────┘
APPLICATION STATUSES:
DRAFT ──[submit]──> SUBMITTED ──[review]──> UNDER_REVIEW
│ │
│ ├──> ACCEPTED
│ └──> REJECTED
│
[withdraw]──> WITHDRAWN
┌─────────────────────────────────────────────────────────────────────────────┐
│ FORM-APPLICATION INTEGRATION │
└─────────────────────────────────────────────────────────────────────────────┘
CallsEntity
└── applicationFormId ──> FormEntity (Form Builder)
└── pages[] ──> FormPageEntity
└── fields[] ──> FormFieldEntity
CallApplicationEntity
└── responseId ──> FormResponseEntity (Form Builder)
└── answers[] ──> FormAnswerEntity
└── links to FormFieldEntity
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-30T10:30:45",
"data": {
// Actual response data goes here
}
}
Error Response Structure
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Error description",
"action_time": "2025-01-30T10: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)
1. Create Call
Purpose: Creates a new call (opportunity/posting). The authenticated user becomes the owner. The call is created in DRAFT status by default.
Endpoint: POST {base_url}
Access Level: 🔒 Protected (Requires Bearer Token · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Request JSON Sample:
{
"title": "Software Engineer Intern",
"description": "<p>We are looking for a talented intern...</p>",
"images": [
"https://cdn.example.com/banner1.jpg",
"https://cdn.example.com/banner2.jpg"
],
"applicantsAccepting": 10,
"applicationStartDate": "2025-10-01T08:00:00",
"applicationEndDate": "2025-11-01T23:59:59",
"location": "Dar es Salaam, Tanzania",
"applicationFormId": null,
"additionalInfo": {
"salary": "500 USD/month",
"duration": "3 months"
},
"allowMultipleApplications": false
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
title |
string | Yes | Title of the call | Max: 255 characters |
description |
string | No | Rich text (HTML) description of the call | Max: 5000 characters |
images |
array<string> | No | List of image URLs for the call banner/gallery | Each item must be a valid URL string |
applicantsAccepting |
integer | Yes | Maximum number of applicants the call will accept | Min: 1 |
applicationStartDate |
string (datetime) | Yes | Start date/time for accepting applications | ISO 8601 format |
applicationEndDate |
string (datetime) | Yes | End date/time for accepting applications | ISO 8601 format · Must be after applicationStartDate |
location |
string | No | Location or address for the call | Max: 255 characters |
applicationFormId |
string (UUID) | No | Link an existing form to this call. Usually set later via the form endpoints | Valid UUID or null |
additionalInfo |
object | No | Flexible key-value map for extra details (salary, duration, etc.) | Stored as JSON |
allowMultipleApplications |
boolean | No | Whether one user can submit more than one application | Defaults to false |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Call created successfully",
"action_time": "2025-10-01T10:30:45",
"data": {
"callId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"title": "Software Engineer Intern",
"description": "<p>We are looking for a talented intern...</p>",
"images": ["https://cdn.example.com/banner1.jpg"],
"applicantsAccepting": 10,
"applicationStartDate": "2025-10-01T08:00:00",
"applicationEndDate": "2025-11-01T23:59:59",
"location": "Dar es Salaam, Tanzania",
"applicationFormId": null,
"additionalInfo": { "salary": "500 USD/month" },
"isActive": false,
"allowMultipleApplications": false,
"status": "DRAFT",
"createdBy": "johndoe",
"createdAt": "2025-10-01T10:30:45",
"publishedAt": null,
"closedAt": null,
"applicationCount": 0
}
}
Success Response Fields:
| Field | Description |
|---|---|
callId |
Unique identifier (UUID) of the newly created call |
title |
Title of the call |
description |
Rich text (HTML) description |
images |
List of image URLs |
applicantsAccepting |
Maximum number of applicants allowed |
applicationStartDate |
Application window start timestamp |
applicationEndDate |
Application window end timestamp |
location |
Location string |
applicationFormId |
Linked form UUID (null if no form attached yet) |
additionalInfo |
Custom key-value metadata object |
isActive |
Whether the call is currently active (false on creation) |
allowMultipleApplications |
Whether multiple applications per user are permitted |
status |
Current lifecycle status: DRAFT | PUBLISHED | CLOSED | ARCHIVED | DELETED |
createdBy |
Username of the authenticated creator |
createdAt |
ISO 8601 creation timestamp |
publishedAt |
Timestamp when published (null until published) |
closedAt |
Timestamp when closed (null until closed) |
applicationCount |
Total number of active applications (0 on creation) |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "UNPROCESSABLE_ENTITY",
"message": "Validation failed",
"action_time": "2025-10-01T10:30:45",
"data": {
"title": "must not be blank",
"applicantsAccepting": "must not be null"
}
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone number not verified |
422 UNPROCESSABLE_ENTITY |
Validation failed (e.g. missing title, applicantsAccepting < 1) |
2. Get Call
Purpose: Retrieves full details of a single call by its ID. Public — no authentication required.
Endpoint: GET {base_url}/{callId}
Access Level: 🌐 Public (No authentication required)
Authentication: None
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | Unique identifier of the call | Valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Call retrieved successfully",
"action_time": "2025-10-01T12:00:00",
"data": {
"callId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"title": "Software Engineer Intern",
"description": "<p>We are looking for a talented intern...</p>",
"images": ["https://cdn.example.com/banner1.jpg"],
"applicantsAccepting": 10,
"applicationStartDate": "2025-10-01T08:00:00",
"applicationEndDate": "2025-11-01T23:59:59",
"location": "Dar es Salaam, Tanzania",
"applicationFormId": "f1a2b3c4-d5e6-7890-abcd-ef1234567890",
"additionalInfo": { "salary": "500 USD/month" },
"isActive": true,
"allowMultipleApplications": false,
"status": "PUBLISHED",
"createdBy": "johndoe",
"createdAt": "2025-10-01T10:30:45",
"publishedAt": "2025-10-02T09:00:00",
"closedAt": null,
"applicationCount": 5
}
}
Success Response Fields:
| Field | Description |
|---|---|
callId |
Unique identifier (UUID) of the call |
title |
Title of the call |
description |
Rich text (HTML) description |
images |
List of image URLs |
applicantsAccepting |
Maximum number of applicants allowed |
applicationStartDate |
Application window start |
applicationEndDate |
Application window end |
location |
Location string |
applicationFormId |
Linked application form UUID |
additionalInfo |
Custom metadata object |
isActive |
Active flag |
allowMultipleApplications |
Multi-application flag |
status |
DRAFT | PUBLISHED | CLOSED | ARCHIVED | DELETED |
createdBy |
Owner username |
createdAt |
Creation timestamp |
publishedAt |
Published timestamp |
closedAt |
Closed timestamp |
applicationCount |
Total active applications |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Call not found",
"action_time": "2025-10-01T12:00:00",
"data": "Call not found"
}
| HTTP Status | Description |
|---|---|
404 NOT_FOUND |
Call with given ID does not exist or has been soft-deleted |
3. Update Call
Purpose: Updates an existing call. Only the call owner (createdBy) can perform this action. All fields are optional — only provided fields are updated (partial update).
Endpoint: PUT {base_url}/{callId}
Access Level: 🔒 Protected (Requires Bearer Token · Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | Unique identifier of the call to update | Valid UUID |
Request JSON Sample:
{
"title": "Senior Software Engineer",
"description": "<p>Updated job description...</p>",
"images": ["https://cdn.example.com/new-banner.jpg"],
"applicantsAccepting": 15,
"applicationStartDate": "2025-10-05T08:00:00",
"applicationEndDate": "2025-11-15T23:59:59",
"location": "Arusha, Tanzania",
"applicationFormId": "f1a2b3c4-d5e6-7890-abcd-ef1234567890",
"additionalInfo": { "salary": "800 USD/month" },
"isActive": true,
"allowMultipleApplications": true
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
title |
string | No | New title for the call | Max: 255 characters |
description |
string | No | New rich text (HTML) description | Max: 5000 characters |
images |
array<string> | No | Replace the full image list | Array of URL strings |
applicantsAccepting |
integer | No | Update the applicant capacity | Min: 1 |
applicationStartDate |
string (datetime) | No | New application start date | ISO 8601 format |
applicationEndDate |
string (datetime) | No | New application end date | ISO 8601 format |
location |
string | No | New location string | Max: 255 characters |
applicationFormId |
string (UUID) | No | Change or set the linked form | Valid UUID or null |
additionalInfo |
object | No | Replace the entire additional info map | Stored as JSON |
isActive |
boolean | No | Manually toggle the active flag | true or false |
allowMultipleApplications |
boolean | No | Toggle multi-application permission | true or false |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Call updated successfully",
"action_time": "2025-10-03T14:00:00",
"data": {
"callId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"title": "Senior Software Engineer",
"description": "<p>Updated job description...</p>",
"images": ["https://cdn.example.com/new-banner.jpg"],
"applicantsAccepting": 15,
"applicationStartDate": "2025-10-05T08:00:00",
"applicationEndDate": "2025-11-15T23:59:59",
"location": "Arusha, Tanzania",
"applicationFormId": "f1a2b3c4-d5e6-7890-abcd-ef1234567890",
"additionalInfo": { "salary": "800 USD/month" },
"isActive": true,
"allowMultipleApplications": true,
"status": "PUBLISHED",
"createdBy": "johndoe",
"createdAt": "2025-10-01T10:30:45",
"publishedAt": "2025-10-02T09:00:00",
"closedAt": null,
"applicationCount": 5
}
}
Success Response Fields:
| Field | Description |
|---|---|
callId |
UUID of the updated call |
title |
Updated title |
description |
Updated description |
images |
Updated image list |
applicantsAccepting |
Updated capacity |
applicationStartDate |
Updated start date |
applicationEndDate |
Updated end date |
location |
Updated location |
applicationFormId |
Updated linked form UUID |
additionalInfo |
Updated metadata |
isActive |
Updated active flag |
allowMultipleApplications |
Updated multi-application flag |
status |
Current call status (unchanged by update) |
createdBy |
Original owner username |
createdAt |
Original creation timestamp |
publishedAt |
Published timestamp |
closedAt |
Closed timestamp |
applicationCount |
Total active applications |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Access denied: Insufficient permissions",
"action_time": "2025-10-03T14:00:00",
"data": "Access denied: Insufficient permissions"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Call not found |
422 UNPROCESSABLE_ENTITY |
Validation failed on provided fields |
4. Delete Call
Purpose: Soft-deletes a call by setting its status to DELETED and recording the deleted_at timestamp. Only the call owner can delete. The call remains in the database but is excluded from all queries.
Endpoint: DELETE {base_url}/{callId}
Access Level: 🔒 Protected (Requires Bearer Token · Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | Unique identifier of the call to delete | Valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Call deleted successfully",
"action_time": "2025-10-05T16:00:00",
"data": null
}
Success Response Fields:
| Field | Description |
|---|---|
data |
null — no payload returned on successful deletion |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Call not found",
"action_time": "2025-10-05T16:00:00",
"data": "Call not found"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Call not found |
5. Publish Call
Purpose: Transitions a call from DRAFT to PUBLISHED status, sets isActive to true, and records the publishedAt timestamp. A call must have an application form attached before it can be published.
Endpoint: POST {base_url}/{callId}/publish
Access Level: 🔒 Protected (Requires Bearer Token · Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | ID of the call to publish | Valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Call published successfully",
"action_time": "2025-10-02T09:00:00",
"data": null
}
Success Response Fields:
| Field | Description |
|---|---|
data |
null — no payload returned on successful publish |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Cannot publish call without application form",
"action_time": "2025-10-02T09:00:00",
"data": "Cannot publish call without application form"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Call not found |
400 BAD_REQUEST |
Call is not in DRAFT status or no application form is attached |
6. Close Call
Purpose: Manually closes a call — sets status to CLOSED, isActive to false, and records closedAt. After closing, the call no longer accepts new applications. Calls are also auto-closed when their applicationEndDate passes.
Endpoint: POST {base_url}/{callId}/close
Access Level: 🔒 Protected (Requires Bearer Token · Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | ID of the call to close | Valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Call closed successfully",
"action_time": "2025-10-10T18:00:00",
"data": null
}
Success Response Fields:
| Field | Description |
|---|---|
data |
null — no payload returned on successful close |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Access denied: Insufficient permissions",
"action_time": "2025-10-10T18:00:00",
"data": "Access denied: Insufficient permissions"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Call not found |
7. List Calls
Purpose: Returns a paginated list of calls. If a status filter is provided, only calls with that status are returned. Otherwise, only active (isActive = true) calls are returned by default. Public endpoint — no authentication required.
Endpoint: GET {base_url}
Access Level: 🌐 Public (No authentication required)
Authentication: None
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
status |
string | No | Filter calls by lifecycle status | enum: DRAFT, PUBLISHED, CLOSED, ARCHIVED, DELETED |
— (returns active calls if omitted) |
page |
integer | No | Page number (1-based) | Min: 1 | 1 |
size |
integer | No | Number of results per page | Min: 1 | 20 |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Calls retrieved successfully",
"action_time": "2025-10-01T12:00:00",
"data": {
"content": [
{
"callId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"title": "Software Engineer Intern",
"shortDescription": "We are looking for a talented intern to join...",
"bannerImage": "https://cdn.example.com/banner1.jpg",
"applicantsAccepting": 10,
"applicationEndDate": "2025-11-01T23:59:59",
"location": "Dar es Salaam, Tanzania",
"status": "PUBLISHED",
"applicationCount": 5,
"topApplicants": [
{
"userId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"fullName": "Jane Smith",
"profileImage": "https://cdn.example.com/avatars/jane.jpg"
}
]
}
],
"totalElements": 42,
"totalPages": 3,
"currentPage": 1,
"hasMore": true
}
}
Success Response Fields:
| Field | Description |
|---|---|
data.content |
Array of CallSummary objects |
data.content[].callId |
UUID of the call |
data.content[].title |
Call title |
data.content[].shortDescription |
First 200 characters of the description (truncated with ... if longer) |
data.content[].bannerImage |
First image URL used as banner (null if no images) |
data.content[].applicantsAccepting |
Maximum applicants capacity |
data.content[].applicationEndDate |
Application deadline |
data.content[].location |
Location string |
data.content[].status |
DRAFT | PUBLISHED | CLOSED | ARCHIVED | DELETED |
data.content[].applicationCount |
Total number of active applications |
data.content[].topApplicants |
Preview of up to 5 most recent applicants |
data.content[].topApplicants[].userId |
Applicant user UUID |
data.content[].topApplicants[].fullName |
Applicant full name |
data.content[].topApplicants[].profileImage |
Applicant profile photo URL |
data.totalElements |
Total number of matching records |
data.totalPages |
Total number of pages |
data.currentPage |
Current page number |
data.hasMore |
true if more pages exist |
8. Get My Calls
Purpose: Returns a paginated list of all calls created by the authenticated user, regardless of status. Useful for call owners to manage their own postings.
Endpoint: GET {base_url}/my-calls
Access Level: 🔒 Protected (Requires Bearer Token · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
page |
integer | No | Page number (1-based) | Min: 1 | 1 |
size |
integer | No | Number of results per page | Min: 1 | 20 |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Your calls retrieved successfully",
"action_time": "2025-10-01T12:00:00",
"data": {
"content": [
{
"callId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"title": "Software Engineer Intern",
"shortDescription": "We are looking for...",
"bannerImage": "https://cdn.example.com/banner1.jpg",
"applicantsAccepting": 10,
"applicationEndDate": "2025-11-01T23:59:59",
"location": "Dar es Salaam, Tanzania",
"status": "DRAFT",
"applicationCount": 0,
"topApplicants": []
}
],
"totalElements": 3,
"totalPages": 1,
"currentPage": 1,
"hasMore": false
}
}
Success Response Fields:
| Field | Description |
|---|---|
data.content |
Array of CallSummary objects belonging to the authenticated user |
data.content[].callId |
UUID of the call |
data.content[].title |
Call title |
data.content[].shortDescription |
Truncated description (max 200 chars) |
data.content[].bannerImage |
First image URL or null |
data.content[].applicantsAccepting |
Applicant capacity |
data.content[].applicationEndDate |
Application deadline |
data.content[].location |
Location |
data.content[].status |
Current status |
data.content[].applicationCount |
Application count |
data.content[].topApplicants |
Up to 5 applicant previews |
data.totalElements |
Total records |
data.totalPages |
Total pages |
data.currentPage |
Current page |
data.hasMore |
Pagination flag |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "UNAUTHORIZED",
"message": "Token has expired",
"action_time": "2025-10-01T12:00:00",
"data": "Token has expired"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone number not verified |
9. Get User Published Calls
Purpose: Returns a paginated list of all PUBLISHED calls created by a specific user. Public endpoint — useful for viewing a user's active postings on their profile.
Endpoint: GET {base_url}/users/{userId}/calls
Access Level: 🌐 Public (No authentication required)
Authentication: None
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
userId |
string (UUID) | Yes | ID of the user whose published calls to retrieve | Valid UUID |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
page |
integer | No | Page number (1-based) | Min: 1 | 1 |
size |
integer | No | Number of results per page | Min: 1 | 20 |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "User calls retrieved successfully",
"action_time": "2025-10-01T12:00:00",
"data": {
"content": [
{
"callId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"title": "Software Engineer Intern",
"shortDescription": "We are looking for...",
"bannerImage": "https://cdn.example.com/banner1.jpg",
"applicantsAccepting": 10,
"applicationEndDate": "2025-11-01T23:59:59",
"location": "Dar es Salaam, Tanzania",
"status": "PUBLISHED",
"applicationCount": 5,
"topApplicants": []
}
],
"totalElements": 2,
"totalPages": 1,
"currentPage": 1,
"hasMore": false
}
}
Success Response Fields:
| Field | Description |
|---|---|
data.content |
Array of CallSummary objects with status PUBLISHED only |
data.content[].callId |
UUID of the call |
data.content[].title |
Call title |
data.content[].shortDescription |
Truncated description |
data.content[].bannerImage |
First image URL or null |
data.content[].applicantsAccepting |
Applicant capacity |
data.content[].applicationEndDate |
Application deadline |
data.content[].location |
Location |
data.content[].status |
Always PUBLISHED for this endpoint |
data.content[].applicationCount |
Application count |
data.content[].topApplicants |
Up to 5 applicant previews |
data.totalElements |
Total records |
data.totalPages |
Total pages |
data.currentPage |
Current page |
data.hasMore |
Pagination flag |
10. Create Form for Call
Purpose: Creates a new application form and automatically links it to the specified call. A first page titled Application Details is auto-created. A call can only have one form — attempting to create another will return an error.
Endpoint: POST {base_url}calls/{callId}/form
Access Level: 🔒 Protected (Requires Bearer Token · Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | ID of the call to attach the form to | Valid UUID |
Request JSON Sample:
{
"title": "Software Engineer Application",
"description": "Please complete all sections of this application form.",
"coverPage": {
"title": "Welcome",
"message": "Thank you for your interest. This form will take about 10 minutes."
},
"isActive": true,
"allowMultipleSubmissions": false
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
title |
string | No | Title of the form | Max: 255 characters |
description |
string | No | Description shown at the top of the form | Max: 1000 characters |
coverPage |
object | No | Optional cover/welcome page settings rendered before form pages | Stored as JSON |
isActive |
boolean | Yes | Whether the form accepts responses | Required |
allowMultipleSubmissions |
boolean | Yes | Whether the same user can submit the form multiple times | Required |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form created successfully",
"action_time": "2025-10-01T11:00:00",
"data": {
"formId": "f1a2b3c4-d5e6-7890-abcd-ef1234567890",
"title": "Software Engineer Application",
"description": "Please complete all sections...",
"coverPage": { "title": "Welcome", "message": "..." },
"isActive": true,
"allowMultipleSubmissions": false,
"createdBy": "johndoe",
"createdAt": "2025-10-01T11:00:00",
"updatedBy": null,
"updatedAt": null,
"pages": [
{
"pageId": "p1a2b3c4-d5e6-7890-abcd-ef1234567890",
"title": "Application Details",
"description": "Please provide your information",
"displayOrder": 1,
"nextButtonText": "Next",
"fields": []
}
]
}
}
Success Response Fields:
| Field | Description |
|---|---|
formId |
UUID of the newly created form |
title |
Form title |
description |
Form description |
coverPage |
Cover page configuration object |
isActive |
Active flag for the form |
allowMultipleSubmissions |
Multi-submission setting |
createdBy |
Owner username |
createdAt |
Creation timestamp |
updatedBy |
Last updater (null initially) |
updatedAt |
Last update timestamp (null initially) |
pages |
Array of page objects. An initial Application Details page is auto-created |
pages[].pageId |
UUID of the page |
pages[].title |
Page title |
pages[].description |
Page description |
pages[].displayOrder |
Order in the form (1-based) |
pages[].nextButtonText |
Label of the Next button (defaults to Next) |
pages[].fields |
Array of field objects on this page (empty initially) |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Call already has a form",
"action_time": "2025-10-01T11:00:00",
"data": "Call already has a form"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Call not found |
400 BAD_REQUEST |
Call already has a form attached |
422 UNPROCESSABLE_ENTITY |
Validation failed (e.g. missing isActive or allowMultipleSubmissions) |
11. Get Call Form
Purpose: Retrieves the application form attached to a call. The call owner can always access the form. Other users can only access it if the call is in PUBLISHED status.
Endpoint: GET {base_url}/calls/{callId}/form
Access Level: 🔒 Protected (Requires Bearer Token · Phone Verified · Owner or Published Call)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | ID of the call whose form to retrieve | Valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form retrieved successfully",
"action_time": "2025-10-02T10:00:00",
"data": {
"formId": "f1a2b3c4-d5e6-7890-abcd-ef1234567890",
"title": "Software Engineer Application",
"description": "Please complete all sections...",
"coverPage": { "title": "Welcome" },
"isActive": true,
"allowMultipleSubmissions": false,
"createdBy": "johndoe",
"createdAt": "2025-10-01T11:00:00",
"updatedBy": null,
"updatedAt": null,
"pages": [
{
"pageId": "p1a2b3c4-d5e6-7890-abcd-ef1234567890",
"title": "Application Details",
"description": "Please provide your information",
"displayOrder": 1,
"nextButtonText": "Next",
"fields": [
{
"fieldId": "fd1a2b3c-d5e6-7890-abcd-ef1234567890",
"type": "TEXT",
"label": "Full Name",
"description": "Enter your legal full name",
"placeholder": "e.g. Jane Doe",
"displayOrder": 1,
"required": true,
"validation": { "minLength": 2, "maxLength": 100 },
"options": []
}
]
}
]
}
}
Success Response Fields:
| Field | Description |
|---|---|
formId |
Form UUID |
title |
Form title |
description |
Form description |
coverPage |
Cover page config |
isActive |
Active flag |
allowMultipleSubmissions |
Multi-submission flag |
createdBy |
Owner username |
createdAt |
Creation timestamp |
updatedBy |
Last updater |
updatedAt |
Last update timestamp |
pages |
Array of pages with their fields |
pages[].pageId |
Page UUID |
pages[].title |
Page title |
pages[].description |
Page description |
pages[].displayOrder |
Display order |
pages[].nextButtonText |
Next button label |
pages[].fields |
Array of FieldDetail objects |
pages[].fields[].fieldId |
Field UUID |
pages[].fields[].type |
Field type: TEXT | TEXTAREA | EMAIL | PHONE | NUMBER | URL | DATE | TIME | DATETIME | DROPDOWN | RADIO | CHECKBOX | FILE | RATING |
pages[].fields[].label |
Field label |
pages[].fields[].description |
Field description/hint |
pages[].fields[].placeholder |
Placeholder text |
pages[].fields[].displayOrder |
Order within the page |
pages[].fields[].required |
Whether the field is mandatory |
pages[].fields[].validation |
Custom validation rules (minLength, maxLength, min, max, pattern, etc.) |
pages[].fields[].options |
Options for DROPDOWN/RADIO/CHECKBOX fields (empty for other types) |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Call has no form",
"action_time": "2025-10-02T10:00:00",
"data": "Call has no form"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or form not accessible (call is not published and user is not owner) |
404 NOT_FOUND |
Call not found |
400 BAD_REQUEST |
Call has no form attached |
12. Delete Form for Call
Purpose: Soft-deletes the application form attached to a call and unlinks it from the call (sets applicationFormId to null). Only the call owner can perform this action.
Endpoint: DELETE {base_url}/{callId}/form
Access Level: 🔒 Protected (Requires Bearer Token · Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | ID of the call whose form to delete | Valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form deleted successfully",
"action_time": "2025-10-03T15:00:00",
"data": null
}
Success Response Fields:
| Field | Description |
|---|---|
data |
null — no payload returned on successful deletion |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Call has no form",
"action_time": "2025-10-03T15:00:00",
"data": "Call has no form"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Call not found |
400 BAD_REQUEST |
Call has no form attached |
13. Add Page to Call Form
Purpose: Adds a new page to the call's application form. Pages are appended in order with an auto-incrementing displayOrder. Only the call owner can add pages.
Endpoint: POST {base_url}/{callId}/form/pages
Access Level: 🔒 Protected (Requires Bearer Token · Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | ID of the call whose form to add a page to | Valid UUID |
Request JSON Sample:
{
"title": "Work Experience",
"description": "Please describe your relevant work experience.",
"nextButtonText": "Continue"
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
title |
string | No | Page title displayed as the page heading | Max: 255 characters |
description |
string | No | Page description shown below the title | Max: 1000 characters |
nextButtonText |
string | No | Custom label for the navigation button | Max: 50 characters · Defaults to Next |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Page added successfully",
"action_time": "2025-10-02T11:00:00",
"data": {
"pageId": "p2a3b4c5-d6e7-8901-abcd-ef1234567890",
"title": "Work Experience",
"description": "Please describe your relevant work experience.",
"displayOrder": 2,
"nextButtonText": "Continue",
"fields": []
}
}
Success Response Fields:
| Field | Description |
|---|---|
pageId |
UUID of the newly created page |
title |
Page title |
description |
Page description |
displayOrder |
Auto-assigned order (incremented from the last page) |
nextButtonText |
Navigation button label |
fields |
Empty array — fields are added separately via the add field endpoint |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Call has no form",
"action_time": "2025-10-02T11:00:00",
"data": "Call has no form"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Call not found |
400 BAD_REQUEST |
Call has no form attached |
14. Update Page in Call Form
Purpose: Updates the title, description, or next button text of an existing page in the call's form. Only the call owner can update pages. All fields are optional.
Endpoint: PUT {base_url}/{callId}/form/pages/{pageId}
Access Level: 🔒 Protected (Requires Bearer Token · Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | ID of the call | Valid UUID |
pageId |
string (UUID) | Yes | ID of the page to update | Valid UUID |
Request JSON Sample:
{
"title": "Professional Experience",
"description": "Updated: List your last 3 positions.",
"nextButtonText": "Save & Continue"
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
title |
string | No | New page title | Max: 255 characters |
description |
string | No | New page description | Max: 1000 characters |
nextButtonText |
string | No | New navigation button label | Max: 50 characters |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Page updated successfully",
"action_time": "2025-10-03T10:00:00",
"data": {
"pageId": "p2a3b4c5-d6e7-8901-abcd-ef1234567890",
"title": "Professional Experience",
"description": "Updated: List your last 3 positions.",
"displayOrder": 2,
"nextButtonText": "Save & Continue",
"fields": []
}
}
Success Response Fields:
| Field | Description |
|---|---|
pageId |
UUID of the updated page |
title |
Updated title |
description |
Updated description |
displayOrder |
Unchanged display order |
nextButtonText |
Updated button label |
fields |
Array of existing fields on this page |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Page not found",
"action_time": "2025-10-03T10:00:00",
"data": "Page not found"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Call or page not found |
15. Delete Page from Call Form
Purpose: Soft-deletes a page from the call's application form. The page and all its fields are marked as deleted and excluded from subsequent queries.
Endpoint: DELETE {base_url}/{callId}/form/pages/{pageId}
Access Level: 🔒 Protected (Requires Bearer Token · Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | ID of the call | Valid UUID |
pageId |
string (UUID) | Yes | ID of the page to delete | Valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Page deleted successfully",
"action_time": "2025-10-04T09:00:00",
"data": null
}
Success Response Fields:
| Field | Description |
|---|---|
data |
null — no payload returned on successful deletion |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Page not found",
"action_time": "2025-10-04T09:00:00",
"data": "Page not found"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Call or page not found |
16. Add Field to Call Form Page
Purpose: Adds a new input field to a specific page of the call's application form. Fields are appended with an auto-incrementing displayOrder. For DROPDOWN, RADIO, and CHECKBOX types, options must be added separately after creating the field.
Endpoint: POST {base_url}/{callId}/form/pages/{pageId}/fields
Access Level: 🔒 Protected (Requires Bearer Token · Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | ID of the call | Valid UUID |
pageId |
string (UUID) | Yes | ID of the page to add the field to | Valid UUID |
Request JSON Sample:
{
"type": "EMAIL",
"label": "Personal Email",
"description": "We will use this to send you updates about your application.",
"placeholder": "you@example.com",
"required": true,
"validation": {
"minLength": 5,
"maxLength": 100
}
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
type |
string | Yes | The input type of the field | enum: TEXT, TEXTAREA, EMAIL, PHONE, NUMBER, URL, DATE, TIME, DATETIME, DROPDOWN, RADIO, CHECKBOX, FILE, RATING |
label |
string | Yes | Display label for the field | Min: 1 · Max: 255 characters |
description |
string | No | Helper text shown below the field | Max: 500 characters |
placeholder |
string | No | Placeholder text inside the input | Max: 255 characters |
required |
boolean | No | Whether this field must be answered before moving to the next page | Defaults to false |
validation |
object | No | Custom validation rules. Supported keys: minLength, maxLength (strings); min, max (numbers); minSelections, maxSelections (checkboxes); pattern, patternMessage (regex) |
Stored as JSON |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Field added successfully",
"action_time": "2025-10-02T11:30:00",
"data": {
"fieldId": "fd1a2b3c-d5e6-7890-abcd-ef1234567890",
"type": "EMAIL",
"label": "Personal Email",
"description": "We will use this to send you updates...",
"placeholder": "you@example.com",
"displayOrder": 1,
"required": true,
"validation": { "minLength": 5, "maxLength": 100 },
"options": []
}
}
Success Response Fields:
| Field | Description |
|---|---|
fieldId |
UUID of the newly created field |
type |
Field input type |
label |
Field label |
description |
Helper text |
placeholder |
Placeholder text |
displayOrder |
Auto-assigned order within the page |
required |
Mandatory flag |
validation |
Custom validation rules object |
options |
Empty array — add options separately for DROPDOWN, RADIO, CHECKBOX fields |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "UNPROCESSABLE_ENTITY",
"message": "Validation failed",
"action_time": "2025-10-02T11:30:00",
"data": {
"type": "must not be null",
"label": "must not be blank"
}
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Call or page not found |
400 BAD_REQUEST |
Call has no form attached |
422 UNPROCESSABLE_ENTITY |
Validation failed (e.g. missing type or label) |
17. Update Field in Call Form
Purpose: Updates an existing field in the call's application form. All fields are optional — only provided properties are updated.
Endpoint: PUT {base_url}/{callId}/form/fields/{fieldId}
Access Level: 🔒 Protected (Requires Bearer Token · Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | ID of the call | Valid UUID |
fieldId |
string (UUID) | Yes | ID of the field to update | Valid UUID |
Request JSON Sample:
{
"label": "Work Email",
"description": "Enter your current work email address.",
"placeholder": "name@company.com",
"required": false,
"validation": { "maxLength": 150 }
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
type |
string | No | Change the field type | enum: TEXT, TEXTAREA, EMAIL, PHONE, NUMBER, URL, DATE, TIME, DATETIME, DROPDOWN, RADIO, CHECKBOX, FILE, RATING |
label |
string | No | New field label | Max: 255 characters |
description |
string | No | New helper text | Max: 500 characters |
placeholder |
string | No | New placeholder text | Max: 255 characters |
required |
boolean | No | Update the mandatory flag | true or false |
validation |
object | No | Replace the entire validation rules object | Stored as JSON |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Field updated successfully",
"action_time": "2025-10-03T11:00:00",
"data": {
"fieldId": "fd1a2b3c-d5e6-7890-abcd-ef1234567890",
"type": "EMAIL",
"label": "Work Email",
"description": "Enter your current work email address.",
"placeholder": "name@company.com",
"displayOrder": 1,
"required": false,
"validation": { "maxLength": 150 },
"options": []
}
}
Success Response Fields:
| Field | Description |
|---|---|
fieldId |
UUID of the updated field |
type |
Field type (updated or unchanged) |
label |
Updated label |
description |
Updated description |
placeholder |
Updated placeholder |
displayOrder |
Unchanged display order |
required |
Updated mandatory flag |
validation |
Updated validation rules |
options |
Existing options for choice-type fields |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Field not found",
"action_time": "2025-10-03T11:00:00",
"data": "Field not found"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Call or field not found |
400 BAD_REQUEST |
Call has no form attached |
18. Delete Field from Call Form
Purpose: Soft-deletes a field from the call's application form. The field is marked as deleted and excluded from form rendering. Existing answers referencing this field are preserved with fieldDeleted flag set to true.
Endpoint: DELETE {base_url}/{callId}/form/fields/{fieldId}
Access Level: 🔒 Protected (Requires Bearer Token · Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | ID of the call | Valid UUID |
fieldId |
string (UUID) | Yes | ID of the field to delete | Valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Field deleted successfully",
"action_time": "2025-10-04T10:00:00",
"data": null
}
Success Response Fields:
| Field | Description |
|---|---|
data |
null — no payload returned on successful deletion |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Field not found",
"action_time": "2025-10-04T10:00:00",
"data": "Field not found"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Call or field not found |
19. Apply to Call
Purpose: Starts a new application for the authenticated user on a published call. Creates a DRAFT application and initializes a form response session. If the call does not allow multiple applications, the user can only have one active application.
Endpoint: POST {base_url}/{callId}/apply
Access Level: 🔒 Protected (Requires Bearer Token · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | ID of the call to apply to | Valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Application started successfully",
"action_time": "2025-10-05T08:00:00",
"data": {
"applicationId": "app1a2b3-c4d5-e6f7-8901-234567890abc",
"callId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"callTitle": "Software Engineer Intern",
"responseId": "res1a2b3-c4d5-e6f7-8901-234567890abc",
"status": "DRAFT",
"appliedAt": "2025-10-05T08:00:00",
"submittedAt": null,
"reviewedAt": null,
"reviewedBy": null,
"reviewNotes": null,
"applicant": {
"userId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"fullName": "Jane Smith",
"profileImage": "https://cdn.example.com/avatars/jane.jpg"
}
}
}
Success Response Fields:
| Field | Description |
|---|---|
applicationId |
UUID of the newly created application |
callId |
UUID of the call being applied to |
callTitle |
Title of the call |
responseId |
UUID of the form response session — use this in Save Application Page and Submit Application calls |
status |
Initial status: DRAFT |
appliedAt |
Timestamp when application was started |
submittedAt |
null until submitted |
reviewedAt |
null until reviewed by call owner |
reviewedBy |
null until reviewed |
reviewNotes |
null until reviewed |
applicant |
Preview object of the applicant |
applicant.userId |
Applicant's user UUID |
applicant.fullName |
Applicant's full name |
applicant.profileImage |
Applicant's profile photo URL |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "You have already applied",
"action_time": "2025-10-05T08:00:00",
"data": "You have already applied"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone number not verified |
404 NOT_FOUND |
Call not found |
400 BAD_REQUEST |
Call is not PUBLISHED, application period has ended, call has no form, or user has already applied (when multiple applications are disabled) |
20. Save Application Page
Purpose: Saves the user's answers for a single page of their application form. Can be used for draft-saving (moveToNextPage = false) or for validated progression to the next page (moveToNextPage = true). When moveToNextPage is true, all required fields on the page must be answered and pass validation.
Endpoint: POST {base_url}/applications/{applicationId}/pages/{pageId}
Access Level: 🔒 Protected (Requires Bearer Token · Application Owner · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
applicationId |
string (UUID) | Yes | ID of the application | Valid UUID |
pageId |
string (UUID) | Yes | ID of the form page to save answers for | Valid UUID |
Request JSON Sample:
{
"pageId": "p1a2b3c4-d5e6-7890-abcd-ef1234567890",
"answers": {
"fd1a2b3c-d5e6-7890-abcd-ef1234567890": {
"value": "Jane Smith",
"fileUrl": null,
"fileName": null,
"fileSize": null,
"fileType": null
},
"fd2b3c4d-e6f7-8901-bcde-f12345678901": {
"value": "jane@example.com"
}
},
"moveToNextPage": true
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
pageId |
string (UUID) | Yes | ID of the page being answered | Must match the pageId in the URL |
answers |
object | Yes | Map of fieldId → AnswerValue. Keys are field UUIDs, values contain the answer |
See AnswerValue structure below |
answers.<fieldId>.value |
any | Yes | The answer value. Type depends on field type: string for TEXT/EMAIL/etc, number for NUMBER/RATING, array of option UUIDs for CHECKBOX, single option UUID for DROPDOWN/RADIO | Must match the field's expected type |
answers.<fieldId>.fileUrl |
string | No | URL of an uploaded file (for FILE type fields) | Valid URL or null |
answers.<fieldId>.fileName |
string | No | Original file name | null for non-file fields |
answers.<fieldId>.fileSize |
integer | No | File size in bytes | null for non-file fields |
answers.<fieldId>.fileType |
string | No | MIME type of the file | null for non-file fields |
moveToNextPage |
boolean | Yes | If true, validates required fields and marks the page as complete. If false, saves as draft without validation |
true or false |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Page saved successfully",
"action_time": "2025-10-05T08:30:00",
"data": {
"responseId": "res1a2b3-c4d5-e6f7-8901-234567890abc",
"formId": "f1a2b3c4-d5e6-7890-abcd-ef1234567890",
"submittedBy": "janesmith",
"status": "DRAFT",
"completedPageIds": ["p1a2b3c4-d5e6-7890-abcd-ef1234567890"],
"currentPageIndex": 1,
"startedAt": "2025-10-05T08:00:00",
"submittedAt": null,
"completionTimeSeconds": null,
"answers": [
{
"answerId": "ans1a2b3-c4d5-e6f7-8901-234567890abc",
"fieldId": "fd1a2b3c-d5e6-7890-abcd-ef1234567890",
"fieldLabel": "Full Name",
"fieldType": "TEXT",
"value": "Jane Smith",
"answeredAt": "2025-10-05T08:30:00",
"fieldDeleted": false,
"fileUrl": null,
"fileName": null,
"fileSize": null,
"fileType": null
}
]
}
}
Success Response Fields:
| Field | Description |
|---|---|
responseId |
UUID of the form response session |
formId |
UUID of the associated form |
submittedBy |
Username of the applicant |
status |
Response status: DRAFT | SUBMITTED | WITHDRAWN |
completedPageIds |
Set of page UUIDs that have been fully completed |
currentPageIndex |
0-based index of the current page the user is on |
startedAt |
When the form response was started |
submittedAt |
null until the application is submitted |
completionTimeSeconds |
null until submitted |
answers |
Array of all answers saved so far across all pages |
answers[].answerId |
UUID of the answer record |
answers[].fieldId |
UUID of the field this answer belongs to |
answers[].fieldLabel |
Snapshot of the field label at answer time |
answers[].fieldType |
Snapshot of the field type |
answers[].value |
The saved answer value |
answers[].answeredAt |
Timestamp when the answer was saved |
answers[].fieldDeleted |
true if the field has been deleted since the answer was saved |
answers[].fileUrl |
File URL (for FILE fields) |
answers[].fileName |
File name |
answers[].fileSize |
File size in bytes |
answers[].fileType |
File MIME type |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "UNPROCESSABLE_ENTITY",
"message": "Validation failed",
"action_time": "2025-10-05T08:30:00",
"data": {
"message": "Validation failed",
"fieldErrors": [
{
"pageId": "p1a2b3c4-d5e6-7890-abcd-ef1234567890",
"pageTitle": "Application Details",
"fieldId": "fd1a2b3c-d5e6-7890-abcd-ef1234567890",
"fieldLabel": "Full Name",
"errorMessage": "This field is required",
"errorType": "REQUIRED"
}
]
}
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the application owner |
404 NOT_FOUND |
Application or page not found |
400 BAD_REQUEST |
Application is not in DRAFT status |
422 UNPROCESSABLE_ENTITY |
Validation failed. Includes detailed field-level errors with pageId, fieldId, fieldLabel, errorMessage, and errorType (REQUIRED | INVALID_TYPE | INVALID_FORMAT | VALIDATION_FAILED) |
21. Submit Application
Purpose: Submits a completed application. All pages must be marked as complete before submission is allowed. On success, the application status changes to SUBMITTED and the completion time is recorded.
Endpoint: POST {base_url}/applications/{applicationId}/submit
Access Level: 🔒 Protected (Requires Bearer Token · Application Owner · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
applicationId |
string (UUID) | Yes | ID of the application to submit | Valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Application submitted successfully",
"action_time": "2025-10-05T09:00:00",
"data": {
"applicationId": "app1a2b3-c4d5-e6f7-8901-234567890abc",
"callId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"callTitle": "Software Engineer Intern",
"responseId": "res1a2b3-c4d5-e6f7-8901-234567890abc",
"status": "SUBMITTED",
"appliedAt": "2025-10-05T08:00:00",
"submittedAt": "2025-10-05T09:00:00",
"reviewedAt": null,
"reviewedBy": null,
"reviewNotes": null,
"applicant": {
"userId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"fullName": "Jane Smith",
"profileImage": "https://cdn.example.com/avatars/jane.jpg"
}
}
}
Success Response Fields:
| Field | Description |
|---|---|
applicationId |
UUID of the submitted application |
callId |
UUID of the call |
callTitle |
Title of the call |
responseId |
UUID of the form response |
status |
Now SUBMITTED |
appliedAt |
When the application was started |
submittedAt |
Timestamp of successful submission |
reviewedAt |
null until reviewed |
reviewedBy |
null until reviewed |
reviewNotes |
null until reviewed |
applicant |
Applicant preview object |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "UNPROCESSABLE_ENTITY",
"message": "Cannot submit. Please complete all pages.",
"action_time": "2025-10-05T09:00:00",
"data": {
"message": "Cannot submit. Please complete all pages.",
"fieldErrors": [
{
"pageId": "p2a3b4c5-d6e7-8901-abcd-ef1234567890",
"pageTitle": "Work Experience",
"fieldId": "fd3c4d5e-f6a7-8901-bcde-f12345678901",
"fieldLabel": "Previous Company",
"errorMessage": "This field is required",
"errorType": "REQUIRED"
}
]
}
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the application owner |
404 NOT_FOUND |
Application not found |
400 BAD_REQUEST |
Application is not in DRAFT status |
422 UNPROCESSABLE_ENTITY |
Incomplete pages — includes field-level errors for all required fields on incomplete pages |
22. Get Application
Purpose: Retrieves full details of a single application including its current status, timestamps, and review information. Accessible by both the applicant and the call owner.
Endpoint: GET {base_url}/applications/{applicationId}
Access Level: 🔒 Protected (Requires Bearer Token · Application Owner or Call Owner · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
applicationId |
string (UUID) | Yes | ID of the application to retrieve | Valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Application retrieved successfully",
"action_time": "2025-10-06T10:00:00",
"data": {
"applicationId": "app1a2b3-c4d5-e6f7-8901-234567890abc",
"callId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"callTitle": "Software Engineer Intern",
"responseId": "res1a2b3-c4d5-e6f7-8901-234567890abc",
"status": "UNDER_REVIEW",
"appliedAt": "2025-10-05T08:00:00",
"submittedAt": "2025-10-05T09:00:00",
"reviewedAt": "2025-10-06T10:00:00",
"reviewedBy": "johndoe",
"reviewNotes": "Strong candidate, moving to interview.",
"applicant": {
"userId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"fullName": "Jane Smith",
"profileImage": "https://cdn.example.com/avatars/jane.jpg"
}
}
}
Success Response Fields:
| Field | Description |
|---|---|
applicationId |
Application UUID |
callId |
Call UUID |
callTitle |
Call title |
responseId |
Form response UUID |
status |
DRAFT | SUBMITTED | UNDER_REVIEW | ACCEPTED | REJECTED | WITHDRAWN |
appliedAt |
Application start timestamp |
submittedAt |
Submission timestamp |
reviewedAt |
Review timestamp |
reviewedBy |
Username of the reviewer (call owner) |
reviewNotes |
Reviewer notes |
applicant |
Applicant preview (userId, fullName, profileImage) |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Access denied: Insufficient permissions",
"action_time": "2025-10-06T10:00:00",
"data": "Access denied: Insufficient permissions"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or user is neither the applicant nor the call owner |
404 NOT_FOUND |
Application not found |
23. Get Call Applications
Purpose: Returns a paginated list of all applications for a specific call. Only the call owner can access this endpoint — it is used for reviewing and managing incoming applications.
Endpoint: GET {base_url}/{callId}/applications
Access Level: 🔒 Protected (Requires Bearer Token · Call Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | ID of the call to list applications for | Valid UUID |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
page |
integer | No | Page number (1-based) | Min: 1 | 1 |
size |
integer | No | Number of results per page | Min: 1 | 20 |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Applications retrieved successfully",
"action_time": "2025-10-06T11:00:00",
"data": {
"content": [
{
"applicationId": "app1a2b3-c4d5-e6f7-8901-234567890abc",
"callId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"callTitle": "Software Engineer Intern",
"callBannerImage": "https://cdn.example.com/banner1.jpg",
"status": "SUBMITTED",
"appliedAt": "2025-10-05T08:00:00",
"submittedAt": "2025-10-05T09:00:00",
"applicant": {
"userId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"fullName": "Jane Smith",
"profileImage": "https://cdn.example.com/avatars/jane.jpg"
}
}
],
"totalElements": 12,
"totalPages": 1,
"currentPage": 1,
"hasMore": false
}
}
Success Response Fields:
| Field | Description |
|---|---|
data.content |
Array of ApplicationSummary objects |
data.content[].applicationId |
Application UUID |
data.content[].callId |
Call UUID |
data.content[].callTitle |
Call title |
data.content[].callBannerImage |
First image of the call used as banner (or null) |
data.content[].status |
DRAFT | SUBMITTED | UNDER_REVIEW | ACCEPTED | REJECTED | WITHDRAWN |
data.content[].appliedAt |
Application start timestamp |
data.content[].submittedAt |
Submission timestamp (null if still draft) |
data.content[].applicant |
Applicant preview (userId, fullName, profileImage) |
data.totalElements |
Total matching records |
data.totalPages |
Total pages |
data.currentPage |
Current page |
data.hasMore |
Pagination flag |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Access denied: Insufficient permissions",
"action_time": "2025-10-06T11:00:00",
"data": "Access denied: Insufficient permissions"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Call not found |
24. Get My Applications
Purpose: Returns a paginated list of all applications submitted by the authenticated user across all calls. Useful for applicants to track the status of their submissions.
Endpoint: GET {base_url}/my-applications
Access Level: 🔒 Protected (Requires Bearer Token · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
page |
integer | No | Page number (1-based) | Min: 1 | 1 |
size |
integer | No | Number of results per page | Min: 1 | 20 |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Your applications retrieved successfully",
"action_time": "2025-10-06T12:00:00",
"data": {
"content": [
{
"applicationId": "app1a2b3-c4d5-e6f7-8901-234567890abc",
"callId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"callTitle": "Software Engineer Intern",
"callBannerImage": "https://cdn.example.com/banner1.jpg",
"status": "ACCEPTED",
"appliedAt": "2025-10-05T08:00:00",
"submittedAt": "2025-10-05T09:00:00",
"applicant": {
"userId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"fullName": "Jane Smith",
"profileImage": "https://cdn.example.com/avatars/jane.jpg"
}
}
],
"totalElements": 4,
"totalPages": 1,
"currentPage": 1,
"hasMore": false
}
}
Success Response Fields:
| Field | Description |
|---|---|
data.content |
Array of ApplicationSummary objects for the authenticated user |
data.content[].applicationId |
Application UUID |
data.content[].callId |
Call UUID |
data.content[].callTitle |
Call title |
data.content[].callBannerImage |
Call banner image URL |
data.content[].status |
Current application status |
data.content[].appliedAt |
Start timestamp |
data.content[].submittedAt |
Submission timestamp |
data.content[].applicant |
Applicant preview |
data.totalElements |
Total records |
data.totalPages |
Total pages |
data.currentPage |
Current page |
data.hasMore |
Pagination flag |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "UNAUTHORIZED",
"message": "Token has expired",
"action_time": "2025-10-06T12:00:00",
"data": "Token has expired"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone number not verified |
25. Get Call Applicants
Purpose: Returns a list of all unique applicants (user previews) for a given call. Only the call owner can access this. Useful for quickly viewing who has applied without full application details.
Endpoint: GET {base_url}/{callId}/applicants
Access Level: 🔒 Protected (Requires Bearer Token · Call Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | ID of the call to get applicants for | Valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Applicants retrieved successfully",
"action_time": "2025-10-06T13:00:00",
"data": [
{
"userId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"fullName": "Jane Smith",
"profileImage": "https://cdn.example.com/avatars/jane.jpg"
},
{
"userId": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"fullName": "John Doe",
"profileImage": "https://cdn.example.com/avatars/john.jpg"
}
]
}
Success Response Fields:
| Field | Description |
|---|---|
data |
Array of ApplicantPreview objects |
data[].userId |
UUID of the applicant |
data[].fullName |
Applicant's full name |
data[].profileImage |
Applicant's profile photo URL |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Access denied: Insufficient permissions",
"action_time": "2025-10-06T13:00:00",
"data": "Access denied: Insufficient permissions"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Call not found |
26. Review Application
Purpose: Allows the call owner to review an application by updating its status (e.g., UNDER_REVIEW, ACCEPTED, REJECTED) and optionally adding review notes. Only the call owner can perform reviews.
Endpoint: POST {base_url}/applications/{applicationId}/review
Access Level: 🔒 Protected (Requires Bearer Token · Call Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
applicationId |
string (UUID) | Yes | ID of the application to review | Valid UUID |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
status |
string | Yes | The new status to set on the application | enum: DRAFT, SUBMITTED, UNDER_REVIEW, ACCEPTED, REJECTED, WITHDRAWN |
— |
notes |
string | No | Optional review notes or feedback for the applicant | Any string | — |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Application reviewed successfully",
"action_time": "2025-10-07T14:00:00",
"data": null
}
Success Response Fields:
| Field | Description |
|---|---|
data |
null — no payload returned on successful review |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Application not found",
"action_time": "2025-10-07T14:00:00",
"data": "Application not found"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Application not found |
27. Withdraw Application
Purpose: Allows an applicant to withdraw their own application. Sets the status to WITHDRAWN and soft-deletes the application record. This action cannot be undone.
Endpoint: POST {base_url}/applications/{applicationId}/withdraw
Access Level: 🔒 Protected (Requires Bearer Token · Application Owner · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
applicationId |
string (UUID) | Yes | ID of the application to withdraw | Valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Application withdrawn successfully",
"action_time": "2025-10-08T15:00:00",
"data": null
}
Success Response Fields:
| Field | Description |
|---|---|
data |
null — no payload returned on successful withdrawal |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Access denied: Insufficient permissions",
"action_time": "2025-10-08T15:00:00",
"data": "Access denied: Insufficient permissions"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the application owner |
404 NOT_FOUND |
Application not found |
28. Get Call Form Analytics
Purpose: Returns aggregated analytics for the application form of a call — including total responses, status breakdown, and average completion time. Only the call owner can access analytics.
Endpoint: GET {base_url}/{callId}/analytics
Access Level: 🔒 Protected (Requires Bearer Token · Call Owner Only · Phone Verified)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Yes | Bearer token: Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
callId |
string (UUID) | Yes | ID of the call to get analytics for | Valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Analytics retrieved successfully",
"action_time": "2025-10-08T16:00:00",
"data": {
"totalResponses": 42,
"submittedCount": 35,
"draftCount": 5,
"averageCompletionTimeSeconds": 487,
"statusBreakdown": {
"SUBMITTED": 35,
"DRAFT": 5,
"WITHDRAWN": 2
}
}
}
Success Response Fields:
| Field | Description |
|---|---|
totalResponses |
Total number of form responses (all statuses) |
submittedCount |
Number of fully submitted responses |
draftCount |
Number of responses still in DRAFT |
averageCompletionTimeSeconds |
Average time (in seconds) from form start to submission, across all submitted responses |
statusBreakdown |
Object mapping each response status to its count |
statusBreakdown.SUBMITTED |
Count of submitted responses |
statusBreakdown.DRAFT |
Count of draft responses |
statusBreakdown.WITHDRAWN |
Count of withdrawn responses |
Error Response JSON Sample:
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Call has no form",
"action_time": "2025-10-08T16:00:00",
"data": "Call has no form"
}
| HTTP Status | Description |
|---|---|
401 UNAUTHORIZED |
Token missing, invalid, or expired |
403 FORBIDDEN |
Phone not verified or not the call owner |
404 NOT_FOUND |
Call not found |
400 BAD_REQUEST |
Call has no form attached |
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.