Skip to main content

Events Applicant Form API

Author: Josh S. Sakweli, Backend Lead Team Last Updated: 2026-05-22 Version: v1.2

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 (registrationOpensAtregistrationClosesAt).
  • enableForm creates the underlying form with no pages. Pages must be added by the organizer via the page endpoints. The form must have at least one page before the event can be published.
  • Use GET /events/{eventId}/full-form to load the complete form state (all pages, fields, and options) in a single call — intended for the form builder UI.
  • startSubmission is idempotent — if the attendee already has a draft response it returns the existing one instead of creating a new one.
  • savePage accepts a ?moveToNextPage=false/true query parameter that controls validation behaviour. When false (default), answers are written to the draft with no validation — use this for background auto-save. When true, the page is validated first; if any field fails, errors are returned and nothing is saved; if all fields pass, answers are saved, the page is marked complete, and the index advances to the next page. This is the "Next" button action.
  • submit requires every page to have been completed via ?moveToNextPage=true at least once. Pages that were only auto-saved (without passing "Next" validation) will block submission with a PAGE_INCOMPLETE error. This ensures every page was validated before the form is accepted.
  • Delete endpoints accept a ?hard=false query parameter. Soft delete (hard=false, default) preserves historical response data. Hard delete (hard=true) permanently removes the record.
  • DROPDOWN, RADIO, and CHECKBOX field types require options to be added separately after the field is created.
  • The HEADER field type is a display-only section divider — it has no required flag 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, or CHECKBOX must have options added after the field is created — no other field type has options.
  • HEADER is 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 (empty)              │
  │   - Form created internally         │
  │   - No pages yet (pages: [])        │
  │   - Config saved (displayTime etc.) │
  └──────────────┬──────────────────────┘
                 │
                 │  Load builder state (on re-open):
                 │  GET  /events/{eventId}/full-form
                 │
                 │  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    │
  │   ⚠ Publish blocked if 0 pages     │
  └─────────────────────────────────────┘

Attendee Submission Journey

  [Attendee — event must be PUBLISHED and within registration window]
         │
         │  POST /events/{eventId}/start
         ▼
  ┌──────────────────────────────────────────────────┐
  │  Response created (DRAFT)                        │
  │  or existing draft returned (idempotent)         │
  │  status: DRAFT, completedPageIds: [], index: 0   │
  └──────────────┬───────────────────────────────────┘
                 │
                 │  ┌──────────────────────────────────────────────────────────┐
                 │  │  For each page (repeat until all pages completed):       │
                 │  │                                                          │
                 │  │  [Background auto-save while typing]                     │
                 │  │  PUT /pages/{pageId}/save?moveToNextPage=false           │
                 │  │  → No validation. Saves whatever is there. Always 200.  │
                 │  │  → completedPageIds unchanged.                           │
                 │  │                                                          │
                 │  │  [User clicks "Next"]                                    │
                 │  │  PUT /pages/{pageId}/save?moveToNextPage=true            │
                 │  │       ├─ Validation FAILS → returns errors, nothing      │
                 │  │       │  saved, page stays, success: false               │
                 │  │       └─ Validation PASSES → answers saved, page        │
                 │  │          added to completedPageIds, index advances       │
                 │  └──────────────────────────────────────────────────────────┘
                 │
                 │  POST /events/{eventId}/submit
                 │       ├─ Any page NOT in completedPageIds → 422 PAGE_INCOMPLETE
                 │       └─ All pages complete + required fields present → SUBMITTED
                 ▼
  ┌──────────────────────────────────────────────────┐
  │  Response SUBMITTED                              │
  │  status: SUBMITTED, completionTimeSeconds set    │
  └──────────────────────────────────────────────────┘

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. SavePageResponse

Returned by the Save Page Answers endpoint (Endpoint 27). The shape of the response is the same whether the save succeeded or validation failed — the client always reads saved and isValid to decide what to do next.

Field Type Description
eventId UUID The event ID
saved boolean true if answers were actually written to the database. false if validation failed and nothing was saved
savedAt LocalDateTime Timestamp of the save. null when saved is false
isValid boolean true if all fields on the page passed validation. Mirrors saved
errors array / null null when isValid is true. Array of FieldValidationError when validation failed
errors[].fieldId UUID The field that failed validation
errors[].fieldLabel string Label of the failing field (e.g. "Email")
errors[].errorCode string Machine-readable error type: REQUIRED, INVALID_FORMAT, INVALID_TYPE, VALIDATION_FAILED
errors[].message string Human-readable error description (e.g. "must be valid email")

Note: totalFieldsOnPage, answeredFieldsOnPage, and overallProgress are reserved fields in the response object but are not currently populated — they will be null and omitted from the JSON (@JsonInclude(NON_NULL)).

K. 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 submitted
  • 401 UNAUTHORIZED — Missing, expired, or malformed Bearer token
  • 403 FORBIDDEN — Authenticated but not the event organizer; or registration window not open/already closed
  • 404 NOT_FOUND — Event not found, form not enabled, page/field/option not found, no response found
  • 422 UNPROCESSABLE_ENTITY — Bean validation failures; or submit called when one or more pages were not completed via ?moveToNextPage=true (PAGE_INCOMPLETE error type); or required field still unanswered at submit time (REQUIRED error type). For save validation failures (?moveToNextPage=true), the response returns HTTP 200 with success: false — not a 422 — because the client needs to display inline errors without treating it as a hard failure

Server-Level Exceptions (500+)

  • 500 INTERNAL_SERVER_ERROR — Unexpected runtime error

Shared Error Response Examples

401 — Unauthorized:

{
  "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}" with no pages. Pages are added separately by the organizer. Only the event organizer can call this. Returns the empty 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",
  "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": []
    }
  }
}

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

4. Get Full Form

Purpose: Returns the complete form structure — all pages, fields, and options — in a single call. Intended for the form builder UI to load the current state when the organizer opens the builder. Only the event organizer can call this.

Endpoint: GET /api/v1/e-events/applicant-form/events/{eventId}/full-form

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": "Form retrieved",
  "action_time": "2026-05-21T10:30:45",
  "data": {
    "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": "2026-05-21T10:30:45",
    "pages": [
      {
        "pageId": "1a2b3c4d-...",
        "title": "Personal Details",
        "description": null,
        "displayOrder": 1,
        "actionButtonText": "Next",
        "fields": [
          {
            "fieldId": "c3d4e5f6-...",
            "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": []
          },
          {
            "fieldId": "d4e5f6a7-...",
            "type": "DROPDOWN",
            "label": "T-Shirt Size",
            "displayOrder": 2,
            "required": true,
            "validation": null,
            "options": [
              { "optionId": "a1b2c3d4-...", "label": "Small (S)", "displayOrder": 1 },
              { "optionId": "b2c3d4e5-...", "label": "Medium (M)", "displayOrder": 2 }
            ]
          }
        ]
      },
      {
        "pageId": "2b3c4d5e-...",
        "title": "Dietary Requirements",
        "displayOrder": 2,
        "actionButtonText": "Submit",
        "fields": []
      }
    ]
  }
}

Success Response Fields: data is a FormResponse with all pages, fields, and options fully nested. Soft-deleted items are excluded. Pages and fields are ordered by displayOrder.

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, message is "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, and CHECKBOX fields 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 can be passed inline in the same request or added separately via the Add Option endpoint. 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 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
options array No Inline options for DROPDOWN, RADIO, CHECKBOX. Ignored for other types. Blank labels are skipped
options[].label string Yes (if options provided) Option label Max: 255 characters

Example 1 — TEXT field with validation

Request:

{
  "type": "TEXT",
  "label": "Full Name",
  "description": "As it appears on your ID.",
  "placeholder": "e.g. Amina Hassan",
  "required": true,
  "validation": {
    "minLength": 2,
    "maxLength": 100
  }
}

Response:

{
  "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": []
  }
}

Example 2 — DROPDOWN field with inline options

Request:

{
  "type": "DROPDOWN",
  "label": "T-Shirt Size",
  "description": "Select your preferred size.",
  "placeholder": "Choose a size",
  "required": true,
  "options": [
    { "label": "Small (S)" },
    { "label": "Medium (M)" },
    { "label": "Large (L)" },
    { "label": "Extra Large (XL)" }
  ]
}

Response:

{
  "success": true,
  "httpStatus": "CREATED",
  "message": "Field added",
  "action_time": "2025-02-17T10:30:45",
  "data": {
    "fieldId": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a",
    "type": "DROPDOWN",
    "label": "T-Shirt Size",
    "description": "Select your preferred size.",
    "placeholder": "Choose a size",
    "displayOrder": 2,
    "required": true,
    "validation": null,
    "options": [
      { "optionId": "a1b2c3d4-...", "label": "Small (S)", "displayOrder": 1 },
      { "optionId": "b2c3d4e5-...", "label": "Medium (M)", "displayOrder": 2 },
      { "optionId": "c3d4e5f6-...", "label": "Large (L)", "displayOrder": 3 },
      { "optionId": "d4e5f6a7-...", "label": "Extra Large (XL)", "displayOrder": 4 }
    ]
  }
}

Example 3 — RADIO field with inline options

Request:

{
  "type": "RADIO",
  "label": "What is your attendance mode?",
  "description": "Select how you will attend the event.",
  "required": true,
  "options": [
    { "label": "In Person" },
    { "label": "Online" }
  ]
}

Response:

{
  "success": true,
  "httpStatus": "CREATED",
  "message": "Field added",
  "action_time": "2025-02-17T10:30:45",
  "data": {
    "fieldId": "e5f6a7b8-c9d0-1e2f-3a4b-5c6d7e8f9a0b",
    "type": "RADIO",
    "label": "What is your attendance mode?",
    "description": "Select how you will attend the event.",
    "placeholder": null,
    "displayOrder": 3,
    "required": true,
    "validation": null,
    "options": [
      { "optionId": "e5f6a7b8-...", "label": "In Person", "displayOrder": 1 },
      { "optionId": "f6a7b8c9-...", "label": "Online", "displayOrder": 2 }
    ]
  }
}

Example 4 — CHECKBOX field with inline options and validation

Request:

{
  "type": "CHECKBOX",
  "label": "Which sessions will you attend?",
  "description": "Select all that apply. You may choose up to 3.",
  "required": false,
  "validation": {
    "minSelections": 1,
    "maxSelections": 3
  },
  "options": [
    { "label": "Morning Session (9am - 12pm)" },
    { "label": "Afternoon Session (1pm - 4pm)" },
    { "label": "Evening Session (6pm - 9pm)" }
  ]
}

Response:

{
  "success": true,
  "httpStatus": "CREATED",
  "message": "Field added",
  "action_time": "2025-02-17T10:30:45",
  "data": {
    "fieldId": "f6a7b8c9-d0e1-2f3a-4b5c-6d7e8f9a0b1c",
    "type": "CHECKBOX",
    "label": "Which sessions will you attend?",
    "description": "Select all that apply. You may choose up to 3.",
    "placeholder": null,
    "displayOrder": 4,
    "required": false,
    "validation": { "minSelections": 1, "maxSelections": 3 },
    "options": [
      { "optionId": "g7a8b9c0-...", "label": "Morning Session (9am - 12pm)", "displayOrder": 1 },
      { "optionId": "h8b9c0d1-...", "label": "Afternoon Session (1pm - 4pm)", "displayOrder": 2 },
      { "optionId": "i9c0d1e2-...", "label": "Evening Session (6pm - 9pm)", "displayOrder": 3 }
    ]
  }
}

Example 5 — HEADER field (section divider)

Request:

{
  "type": "HEADER",
  "label": "Emergency Contact Information"
}

Response:

{
  "success": true,
  "httpStatus": "CREATED",
  "message": "Field added",
  "action_time": "2025-02-17T10:30:45",
  "data": {
    "fieldId": "a0b1c2d3-e4f5-6a7b-8c9d-0e1f2a3b4c5d",
    "type": "HEADER",
    "label": "Emergency Contact Information",
    "description": null,
    "placeholder": null,
    "displayOrder": 5,
    "required": false,
    "validation": null,
    "options": []
  }
}

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 metadata of an existing field. All fields are optional. Field type cannot be changed — if a different type is needed, delete the field and create a new one. Options are managed via dedicated option endpoints. 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
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

⚠️ Note: type cannot be changed via this endpoint. Attempting to pass a different type will return a 400 error with the message: "Field type cannot be changed. Delete this field and create a new one with the correct type." To change the field type, delete this field and create a new one.

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
400 Attempting to change field type

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, message is "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. For DROPDOWN, RADIO, and CHECKBOX types, options can be passed inline per field. 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": true,
      "options": [
        { "label": "Flight" },
        { "label": "Bus" },
        { "label": "Car" }
      ]
    }
  ]
}

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
fields[].options array No Inline options for DROPDOWN, RADIO, CHECKBOX. Ignored for other types. Blank labels are skipped
fields[].options[].label string Yes (if options provided) Option label Max: 255 characters

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, message is "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


23. Get Preview Metadata

Purpose: Returns a lightweight summary of the form structure — total pages, page numbers, and titles — without loading full field data. Used by the attendee to render a progress indicator before filling. Also returns the attendee's current response state (responseId, currentPageIndex, completedPageIds) if they have an existing draft.

Endpoint: GET /api/v1/e-events/applicant-form/events/{eventId}/preview/metadata

Access Level: 🔒 Protected (Organizer always; attendee when event is PUBLISHED)

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",
  "data": {
    "formId": "uuid",
    "formTitle": "Attendee Questions - Tech Summit 2025",
    "totalPages": 3,
    "pageNumbers": [
      { "pageNumber": 1, "pageTitle": "Personal Info" },
      { "pageNumber": 2, "pageTitle": "Experience" },
      { "pageNumber": 3, "pageTitle": "Preferences" }
    ],
    "responseId": "uuid",
    "responseStatus": "DRAFT",
    "currentPageIndex": 1,
    "completedPageIds": ["page-uuid-1"]
  }
}

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

24. Preview Page by Number

Purpose: Returns a specific page by its 1-based position number, including all its active fields and options. Used by attendees to load each page as they fill the form. Also accessible to the organizer for previewing before publishing.

Endpoint: GET /api/v1/e-events/applicant-form/events/{eventId}/preview/pages/{pageNumber}

Access Level: 🔒 Protected (Organizer always; attendee when event is PUBLISHED)

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

25. 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 (Organizer always; attendee when event is PUBLISHED)

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


26. 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

27. Save Page Answers

Purpose: Saves the attendee's answers for a specific page. Behaviour is controlled by the ?moveToNextPage query parameter which maps directly to two distinct client actions — background auto-save and the "Next" button.

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

Query Parameters:

Parameter Type Required Description Default
moveToNextPage boolean No Controls validation and page advancement. See behaviour table below false

moveToNextPage Behaviour

Value Intended Use Validation What Happens on Success What Happens on Failure
false Background auto-save while the user is typing None — answers are stored as-is regardless of format or required state Answers written. completedPageIds unchanged. Always success: true N/A — cannot fail
true User clicks "Next" to advance to the next page Full — all fields on the page are validated (required + format + type) Answers written, page added to completedPageIds, currentPageIndex advances. success: true Nothing saved, nothing advanced. success: false with errors[] in data

Key rule: A page only enters completedPageIds through a successful ?moveToNextPage=true call. submit will reject the form if any page is missing from completedPageIds.

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

Example 1 — Auto-save (moveToNextPage=false)

Request:

PUT /events/{eventId}/pages/{pageId}/save?moveToNextPage=false
{
  "091467dd-50f9-413f-aa5f-0feb92682945": { "value": "Eddie Murphy" },
  "6246ef54-a1b1-4b06-bd7c-cc1bc7950b8e": { "value": "notanemail@@bad" }
}

Response — always 200 OK, always success: true, no validation applied:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Page saved",
  "action_time": "2026-05-22T14:30:00",
  "data": {
    "eventId": "d7c52ae3-627f-42b4-a069-dd7c2d7cd78c",
    "saved": true,
    "savedAt": "2026-05-22T14:30:00",
    "isValid": true,
    "errors": null
  }
}

Example 2 — User clicks "Next", validation fails (moveToNextPage=true)

Request:

PUT /events/{eventId}/pages/{pageId}/save?moveToNextPage=true
{
  "091467dd-50f9-413f-aa5f-0feb92682945": { "value": "Eddie Murphy" },
  "6246ef54-a1b1-4b06-bd7c-cc1bc7950b8e": { "value": "notanemail@@bad" },
  "956b1e2e-3e47-4ba9-8248-a6668305ca42": { "value": "" },
  "7bfb4439-1d4d-43e5-a6df-a7dba86f45ea": { "value": "Male" }
}

Response200 OK but success: false. Nothing saved. Client shows inline errors and keeps user on the same page:

{
  "success": false,
  "httpStatus": "OK",
  "message": "Validation failed",
  "action_time": "2026-05-22T14:31:00",
  "data": {
    "eventId": "d7c52ae3-627f-42b4-a069-dd7c2d7cd78c",
    "saved": false,
    "savedAt": null,
    "isValid": false,
    "errors": [
      {
        "fieldId": "6246ef54-a1b1-4b06-bd7c-cc1bc7950b8e",
        "fieldLabel": "Email",
        "errorCode": "INVALID_FORMAT",
        "message": "must be valid email"
      },
      {
        "fieldId": "956b1e2e-3e47-4ba9-8248-a6668305ca42",
        "fieldLabel": "Phone Number",
        "errorCode": "REQUIRED",
        "message": "Phone Number is required"
      }
    ]
  }
}

Example 3 — User clicks "Next", validation passes (moveToNextPage=true)

Request:

PUT /events/{eventId}/pages/{pageId}/save?moveToNextPage=true
{
  "091467dd-50f9-413f-aa5f-0feb92682945": { "value": "Eddie Murphy" },
  "6246ef54-a1b1-4b06-bd7c-cc1bc7950b8e": { "value": "graphereddy@gmail.com" },
  "956b1e2e-3e47-4ba9-8248-a6668305ca42": { "value": "0627489964" },
  "7bfb4439-1d4d-43e5-a6df-a7dba86f45ea": { "value": "Male" }
}

Response200 OK, success: true. Page written, added to completedPageIds, index advances:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Page saved",
  "action_time": "2026-05-22T14:32:00",
  "data": {
    "eventId": "d7c52ae3-627f-42b4-a069-dd7c2d7cd78c",
    "saved": true,
    "savedAt": "2026-05-22T14:32:00",
    "isValid": true,
    "errors": null
  }
}

Error Codes in errors[].errorCode

errorCode Meaning
REQUIRED Field is marked required and no value was provided
INVALID_FORMAT Value format is wrong (e.g. bad email, invalid phone pattern)
INVALID_TYPE Value is the wrong data type for the field (e.g. passing a string to a DROPDOWN expecting a UUID)
VALIDATION_FAILED Value fails a custom rule (minLength, maxLength, min, max, minSelections, etc.)

Success Response Fields: data is a SavePageResponse.

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

28. 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

29. Submit

Purpose: Finalises and submits the attendee's response. The server performs a two-stage validation before accepting: first it checks that every page is in completedPageIds (meaning the attendee clicked "Next" and passed validation for each page), then it checks that all required fields still have answers. If either check fails the response is rejected with 422 and a list of field-level errors in data. On success, status transitions to SUBMITTED and completionTimeSeconds is recorded.

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": "2026-05-22T14:35:00",
  "data": {
    "responseId": "8a067ebe-5eff-496c-a7eb-e3f8ad853b9f",
    "formId": "9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    "submittedBy": "john.doe",
    "status": "SUBMITTED",
    "completedPageIds": ["a64a2f29-428e-41fc-8d14-043841d857a2"],
    "currentPageIndex": 1,
    "startedAt": "2026-05-22T14:30:00",
    "submittedAt": "2026-05-22T14:35:00",
    "completionTimeSeconds": 312,
    "answers": [ "..." ]
  }
}

Success Response Fields: data is a FormResponseObject. data.status will be "SUBMITTED".

Error Response — page not completed via "Next" (422):

{
  "success": false,
  "httpStatus": "UNPROCESSABLE_ENTITY",
  "message": "Please complete all required pages",
  "action_time": "2026-05-22T14:34:00",
  "data": [
    {
      "pageId": "a64a2f29-428e-41fc-8d14-043841d857a2",
      "pageTitle": "Personal Info",
      "fieldId": null,
      "fieldLabel": null,
      "errorType": "PAGE_INCOMPLETE",
      "errorMessage": "Page not completed — please review all fields and click Next"
    }
  ]
}

Error Response — required field still unanswered (422):

{
  "success": false,
  "httpStatus": "UNPROCESSABLE_ENTITY",
  "message": "Please complete all required pages",
  "action_time": "2026-05-22T14:34:00",
  "data": [
    {
      "pageId": "a64a2f29-428e-41fc-8d14-043841d857a2",
      "pageTitle": "Personal Info",
      "fieldId": "956b1e2e-3e47-4ba9-8248-a6668305ca42",
      "fieldLabel": "Phone Number",
      "errorType": "REQUIRED",
      "errorMessage": "This field is required"
    }
  ]
}

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 One or more pages not in completedPageIds (PAGE_INCOMPLETE); or a required field has no answer (REQUIRED). Error list is in data[]

Organizer Response Management


30. 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

31. 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=0 is the first page), matching the Spring Pageable default 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

32. 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 (empty — no pages)
2 PUT /events/{eventId}/settings 🔒 Organizer Update form display settings
3 DELETE /events/{eventId}/disable 🔒 Organizer Disable and remove form
4 GET /events/{eventId}/full-form 🔒 Organizer Load full form (all pages + fields) for builder
Page Management
5 POST /events/{eventId}/pages 🔒 Organizer Add a page
6 PUT /events/{eventId}/pages/{pageId} 🔒 Organizer Update a page
7 DELETE /events/{eventId}/pages/{pageId}?hard=false 🔒 Organizer Delete a page (soft or hard)
8 POST /events/{eventId}/pages/bulk 🔒 Organizer Bulk add pages with fields
9 DELETE /events/{eventId}/pages/bulk?hard=false 🔒 Organizer Bulk delete pages
10 POST /events/{eventId}/pages/{pageId}/clone 🔒 Organizer Clone a page
Field Management
11 POST /events/{eventId}/pages/{pageId}/fields 🔒 Organizer Add a field to a page
12 PUT /events/{eventId}/fields/{fieldId} 🔒 Organizer Update a field
13 DELETE /events/{eventId}/fields/{fieldId}?hard=false 🔒 Organizer Delete a field (soft or hard)
14 POST /events/{eventId}/pages/{pageId}/fields/bulk 🔒 Organizer Bulk add fields
15 DELETE /events/{eventId}/pages/{pageId}/fields/bulk?hard=false 🔒 Organizer Bulk delete fields
16 PATCH /events/{eventId}/fields/bulk 🔒 Organizer Bulk update fields
17 POST /events/{eventId}/fields/{fieldId}/clone 🔒 Organizer Clone a field
Option Management
18 POST /events/{eventId}/fields/{fieldId}/options 🔒 Organizer Add option to a field
19 PUT /events/{eventId}/options/{optionId} 🔒 Organizer Update an option
20 DELETE /events/{eventId}/options/{optionId}?hard=false 🔒 Organizer Delete an option (soft or hard)
21 DELETE /events/{eventId}/fields/{fieldId}/options/bulk?hard=false 🔒 Organizer Bulk delete options
22 PATCH /events/{eventId}/options/bulk 🔒 Organizer Bulk update option labels
Preview
23 GET /events/{eventId}/preview/metadata 🔒 Organizer + Attendee* Form page metadata + attendee progress
24 GET /events/{eventId}/preview/pages/{pageNumber} 🔒 Organizer + Attendee* Load a page by number (fields + options)
25 POST /events/{eventId}/preview/pages/{pageNumber}/validate 🔒 Organizer + Attendee* Validate answers without saving
Attendee Submission
26 POST /events/{eventId}/start 🔒 Attendee Start form / get existing draft
27 PUT /events/{eventId}/pages/{pageId}/save?moveToNextPage=false 🔒 Attendee Auto-save answers (no validation)
27 PUT /events/{eventId}/pages/{pageId}/save?moveToNextPage=true 🔒 Attendee "Next" — validate page and advance if clean
28 GET /events/{eventId}/my-response 🔒 Attendee Get my response
29 POST /events/{eventId}/submit 🔒 Attendee Submit form (requires all pages completed via "Next")
Organizer — Responses & Analytics
30 GET /events/{eventId}/responses/{responseId} 🔒 Organizer Get response by ID
31 GET /events/{eventId}/responses 🔒 Organizer Get all responses (paginated)
32 GET /events/{eventId}/analytics 🔒 Organizer Get form analytics

* Attendee access to preview endpoints requires the event to be PUBLISHED.

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-DD2025-07-18
Times HH:mm18: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