Applicant Form API
Base URL: https://your-api-domain.com/api/v1/e-events/applicant-form
Short Description: The Applicant Form API allows event organizers to attach an optional custom multi-page form to their event. When enabled, attendees are prompted to fill in the form as part of the registration flow. The form is fully scoped to the event — all endpoints use eventId as the primary key, so the organizer never needs to track a separate formId. The entire feature is optional; if never enabled, the event registration proceeds with no form step.
Hints:
- All endpoints require a valid Bearer token.
- Form setup and management (enable, pages, fields, options) require the authenticated user to be the event organizer. Any other user gets
403. - Attendee submission endpoints (
/start,/pages/{pageId}/save,/submit,/my-response) require the event to be PUBLISHED and within its registration window (registrationOpensAt→registrationClosesAt). enableFormautomatically creates the underlying form and a default first page — you do not create them separately.startSubmissionis idempotent — if the attendee already has a draft response it returns the existing one instead of creating a new one.savePagesaves answers for a page without advancing the page index — it is a save-in-place operation. Callsubmitwhen all pages are done.- Delete endpoints accept a
?hard=falsequery parameter. Soft delete (hard=false, default) preserves historical response data. Hard delete (hard=true) permanently removes the record. DROPDOWN,RADIO, andCHECKBOXfield types require options to be added separately after the field is created.- The
HEADERfield type is a display-only section divider — it has norequiredflag and stores no answer data.
Form Structure — Layers
┌─────────────────────────────────────────────────────────────────────────┐
│ FORM │
│ title · description · settings · cover page │
│ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ PAGE 1 │ │
│ │ title · description · action button text │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────┐ │ │
│ │ │ FIELD (e.g. TEXT, EMAIL, DATE, FILE, RATING …) │ │ │
│ │ │ label · placeholder · required · validation rules │ │ │
│ │ └─────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────┐ │ │
│ │ │ FIELD (DROPDOWN / RADIO / CHECKBOX) │ │ │
│ │ │ label · required │ │ │
│ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │
│ │ │ │ Option 1 │ │ Option 2 │ │ Option 3 │ … │ │ │
│ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │
│ │ └─────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────┐ │ │
│ │ │ FIELD (HEADER — display only, no answer stored) │ │ │
│ │ │ label (section divider text) │ │ │
│ │ └─────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ PAGE 2 │ │
│ │ ┌──────────────────────────┐ ┌──────────────────────────┐ │ │
│ │ │ FIELD │ │ FIELD │ … │ │
│ │ └──────────────────────────┘ └──────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ PAGE N … │ │
│ └───────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
Rules at a glance:
- A form has one or more pages displayed in
displayOrder. - Each page has one or more fields displayed in
displayOrder. - Fields of type
DROPDOWN,RADIO, orCHECKBOXmust have options added after the field is created — no other field type has options. HEADERis the only field type that stores no answer and cannot be marked required. It acts purely as a section label between other fields.- Every other field type (
TEXT,TEXTAREA,EMAIL,PHONE,NUMBER,URL,DATE,TIME,DATETIME,RATING,FILE) stores exactly one answer per attendee.
Organizer Workflow
[Organizer]
│
│ POST /events/{eventId}/enable
▼
┌─────────────────────────────────────┐
│ Form ENABLED │
│ - Form auto-created internally │
│ - Default page auto-created │
│ - Config saved (displayTime etc.) │
└──────────────┬──────────────────────┘
│
│ Build the form structure:
│
│ POST /events/{eventId}/pages
│ POST /events/{eventId}/pages/{pageId}/fields
│ POST /events/{eventId}/fields/{fieldId}/options
│ (DROPDOWN / RADIO / CHECKBOX only)
│
│ (Optional bulk / clone shortcuts)
│ POST /events/{eventId}/pages/bulk
│ POST /events/{eventId}/pages/{pageId}/fields/bulk
│ POST /events/{eventId}/pages/{pageId}/clone
│ POST /events/{eventId}/fields/{fieldId}/clone
│
│ Preview before publishing:
│ GET /events/{eventId}/preview/metadata
│ GET /events/{eventId}/preview/pages/{pageNumber}
│ POST /events/{eventId}/preview/pages/{pageNumber}/validate
▼
┌─────────────────────────────────────┐
│ Form ready — event can publish │
└─────────────────────────────────────┘
Attendee Submission Journey
[Attendee — event must be PUBLISHED and within registration window]
│
│ POST /events/{eventId}/start
▼
┌──────────────────────────────────┐
│ Response created (DRAFT) │ Returns existing draft if one
│ or existing draft returned │ already exists (idempotent)
└──────────────┬───────────────────┘
│
│ For each page:
│ PUT /events/{eventId}/pages/{pageId}/save
│ Body: { fieldId: { value, fileUrl, ... }, ... }
▼
┌──────────────────────────────────┐
│ Page answers saved │ Save is in-place, does NOT
│ (repeat per page) │ advance page index automatically
└──────────────┬───────────────────┘
│
│ POST /events/{eventId}/submit
▼
┌──────────────────────────────────┐
│ Response SUBMITTED │ completionTimeSeconds recorded
└──────────────────────────────────┘
Response Status Flow
DRAFT ──────────────────────────────► SUBMITTED
│ │
│ (withdraw — not in this API) │ (organizer action — outside scope)
▼ ▼
WITHDRAWN UNDER_REVIEW → APPROVED / REJECTED
Standard Response Format
All API responses follow a consistent structure using the Globe Response Builder pattern.
Success Response Structure
{
"success": true,
"httpStatus": "OK",
"message": "Operation completed successfully",
"action_time": "2025-02-17T10:30:45",
"data": { }
}
Error Response Structure
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Error description",
"action_time": "2025-02-17T10:30:45",
"data": "Error description"
}
Standard Response Fields
| Field | Type | Description |
|---|---|---|
success |
boolean | true for successful operations, false for errors |
httpStatus |
string | HTTP status name (OK, CREATED, BAD_REQUEST, etc.) |
message |
string | Human-readable description of the result |
action_time |
string | ISO 8601 timestamp of when the response was generated |
data |
object / string | Response payload on success; error detail on failure |
HTTP Method Badge Standards
- GET — Green (
#28a745) — Safe, read-only operations - POST — Blue (
#007bff) — Create new resources - PUT — Yellow (
#ffc107, black text) — Update / replace - PATCH — Orange (
#fd7e14) — Partial update - DELETE — Red (
#dc3545) — Remove resource
Shared Response Object Definitions
A. ApplicantFormSetupResponse
Returned only by the Enable Form endpoint (Endpoint 1).
| Field | Type | Description |
|---|---|---|
config |
object | The saved EventApplicantFormEntity — see config fields below |
config.id |
UUID | Config record ID |
config.formId |
UUID | Internal Form Builder form ID (not needed for subsequent API calls) |
config.displayTime |
string | BEFORE_CHECKOUT or AFTER_CHECKOUT |
config.isRequiredOnline |
boolean | Whether online buyers must complete the form |
config.applyToAtDoor |
boolean | Whether walk-in attendees see the form |
config.createdAt |
ZonedDateTime | Config creation timestamp |
config.updatedAt |
ZonedDateTime | Last update timestamp |
form |
object | Full FormResponse — see FormResponse definition below |
B. EventApplicantFormEntity (Config Object)
Returned by the Update Settings endpoint.
| Field | Type | Description |
|---|---|---|
id |
UUID | Config record ID |
formId |
UUID | Internal Form Builder form ID |
displayTime |
string | BEFORE_CHECKOUT or AFTER_CHECKOUT |
isRequiredOnline |
boolean | Whether online buyers must complete the form |
applyToAtDoor |
boolean | Whether walk-in attendees see the form |
createdAt |
ZonedDateTime | ISO 8601 with offset |
updatedAt |
ZonedDateTime | ISO 8601 with offset |
C. FormResponse (Full Form Object)
| Field | Type | Description |
|---|---|---|
formId |
UUID | Form identifier (Form Builder internal ID) |
title |
string | Auto-set to "Attendee Questions - {event title}" on enable |
description |
string | Form description |
settings |
object | Form open/close settings (see FormSettings below) |
settings.acceptResponses |
boolean | Whether the form is accepting responses |
settings.allowMultipleSubmissions |
boolean | Whether a user can submit more than once |
settings.responseStartTime |
Instant | UTC datetime when responses open |
settings.responseDeadline |
Instant | UTC datetime when responses close |
settings.allowSaveDraft |
boolean | Whether respondents can save progress |
coverPage |
object | Optional cover page config |
createdBy |
string | Username of creator |
createdAt |
LocalDateTime | Creation timestamp |
pages[] |
array | Ordered list of PageResponse objects |
D. PageResponse
| Field | Type | Description |
|---|---|---|
pageId |
UUID | Page identifier |
title |
string | Page heading shown to attendee |
description |
string | Subheading or instruction text |
displayOrder |
integer | 1-based position within the form |
actionButtonText |
string | Label for the next/submit button |
fields[] |
array | Ordered list of FieldResponse objects (soft-deleted excluded) |
E. FieldResponse
| Field | Type | Description |
|---|---|---|
fieldId |
UUID | Field identifier |
type |
string | TEXT, TEXTAREA, EMAIL, PHONE, NUMBER, URL, DATE, TIME, DATETIME, DROPDOWN, RADIO, CHECKBOX, FILE, RATING, HEADER |
label |
string | Field label. For HEADER type this is the section title |
description |
string | Helper text shown below the field |
placeholder |
string | Input placeholder text |
displayOrder |
integer | 1-based order within the page |
required |
boolean | Whether the field must be answered. Always false for HEADER |
validation |
object | See FieldValidation below |
options[] |
array | OptionResponse entries — only for DROPDOWN, RADIO, CHECKBOX |
FieldValidation Object
| Field | Applicable To | Description |
|---|---|---|
minLength / maxLength |
TEXT, TEXTAREA |
Character count constraints |
pattern / patternMessage |
TEXT |
Regex pattern and custom error message |
min / max |
NUMBER |
Numeric range |
minDate / maxDate |
DATE |
Date range (YYYY-MM-DD) |
minSelections / maxSelections |
CHECKBOX |
Selection count constraints |
maxSizeMb / accept |
FILE |
File size limit and accepted MIME types |
F. OptionResponse
| Field | Type | Description |
|---|---|---|
optionId |
UUID | Option identifier |
label |
string | Display label shown to attendee |
displayOrder |
integer | 1-based order within the field |
G. FormResponseObject (Attendee Submission)
| Field | Type | Description |
|---|---|---|
responseId |
UUID | Unique response identifier |
formId |
UUID | Internal form ID |
submittedBy |
string | Username of the attendee |
status |
string | DRAFT, SUBMITTED, UNDER_REVIEW, APPROVED, REJECTED, WITHDRAWN |
completedPageIds |
array | UUIDs of pages marked complete |
currentPageIndex |
integer | 0-based index of current page |
startedAt |
LocalDateTime | When the attendee started the form |
submittedAt |
LocalDateTime | When the response was submitted |
completionTimeSeconds |
integer | Total seconds from start to submit |
answers[] |
array | See AnswerResponse below |
AnswerResponse
| Field | Type | Description |
|---|---|---|
answerId |
UUID | Answer identifier |
fieldId |
UUID | Field ID (null if field was hard-deleted) |
fieldLabel |
string | Label snapshot — preserved even if field is later deleted |
fieldType |
string | Type snapshot — preserved even if field is later deleted |
fieldDeleted |
boolean | true when the source field has been soft-deleted |
value |
any | Submitted value. String for text/single-choice, array of strings for checkbox, number for NUMBER/RATING |
answeredAt |
LocalDateTime | When this answer was saved |
fileUrl / fileName / fileSize / fileType |
various | File upload metadata (FILE fields only) |
H. BulkOperationResult
| Field | Type | Description |
|---|---|---|
successCount |
integer | Number of items successfully processed |
failureCount |
integer | Number of items that failed |
errors[] |
array | Error message per failed item |
createdFields[] |
array | FieldResponse objects (bulk field operations) |
createdPages[] |
array | PageResponse objects (bulk page operations) |
I. BulkDeleteResult
| Field | Type | Description |
|---|---|---|
successCount |
integer | Number of items successfully deleted |
failureCount |
integer | Number of items that failed |
errors[] |
array | Error message per failed item |
deletedIds[] |
array | UUIDs of successfully deleted items |
J. FormAnalytics
| Field | Type | Description |
|---|---|---|
formId |
UUID | Form identifier |
formTitle |
string | Form title |
stats.totalStarted |
integer | Total responses started (including drafts) |
stats.totalDrafts |
integer | Responses still in DRAFT |
stats.totalSubmitted |
integer | Responses with SUBMITTED status |
stats.totalWithdrawn |
integer | Withdrawn responses |
stats.completionRate |
double | Submitted / totalStarted × 100 |
stats.dropOffRate |
double | Inverse of completion rate |
stats.avgCompletionTimeSeconds |
double | Mean time from start to submit |
stats.fastestTimeSeconds |
integer | Fastest submission time |
stats.slowestTimeSeconds |
integer | Slowest submission time |
fieldAnalytics[] |
array | Per-field breakdown |
fieldAnalytics[].fieldId |
UUID | Field ID |
fieldAnalytics[].fieldLabel |
string | Field label snapshot |
fieldAnalytics[].fieldType |
string | Field type snapshot |
fieldAnalytics[].fieldDeleted |
boolean | Whether field is soft-deleted |
fieldAnalytics[].totalResponses |
integer | Total answers for this field |
fieldAnalytics[].choiceDistribution[] |
array | { option, count, percentage } — choice fields |
fieldAnalytics[].numericStats |
object | { min, max, avg, median } — NUMBER/RATING fields |
fieldAnalytics[].textResponses[] |
array | Raw text answers — TEXT/TEXTAREA fields |
dailySubmissions[] |
array | { date, count } — submissions per day |
Standard Error Types
Application-Level Exceptions (400–499)
400 BAD_REQUEST— Form already enabled for this event, field type does not support options, already submitted401 UNAUTHORIZED— Missing, expired, or malformed Bearer token403 FORBIDDEN— Authenticated but not the event organizer; or registration window not open/already closed404 NOT_FOUND— Event not found, form not enabled, page/field/option not found, no response found422 UNPROCESSABLE_ENTITY— Bean validation failures, required field missing on save
Server-Level Exceptions (500+)
500 INTERNAL_SERVER_ERROR— Unexpected runtime error
Shared Error Response Examples
{
"success": false,
"httpStatus": "UNAUTHORIZED",
"message": "Token has expired",
"action_time": "2025-02-17T10:30:45",
"data": "Token has expired"
}
403 — Forbidden (not organizer):
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Only organizer can manage form",
"action_time": "2025-02-17T10:30:45",
"data": "Only organizer can manage form"
}
403 — Forbidden (registration closed):
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Registration closed",
"action_time": "2025-02-17T10:30:45",
"data": "Registration closed"
}
404 — Form not enabled:
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Form not enabled",
"action_time": "2025-02-17T10:30:45",
"data": "Form not enabled"
}
Endpoints
Form Setup
1. Enable Applicant Form
Purpose: Enables the applicant form for an event. Internally creates a Form Builder form titled "Attendee Questions - {event title}" and an initial default page titled "Attendee Information". Only the event organizer can call this. Returns the full form structure alongside the config.
Endpoint: POST /api/v1/e-events/applicant-form/events/{eventId}/enable
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event to enable the form for | Must be a valid UUID |
Request JSON Sample:
{
"displayTime": "BEFORE_CHECKOUT",
"isRequiredOnline": true,
"applyToAtDoor": false
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
displayTime |
string | No | When attendees see the form in the UI flow | Enum: BEFORE_CHECKOUT, AFTER_CHECKOUT. Defaults to BEFORE_CHECKOUT |
isRequiredOnline |
boolean | No | Whether online ticket buyers must complete the form before proceeding | Defaults to false |
applyToAtDoor |
boolean | No | Whether at-door / walk-in attendees also see the form | Defaults to false |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "CREATED",
"message": "Applicant form enabled with default page",
"action_time": "2025-02-17T10:30:45",
"data": {
"config": {
"id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"formId": "9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"displayTime": "BEFORE_CHECKOUT",
"isRequiredOnline": true,
"applyToAtDoor": false,
"createdAt": "2025-02-17T10:30:45+03:00",
"updatedAt": null
},
"form": {
"formId": "9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"title": "Attendee Questions - Dar es Salaam Jazz Festival 2025",
"description": null,
"settings": null,
"coverPage": null,
"createdBy": "amina.hassan",
"createdAt": "2025-02-17T10:30:45",
"pages": [
{
"pageId": "1a2b3c4d-...",
"title": "Attendee Information",
"description": "Please provide your details",
"displayOrder": 1,
"actionButtonText": "Next",
"fields": []
}
]
}
}
}
Success Response Fields: data is an ApplicantFormSetupResponse.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer, or form is already enabled for this event |
404 |
Event not found |
2. Update Form Settings
Purpose: Updates the form configuration for the event — displayTime, isRequiredOnline, and applyToAtDoor. Does not affect the form structure (pages/fields). All fields are optional.
Endpoint: PUT /api/v1/e-events/applicant-form/events/{eventId}/settings
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
Request JSON Sample:
{
"displayTime": "AFTER_CHECKOUT",
"isRequiredOnline": false,
"applyToAtDoor": true
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
displayTime |
string | No | Updated display time | Enum: BEFORE_CHECKOUT, AFTER_CHECKOUT |
isRequiredOnline |
boolean | No | Updated required flag for online buyers | — |
applyToAtDoor |
boolean | No | Updated at-door flag | — |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form settings updated",
"action_time": "2025-02-17T10:30:45",
"data": {
"id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"formId": "9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"displayTime": "AFTER_CHECKOUT",
"isRequiredOnline": false,
"applyToAtDoor": true,
"createdAt": "2025-02-17T10:30:45+03:00",
"updatedAt": "2025-02-17T11:00:00+03:00"
}
}
Success Response Fields: data is an EventApplicantFormEntity config object.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or form not enabled |
3. Disable Form
Purpose: Disables and permanently removes the applicant form from the event. The underlying Form Builder form is soft-deleted. Existing submitted responses are preserved. This action cannot be undone — to re-enable a form, call Endpoint 1 again which will create a fresh form.
Endpoint: DELETE /api/v1/e-events/applicant-form/events/{eventId}/disable
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Applicant form disabled",
"action_time": "2025-02-17T10:30:45",
"data": null
}
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or form not enabled |
Page Management
4. Add Page
Purpose: Appends a new blank page to the form. displayOrder is auto-assigned as the next position. Fields are added to the page separately.
Endpoint: POST /api/v1/e-events/applicant-form/events/{eventId}/pages
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
Request JSON Sample:
{
"title": "Emergency Contact",
"description": "In case we need to reach someone on your behalf.",
"actionButtonText": "Next"
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
title |
string | Yes | Page heading shown to attendee | Max: 255 characters |
description |
string | No | Subheading or instruction text | Max: 500 characters |
actionButtonText |
string | No | Label for the page's action button | Max: 50 characters |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "CREATED",
"message": "Page added",
"action_time": "2025-02-17T10:30:45",
"data": {
"pageId": "2b3c4d5e-f6a7-8b9c-0d1e-2f3a4b5c6d7e",
"title": "Emergency Contact",
"description": "In case we need to reach someone on your behalf.",
"displayOrder": 2,
"actionButtonText": "Next",
"fields": []
}
}
Success Response Fields: data is a PageResponse.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or form not enabled |
422 |
title is blank |
5. Update Page
Purpose: Updates the title, description, or action button label of an existing page.
Endpoint: PUT /api/v1/e-events/applicant-form/events/{eventId}/pages/{pageId}
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
pageId |
UUID | Yes | The page to update | Must be a valid UUID |
Request JSON Sample:
{
"title": "Your Background",
"actionButtonText": "Continue"
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
title |
string | No | Updated page title | Max: 255 characters |
description |
string | No | Updated description | Max: 500 characters |
actionButtonText |
string | No | Updated button label | Max: 50 characters |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Page updated",
"action_time": "2025-02-17T10:30:45",
"data": { "...": "PageResponse object" }
}
Success Response Fields: data is a PageResponse.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or page not found |
6. Delete Page
Purpose: Deletes a page. Pass ?hard=false (default) for soft delete — the page is hidden but historical answer data is preserved. Pass ?hard=true to permanently remove the page and all its fields.
Endpoint: DELETE /api/v1/e-events/applicant-form/events/{eventId}/pages/{pageId}
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
pageId |
UUID | Yes | The page to delete | Must be a valid UUID |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
hard |
boolean | No | true = permanent delete, false = soft delete |
— | false |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Page deleted",
"action_time": "2025-02-17T10:30:45",
"data": null
}
When
hard=true,messageis"Page permanently deleted".
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or page not found |
7. Bulk Add Pages (with Fields)
Purpose: Creates multiple pages in one call. Each page can optionally include an inline list of fields.
Endpoint: POST /api/v1/e-events/applicant-form/events/{eventId}/pages/bulk
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
Request JSON Sample:
{
"pages": [
{
"title": "Personal Details",
"actionButtonText": "Next",
"fields": [
{ "type": "TEXT", "label": "Full Name", "required": true },
{ "type": "EMAIL", "label": "Email", "required": true }
]
},
{
"title": "Dietary Requirements",
"actionButtonText": "Submit",
"fields": [
{ "type": "DROPDOWN", "label": "Dietary preference", "required": false }
]
}
]
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
pages |
array | Yes | Pages to create | Min 1 item |
pages[].title |
string | Yes | Page title | Max: 255 characters |
pages[].description |
string | No | Page description | Max: 500 characters |
pages[].actionButtonText |
string | No | Button label | Max: 50 characters |
pages[].fields |
array | No | Fields to create inline | See CreateField below |
pages[].fields[].type |
string | Yes | Field type | See FieldType enum |
pages[].fields[].label |
string | Yes | Field label | Max: 255 characters |
pages[].fields[].description |
string | No | Helper text | Max: 500 characters |
pages[].fields[].placeholder |
string | No | Placeholder text | Max: 255 characters |
pages[].fields[].required |
boolean | No | Required flag | Defaults to false |
pages[].fields[].validation |
object | No | Validation rules | See FieldValidation |
Note: For
DROPDOWN,RADIO, andCHECKBOXfields created via bulk, options must still be added separately using the option endpoints after this call.
Success Response JSON Sample:
{
"success": true,
"httpStatus": "CREATED",
"message": "2 pages added, 0 failed",
"action_time": "2025-02-17T10:30:45",
"data": {
"successCount": 2,
"failureCount": 0,
"errors": [],
"createdPages": [
{ "...": "PageResponse for page 1" },
{ "...": "PageResponse for page 2" }
]
}
}
Success Response Fields: data is a BulkOperationResult.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or form not enabled |
8. Bulk Delete Pages
Purpose: Deletes multiple pages in one call. Supports both soft delete (default) and hard delete via ?hard query param. Items are processed individually — a failure on one does not stop the rest.
Endpoint: DELETE /api/v1/e-events/applicant-form/events/{eventId}/pages/bulk
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
hard |
boolean | No | true = permanent delete |
— | false |
Request JSON Sample:
{
"ids": ["pageId-1", "pageId-2"]
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
ids |
array | Yes | UUIDs of pages to delete | Min 1 item |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "2 pages deleted, 0 failed",
"action_time": "2025-02-17T10:30:45",
"data": {
"successCount": 2,
"failureCount": 0,
"errors": [],
"deletedIds": ["pageId-1", "pageId-2"]
}
}
Success Response Fields: data is a BulkDeleteResult.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found. Individual page errors reported in data.errors[] |
9. Clone Page
Purpose: Creates an exact copy of an existing page including all its active fields and options. The clone is appended at the end of the form with "(Copy)" added to the title.
Endpoint: POST /api/v1/e-events/applicant-form/events/{eventId}/pages/{pageId}/clone
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
pageId |
UUID | Yes | The page to clone | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "CREATED",
"message": "Page cloned successfully",
"action_time": "2025-02-17T10:30:45",
"data": { "...": "PageResponse for the cloned page" }
}
Success Response Fields: data is a PageResponse for the new clone.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or page not found |
Field Management
10. Add Field
Purpose: Adds a single field to a page. displayOrder is auto-assigned. For DROPDOWN, RADIO, and CHECKBOX types, options must be added separately after this call.
Endpoint: POST /api/v1/e-events/applicant-form/events/{eventId}/pages/{pageId}/fields
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
pageId |
UUID | Yes | The page to add the field to | Must be a valid UUID |
Request JSON Sample:
{
"type": "TEXT",
"label": "Full Name",
"description": "As it appears on your ID.",
"placeholder": "e.g. Amina Hassan",
"required": true,
"validation": {
"minLength": 2,
"maxLength": 100
}
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
type |
string | Yes | Field type | Enum: TEXT, TEXTAREA, EMAIL, PHONE, NUMBER, URL, DATE, TIME, DATETIME, DROPDOWN, RADIO, CHECKBOX, FILE, RATING, HEADER |
label |
string | Yes | Field label (or section title for HEADER) |
Max: 255 characters |
description |
string | No | Helper text | Max: 500 characters |
placeholder |
string | No | Input placeholder | Max: 255 characters |
required |
boolean | No | Required flag. Forced false for HEADER |
Defaults to false |
validation |
object | No | Validation rules | See FieldValidation |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "CREATED",
"message": "Field added",
"action_time": "2025-02-17T10:30:45",
"data": {
"fieldId": "c3d4e5f6-a7b8-9c0d-1e2f-3a4b5c6d7e8f",
"type": "TEXT",
"label": "Full Name",
"description": "As it appears on your ID.",
"placeholder": "e.g. Amina Hassan",
"displayOrder": 1,
"required": true,
"validation": { "minLength": 2, "maxLength": 100 },
"options": []
}
}
Success Response Fields: data is a FieldResponse.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or page not found |
422 |
type is null, or label is blank |
11. Update Field
Purpose: Updates the configuration of an existing field. All fields are optional.
Endpoint: PUT /api/v1/e-events/applicant-form/events/{eventId}/fields/{fieldId}
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
fieldId |
UUID | Yes | The field to update | Must be a valid UUID |
Request JSON Sample:
{
"label": "Legal Full Name",
"required": true,
"validation": {
"minLength": 3,
"maxLength": 150
}
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
type |
string | No | Updated field type | See FieldType enum |
label |
string | No | Updated label | Max: 255 characters |
description |
string | No | Updated helper text | Max: 500 characters |
placeholder |
string | No | Updated placeholder | Max: 255 characters |
required |
boolean | No | Updated required flag. Forced false if type is HEADER |
— |
validation |
object | No | Updated validation rules (full replacement) | See FieldValidation |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Field updated",
"action_time": "2025-02-17T10:30:45",
"data": { "...": "FieldResponse object" }
}
Success Response Fields: data is a FieldResponse.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or field not found |
12. Delete Field
Purpose: Deletes a field. Soft delete (default) preserves historical answer snapshots. Hard delete permanently removes the field record.
Endpoint: DELETE /api/v1/e-events/applicant-form/events/{eventId}/fields/{fieldId}
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
fieldId |
UUID | Yes | The field to delete | Must be a valid UUID |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
hard |
boolean | No | true = permanent delete |
— | false |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Field deleted",
"action_time": "2025-02-17T10:30:45",
"data": null
}
When
hard=true,messageis"Field permanently deleted".
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or field not found |
13. Bulk Add Fields
Purpose: Adds multiple fields to a page in one call. Fields are appended after existing fields in array order.
Endpoint: POST /api/v1/e-events/applicant-form/events/{eventId}/pages/{pageId}/fields/bulk
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
pageId |
UUID | Yes | The page to add fields to | Must be a valid UUID |
Request JSON Sample:
{
"fields": [
{ "type": "EMAIL", "label": "Email Address", "required": true },
{ "type": "PHONE", "label": "Phone Number", "required": false },
{ "type": "HEADER", "label": "Travel Details" },
{ "type": "DROPDOWN", "label": "Arrival method", "required": false }
]
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
fields |
array | Yes | Fields to create | Min 1 item |
fields[].type |
string | Yes | Field type | See FieldType enum |
fields[].label |
string | Yes | Field label | Max: 255 characters |
fields[].description |
string | No | Helper text | Max: 500 characters |
fields[].placeholder |
string | No | Placeholder text | Max: 255 characters |
fields[].required |
boolean | No | Required flag | Defaults to false |
fields[].validation |
object | No | Validation rules | See FieldValidation |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "CREATED",
"message": "4 fields added, 0 failed",
"action_time": "2025-02-17T10:30:45",
"data": {
"successCount": 4,
"failureCount": 0,
"errors": [],
"createdFields": [ "[ FieldResponse objects ]" ]
}
}
Success Response Fields: data is a BulkOperationResult.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or page not found |
14. Bulk Delete Fields
Purpose: Deletes multiple fields from a page in one call. Supports soft and hard delete via ?hard.
Endpoint: DELETE /api/v1/e-events/applicant-form/events/{eventId}/pages/{pageId}/fields/bulk
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
pageId |
UUID | Yes | The page containing the fields | Must be a valid UUID |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
hard |
boolean | No | true = permanent delete |
— | false |
Request JSON Sample:
{
"ids": ["fieldId-1", "fieldId-2"]
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
ids |
array | Yes | UUIDs of fields to delete | Min 1 item |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "2 fields deleted, 0 failed",
"action_time": "2025-02-17T10:30:45",
"data": {
"successCount": 2,
"failureCount": 0,
"errors": [],
"deletedIds": ["fieldId-1", "fieldId-2"]
}
}
Success Response Fields: data is a BulkDeleteResult.
Possible Error Responses: Same as Endpoint 8 (401, 403, 404).
15. Bulk Update Fields
Purpose: Updates required flag and/or validation rules across multiple fields at once.
Endpoint: PATCH /api/v1/e-events/applicant-form/events/{eventId}/fields/bulk
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
Request JSON Sample:
{
"fieldIds": ["fieldId-1", "fieldId-2"],
"required": true,
"validation": { "maxLength": 200 }
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
fieldIds |
array | Yes | UUIDs of fields to update | Min 1 item |
required |
boolean | No | New required value for all listed fields | — |
validation |
object | No | New validation rules for all listed fields (full replacement) | See FieldValidation |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "2 fields updated, 0 failed",
"action_time": "2025-02-17T10:30:45",
"data": {
"successCount": 2,
"failureCount": 0,
"errors": [],
"createdFields": [ "[ Updated FieldResponse objects ]" ]
}
}
Success Response Fields: data is a BulkOperationResult.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
One or more field IDs not found — reported in data.errors[] |
16. Clone Field
Purpose: Creates a copy of a field (with its options) and appends it to a target page. Label gets "(Copy)" appended.
Endpoint: POST /api/v1/e-events/applicant-form/events/{eventId}/fields/{fieldId}/clone
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
fieldId |
UUID | Yes | The field to clone | Must be a valid UUID |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
targetPageId |
UUID | Yes | The page to clone the field into | Must be a valid UUID | — |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "CREATED",
"message": "Field cloned successfully",
"action_time": "2025-02-17T10:30:45",
"data": { "...": "FieldResponse for the cloned field" }
}
Success Response Fields: data is a FieldResponse for the new clone.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found, field not found, or target page not found |
Option Management
17. Add Option
Purpose: Adds a choice option to a DROPDOWN, RADIO, or CHECKBOX field. Calling this on any other field type returns 400.
Endpoint: POST /api/v1/e-events/applicant-form/events/{eventId}/fields/{fieldId}/options
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
fieldId |
UUID | Yes | The field to add an option to | Must be DROPDOWN, RADIO, or CHECKBOX type |
Request JSON Sample:
{
"label": "By Car"
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
label |
string | Yes | Display label for this option | Max: 255 characters |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "CREATED",
"message": "Option added",
"action_time": "2025-02-17T10:30:45",
"data": {
"optionId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a",
"label": "By Car",
"displayOrder": 1
}
}
Success Response Fields: data is an OptionResponse.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
400 |
Field type does not support options |
403 |
Not the event organizer |
404 |
Event not found or field not found |
422 |
label is blank |
18. Update Option
Purpose: Updates the label of an existing option.
Endpoint: PUT /api/v1/e-events/applicant-form/events/{eventId}/options/{optionId}
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
optionId |
UUID | Yes | The option to update | Must be a valid UUID |
Request JSON Sample:
{
"label": "Public Transport"
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
label |
string | No | Updated label | Max: 255 characters |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Option updated",
"action_time": "2025-02-17T10:30:45",
"data": {
"optionId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a",
"label": "Public Transport",
"displayOrder": 1
}
}
Success Response Fields: data is an OptionResponse.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or option not found |
19. Delete Option
Purpose: Deletes an option. Soft delete (default) preserves previously selected answer values. Hard delete permanently removes the option record.
Endpoint: DELETE /api/v1/e-events/applicant-form/events/{eventId}/options/{optionId}
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
optionId |
UUID | Yes | The option to delete | Must be a valid UUID |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
hard |
boolean | No | true = permanent delete |
— | false |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Option deleted",
"action_time": "2025-02-17T10:30:45",
"data": null
}
When
hard=true,messageis"Option permanently deleted".
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or option not found |
20. Bulk Delete Options
Purpose: Deletes multiple options from a field in one call. Supports soft and hard delete via ?hard.
Endpoint: DELETE /api/v1/e-events/applicant-form/events/{eventId}/fields/{fieldId}/options/bulk
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
fieldId |
UUID | Yes | The field containing the options | Must be a valid UUID |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
hard |
boolean | No | true = permanent delete |
— | false |
Request JSON Sample:
{
"ids": ["optionId-1", "optionId-2"]
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
ids |
array | Yes | UUIDs of options to delete | Min 1 item |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "2 options deleted, 0 failed",
"action_time": "2025-02-17T10:30:45",
"data": {
"successCount": 2,
"failureCount": 0,
"errors": [],
"deletedIds": ["optionId-1", "optionId-2"]
}
}
Success Response Fields: data is a BulkDeleteResult.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or field not found. Individual errors in data.errors[] |
21. Bulk Update Options
Purpose: Updates the labels of multiple options in one call.
Endpoint: PATCH /api/v1/e-events/applicant-form/events/{eventId}/options/bulk
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
Request JSON Sample:
{
"options": [
{ "optionId": "optionId-1", "label": "Train" },
{ "optionId": "optionId-2", "label": "Bus" }
]
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
options |
array | Yes | List of option updates | Min 1 item |
options[].optionId |
UUID | Yes | The option to update | Must be a valid UUID |
options[].label |
string | No | New label | Max: 255 characters |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "2 options updated, 0 failed",
"action_time": "2025-02-17T10:30:45",
"data": {
"successCount": 2,
"failureCount": 0,
"errors": []
}
}
Success Response Fields: data is a BulkOperationResult.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
An option ID not found — reported in data.errors[] |
Preview
22. Get Preview Metadata
Purpose: Returns a lightweight summary of the form structure — total pages, page numbers, and titles — without loading full field data. Used to render a progress indicator before the attendee starts filling.
Endpoint: GET /api/v1/e-events/applicant-form/events/{eventId}/preview/metadata
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Metadata retrieved",
"action_time": "2025-02-17T10:30:45",
"data": {
"formId": "9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"formTitle": "Attendee Questions - Dar es Salaam Jazz Festival 2025",
"totalPages": 3,
"pageNumbers": [
{ "pageNumber": 1, "pageTitle": "Attendee Information" },
{ "pageNumber": 2, "pageTitle": "Emergency Contact" },
{ "pageNumber": 3, "pageTitle": "Dietary Requirements" }
]
}
}
Success Response Fields:
| Field | Description |
|---|---|
formId |
Internal form ID |
formTitle |
Form title |
totalPages |
Total active pages |
pageNumbers[].pageNumber |
1-based page number |
pageNumbers[].pageTitle |
Page heading |
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or form not enabled |
23. Preview Page by Number
Purpose: Returns a specific page by its 1-based position number, including all its active fields and options. Allows the organizer to preview what attendees will see before publishing.
Endpoint: GET /api/v1/e-events/applicant-form/events/{eventId}/preview/pages/{pageNumber}
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
pageNumber |
integer | Yes | 1-based page position | Must be ≥ 1 and ≤ total active pages |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Preview page retrieved",
"action_time": "2025-02-17T10:30:45",
"data": { "...": "PageResponse object" }
}
Success Response Fields: data is a PageResponse.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found, form not enabled, or pageNumber out of range |
24. Validate Preview Page Answers
Purpose: Runs validation on a set of answers for a specific page number without creating or saving any data. Lets the organizer test field validation rules before the form goes live.
Endpoint: POST /api/v1/e-events/applicant-form/events/{eventId}/preview/pages/{pageNumber}/validate
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
pageNumber |
integer | Yes | 1-based page number to validate against | Must be ≥ 1 and ≤ total active pages |
Request JSON Sample:
{
"fieldId-fullname": { "value": "" },
"fieldId-email": { "value": "not-an-email" }
}
Request Body: A flat map of fieldId (UUID) → AnswerValue. AnswerValue has value (any), plus optional fileUrl, fileName, fileSize, fileType for FILE fields.
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Validation complete",
"action_time": "2025-02-17T10:30:45",
"data": {
"valid": false,
"errors": [
{
"pageId": "1a2b3c4d-...",
"pageTitle": "Attendee Information",
"fieldId": "fieldId-fullname",
"fieldLabel": "Full Name",
"errorMessage": "Full Name is required",
"errorType": "REQUIRED"
},
{
"pageId": "1a2b3c4d-...",
"pageTitle": "Attendee Information",
"fieldId": "fieldId-email",
"fieldLabel": "Email",
"errorMessage": "Email must be valid email",
"errorType": "INVALID_FORMAT"
}
]
}
}
Success Response Fields:
| Field | Description |
|---|---|
data.valid |
true if all fields passed validation |
data.errors[].pageId |
Page UUID |
data.errors[].pageTitle |
Page title |
data.errors[].fieldId |
Field UUID |
data.errors[].fieldLabel |
Field label |
data.errors[].errorMessage |
Human-readable error |
data.errors[].errorType |
REQUIRED, INVALID_FORMAT, INVALID_TYPE, VALIDATION_FAILED |
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found, form not enabled, or pageNumber out of range |
Attendee Submission
25. Start Submission
Purpose: Initiates the attendee's form response session. Creates a new DRAFT response tied to this event's form. If the attendee already has a draft or submitted response for this event's form, the existing response is returned — this endpoint is idempotent. Requires the event to be PUBLISHED and within its registration window.
Endpoint: POST /api/v1/e-events/applicant-form/events/{eventId}/start
Access Level: 🔒 Protected (Any authenticated attendee)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The published event | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form submission started",
"action_time": "2025-02-17T10:30:45",
"data": {
"responseId": "e5f6a7b8-c9d0-1e2f-3a4b-5c6d7e8f9a0b",
"formId": "9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"submittedBy": "john.doe",
"status": "DRAFT",
"completedPageIds": [],
"currentPageIndex": 0,
"startedAt": "2025-02-17T10:30:45",
"submittedAt": null,
"completionTimeSeconds": null,
"answers": []
}
}
Success Response Fields: data is a FormResponseObject.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Event not published, registration not yet open, or registration already closed |
404 |
Event not found or form not enabled |
26. Save Page Answers
Purpose: Saves the attendee's answers for a specific page. Can be called multiple times — each call replaces the previous answers for that page. This is a save-in-place operation; it does not advance the page index. Call submit (Endpoint 28) when all pages are complete.
Endpoint: PUT /api/v1/e-events/applicant-form/events/{eventId}/pages/{pageId}/save
Access Level: 🔒 Protected (Attendee — response owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
pageId |
UUID | Yes | The page being answered | Must be a valid UUID belonging to this event's form |
Request JSON Sample:
{
"c3d4e5f6-a7b8-9c0d-1e2f-3a4b5c6d7e8f": {
"value": "Amina Hassan"
},
"d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a": {
"value": "amina@example.com"
},
"e5f6a7b8-c9d0-1e2f-3a4b-5c6d7e8f9a0b": {
"value": "optionId-bycar"
},
"f6a7b8c9-d0e1-2f3a-4b5c-6d7e8f9a0b1c": {
"value": null,
"fileUrl": "https://cdn.example.com/uploads/id.pdf",
"fileName": "national-id.pdf",
"fileSize": 204800,
"fileType": "application/pdf"
}
}
Request Body: A flat Map<UUID, AnswerValue> where each key is a fieldId.
| Key | Type | Description |
|---|---|---|
{fieldId} |
UUID (map key) | The field being answered |
.value |
any | Answer value. See answer value types below |
.fileUrl |
string | FILE fields — uploaded file URL |
.fileName |
string | FILE fields — original file name |
.fileSize |
long | FILE fields — file size in bytes |
.fileType |
string | FILE fields — MIME type |
Answer Value Types
| Field Type | Expected Value |
|---|---|
TEXT, TEXTAREA, EMAIL, PHONE, URL |
String |
NUMBER |
Number (integer or decimal) |
DATE |
String — YYYY-MM-DD |
TIME |
String — HH:mm |
DATETIME |
String — ISO 8601 datetime |
DROPDOWN, RADIO |
String — UUID of selected option |
CHECKBOX |
Array of strings — UUIDs of selected options |
RATING |
Integer — 1 to 5 |
FILE |
null — metadata goes in fileUrl, fileName, etc. |
HEADER |
Omit entirely — no answer needed |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Page saved",
"action_time": "2025-02-17T10:30:45",
"data": { "...": "Full FormResponseObject with updated answers" }
}
Success Response Fields: data is a FormResponseObject reflecting the updated answer state.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Registration window closed or event not published |
404 |
Event not found, form not enabled, or no active draft found — call /start first |
422 |
A required field has no value |
27. Get My Response
Purpose: Returns the authenticated attendee's current response for the event's form — whether still in draft or already submitted.
Endpoint: GET /api/v1/e-events/applicant-form/events/{eventId}/my-response
Access Level: 🔒 Protected (Any authenticated attendee)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Response retrieved",
"action_time": "2025-02-17T10:30:45",
"data": { "...": "Full FormResponseObject" }
}
Success Response Fields: data is a FormResponseObject.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
No response found for this attendee on this event's form |
28. Submit
Purpose: Finalises and submits the attendee's response. The system validates all pages before accepting. Sets status to SUBMITTED and records completionTimeSeconds.
Endpoint: POST /api/v1/e-events/applicant-form/events/{eventId}/submit
Access Level: 🔒 Protected (Attendee — response owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form submitted successfully",
"action_time": "2025-02-17T10:30:45",
"data": { "...": "Full FormResponseObject with status SUBMITTED" }
}
Success Response Fields: data is a FormResponseObject. data.status will be "SUBMITTED".
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Already submitted, or registration window closed |
404 |
Event not found, form not enabled, or no draft response found |
422 |
Required fields on one or more pages are unanswered |
Organizer Response Management
29. Get Response by ID
Purpose: Retrieves a specific attendee response by ID. Available to the event organizer only.
Endpoint: GET /api/v1/e-events/applicant-form/events/{eventId}/responses/{responseId}
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
responseId |
UUID | Yes | The response to retrieve | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Response retrieved",
"action_time": "2025-02-17T10:30:45",
"data": { "...": "Full FormResponseObject" }
}
Success Response Fields: data is a FormResponseObject.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or response not found |
30. Get All Responses
Purpose: Returns a paginated list of all attendee responses for the event's form. For organizer review and export.
Endpoint: GET /api/v1/e-events/applicant-form/events/{eventId}/responses
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
page |
integer | No | Page number (0-based) | Min: 0 | 0 |
size |
integer | No | Items per page | Min: 1 | 20 |
Note: This endpoint uses 0-based pagination (
page=0is the first page), matching the SpringPageabledefault passed from the controller.
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Responses retrieved",
"action_time": "2025-02-17T10:30:45",
"data": {
"content": [ "[ FormResponseObject entries ]" ],
"totalElements": 48,
"totalPages": 3,
"first": true,
"last": false,
"empty": false
}
}
Success Response Fields: data.content[] contains FormResponseObject entries.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or form not enabled |
31. Get Analytics
Purpose: Returns full submission analytics for the event's form — stats overview, per-field distributions, and daily submission trends.
Endpoint: GET /api/v1/e-events/applicant-form/events/{eventId}/analytics
Access Level: 🔒 Protected (Event organizer only)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
eventId |
UUID | Yes | The event | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Analytics retrieved",
"action_time": "2025-02-17T10:30:45",
"data": {
"formId": "9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"formTitle": "Attendee Questions - Dar es Salaam Jazz Festival 2025",
"stats": {
"totalStarted": 120,
"totalDrafts": 18,
"totalSubmitted": 95,
"totalWithdrawn": 7,
"completionRate": 79.2,
"dropOffRate": 20.8,
"avgCompletionTimeSeconds": 312.0,
"fastestTimeSeconds": 45,
"slowestTimeSeconds": 1890
},
"fieldAnalytics": [
{
"fieldId": "c3d4e5f6-...",
"fieldLabel": "Full Name",
"fieldType": "TEXT",
"fieldDeleted": false,
"totalResponses": 95,
"uniqueResponses": 95,
"textResponses": ["Amina Hassan", "John Doe", "..."]
},
{
"fieldId": "e5f6a7b8-...",
"fieldLabel": "Arrival method",
"fieldType": "DROPDOWN",
"fieldDeleted": false,
"totalResponses": 95,
"choiceDistribution": [
{ "option": "By Car", "count": 42, "percentage": 44.2 },
{ "option": "Public Transport", "count": 35, "percentage": 36.8 },
{ "option": "On Foot", "count": 18, "percentage": 18.9 }
]
}
],
"dailySubmissions": [
{ "date": "2025-07-15", "count": 12 },
{ "date": "2025-07-16", "count": 28 }
]
}
}
Success Response Fields: data is a FormAnalytics.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
403 |
Not the event organizer |
404 |
Event not found or form not enabled |
Quick Reference — Endpoint Summary
| # | Method | Path | Auth | Who | Description |
|---|---|---|---|---|---|
| Form Setup | |||||
| 1 | POST | /events/{eventId}/enable |
🔒 | Organizer | Enable form + create default page |
| 2 | PUT | /events/{eventId}/settings |
🔒 | Organizer | Update form display settings |
| 3 | DELETE | /events/{eventId}/disable |
🔒 | Organizer | Disable and remove form |
| Page Management | |||||
| 4 | POST | /events/{eventId}/pages |
🔒 | Organizer | Add a page |
| 5 | PUT | /events/{eventId}/pages/{pageId} |
🔒 | Organizer | Update a page |
| 6 | DELETE | /events/{eventId}/pages/{pageId}?hard=false |
🔒 | Organizer | Delete a page (soft or hard) |
| 7 | POST | /events/{eventId}/pages/bulk |
🔒 | Organizer | Bulk add pages with fields |
| 8 | DELETE | /events/{eventId}/pages/bulk?hard=false |
🔒 | Organizer | Bulk delete pages |
| 9 | POST | /events/{eventId}/pages/{pageId}/clone |
🔒 | Organizer | Clone a page |
| Field Management | |||||
| 10 | POST | /events/{eventId}/pages/{pageId}/fields |
🔒 | Organizer | Add a field to a page |
| 11 | PUT | /events/{eventId}/fields/{fieldId} |
🔒 | Organizer | Update a field |
| 12 | DELETE | /events/{eventId}/fields/{fieldId}?hard=false |
🔒 | Organizer | Delete a field (soft or hard) |
| 13 | POST | /events/{eventId}/pages/{pageId}/fields/bulk |
🔒 | Organizer | Bulk add fields |
| 14 | DELETE | /events/{eventId}/pages/{pageId}/fields/bulk?hard=false |
🔒 | Organizer | Bulk delete fields |
| 15 | PATCH | /events/{eventId}/fields/bulk |
🔒 | Organizer | Bulk update fields |
| 16 | POST | /events/{eventId}/fields/{fieldId}/clone |
🔒 | Organizer | Clone a field |
| Option Management | |||||
| 17 | POST | /events/{eventId}/fields/{fieldId}/options |
🔒 | Organizer | Add option to a field |
| 18 | PUT | /events/{eventId}/options/{optionId} |
🔒 | Organizer | Update an option |
| 19 | DELETE | /events/{eventId}/options/{optionId}?hard=false |
🔒 | Organizer | Delete an option (soft or hard) |
| 20 | DELETE | /events/{eventId}/fields/{fieldId}/options/bulk?hard=false |
🔒 | Organizer | Bulk delete options |
| 21 | PATCH | /events/{eventId}/options/bulk |
🔒 | Organizer | Bulk update option labels |
| Preview | |||||
| 22 | GET | /events/{eventId}/preview/metadata |
🔒 | Organizer | Get form page metadata |
| 23 | GET | /events/{eventId}/preview/pages/{pageNumber} |
🔒 | Organizer | Preview a page by number |
| 24 | POST | /events/{eventId}/preview/pages/{pageNumber}/validate |
🔒 | Organizer | Validate answers without saving |
| Attendee Submission | |||||
| 25 | POST | /events/{eventId}/start |
🔒 | Attendee | Start form / get existing draft |
| 26 | PUT | /events/{eventId}/pages/{pageId}/save |
🔒 | Attendee | Save page answers |
| 27 | GET | /events/{eventId}/my-response |
🔒 | Attendee | Get my response |
| 28 | POST | /events/{eventId}/submit |
🔒 | Attendee | Submit form |
| Organizer — Responses & Analytics | |||||
| 29 | GET | /events/{eventId}/responses/{responseId} |
🔒 | Organizer | Get response by ID |
| 30 | GET | /events/{eventId}/responses |
🔒 | Organizer | Get all responses (paginated) |
| 31 | GET | /events/{eventId}/analytics |
🔒 | Organizer | Get form analytics |
All paths are prefixed with
/api/v1/e-events/applicant-form.
Data Format Standards
| Concern | Standard |
|---|---|
| Timestamps | ZonedDateTime — ISO 8601 with offset: 2025-02-17T10:30:45+03:00 |
| Local timestamps | LocalDateTime — ISO 8601 no offset: 2025-02-17T10:30:45 |
| Dates | YYYY-MM-DD — 2025-07-18 |
| Times | HH:mm — 18:00 |
| IDs | UUID v4 — 3fa85f64-5717-4562-b3fc-2c963f66afa6 |
| Pagination (responses) | 0-based page param, Spring Page wrapper |
| Enums | Uppercase: BEFORE_CHECKOUT, SUBMITTED, DROPDOWN, REQUIRED |
No comments to display
No comments to display