Skip to main content

Form Builder API

Author: Josh S. Sakweli, Backend Lead Team Last Updated: 2025-02-17 Version: v1.0

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, 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.
  • Soft delete is used throughout. Deleted pages, fields, and options are flagged with deletedAt and 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 = false temporarily 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=1 is 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 mismatch
  • 401 UNAUTHORIZED — Missing, expired, or malformed Bearer token
  • 403 FORBIDDEN — Authenticated but not the form owner
  • 404 NOT_FOUND — Form, page, field, option, or response not found or has been deleted
  • 422 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.

401 — Unauthorized:

{
  "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, and CHECKBOX fields 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-DD2025-07-18
Times HH:mm18: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