Form Builder API
Base URL: https://your-api-domain.com/api/v1/forms
Short Description: The Form Builder API powers the optional custom applicant/survey form that event organizers can attach to their events on the NextGate platform. Using a multi-page, multi-field builder, organizers collect additional information from attendees beyond the standard ticket purchase flow. The form is a standalone entity — it is built independently and then linked to an event. If no form is linked, the event registration proceeds normally without a form step.
Hints:
- A form must first be created, then built (pages → fields → options), then linked to an event via the Event Core API (
POST /api/v1/e-events/draft/{eventId}/forms/{formId}). - The form feature is entirely optional. Events without a linked form proceed normally through ticket purchase.
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. - Soft delete is used throughout. Deleted pages, fields, and options are flagged with
deletedAtand excluded from live form rendering but preserved for historical response integrity via answer snapshots (fieldLabelSnapshot,fieldTypeSnapshot). - Hard delete endpoints permanently remove data and should only be used when no response history needs to be retained.
FormSettings.acceptResponses = falsetemporarily closes the form for new submissions without deleting anything.- For multi-page forms, attendees save answers page-by-page with
moveToNextPage: true. The final page triggers the separate submit call. - Pagination uses 1-based page numbers (
page=1is the first page).
Architecture Overview
CLIENT REQUEST
│
▼
┌────────────────────────────────────┐
│ FormController │ ◄─── /api/v1/forms/**
│ (REST Layer — HTTP routing) │
└──────────────────┬─────────────────┘
│
┌───────────┼───────────────────────────┐
▼ ▼ ▼ ▼
┌───────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐
│FormService│ │PageService│ │FieldSvc │ │OptionService │
│ │ │ │ │ │ │ │
│-createForm│ │-createPage│ │-createFld│ │-createOption │
│-updateForm│ │-updatePage│ │-updateFld│ │-updateOption │
│-deleteForm│ │-deletePage│ │-deleteFld│ │-deleteOption │
│-getForm │ │-reorder │ │-reorder │ │-reorder │
└─────┬─────┘ └─────┬────┘ └─────┬────┘ └────────┬─────────┘
│ │ │ │
│ ┌────────┘ │ │
│ │ ┌────────────┘ │
│ │ │ ┌──────────────────┘
▼ ▼ ▼ ▼
┌──────────────────────────────────────────────────┐
│ Repositories (Spring Data JPA) │
│ FormRepo / FormPageRepo / FormFieldRepo │
│ FieldOptionRepo / FormResponseRepo │
│ FormAnswerRepo │
└──────────────────────┬───────────────────────────┘
│
▼
┌────────────────────────────────────────────────────┐
│ DATABASE │
│ │
│ ┌──────────┐ ┌────────────┐ ┌────────────────┐ │
│ │ forms │ │ form_pages │ │ form_fields │ │
│ └──────────┘ └────────────┘ └────────────────┘ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │field_options │ │form_responses│ │
│ └──────────────┘ └──────────────┘ │
│ ┌──────────────┐ │
│ │ form_answers │ │
│ └──────────────┘ │
│ │
│ JSONB columns: │
│ forms → settings, coverPage │
│ form_fields → validation │
│ form_responses → completedPageIds │
│ form_answers → value │
└────────────────────────────────────────────────────┘
Form Data Structure
FormEntity
├── formId (UUID)
├── title / description
├── createdBy / updatedBy ──────────────────► AccountEntity
├── createdAt / updatedAt / deletedAt
│
├── settings (JSONB)
│ ├── acceptResponses (boolean)
│ ├── allowMultipleSubmissions (boolean)
│ ├── responseStartTime (Instant — UTC)
│ ├── responseDeadline (Instant — UTC)
│ └── allowSaveDraft (boolean)
│
├── coverPage (JSONB)
│ ├── enabled (boolean)
│ ├── title / description / imageUrl / buttonText
│
└── pages[] ───────────────────────────────► FormPageEntity
├── pageId / title / description
├── displayOrder / actionButtonText / deletedAt
│
└── fields[] ─────────────────────────► FormFieldEntity
├── fieldId / label / description / placeholder
├── type [ TEXT | TEXTAREA | EMAIL | PHONE |
│ NUMBER | URL | DATE | TIME | DATETIME |
│ DROPDOWN | RADIO | CHECKBOX |
│ FILE | RATING | HEADER ]
├── required (always false for HEADER)
├── displayOrder / deletedAt
├── validation (JSONB)
│ ├── minLength / maxLength / pattern / patternMessage
│ ├── min / max (NUMBER)
│ ├── minDate / maxDate (DATE)
│ ├── minSelections / maxSelections (CHECKBOX)
│ └── maxSizeMb / accept (FILE)
│
└── options[] ────────────────────► FieldOptionEntity
(DROPDOWN, RADIO, CHECKBOX only)
├── optionId / label / displayOrder / deletedAt
Form-to-Event Relationship
EventEntity (Event Core domain)
│
│ POST /api/v1/e-events/draft/{eventId}/forms/{formId}
│ (Link endpoint — lives in Event Core API)
│
└──────────► FormEntity (Form Builder domain)
│
└── If linked: attendees fill this form
after acquiring a ticket.
If not linked: no form step.
Form Builder Workflow (Organizer)
[Organizer]
│
│ POST /forms
▼
┌──────────────────┐
│ CREATE FORM │ title, settings, coverPage
└────────┬─────────┘
│
│ POST /forms/{formId}/pages
│ (or bulk: POST /forms/{formId}/pages/bulk)
▼
┌──────────────────┐
│ ADD PAGES │ title, actionButtonText, displayOrder
└────────┬─────────┘
│
│ POST /forms/{formId}/pages/{pageId}/fields
│ (or bulk: POST /forms/{formId}/pages/{pageId}/fields/bulk)
▼
┌──────────────────────────────────────────────────┐
│ ADD FIELDS (per page) │
│ TEXT / TEXTAREA / EMAIL / PHONE / NUMBER │
│ URL / DATE / TIME / DATETIME / RATING / FILE │
│ HEADER (display only — no answer stored) │
│ DROPDOWN / RADIO / CHECKBOX ──► needs options │
└────────┬─────────────────────────────────────────┘
│
│ (DROPDOWN / RADIO / CHECKBOX only)
│ POST /forms/fields/{fieldId}/options
▼
┌──────────────────┐
│ ADD OPTIONS │
└────────┬─────────┘
│
│ (Link to event via Event Core API)
│ POST /api/v1/e-events/draft/{eventId}/forms/{formId}
▼
┌─────────────────────────────────┐
│ FORM ATTACHED TO EVENT │
└─────────────────────────────────┘
Attendee Response Journey
[Attendee acquires ticket]
│
│ POST /forms/{formId}/responses/start
▼
┌──────────────────────────────┐
│ Response Created (DRAFT) │ currentPageIndex: 0
└──────────────┬───────────────┘
│
│ PUT /forms/responses/{responseId}/pages
│ { pageId, answers: { fieldId: value }, moveToNextPage: true }
│ (repeated for each page)
▼
┌──────────────────────────────┐
│ Page Answers Saved │ Validation runs on each save.
│ (repeat per page) │ currentPageIndex advances on moveToNextPage.
└──────────────┬───────────────┘
│
│ POST /forms/responses/{responseId}/submit
▼
┌──────────────────────────────┐
│ Response SUBMITTED │ completionTimeSeconds auto-calculated.
└──────────────────────────────┘
Response Status Flow
DRAFT ──────────────────────────────► SUBMITTED
│ │
│ (withdraw) │ (organizer action)
▼ ▼
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 - PATCH — Orange (
#fd7e14) — Partial update - DELETE — Red (
#dc3545) — Remove resource - PUT — Yellow (
#ffc107, black text) — Replace / full update
Shared Response Object Definitions
The following objects are returned by multiple endpoints. Defined once here and referenced throughout.
A. FormResponse (Full Form Object)
| Field | Type | Description |
|---|---|---|
formId |
UUID | Unique form identifier |
title |
string | Form title |
description |
string | Form description |
settings.acceptResponses |
boolean | Whether the form is accepting new responses |
settings.allowMultipleSubmissions |
boolean | Whether a user can submit more than once |
settings.responseStartTime |
Instant | ISO 8601 UTC — when responses open |
settings.responseDeadline |
Instant | ISO 8601 UTC — when responses close |
settings.allowSaveDraft |
boolean | Whether respondents can save progress mid-form |
coverPage.enabled |
boolean | Whether a cover page is shown before the form |
coverPage.title |
string | Cover page heading |
coverPage.description |
string | Cover page body text |
coverPage.imageUrl |
string | Cover page image URL |
coverPage.buttonText |
string | CTA button label (e.g., "Start Application") |
createdBy |
string | Username of the form creator |
createdAt |
LocalDateTime | Creation timestamp |
updatedBy |
string | Username of last editor |
updatedAt |
LocalDateTime | Last update timestamp |
pages[] |
array | Ordered list of PageResponse objects (soft-deleted excluded) |
B. PageResponse
| Field | Type | Description |
|---|---|---|
pageId |
UUID | Page identifier |
title |
string | Page heading shown to respondent |
description |
string | Subheading or instruction text |
displayOrder |
integer | 1-based position within the form |
actionButtonText |
string | Label for the page's next/submit button |
fields[] |
array | Ordered list of FieldResponse objects (soft-deleted excluded) |
C. FieldResponse
| Field | Type | Description |
|---|---|---|
fieldId |
UUID | Field identifier |
type |
string | See FieldType enum values below |
label |
string | Field label (or section heading for HEADER type) |
description |
string | Helper text shown below the field |
placeholder |
string | Input placeholder text |
displayOrder |
integer | 1-based position within the page |
required |
boolean | Whether the field must be answered. Always false for HEADER |
validation |
object | See FieldValidation definition below |
options[] |
array | OptionResponse entries — only present for DROPDOWN, RADIO, CHECKBOX |
FieldType Enum Values
| Value | Description |
|---|---|
TEXT |
Single-line text input |
TEXTAREA |
Multi-line text input |
EMAIL |
Email address — validated against email format |
PHONE |
Phone number — validated against +?[0-9]{10,15} |
NUMBER |
Numeric input |
URL |
URL input — validated against https?://... pattern |
DATE |
Date picker — value format YYYY-MM-DD |
TIME |
Time picker — value format HH:mm |
DATETIME |
Date and time — value format ISO 8601 datetime |
DROPDOWN |
Single-select from a list of options |
RADIO |
Single-select radio buttons |
CHECKBOX |
Multi-select checkboxes |
FILE |
File upload |
RATING |
Star rating — integer value 1–5 |
HEADER |
Display-only section divider — no answer stored |
FieldValidation Object
| Field | Type | Applicable To | Description |
|---|---|---|---|
minLength |
integer | TEXT, TEXTAREA |
Minimum character count |
maxLength |
integer | TEXT, TEXTAREA |
Maximum character count |
pattern |
string | TEXT |
Regex pattern the value must match |
patternMessage |
string | TEXT |
Custom error message when pattern fails |
min |
double | NUMBER |
Minimum numeric value |
max |
double | NUMBER |
Maximum numeric value |
minDate |
string | DATE |
Earliest allowed date (YYYY-MM-DD) |
maxDate |
string | DATE |
Latest allowed date (YYYY-MM-DD) |
minSelections |
integer | CHECKBOX |
Minimum number of boxes to check |
maxSelections |
integer | CHECKBOX |
Maximum number of boxes to check |
maxSizeMb |
integer | FILE |
Maximum file size in megabytes |
accept |
string | FILE |
Accepted MIME types (e.g., image/*,application/pdf) |
D. OptionResponse
| Field | Type | Description |
|---|---|---|
optionId |
UUID | Option identifier |
label |
string | Display label shown to respondent |
displayOrder |
integer | 1-based position within the field |
E. FormResponseObject (Respondent Submission)
| Field | Type | Description |
|---|---|---|
responseId |
UUID | Unique response identifier |
formId |
UUID | The form this response belongs to |
submittedBy |
string | Username of the respondent |
status |
string | DRAFT, SUBMITTED, UNDER_REVIEW, APPROVED, REJECTED, WITHDRAWN |
completedPageIds |
array | UUIDs of pages the respondent has completed |
currentPageIndex |
integer | 0-based index of the current page |
startedAt |
LocalDateTime | When the respondent 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 | ID of the field answered (null if field was hard-deleted) |
fieldLabel |
string | Snapshot of the field label at time of answering — preserved even if field is later deleted |
fieldType |
string | Snapshot of the field type — preserved even if field is later deleted |
fieldDeleted |
boolean | true when the source field has been soft-deleted |
value |
any | The submitted value. Type varies: string for text/choice fields, number for NUMBER/RATING, array of UUID strings for CHECKBOX |
answeredAt |
LocalDateTime | When this answer was saved |
fileUrl |
string | Uploaded file URL (FILE fields only) |
fileName |
string | Original file name (FILE fields only) |
fileSize |
long | File size in bytes (FILE fields only) |
fileType |
string | MIME type (FILE fields only) |
F. BulkOperationResult
| Field | Type | Description |
|---|---|---|
successCount |
integer | Number of items successfully processed |
failureCount |
integer | Number of items that failed |
errors[] |
array | Error messages for each failed item |
createdFields[] |
array | FieldResponse objects (bulk field create only) |
createdPages[] |
array | PageResponse objects (bulk page create only) |
G. BulkDeleteResult
| Field | Type | Description |
|---|---|---|
successCount |
integer | Number of items successfully deleted |
failureCount |
integer | Number of items that failed |
errors[] |
array | Error messages for each failed item |
deletedIds[] |
array | UUIDs of successfully deleted items |
Standard Error Types
Application-Level Exceptions (400–499)
400 BAD_REQUEST— Field type does not support options, form is not accepting responses, user already submitted, reorder size mismatch401 UNAUTHORIZED— Missing, expired, or malformed Bearer token403 FORBIDDEN— Authenticated but not the form owner404 NOT_FOUND— Form, page, field, option, or response not found or has been deleted422 UNPROCESSABLE_ENTITY— Bean validation failures with per-field detail
Server-Level Exceptions (500+)
500 INTERNAL_SERVER_ERROR— Unexpected runtime error
Shared Error Response Examples
All endpoints may return these shapes. Endpoint sections reference them by name rather than repeating the full JSON.
{
"success": false,
"httpStatus": "UNAUTHORIZED",
"message": "Token has expired",
"action_time": "2025-02-17T10:30:45",
"data": "Token has expired"
}
403 — Forbidden:
{
"success": false,
"httpStatus": "FORBIDDEN",
"message": "Access denied: Insufficient permissions",
"action_time": "2025-02-17T10:30:45",
"data": "Access denied: Insufficient permissions"
}
404 — Not Found:
{
"success": false,
"httpStatus": "NOT_FOUND",
"message": "Form not found with ID: 9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"action_time": "2025-02-17T10:30:45",
"data": "Form not found with ID: 9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c"
}
422 — Validation Error:
{
"success": false,
"httpStatus": "UNPROCESSABLE_ENTITY",
"message": "Validation failed",
"action_time": "2025-02-17T10:30:45",
"data": {
"title": "must not be blank"
}
}
Endpoints
1. Create Form
Purpose: Creates a new blank form. The form is standalone at this point — pages and fields are added separately, and the form is linked to an event via the Event Core API once ready.
Endpoint: POST /api/v1/forms
Access Level: 🔒 Protected (Any authenticated user — becomes form owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Request JSON Sample:
{
"title": "Jazz Festival 2025 — Attendee Registration",
"description": "Please fill in this form to complete your event registration.",
"settings": {
"acceptResponses": true,
"allowMultipleSubmissions": false,
"responseStartTime": "2025-05-01T00:00:00Z",
"responseDeadline": "2025-07-17T23:59:00Z",
"allowSaveDraft": true
},
"coverPage": {
"enabled": true,
"title": "Welcome to Jazz Fest 2025",
"description": "Please take a few minutes to complete your registration.",
"imageUrl": "https://cdn.example.com/banners/jazz-2025.jpg",
"buttonText": "Start Registration"
}
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
title |
string | Yes | Form title | Max: 255 characters |
description |
string | No | Form description | Max: 1000 characters |
settings |
object | No | Form behaviour settings | All sub-fields optional |
settings.acceptResponses |
boolean | No | Open (true) or close (false) the form |
Defaults to true |
settings.allowMultipleSubmissions |
boolean | No | Allow same user to submit more than once | Defaults to false |
settings.responseStartTime |
Instant | No | UTC datetime when the form opens | ISO 8601 UTC |
settings.responseDeadline |
Instant | No | UTC datetime when the form closes | ISO 8601 UTC |
settings.allowSaveDraft |
boolean | No | Let respondents save progress mid-form | Defaults to false |
coverPage |
object | No | Cover page shown before the first form page | All sub-fields optional |
coverPage.enabled |
boolean | No | Show or hide the cover page | Defaults to false |
coverPage.title |
string | No | Cover page heading | — |
coverPage.description |
string | No | Cover page body text | — |
coverPage.imageUrl |
string | No | Cover page image URL | — |
coverPage.buttonText |
string | No | CTA button label (e.g., "Start Registration") | — |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "CREATED",
"message": "Form created",
"action_time": "2025-02-17T10:30:45",
"data": {
"formId": "9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"title": "Jazz Festival 2025 — Attendee Registration",
"description": "Please fill in this form to complete your event registration.",
"settings": {
"acceptResponses": true,
"allowMultipleSubmissions": false,
"responseStartTime": "2025-05-01T00:00:00Z",
"responseDeadline": "2025-07-17T23:59:00Z",
"allowSaveDraft": true
},
"coverPage": {
"enabled": true,
"title": "Welcome to Jazz Fest 2025",
"description": "Please take a few minutes to complete your registration.",
"imageUrl": "https://cdn.example.com/banners/jazz-2025.jpg",
"buttonText": "Start Registration"
},
"createdBy": "amina.hassan",
"createdAt": "2025-02-17T10:30:45",
"updatedBy": null,
"updatedAt": null,
"pages": []
}
}
Success Response Fields: data is a FormResponse. pages is empty until pages are added.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token — see Shared Error: 401 |
422 |
title is blank or exceeds 255 characters — see Shared Error: 422 |
2. Get Form by ID
Purpose: Retrieves the full form including all active pages, fields, and options. Soft-deleted pages, fields, and options are automatically excluded.
Endpoint: GET /api/v1/forms/{formId}
Access Level: 🔒 Protected (Form owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
formId |
UUID | Yes | The form to retrieve | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form retrieved",
"action_time": "2025-02-17T10:30:45",
"data": { "...": "Full FormResponse object" }
}
Success Response Fields: data is a full FormResponse.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form not found or has been deleted |
3. Update Form
Purpose: Updates form metadata and/or settings. All fields are optional — only provided fields are changed.
Endpoint: PATCH /api/v1/forms/{formId}
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
formId |
UUID | Yes | The form to update | Must be a valid UUID |
Request JSON Sample:
{
"title": "Jazz Festival 2025 — Updated Registration",
"settings": {
"acceptResponses": false
}
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
title |
string | No | Updated form title | Max: 255 characters |
description |
string | No | Updated description | Max: 1000 characters |
settings |
object | No | Settings to update (full object replacement) | See Endpoint 1 |
coverPage |
object | No | Cover page to update (full object replacement) | See Endpoint 1 |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form updated",
"action_time": "2025-02-17T10:30:45",
"data": { "...": "Full FormResponse object" }
}
Success Response Fields: data is a full FormResponse.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form not found |
422 |
Title exceeds 255 characters |
4. Delete Form
Purpose: Soft-deletes a form. The form is flagged as deleted and no longer accessible for new responses. Existing submitted responses are preserved. This action does not physically remove any data.
Endpoint: DELETE /api/v1/forms/{formId}
Access Level: 🔒 Protected (Form owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
formId |
UUID | Yes | The form to delete | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form deleted",
"action_time": "2025-02-17T10:30:45",
"data": null
}
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form not found |
Page Management Endpoints
5. Add Page to Form
Purpose: Appends a new blank page to the form. displayOrder is auto-assigned as the next available position. Fields are added to the page separately.
Endpoint: POST /api/v1/forms/{formId}/pages
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
formId |
UUID | Yes | The form to add a page to | Must be a valid UUID |
Request JSON Sample:
{
"title": "Personal Information",
"description": "Tell us a bit about yourself.",
"actionButtonText": "Next"
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
title |
string | Yes | Page heading shown to respondent | 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 created",
"action_time": "2025-02-17T10:30:45",
"data": {
"pageId": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"title": "Personal Information",
"description": "Tell us a bit about yourself.",
"displayOrder": 1,
"actionButtonText": "Next",
"fields": []
}
}
Success Response Fields: data is a PageResponse. fields is empty until fields are added.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form not found |
422 |
title is blank |
6. Update Page
Purpose: Updates the title, description, or action button label of a page. All fields are optional.
Endpoint: PATCH /api/v1/forms/pages/{pageId}
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
pageId |
UUID | Yes | The page to update | Must be a valid UUID |
Request JSON Sample:
{
"title": "About You",
"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 |
404 |
Page not found |
7. Delete Page
Purpose: Soft-deletes a page. All fields within the page are also soft-deleted. Existing answer snapshots for fields on this page are preserved.
Endpoint: DELETE /api/v1/forms/pages/{pageId}
Access Level: 🔒 Protected (Form owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
pageId |
UUID | Yes | The page to delete | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Page deleted",
"action_time": "2025-02-17T10:30:45",
"data": null
}
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Page not found |
8. Reorder Pages
Purpose: Reassigns the displayOrder of all active pages within a form. The array position determines the new order — the first ID in the array becomes order 1. The request must include all active page IDs.
Endpoint: POST /api/v1/forms/{formId}/pages/reorder
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
formId |
UUID | Yes | The form whose pages to reorder | Must be a valid UUID |
Request JSON Sample:
{
"orderedIds": [
"3rd-page-uuid",
"1st-page-uuid",
"2nd-page-uuid"
]
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
orderedIds |
array | Yes | All active page UUIDs in desired display order | Must contain every active page — no extras, no omissions |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Pages reordered",
"action_time": "2025-02-17T10:30:45",
"data": null
}
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form or a page ID not found |
400 |
Array length does not match the number of active pages in the form |
9. Bulk Create Pages (with Fields)
Purpose: Creates multiple pages in a single call. Each page can optionally include an inline list of fields, which is useful when building a complete form from scratch without separate field creation calls.
Endpoint: POST /api/v1/forms/{formId}/pages/bulk
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
formId |
UUID | Yes | The form to add pages to | Must be a valid UUID |
Request JSON Sample:
{
"pages": [
{
"title": "Personal Information",
"description": "Tell us about yourself.",
"actionButtonText": "Next",
"fields": [
{
"type": "TEXT",
"label": "Full Name",
"required": true,
"validation": { "minLength": 2, "maxLength": 100 }
},
{
"type": "EMAIL",
"label": "Email Address",
"required": true
}
]
},
{
"title": "Preferences",
"actionButtonText": "Submit",
"fields": [
{
"type": "DROPDOWN",
"label": "How did you hear about us?",
"required": false
}
]
}
]
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
pages |
array | Yes | List of 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 on this page | 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. Forced false for HEADER type |
pages[].fields[].validation |
object | No | Validation rules | See FieldValidation definition |
Note: For
DROPDOWN,RADIO, andCHECKBOXfields created via bulk, options must still be added separately using the option endpoints after the bulk creation call completes.
Success Response JSON Sample:
{
"success": true,
"httpStatus": "CREATED",
"message": "Bulk pages created",
"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. data.createdPages[] contains PageResponse objects.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form not found |
422 |
A page title is blank — the failing page is reported in errors[], others still succeed |
10. Bulk Delete Pages
Purpose: Soft-deletes multiple pages from a form in one call. Items are processed individually — a failure on one page does not stop the others.
Endpoint: DELETE /api/v1/forms/{formId}/pages/bulk
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
formId |
UUID | Yes | The form containing the pages | Must be a valid UUID |
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": "Bulk pages deleted",
"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 |
404 |
Form not found. Individual page ID errors are reported in data.errors[] rather than failing the whole request |
11. 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/forms/pages/{pageId}/clone
Access Level: 🔒 Protected (Form owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
pageId |
UUID | Yes | The page to clone | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "CREATED",
"message": "Page cloned",
"action_time": "2025-02-17T10:30:45",
"data": { "...": "PageResponse for the cloned page" }
}
Success Response Fields: data is a PageResponse for the newly created clone.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Page not found |
12. Get Page by Number
Purpose: Retrieves a specific page by its 1-based position number within the form. Useful for rendering the form page-by-page without knowing individual page IDs.
Endpoint: GET /api/v1/forms/{formId}/pages/preview/{pageNumber}
Access Level: 🔒 Protected (Form owner or authenticated respondent)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
formId |
UUID | Yes | The form | Must be a valid UUID |
pageNumber |
integer | Yes | 1-based page position | Must be between 1 and total active pages |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "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 |
404 |
Form not found, or pageNumber is out of range |
13. Get Form Page Metadata
Purpose: Returns a lightweight summary of all pages in the form — page count, page numbers, and titles — without the full field data. Used to render a progress bar or page navigator before loading individual pages.
Endpoint: GET /api/v1/forms/{formId}/pages/metadata
Access Level: 🔒 Protected (Form owner or authenticated respondent)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
formId |
UUID | Yes | The form to get metadata for | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form metadata retrieved",
"action_time": "2025-02-17T10:30:45",
"data": {
"formId": "9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"formTitle": "Jazz Festival 2025 — Attendee Registration",
"totalPages": 3,
"pageNumbers": [
{ "pageNumber": 1, "pageTitle": "Personal Information" },
{ "pageNumber": 2, "pageTitle": "Event Preferences" },
{ "pageNumber": 3, "pageTitle": "Consent & Submission" }
]
}
}
Success Response Fields:
| Field | Description |
|---|---|
formId |
Form UUID |
formTitle |
Form title |
totalPages |
Total number of active pages |
pageNumbers[].pageNumber |
1-based page number |
pageNumbers[].pageTitle |
Page heading |
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form not found |
Field Management Endpoints
14. Add Field to Page
Purpose: Adds a single field to an existing page. displayOrder is auto-assigned as the next position. For DROPDOWN, RADIO, and CHECKBOX types, options must be added separately after the field is created.
Endpoint: POST /api/v1/forms/{formId}/pages/{pageId}/fields
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
formId |
UUID | Yes | The parent form | 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": "Enter your full name",
"required": true,
"validation": {
"minLength": 2,
"maxLength": 100
}
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
type |
string | Yes | Field type | See FieldType enum |
label |
string | Yes | Field label shown to respondent. For HEADER, this is the section title |
Max: 255 characters |
description |
string | No | Helper text shown below the field | Max: 500 characters |
placeholder |
string | No | Placeholder text for input fields | Max: 255 characters |
required |
boolean | No | Whether the field must be answered | Defaults to false. Forced false for HEADER type |
validation |
object | No | Validation constraints | See FieldValidation definition |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "CREATED",
"message": "Field created",
"action_time": "2025-02-17T10:30:45",
"data": {
"fieldId": "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d",
"type": "TEXT",
"label": "Full Name",
"description": "As it appears on your ID.",
"placeholder": "Enter your full name",
"displayOrder": 1,
"required": true,
"validation": {
"minLength": 2,
"maxLength": 100
},
"options": []
}
}
Success Response Fields: data is a FieldResponse. options is always empty at creation — add them separately for choice types.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form or page not found |
422 |
type is null, or label is blank for non-HEADER types |
15. Update Field
Purpose: Updates the configuration of an existing field. All fields are optional — only provided values are changed.
Endpoint: PATCH /api/v1/forms/fields/{fieldId}
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
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 field type is HEADER |
validation |
object | No | Updated validation rules (full replacement) | See FieldValidation definition |
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 |
404 |
Field not found |
16. Delete Field
Purpose: Soft-deletes a field. The field is hidden from the live form but existing answer snapshots that reference it are preserved.
Endpoint: DELETE /api/v1/forms/fields/{fieldId}
Access Level: 🔒 Protected (Form owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
fieldId |
UUID | Yes | The field to delete | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Field deleted",
"action_time": "2025-02-17T10:30:45",
"data": null
}
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Field not found |
17. Reorder Fields
Purpose: Reassigns the displayOrder of all active fields within a page. The array position determines the new order. The request must include all active field IDs for the page.
Endpoint: POST /api/v1/forms/{formId}/pages/{pageId}/fields/reorder
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
formId |
UUID | Yes | The parent form | Must be a valid UUID |
pageId |
UUID | Yes | The page whose fields to reorder | Must be a valid UUID |
Request JSON Sample:
{
"orderedIds": [
"fieldId-3",
"fieldId-1",
"fieldId-2"
]
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
orderedIds |
array | Yes | All active field UUIDs in desired order | Must contain every active field on the page |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Fields reordered",
"action_time": "2025-02-17T10:30:45",
"data": null
}
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form, page, or a field ID not found |
400 |
Array length does not match the number of active fields on the page |
18. Bulk Create Fields
Purpose: Adds multiple fields to a page in one call. Fields are appended after existing fields in array order.
Endpoint: POST /api/v1/forms/{formId}/pages/{pageId}/fields/bulk
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
formId |
UUID | Yes | The parent form | 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": "Emergency Contact"
}
]
}
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 | Input placeholder | Max: 255 characters |
fields[].required |
boolean | No | Required flag | Defaults to false |
fields[].validation |
object | No | Validation rules | See FieldValidation definition |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "CREATED",
"message": "Bulk fields created",
"action_time": "2025-02-17T10:30:45",
"data": {
"successCount": 3,
"failureCount": 0,
"errors": [],
"createdFields": [
{ "...": "FieldResponse" },
{ "...": "FieldResponse" },
{ "...": "FieldResponse" }
]
}
}
Success Response Fields: data is a BulkOperationResult.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form or page not found |
422 |
A field has a null type — reported in errors[], others still succeed |
19. Bulk Delete Fields
Purpose: Soft-deletes multiple fields from a page in one call. Failures on individual IDs are reported without stopping the rest.
Endpoint: DELETE /api/v1/forms/{formId}/pages/{pageId}/fields/bulk
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
formId |
UUID | Yes | The parent form | Must be a valid UUID |
pageId |
UUID | Yes | The page containing the fields | Must be a valid UUID |
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": "Bulk fields deleted",
"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:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form or page not found. Individual field errors in data.errors[] |
20. Bulk Update Fields
Purpose: Updates the required flag and/or validation rules across multiple fields at once. Useful for applying consistent constraints to a group of fields without separate PATCH calls.
Endpoint: PATCH /api/v1/forms/fields/bulk-update
Access Level: 🔒 Protected (Form owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Request JSON Sample:
{
"fieldIds": ["fieldId-1", "fieldId-2", "fieldId-3"],
"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 applied to all listed fields (full replacement) | See FieldValidation definition |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Fields updated",
"action_time": "2025-02-17T10:30:45",
"data": {
"successCount": 3,
"failureCount": 0,
"errors": [],
"createdFields": [
{ "...": "Updated FieldResponse" },
{ "...": "Updated FieldResponse" },
{ "...": "Updated FieldResponse" }
]
}
}
Success Response Fields: data is a BulkOperationResult. createdFields contains the updated field objects.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
One or more field IDs not found — reported individually in errors[] |
21. Clone Field
Purpose: Creates a copy of a field (and its options if applicable) and appends it to a target page. The clone label has "(Copy)" appended.
Endpoint: POST /api/v1/forms/fields/{fieldId}/clone
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
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",
"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 |
404 |
Field or target page not found |
Option Management Endpoints
22. Add Option to Field
Purpose: Adds a single choice option to a DROPDOWN, RADIO, or CHECKBOX field. Options are appended in order and assigned the next available displayOrder. Calling this on a field type that does not support options (e.g., TEXT, EMAIL) returns a 400.
Endpoint: POST /api/v1/forms/fields/{fieldId}/options
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
fieldId |
UUID | Yes | The field to add an option to | Must be a valid UUID; field type must be DROPDOWN, RADIO, or CHECKBOX |
Request JSON Sample:
{
"label": "Social Media"
}
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 created",
"action_time": "2025-02-17T10:30:45",
"data": {
"optionId": "b2c3d4e5-f6a7-8b9c-0d1e-2f3a4b5c6d7e",
"label": "Social Media",
"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 |
404 |
Field not found |
422 |
label is blank |
23. Update Option
Purpose: Updates the label of an existing option.
Endpoint: PATCH /api/v1/forms/options/{optionId}
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
optionId |
UUID | Yes | The option to update | Must be a valid UUID |
Request JSON Sample:
{
"label": "Word of Mouth"
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
label |
string | No | Updated option label | Max: 255 characters |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Option updated",
"action_time": "2025-02-17T10:30:45",
"data": {
"optionId": "b2c3d4e5-f6a7-8b9c-0d1e-2f3a4b5c6d7e",
"label": "Word of Mouth",
"displayOrder": 1
}
}
Success Response Fields: data is an OptionResponse.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Option not found |
24. Delete Option
Purpose: Soft-deletes a single option. The option is hidden from the live form. Previously selected responses that referenced this option are preserved via the answer value snapshot.
Endpoint: DELETE /api/v1/forms/options/{optionId}
Access Level: 🔒 Protected (Form owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
optionId |
UUID | Yes | The option to delete | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Option deleted",
"action_time": "2025-02-17T10:30:45",
"data": null
}
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Option not found |
25. Reorder Options
Purpose: Reassigns the displayOrder of all active options within a field. The request must include all active option IDs for that field.
Endpoint: POST /api/v1/forms/fields/{fieldId}/options/reorder
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
fieldId |
UUID | Yes | The field whose options to reorder | Must be a valid UUID |
Request JSON Sample:
{
"orderedIds": [
"optionId-3",
"optionId-1",
"optionId-2"
]
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
orderedIds |
array | Yes | All active option UUIDs in desired order | Must match total active option count |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Options reordered",
"action_time": "2025-02-17T10:30:45",
"data": null
}
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Field or an option ID not found |
400 |
Array length does not match the number of active options |
26. Bulk Delete Options
Purpose: Soft-deletes multiple options from a field in one call.
Endpoint: DELETE /api/v1/forms/fields/{fieldId}/options/bulk
Access Level: 🔒 Protected (Form 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 |
|---|---|---|---|---|
fieldId |
UUID | Yes | The field containing the options | Must be a valid UUID |
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": "Bulk options deleted",
"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 |
404 |
Field not found. Individual option errors in data.errors[] |
27. Bulk Update Options
Purpose: Updates the labels of multiple options across one or more fields in a single call.
Endpoint: PATCH /api/v1/forms/options/bulk-update
Access Level: 🔒 Protected (Form owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Content-Type |
string | Yes | application/json |
Request JSON Sample:
{
"options": [
{ "optionId": "optionId-1", "label": "Instagram" },
{ "optionId": "optionId-2", "label": "Facebook" }
]
}
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 for this option | Max: 255 characters |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Options updated",
"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 |
404 |
An option ID not found — reported in errors[] |
Response & Submission Endpoints
28. Start Form (Create Draft Response)
Purpose: Initiates a new form response session for the authenticated user. Creates a DRAFT response linked to the form. Must be called before saving any page answers. Validates that the form is accepting responses and, if allowMultipleSubmissions is false, that the user has not already submitted.
Endpoint: POST /api/v1/forms/{formId}/responses/start
Access Level: 🔒 Protected (Authenticated attendee)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
formId |
UUID | Yes | The form to start a response for | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "CREATED",
"message": "Response started",
"action_time": "2025-02-17T10:30:45",
"data": {
"responseId": "c3d4e5f6-a7b8-9c0d-1e2f-3a4b5c6d7e8f",
"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.
Error Response Example (form closed):
{
"success": false,
"httpStatus": "BAD_REQUEST",
"message": "Form is not accepting responses",
"action_time": "2025-02-17T10:30:45",
"data": "Form is not accepting responses"
}
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form not found |
400 |
Form is not accepting responses (acceptResponses = false), or user has already submitted and allowMultipleSubmissions = false |
29. Save Page Answers
Purpose: Saves the respondent's answers for a specific page. Can be called multiple times per page — each call replaces previous answers for that page. When moveToNextPage is true, field validation is enforced, the page is marked complete, and currentPageIndex advances.
Endpoint: PUT /api/v1/forms/responses/{responseId}/pages
Access Level: 🔒 Protected (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 |
|---|---|---|---|---|
responseId |
UUID | Yes | The draft response to save answers into | Must be a valid UUID; status must be DRAFT |
Request JSON Sample:
{
"pageId": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"answers": {
"fieldId-fullname": { "value": "Amina Hassan" },
"fieldId-email": { "value": "amina@example.com" },
"fieldId-howheard": {
"value": "optionId-socialmedia"
},
"fieldId-file": {
"value": null,
"fileUrl": "https://cdn.example.com/uploads/id-amina.pdf",
"fileName": "national-id.pdf",
"fileSize": 204800,
"fileType": "application/pdf"
}
},
"moveToNextPage": true
}
Request Body Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
pageId |
UUID | Yes | The page being answered | Must be a valid UUID belonging to this form |
answers |
object | No | Map of fieldId → AnswerValue. Keys are field UUIDs |
— |
answers[fieldId].value |
any | Conditional | The answer value. Required if the field is marked required and moveToNextPage = true. Type depends on field type — see value type table below |
— |
answers[fieldId].fileUrl |
string | No | Uploaded file URL (FILE fields) | — |
answers[fieldId].fileName |
string | No | Original file name (FILE fields) | — |
answers[fieldId].fileSize |
long | No | File size in bytes (FILE fields) | — |
answers[fieldId].fileType |
string | No | MIME type (FILE fields) | — |
moveToNextPage |
boolean | No | When true, validates required fields and advances currentPageIndex |
Defaults to false |
Answer Value Types by Field Type
| Field Type | Expected Value Format |
|---|---|
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 the selected option |
CHECKBOX |
Array of strings — UUIDs of selected options |
RATING |
Integer — 1 to 5 |
FILE |
null (file metadata goes in fileUrl, fileName, etc.) |
HEADER |
No answer expected — skip this field ID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Page answers saved",
"action_time": "2025-02-17T10:30:45",
"data": null
}
Error Response Sample (validation failure):
{
"success": false,
"httpStatus": "UNPROCESSABLE_ENTITY",
"message": "Validation failed",
"action_time": "2025-02-17T10:30:45",
"data": {
"errors": [
{
"pageId": "1a2b3c4d-...",
"pageTitle": "Personal Information",
"fieldId": "fieldId-fullname",
"fieldLabel": "Full Name",
"errorMessage": "Full Name is required",
"errorType": "REQUIRED"
}
]
}
}
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Response or page not found |
400 |
Response status is not DRAFT |
422 |
Required field missing or value fails validation when moveToNextPage = true |
30. Submit Form Response
Purpose: Finalises and submits the response. The system validates that all required pages have been completed before allowing submission. Sets status to SUBMITTED and records completionTimeSeconds. A response can only be submitted once.
Endpoint: POST /api/v1/forms/responses/{responseId}/submit
Access Level: 🔒 Protected (Response owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
responseId |
UUID | Yes | The draft response to submit | Must be a valid UUID; status must be DRAFT |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Form submitted successfully",
"action_time": "2025-02-17T10:30:45",
"data": null
}
Error Response Sample (incomplete required page):
{
"success": false,
"httpStatus": "UNPROCESSABLE_ENTITY",
"message": "Please complete all required pages",
"action_time": "2025-02-17T10:30:45",
"data": {
"errors": [
{
"pageId": "...",
"pageTitle": "Event Preferences",
"fieldId": "...",
"fieldLabel": "T-Shirt Size",
"errorMessage": "This field is required",
"errorType": "REQUIRED"
}
]
}
}
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Response not found |
400 |
Response is already submitted (status is not DRAFT) |
422 |
One or more required pages have unanswered required fields |
31. Get Response by ID
Purpose: Retrieves a single response with all answers. Includes answer snapshots so deleted fields are still readable.
Endpoint: GET /api/v1/forms/responses/{responseId}
Access Level: 🔒 Protected (Response owner or form owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
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 |
404 |
Response not found or deleted |
32. Get My Response
Purpose: Returns the authenticated user's response for a specific form. Useful for respondents who want to check their submission status or review their answers.
Endpoint: GET /api/v1/forms/{formId}/responses/mine
Access Level: 🔒 Protected (Authenticated respondent)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
formId |
UUID | Yes | The form to look up the response for | 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 user on this form |
33. Get Page Completion Progress
Purpose: Returns a per-page breakdown of how far the respondent has progressed — which pages are complete, how many fields each page has, and how many have been answered.
Endpoint: GET /api/v1/forms/responses/{responseId}/progress
Access Level: 🔒 Protected (Response owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
responseId |
UUID | Yes | The response to check progress for | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Progress retrieved",
"action_time": "2025-02-17T10:30:45",
"data": [
{
"pageId": "1a2b3c4d-...",
"title": "Personal Information",
"completed": true,
"totalFields": 4,
"answeredFields": 4
},
{
"pageId": "2b3c4d5e-...",
"title": "Event Preferences",
"completed": false,
"totalFields": 3,
"answeredFields": 1
}
]
}
Success Response Fields:
| Field | Description |
|---|---|
data[].pageId |
Page UUID |
data[].title |
Page title |
data[].completed |
Whether the page has been marked complete via moveToNextPage |
data[].totalFields |
Total number of active fields on this page |
data[].answeredFields |
Number of fields that have a non-null answer saved |
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Response not found |
34. Get All Responses (Organizer)
Purpose: Returns a paginated list of all responses for a form, regardless of status. For organizer review and export.
Endpoint: GET /api/v1/forms/{formId}/responses
Access Level: 🔒 Protected (Form owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
formId |
UUID | Yes | The form to list responses for | Must be a valid UUID |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
page |
integer | No | Page number (1-based) | Min: 1 | 1 |
size |
integer | No | Items per page | Min: 1 | 10 |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Responses retrieved",
"action_time": "2025-02-17T10:30:45",
"data": {
"content": [ "[ FormResponseObject entries ]" ],
"totalElements": 24,
"totalPages": 3,
"first": true,
"last": false,
"empty": false
}
}
Success Response Fields: data.content[] contains FormResponseObject entries. Pagination follows the Standard Paginated Response Wrapper.
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form not found |
35. Withdraw Response
Purpose: Allows a respondent to withdraw their own submission. Sets status to WITHDRAWN and soft-deletes the response. Withdrawn responses are excluded from the active list but are preserved for analytics.
Endpoint: POST /api/v1/forms/responses/{responseId}/withdraw
Access Level: 🔒 Protected (Response owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
responseId |
UUID | Yes | The response to withdraw | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Response withdrawn",
"action_time": "2025-02-17T10:30:45",
"data": null
}
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Response not found |
36. Validate Page Answers (Without Saving)
Purpose: Runs validation on a set of answers for a specific page number without creating or modifying any response data. Useful for client-side pre-validation before committing answers.
Endpoint: POST /api/v1/forms/{formId}/validate
Access Level: 🔒 Protected (Authenticated user)
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 |
|---|---|---|---|---|
formId |
UUID | Yes | The form to validate against | Must be a valid UUID |
Query Parameters:
| Parameter | Type | Required | Description | Validation | Default |
|---|---|---|---|---|---|
pageNumber |
integer | Yes | 1-based page number to validate | 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. Same structure as answers in Endpoint 29.
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Validation completed",
"action_time": "2025-02-17T10:30:45",
"data": {
"valid": false,
"errors": [
{
"pageId": "1a2b3c4d-...",
"pageTitle": "Personal Information",
"fieldId": "fieldId-fullname",
"fieldLabel": "Full Name",
"errorMessage": "Full Name is required",
"errorType": "REQUIRED"
},
{
"pageId": "1a2b3c4d-...",
"pageTitle": "Personal Information",
"fieldId": "fieldId-email",
"fieldLabel": "Email Address",
"errorMessage": "Email Address must be valid email",
"errorType": "INVALID_FORMAT"
}
]
}
}
Success Response Fields:
| Field | Description |
|---|---|
data.valid |
true if all fields passed validation |
data.errors[] |
List of per-field validation errors. Empty when valid = true |
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 message |
data.errors[].errorType |
Machine-readable type: REQUIRED, INVALID_FORMAT, INVALID_TYPE, VALIDATION_FAILED |
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form not found |
400 |
pageNumber is out of range |
Analytics Endpoints
37. Get Form Analytics
Purpose: Returns submission statistics for a form — total responses, counts by status, completion rates, and average completion time. Read-only, available to the form owner only.
Endpoint: GET /api/v1/forms/{formId}/analytics
Access Level: 🔒 Protected (Form owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
formId |
UUID | Yes | The form to analyse | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Analytics retrieved",
"action_time": "2025-02-17T10:30:45",
"data": {
"totalResponses": 120,
"submittedCount": 95,
"draftCount": 18,
"averageCompletionTimeSeconds": 312,
"statusBreakdown": {
"SUBMITTED": 95,
"DRAFT": 18,
"WITHDRAWN": 7
}
}
}
Success Response Fields:
| Field | Description |
|---|---|
totalResponses |
Total response records including drafts and withdrawn |
submittedCount |
Responses with status SUBMITTED |
draftCount |
Responses still in DRAFT status |
averageCompletionTimeSeconds |
Mean time from start to submit across all submitted responses |
statusBreakdown |
Count per status |
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form not found |
38. Get Field Analytics
Purpose: Returns answer distribution and fill rate statistics for a specific field. Uses answer snapshots so the field does not need to exist — deleted fields can still be analysed.
Endpoint: GET /api/v1/forms/{formId}/analytics/fields/{fieldId}
Access Level: 🔒 Protected (Form owner)
Authentication: Bearer Token
Request Headers:
| Header | Type | Required | Description |
|---|---|---|---|
Authorization |
string | Yes | Bearer <token> |
Path Parameters:
| Parameter | Type | Required | Description | Validation |
|---|---|---|---|---|
formId |
UUID | Yes | The parent form | Must be a valid UUID |
fieldId |
UUID | Yes | The field to analyse | Must be a valid UUID |
Success Response JSON Sample:
{
"success": true,
"httpStatus": "OK",
"message": "Field analytics retrieved",
"action_time": "2025-02-17T10:30:45",
"data": {
"fieldId": "a1b2c3d4-...",
"fieldLabel": "How did you hear about us?",
"fieldType": "DROPDOWN",
"totalAnswers": 95,
"filledAnswers": 88,
"emptyAnswers": 7,
"fillRate": 92.6,
"valueDistribution": {
"Social Media": 42,
"Word of Mouth": 30,
"Online Search": 16
}
}
}
Success Response Fields:
| Field | Description |
|---|---|
fieldId |
Field UUID |
fieldLabel |
Label from snapshot (works even if field was deleted) |
fieldType |
Type from snapshot |
totalAnswers |
Total answer records for this field |
filledAnswers |
Answers with a non-null value |
emptyAnswers |
Answers with a null value |
fillRate |
filledAnswers / totalAnswers × 100 — percentage rounded to 1 decimal |
valueDistribution |
Map of answer value → count (useful for choice fields) |
Possible Error Responses:
| Status | Scenario |
|---|---|
401 |
No or expired token |
404 |
Form or field not found |
Quick Reference — Endpoint Summary
| # | Method | Path | Auth | Description |
|---|---|---|---|---|
| Form Management | ||||
| 1 | POST | /forms |
🔒 | Create a new form |
| 2 | GET | /forms/{formId} |
🔒 | Get form by ID |
| 3 | PATCH | /forms/{formId} |
🔒 | Update form metadata / settings |
| 4 | DELETE | /forms/{formId} |
🔒 | Soft delete form |
| Page Management | ||||
| 5 | POST | /forms/{formId}/pages |
🔒 | Add a page |
| 6 | PATCH | /forms/pages/{pageId} |
🔒 | Update a page |
| 7 | DELETE | /forms/pages/{pageId} |
🔒 | Soft delete a page |
| 8 | POST | /forms/{formId}/pages/reorder |
🔒 | Reorder pages |
| 9 | POST | /forms/{formId}/pages/bulk |
🔒 | Bulk create pages (with fields) |
| 10 | DELETE | /forms/{formId}/pages/bulk |
🔒 | Bulk soft delete pages |
| 11 | POST | /forms/pages/{pageId}/clone |
🔒 | Clone a page |
| 12 | GET | /forms/{formId}/pages/preview/{pageNumber} |
🔒 | Get page by number |
| 13 | GET | /forms/{formId}/pages/metadata |
🔒 | Get form page metadata |
| Field Management | ||||
| 14 | POST | /forms/{formId}/pages/{pageId}/fields |
🔒 | Add a field to a page |
| 15 | PATCH | /forms/fields/{fieldId} |
🔒 | Update a field |
| 16 | DELETE | /forms/fields/{fieldId} |
🔒 | Soft delete a field |
| 17 | POST | /forms/{formId}/pages/{pageId}/fields/reorder |
🔒 | Reorder fields on a page |
| 18 | POST | /forms/{formId}/pages/{pageId}/fields/bulk |
🔒 | Bulk create fields |
| 19 | DELETE | /forms/{formId}/pages/{pageId}/fields/bulk |
🔒 | Bulk soft delete fields |
| 20 | PATCH | /forms/fields/bulk-update |
🔒 | Bulk update fields |
| 21 | POST | /forms/fields/{fieldId}/clone |
🔒 | Clone a field |
| Option Management | ||||
| 22 | POST | /forms/fields/{fieldId}/options |
🔒 | Add option to a field |
| 23 | PATCH | /forms/options/{optionId} |
🔒 | Update an option |
| 24 | DELETE | /forms/options/{optionId} |
🔒 | Soft delete an option |
| 25 | POST | /forms/fields/{fieldId}/options/reorder |
🔒 | Reorder options |
| 26 | DELETE | /forms/fields/{fieldId}/options/bulk |
🔒 | Bulk soft delete options |
| 27 | PATCH | /forms/options/bulk-update |
🔒 | Bulk update option labels |
| Response & Submission | ||||
| 28 | POST | /forms/{formId}/responses/start |
🔒 | Start form (create draft response) |
| 29 | PUT | /forms/responses/{responseId}/pages |
🔒 | Save page answers |
| 30 | POST | /forms/responses/{responseId}/submit |
🔒 | Submit form response |
| 31 | GET | /forms/responses/{responseId} |
🔒 | Get response by ID |
| 32 | GET | /forms/{formId}/responses/mine |
🔒 | Get my response for a form |
| 33 | GET | /forms/responses/{responseId}/progress |
🔒 | Get page completion progress |
| 34 | GET | /forms/{formId}/responses |
🔒 | Get all responses (organizer) |
| 35 | POST | /forms/responses/{responseId}/withdraw |
🔒 | Withdraw a response |
| 36 | POST | /forms/{formId}/validate |
🔒 | Validate answers without saving |
| Analytics | ||||
| 37 | GET | /forms/{formId}/analytics |
🔒 | Form-level analytics |
| 38 | GET | /forms/{formId}/analytics/fields/{fieldId} |
🔒 | Field-level analytics |
Integration note: To link a completed form to an event, use the Event Core API:
POST /api/v1/e-events/draft/{eventId}/forms/{formId}. To unlink:DELETE /api/v1/e-events/draft/{eventId}/forms/{formId}. These endpoints are documented in the Event Core API.
Data Format Standards
| Concern | Standard |
|---|---|
| Timestamps | ISO 8601 local datetime: 2025-02-17T10:30:45 (stored as LocalDateTime) |
| UTC Instants | ISO 8601 UTC: 2025-05-01T00:00:00Z (used in settings.responseStartTime, settings.responseDeadline) |
| Dates | YYYY-MM-DD — 2025-07-18 |
| Times | HH:mm — 18:00 |
| IDs | UUID v4 — 9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c |
| Pagination | 1-based page query parameter, Spring Page wrapper in response |
| Enums | Uppercase strings as defined (e.g., SUBMITTED, DROPDOWN, REQUIRED) |
| ENDOFAPPEND |