Skip to main content

Attendee Questions API Guide

What Is It?

A customizable questionnaire system that event organizers attach to their events to collect information from attendees during registration. Think of it like Google Forms, but built specifically for events and integrated into the ticket purchase flow.


The Two Sides

Organizer Side (Building the Form)

When an organizer creates an event, they can optionally enable "Attendee Questions." The system automatically creates an empty form with one page. The organizer then builds their questionnaire by:

  1. Adding pages - to organize questions into logical sections (e.g., "Personal Info", "Dietary Needs", "Travel Details")

  2. Adding fields to pages - choosing from various field types like text, email, phone, dropdowns, checkboxes, ratings, file uploads, etc.

  3. Adding options - for choice-based fields (dropdown, radio, checkbox), the organizer adds the available choices

  4. Configuring settings - deciding when to show the form (before or after checkout), whether it's required, and if walk-in attendees should also complete it

The organizer can reorder pages, fields, and options. They can edit labels, add descriptions, set validation rules (minimum length, date ranges, file size limits), and mark fields as required or optional.


Attendee Side (Filling the Form)

When someone registers for a published event, they see the questionnaire. The system works page-by-page:

  1. View a page - attendee sees one page of questions at a time with navigation showing progress (Page 1 of 3)

  2. Fill and save - as the attendee completes a page and moves to the next, their answers are validated and saved automatically. If any answer is invalid (wrong format, too short, invalid selection), the page won't save and they see specific error messages for each problematic field.

  3. Submit - when ready, the attendee clicks submit. The system checks ALL pages to ensure every required field is answered and all answers are valid. If everything passes, the submission is finalized. If not, they see a summary showing which pages have problems.

The key principle: validate before saving, never store invalid data. This keeps the database clean and gives immediate feedback.


The Analytics Side (Viewing Results)

Once attendees start submitting, the organizer can view comprehensive analytics:

  • Summary statistics - total submissions, completion rates, average time to complete, submission trends over time, and which pages have the highest drop-off rates

  • Field-by-field breakdown - for each question, see response rates and detailed analysis. For choice fields, see how many people selected each option with percentages. For numeric fields, see averages, ranges, and distributions. For text fields, see common words and length statistics.

  • Spreadsheet view - all responses in a table format, like Google Forms' response spreadsheet, with each row being one submission and each column being one question

  • Export - download all data as CSV or Excel for external analysis


How Is It Useful?

For Event Organizers

Logistics planning:

  • Collect t-shirt sizes to order the right quantities
  • Gather dietary requirements for catering
  • Know arrival times for transportation planning
  • Get emergency contact information for safety

Attendee profiling:

  • Ask about interests for personalized experiences
  • Collect company/role info for networking features
  • Understand how attendees heard about the event for marketing

Compliance and safety:

  • Collect required documents (ID uploads)
  • Gather health declarations
  • Get consent for photography/recording
  • Verify age requirements

Engagement:

  • Ask what sessions attendees plan to attend
  • Collect questions for Q&A panels
  • Gather song requests for performers
  • Get feedback on previous events

For Attendees

Smoother experience:

  • Complete registration in one flow instead of separate forms
  • Save progress and return later (draft mode)
  • Clear validation messages prevent submission errors
  • Know exactly what's required vs optional

Personalization:

  • Their preferences are captured for a tailored experience
  • Dietary needs are communicated without awkward conversations
  • Special requirements are noted in advance

Real-World Example

Music Festival Scenario:

An organizer creates a 3-day festival. They enable attendee questions with two pages:

Page 1: Essential Info

  • Emergency contact name (required, text)
  • Emergency contact phone (required, phone validation)
  • T-shirt size (required, dropdown: S/M/L/XL)
  • Camping or day pass? (required, radio)

Page 2: Preferences

  • Dietary restrictions (optional, checkbox: vegetarian, vegan, gluten-free, halal, kosher)
  • Other dietary notes (optional, textarea)
  • Which headliner are you most excited for? (optional, dropdown with artist names)

When 500 people register, the organizer sees:

  • 65% chose Medium or Large t-shirts
  • 23% have dietary restrictions (42% of those are vegetarian)
  • Artist X is the most anticipated headliner with 45% of votes
  • Page 2 has 15% drop-off (people skipping optional questions)

They export the data to:

  • Order t-shirts: 50 S, 180 M, 170 L, 100 XL
  • Tell catering: 115 vegetarian meals, 45 vegan, 60 gluten-free
  • Adjust sound check priority based on headliner popularity

Why This Design?

Page-by-page saves prevent data loss. If someone fills 3 pages then loses internet, they don't lose everything.

Strict validation before saving means the database only contains valid, usable data. No garbage entries to clean up later.

Empty-body submit means the final submission is just a validation check, not a data transfer. Everything is already saved from auto-saves.

Parallel page validation on submit makes the final check fast even with many pages.

Separation of draft and published means organizers can freely edit their form while building the event, but once published and people start responding, the structure is stable.


Summary

It's a form builder tailored for events. Organizers build custom questionnaires, attendees fill them page-by-page with auto-save and validation, and organizers get rich analytics to plan better events. The technical design prioritizes data integrity, user experience, and actionable insights.

System Flow

┌─────────────────────────────────────────────────────────────────────────────┐
│                           ORGANIZER FLOW                                    │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  1. Create Event Draft                                                      │
│     POST /api/v1/e-events/drafts                                           │
│                    ↓                                                        │
│  2. Enable Attendee Questions                                               │
│     PUT /api/v1/e-events/drafts/{draftId}/attendee-questions               │
│                    ↓                                                        │
│  3. Add Pages (optional - default page created automatically)               │
│     POST /api/v1/e-events/drafts/{draftId}/attendee-questions/pages        │
│                    ↓                                                        │
│  4. Add Fields to Pages                                                     │
│     POST /api/v1/e-events/drafts/{draftId}/attendee-questions/pages/{pageId}/fields │
│                    ↓                                                        │
│  5. Add Options to Choice Fields (dropdown/radio/checkbox)                  │
│     POST /api/v1/e-events/drafts/{draftId}/attendee-questions/fields/{fieldId}/options │
│                    ↓                                                        │
│  6. Publish Event                                                           │
│     POST /api/v1/e-events/drafts/{draftId}/publish                         │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                           ATTENDEE FLOW                                     │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  1. View Questionnaire (check if registration open)                         │
│     GET /api/v1/e-events/{eventId}/attendee-questions                      │
│                    ↓                                                        │
│  2. Get Each Page                                                           │
│     GET /api/v1/e-events/{eventId}/attendee-questions/pages/{pageNumber}   │
│                    ↓                                                        │
│  3. Save Page Answers (auto-save per page)                                  │
│     PATCH /api/v1/e-events/{eventId}/attendee-questions/responses/pages/{n}│
│                    ↓                                                        │
│  4. Submit Final Response                                                   │
│     POST /api/v1/e-events/{eventId}/attendee-questions/responses/submit    │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                           ANALYTICS FLOW (Organizer Only)                   │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  GET /api/v1/e-events/{eventId}/attendee-questions/analytics/summary       │
│  GET /api/v1/e-events/{eventId}/attendee-questions/analytics/fields        │
│  GET /api/v1/e-events/{eventId}/attendee-questions/analytics/fields/{id}   │
│  GET /api/v1/e-events/{eventId}/attendee-questions/analytics/responses     │
│  GET /api/v1/e-events/{eventId}/attendee-questions/analytics/export/csv    │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Authentication

All endpoints require JWT authentication except public event viewing.

Header: Authorization: Bearer {jwt_token}

PART 1: ORGANIZER ENDPOINTS

Base URL

/api/v1/e-events/drafts/{draftId}/attendee-questions

1.1 Enable Attendee Questions

Creates a new questionnaire for the event draft. Automatically creates an empty form with one default page.

Endpoint:

PUT /api/v1/e-events/drafts/{draftId}/attendee-questions

Request:

{
  "displayTime": "BEFORE_CHECKOUT",
  "isRequiredOnline": true,
  "applyToAtDoor": false
}

Request Fields:

Field Type Required Description
displayTime enum No When to show form: BEFORE_CHECKOUT or AFTER_CHECKOUT. Default: BEFORE_CHECKOUT
isRequiredOnline boolean No Must complete before checkout? Default: false
applyToAtDoor boolean No Show to walk-in attendees? Default: false

Response (201 Created):

{
  "success": true,
  "httpStatus": "CREATED",
  "message": "Attendee questions enabled",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "formId": "770e8400-e29b-41d4-a716-446655440002",
    "displayTime": "BEFORE_CHECKOUT",
    "isRequiredOnline": true,
    "applyToAtDoor": false,
    "createdAt": "2025-01-23T10:30:00Z",
    "updatedAt": "2025-01-23T10:30:00Z"
  }
}

Error Responses:

Status Message
404 Draft not found
403 You don't have access to this draft
403 Attendee questions already enabled. Use update instead.

1.2 Update Attendee Questions Settings

Endpoint:

PATCH /api/v1/e-events/drafts/{draftId}/attendee-questions

Request:

{
  "displayTime": "AFTER_CHECKOUT",
  "isRequiredOnline": false
}

All fields optional - only updates provided fields.

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Settings updated",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "formId": "770e8400-e29b-41d4-a716-446655440002",
    "displayTime": "AFTER_CHECKOUT",
    "isRequiredOnline": false,
    "applyToAtDoor": false,
    "createdAt": "2025-01-23T10:30:00Z",
    "updatedAt": "2025-01-23T10:35:00Z"
  }
}

1.3 Get Attendee Questions (with full form)

Endpoint:

GET /api/v1/e-events/drafts/{draftId}/attendee-questions

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Attendee questions retrieved",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "formId": "770e8400-e29b-41d4-a716-446655440002",
    "displayTime": "BEFORE_CHECKOUT",
    "isRequiredOnline": true,
    "applyToAtDoor": false,
    "createdAt": "2025-01-23T10:30:00Z",
    "updatedAt": "2025-01-23T10:30:00Z",
    "form": {
      "formId": "770e8400-e29b-41d4-a716-446655440002",
      "title": "Attendee Questions - Music Festival 2025",
      "description": "Custom questions for event attendees",
      "pages": [
        {
          "pageId": "880e8400-e29b-41d4-a716-446655440003",
          "title": "Personal Information",
          "description": "Basic attendee details",
          "displayOrder": 1,
          "fields": [
            {
              "fieldId": "990e8400-e29b-41d4-a716-446655440004",
              "type": "TEXT",
              "label": "Emergency Contact Name",
              "description": "Who should we contact in case of emergency?",
              "placeholder": "Full name",
              "displayOrder": 1,
              "required": true,
              "validation": {
                "minLength": 2,
                "maxLength": 100
              },
              "options": []
            },
            {
              "fieldId": "aa0e8400-e29b-41d4-a716-446655440005",
              "type": "PHONE",
              "label": "Emergency Contact Phone",
              "displayOrder": 2,
              "required": true,
              "options": []
            },
            {
              "fieldId": "bb0e8400-e29b-41d4-a716-446655440006",
              "type": "DROPDOWN",
              "label": "T-Shirt Size",
              "displayOrder": 3,
              "required": true,
              "options": [
                {"optionId": "opt1", "label": "Small", "displayOrder": 1},
                {"optionId": "opt2", "label": "Medium", "displayOrder": 2},
                {"optionId": "opt3", "label": "Large", "displayOrder": 3},
                {"optionId": "opt4", "label": "X-Large", "displayOrder": 4}
              ]
            }
          ]
        },
        {
          "pageId": "cc0e8400-e29b-41d4-a716-446655440007",
          "title": "Dietary Requirements",
          "displayOrder": 2,
          "fields": [
            {
              "fieldId": "dd0e8400-e29b-41d4-a716-446655440008",
              "type": "CHECKBOX",
              "label": "Dietary Restrictions",
              "description": "Select all that apply",
              "displayOrder": 1,
              "required": false,
              "options": [
                {"optionId": "opt5", "label": "Vegetarian", "displayOrder": 1},
                {"optionId": "opt6", "label": "Vegan", "displayOrder": 2},
                {"optionId": "opt7", "label": "Gluten-free", "displayOrder": 3},
                {"optionId": "opt8", "label": "Halal", "displayOrder": 4},
                {"optionId": "opt9", "label": "Kosher", "displayOrder": 5}
              ]
            },
            {
              "fieldId": "ee0e8400-e29b-41d4-a716-446655440009",
              "type": "TEXTAREA",
              "label": "Other Dietary Notes",
              "placeholder": "Any allergies or special requirements?",
              "displayOrder": 2,
              "required": false
            }
          ]
        }
      ]
    }
  }
}

Response when not configured (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Attendee questions not configured",
  "data": null
}

1.4 Disable Attendee Questions

Permanently deletes the form and all configuration.

Endpoint:

DELETE /api/v1/e-events/drafts/{draftId}/attendee-questions

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Attendee questions disabled"
}

Pages Management

1.5 Add Page

Endpoint:

POST /api/v1/e-events/drafts/{draftId}/attendee-questions/pages

Request:

{
  "title": "Travel Information",
  "description": "Help us plan your arrival"
}

Response (201 Created):

{
  "success": true,
  "httpStatus": "CREATED",
  "message": "Page added",
  "data": {
    "pageId": "ff0e8400-e29b-41d4-a716-446655440010",
    "title": "Travel Information",
    "description": "Help us plan your arrival",
    "displayOrder": 3
  }
}

1.6 Update Page

Endpoint:

PATCH /api/v1/e-events/drafts/{draftId}/attendee-questions/pages/{pageId}

Request:

{
  "title": "Travel & Accommodation",
  "description": "Updated description"
}

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Page updated",
  "data": {
    "pageId": "ff0e8400-e29b-41d4-a716-446655440010",
    "title": "Travel & Accommodation",
    "description": "Updated description",
    "displayOrder": 3
  }
}

1.7 Delete Page

Endpoint:

DELETE /api/v1/e-events/drafts/{draftId}/attendee-questions/pages/{pageId}

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Page deleted"
}

1.8 Reorder Pages

Endpoint:

POST /api/v1/e-events/drafts/{draftId}/attendee-questions/pages/reorder

Request:

{
  "orderedIds": [
    "cc0e8400-e29b-41d4-a716-446655440007",
    "880e8400-e29b-41d4-a716-446655440003",
    "ff0e8400-e29b-41d4-a716-446655440010"
  ]
}

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Pages reordered"
}

Fields Management

1.9 Add Field

Endpoint:

POST /api/v1/e-events/drafts/{draftId}/attendee-questions/pages/{pageId}/fields

Request (Text Field):

{
  "type": "TEXT",
  "label": "Company Name",
  "description": "Your current employer",
  "placeholder": "Enter company name",
  "required": false,
  "validation": {
    "minLength": 2,
    "maxLength": 100
  }
}

Request (Dropdown Field):

{
  "type": "DROPDOWN",
  "label": "How did you hear about us?",
  "required": true
}

Request (Rating Field):

{
  "type": "RATING",
  "label": "How excited are you for this event?",
  "required": true,
  "validation": {
    "min": 1,
    "max": 5
  }
}

Request (File Upload Field):

{
  "type": "FILE",
  "label": "Upload ID Document",
  "description": "Government-issued ID for verification",
  "required": true,
  "validation": {
    "maxSizeMb": 5,
    "accept": "image/*,.pdf"
  }
}

Available Field Types:

Type Description Has Options
TEXT Single line text No
TEXTAREA Multi-line text No
EMAIL Email with validation No
PHONE Phone number No
NUMBER Numeric input No
DATE Date picker No
TIME Time picker No
DATETIME Date and time No
DROPDOWN Single select dropdown Yes
RADIO Single select radio buttons Yes
CHECKBOX Multi-select checkboxes Yes
RATING Star rating No
SCALE Linear scale (1-10) No
SLIDER Slider input No
FILE File upload No
URL URL with validation No
CURRENCY Money input No
SECTION_HEADER Display only - section title No
PARAGRAPH Display only - text block No

Response (201 Created):

{
  "success": true,
  "httpStatus": "CREATED",
  "message": "Field added",
  "data": {
    "fieldId": "110e8400-e29b-41d4-a716-446655440011",
    "type": "DROPDOWN",
    "label": "How did you hear about us?",
    "displayOrder": 1,
    "required": true,
    "options": []
  }
}

1.10 Update Field

Endpoint:

PATCH /api/v1/e-events/drafts/{draftId}/attendee-questions/fields/{fieldId}

Request:

{
  "label": "How did you discover this event?",
  "required": false,
  "description": "Help us improve our marketing"
}

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Field updated",
  "data": {
    "fieldId": "110e8400-e29b-41d4-a716-446655440011",
    "type": "DROPDOWN",
    "label": "How did you discover this event?",
    "description": "Help us improve our marketing",
    "displayOrder": 1,
    "required": false,
    "options": []
  }
}

1.11 Delete Field

Endpoint:

DELETE /api/v1/e-events/drafts/{draftId}/attendee-questions/fields/{fieldId}

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Field deleted"
}

1.12 Reorder Fields

Endpoint:

POST /api/v1/e-events/drafts/{draftId}/attendee-questions/pages/{pageId}/fields/reorder

Request:

{
  "orderedIds": [
    "bb0e8400-e29b-41d4-a716-446655440006",
    "990e8400-e29b-41d4-a716-446655440004",
    "aa0e8400-e29b-41d4-a716-446655440005"
  ]
}

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Fields reordered"
}

Options Management (for DROPDOWN, RADIO, CHECKBOX)

1.13 Add Option

Endpoint:

POST /api/v1/e-events/drafts/{draftId}/attendee-questions/fields/{fieldId}/options

Request:

{
  "label": "Social Media"
}

Response (201 Created):

{
  "success": true,
  "httpStatus": "CREATED",
  "message": "Option added",
  "data": {
    "optionId": "220e8400-e29b-41d4-a716-446655440012",
    "label": "Social Media",
    "displayOrder": 1
  }
}

1.14 Update Option

Endpoint:

PATCH /api/v1/e-events/drafts/{draftId}/attendee-questions/options/{optionId}

Request:

{
  "label": "Social Media (Facebook, Instagram, etc.)"
}

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Option updated",
  "data": {
    "optionId": "220e8400-e29b-41d4-a716-446655440012",
    "label": "Social Media (Facebook, Instagram, etc.)",
    "displayOrder": 1
  }
}

1.15 Delete Option

Endpoint:

DELETE /api/v1/e-events/drafts/{draftId}/attendee-questions/options/{optionId}

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Option deleted"
}

1.16 Reorder Options

Endpoint:

POST /api/v1/e-events/drafts/{draftId}/attendee-questions/fields/{fieldId}/options/reorder

Request:

{
  "orderedIds": [
    "220e8400-e29b-41d4-a716-446655440012",
    "330e8400-e29b-41d4-a716-446655440013",
    "440e8400-e29b-41d4-a716-446655440014"
  ]
}

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Options reordered"
}

PART 2: ATTENDEE ENDPOINTS (Public)

Base URL

/api/v1/e-events/{eventId}/attendee-questions

Note: These endpoints require the event to be PUBLISHED.


2.1 Get Questionnaire (First Page)

Endpoint:

GET /api/v1/e-events/{eventId}/attendee-questions

Response - No questionnaire configured:

{
  "success": true,
  "httpStatus": "OK",
  "message": "No questionnaire for this event",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "eventTitle": "Music Festival 2025",
    "hasForm": false,
    "registrationOpen": false,
    "message": "No questionnaire for this event"
  }
}

Response - Registration not yet open:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Registration opens on 2025-02-01",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "eventTitle": "Music Festival 2025",
    "hasForm": true,
    "registrationOpen": false,
    "message": "Registration opens on 2025-02-01",
    "registrationOpensAt": "2025-02-01T09:00:00Z",
    "registrationClosesAt": "2025-02-15T18:00:00Z",
    "displayTime": "BEFORE_CHECKOUT",
    "isRequired": true
  }
}

Response - Registration closed:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Registration closed on 2025-02-15",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "eventTitle": "Music Festival 2025",
    "hasForm": true,
    "registrationOpen": false,
    "message": "Registration closed on 2025-02-15",
    "registrationOpensAt": "2025-02-01T09:00:00Z",
    "registrationClosesAt": "2025-02-15T18:00:00Z"
  }
}

Response - Registration open (returns page 1):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Questionnaire retrieved",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "eventTitle": "Music Festival 2025",
    "hasForm": true,
    "registrationOpen": true,
    "registrationOpensAt": "2025-02-01T09:00:00Z",
    "registrationClosesAt": "2025-02-15T18:00:00Z",
    "displayTime": "BEFORE_CHECKOUT",
    "isRequired": true,
    "currentPage": 1,
    "totalPages": 2,
    "formTitle": "Attendee Questions - Music Festival 2025",
    "formDescription": "Please complete this questionnaire",
    "page": {
      "pageId": "880e8400-e29b-41d4-a716-446655440003",
      "title": "Personal Information",
      "description": "Basic attendee details",
      "displayOrder": 1,
      "fields": [
        {
          "fieldId": "990e8400-e29b-41d4-a716-446655440004",
          "type": "TEXT",
          "label": "Emergency Contact Name",
          "description": "Who should we contact in case of emergency?",
          "placeholder": "Full name",
          "displayOrder": 1,
          "required": true,
          "validation": {
            "minLength": 2,
            "maxLength": 100
          },
          "options": []
        },
        {
          "fieldId": "aa0e8400-e29b-41d4-a716-446655440005",
          "type": "PHONE",
          "label": "Emergency Contact Phone",
          "displayOrder": 2,
          "required": true,
          "options": []
        },
        {
          "fieldId": "bb0e8400-e29b-41d4-a716-446655440006",
          "type": "DROPDOWN",
          "label": "T-Shirt Size",
          "displayOrder": 3,
          "required": true,
          "options": [
            {"optionId": "opt1", "label": "Small", "displayOrder": 1},
            {"optionId": "opt2", "label": "Medium", "displayOrder": 2},
            {"optionId": "opt3", "label": "Large", "displayOrder": 3},
            {"optionId": "opt4", "label": "X-Large", "displayOrder": 4}
          ]
        }
      ]
    }
  }
}

2.2 Get Specific Page

Endpoint:

GET /api/v1/e-events/{eventId}/attendee-questions/pages/{pageNumber}

Example:

GET /api/v1/e-events/660e8400-e29b-41d4-a716-446655440001/attendee-questions/pages/2

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Page 2 of 2",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "eventTitle": "Music Festival 2025",
    "hasForm": true,
    "registrationOpen": true,
    "currentPage": 2,
    "totalPages": 2,
    "page": {
      "pageId": "cc0e8400-e29b-41d4-a716-446655440007",
      "title": "Dietary Requirements",
      "displayOrder": 2,
      "fields": [
        {
          "fieldId": "dd0e8400-e29b-41d4-a716-446655440008",
          "type": "CHECKBOX",
          "label": "Dietary Restrictions",
          "description": "Select all that apply",
          "displayOrder": 1,
          "required": false,
          "options": [
            {"optionId": "opt5", "label": "Vegetarian", "displayOrder": 1},
            {"optionId": "opt6", "label": "Vegan", "displayOrder": 2},
            {"optionId": "opt7", "label": "Gluten-free", "displayOrder": 3},
            {"optionId": "opt8", "label": "Halal", "displayOrder": 4},
            {"optionId": "opt9", "label": "Kosher", "displayOrder": 5}
          ]
        },
        {
          "fieldId": "ee0e8400-e29b-41d4-a716-446655440009",
          "type": "TEXTAREA",
          "label": "Other Dietary Notes",
          "placeholder": "Any allergies or special requirements?",
          "displayOrder": 2,
          "required": false
        }
      ]
    }
  }
}

Error - Page not found:

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "Page not found. Valid pages: 1 to 2"
}

2.3 Save Page Answers (Auto-Save)

Saves answers for a single page. Validates ALL fields on the page before saving. If any field is invalid, nothing is saved.

Endpoint:

PATCH /api/v1/e-events/{eventId}/attendee-questions/responses/pages/{pageNumber}

Request:

{
  "answers": {
    "990e8400-e29b-41d4-a716-446655440004": {
      "fieldId": "990e8400-e29b-41d4-a716-446655440004",
      "value": "John Doe"
    },
    "aa0e8400-e29b-41d4-a716-446655440005": {
      "fieldId": "aa0e8400-e29b-41d4-a716-446655440005",
      "value": "+255712345678"
    },
    "bb0e8400-e29b-41d4-a716-446655440006": {
      "fieldId": "bb0e8400-e29b-41d4-a716-446655440006",
      "value": "Large"
    }
  }
}

Answer Format by Field Type:

Field Type Value Format Example
TEXT, TEXTAREA, EMAIL, PHONE, URL string "John Doe"
NUMBER, CURRENCY, RATING, SCALE, SLIDER number 42 or 4.5
DATE string (YYYY-MM-DD) "2025-02-15"
TIME string (HH:MM) "14:30"
DATETIME string (ISO) "2025-02-15T14:30:00"
DROPDOWN, RADIO string (selected label) "Large"
CHECKBOX array of strings ["Vegetarian", "Gluten-free"]
FILE object See below

File Upload Answer:

{
  "fieldId": "file-field-id",
  "value": null,
  "fileUrl": "https://storage.example.com/uploads/id-doc.pdf",
  "fileName": "id-doc.pdf",
  "fileSize": 1048576,
  "fileType": "application/pdf"
}

Response - Success (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Page 1 saved",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "pageNumber": 1,
    "saved": true,
    "savedAt": "2025-01-23T10:45:00Z",
    "isValid": true,
    "errors": [],
    "totalFieldsOnPage": 3,
    "answeredFieldsOnPage": 3,
    "overallProgress": {
      "totalPages": 2,
      "completedPages": 1,
      "totalFields": 5,
      "answeredFields": 3,
      "completionPercentage": 60
    }
  }
}

Response - Validation Failed (400 Bad Request):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Validation failed - page not saved",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "pageNumber": 1,
    "saved": false,
    "isValid": false,
    "errors": [
      {
        "fieldId": "aa0e8400-e29b-41d4-a716-446655440005",
        "fieldLabel": "Emergency Contact Phone",
        "errorCode": "INVALID_PHONE",
        "message": "Please enter a valid phone number"
      },
      {
        "fieldId": "bb0e8400-e29b-41d4-a716-446655440006",
        "fieldLabel": "T-Shirt Size",
        "errorCode": "INVALID_OPTION",
        "message": "Selected option is not valid"
      }
    ],
    "totalFieldsOnPage": 3,
    "answeredFieldsOnPage": 3,
    "overallProgress": {
      "totalPages": 2,
      "completedPages": 0,
      "totalFields": 5,
      "answeredFields": 0,
      "completionPercentage": 0
    }
  }
}

Validation Error Codes:

Code Description
REQUIRED Required field is missing
INVALID_EMAIL Invalid email format
INVALID_PHONE Invalid phone number
INVALID_NUMBER Not a valid number
INVALID_DATE Invalid date format
INVALID_TIME Invalid time format
INVALID_DATETIME Invalid datetime format
INVALID_URL Invalid URL format
INVALID_OPTION Selected option not in list
INVALID_SELECTION Invalid selection format
TOO_SHORT Text too short (minLength)
TOO_LONG Text too long (maxLength)
BELOW_MIN Number below minimum
ABOVE_MAX Number above maximum
DATE_TOO_EARLY Date before minDate
DATE_TOO_LATE Date after maxDate
TOO_FEW_SELECTIONS Not enough checkboxes
TOO_MANY_SELECTIONS Too many checkboxes
PATTERN_MISMATCH Doesn't match regex
FILE_TOO_LARGE File exceeds maxSizeMb
INVALID_FILE_TYPE File type not accepted

2.4 Submit Final Response

Submits the form. No request body needed - validates all saved pages and submits if all valid.

Endpoint:

POST /api/v1/e-events/{eventId}/attendee-questions/responses/submit

Response - Success (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Submission successful",
  "data": {
    "responseId": "550e8400-e29b-41d4-a716-446655440099",
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "success": true,
    "status": "SUBMITTED",
    "submittedAt": "2025-01-23T10:50:00Z",
    "pageValidations": [
      {
        "pageNumber": 1,
        "pageTitle": "Personal Information",
        "isValid": true,
        "hasAnswers": true,
        "totalFields": 3,
        "answeredFields": 3,
        "requiredFields": 3,
        "requiredAnswered": 3,
        "errors": []
      },
      {
        "pageNumber": 2,
        "pageTitle": "Dietary Requirements",
        "isValid": true,
        "hasAnswers": true,
        "totalFields": 2,
        "answeredFields": 1,
        "requiredFields": 0,
        "requiredAnswered": 0,
        "errors": []
      }
    ],
    "totalPages": 2,
    "validPages": 2,
    "invalidPages": 0,
    "allPagesValid": true
  }
}

Response - Validation Failed (400 Bad Request):

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Validation failed - 1 page(s) have errors",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "success": false,
    "status": "DRAFT",
    "pageValidations": [
      {
        "pageNumber": 1,
        "pageTitle": "Personal Information",
        "isValid": false,
        "hasAnswers": true,
        "totalFields": 3,
        "answeredFields": 2,
        "requiredFields": 3,
        "requiredAnswered": 2,
        "errors": [
          {
            "fieldId": "bb0e8400-e29b-41d4-a716-446655440006",
            "fieldLabel": "T-Shirt Size",
            "errorCode": "REQUIRED",
            "message": "T-Shirt Size is required"
          }
        ]
      },
      {
        "pageNumber": 2,
        "pageTitle": "Dietary Requirements",
        "isValid": true,
        "hasAnswers": false,
        "totalFields": 2,
        "answeredFields": 0,
        "requiredFields": 0,
        "requiredAnswered": 0,
        "errors": []
      }
    ],
    "totalPages": 2,
    "validPages": 1,
    "invalidPages": 1,
    "allPagesValid": false
  }
}

Error - No draft found:

{
  "success": false,
  "httpStatus": "NOT_FOUND",
  "message": "No draft found. Please save your answers first."
}

2.5 Get Submission Status

Endpoint:

GET /api/v1/e-events/{eventId}/attendee-questions/responses/status

Response - No submission started:

{
  "success": true,
  "httpStatus": "OK",
  "message": "No submission started",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "success": false,
    "status": null,
    "totalPages": 2,
    "validPages": 0,
    "invalidPages": 0,
    "allPagesValid": false
  }
}

Response - Draft in progress:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Status: DRAFT",
  "data": {
    "responseId": "550e8400-e29b-41d4-a716-446655440099",
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "success": false,
    "status": "DRAFT",
    "submittedAt": null,
    "pageValidations": [
      {
        "pageNumber": 1,
        "pageTitle": "Personal Information",
        "isValid": true,
        "hasAnswers": true,
        "totalFields": 3,
        "answeredFields": 3,
        "requiredFields": 3,
        "requiredAnswered": 3,
        "errors": []
      },
      {
        "pageNumber": 2,
        "pageTitle": "Dietary Requirements",
        "isValid": true,
        "hasAnswers": false,
        "totalFields": 2,
        "answeredFields": 0,
        "requiredFields": 0,
        "requiredAnswered": 0,
        "errors": []
      }
    ],
    "totalPages": 2,
    "validPages": 2,
    "invalidPages": 0,
    "allPagesValid": true
  }
}

Response - Already submitted:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Status: SUBMITTED",
  "data": {
    "responseId": "550e8400-e29b-41d4-a716-446655440099",
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "success": true,
    "status": "SUBMITTED",
    "submittedAt": "2025-01-23T10:50:00Z",
    "totalPages": 2,
    "validPages": 2,
    "invalidPages": 0,
    "allPagesValid": true
  }
}

2.6 Withdraw Submission

Endpoint:

DELETE /api/v1/e-events/{eventId}/attendee-questions/responses

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Submission withdrawn"
}

PART 3: ANALYTICS ENDPOINTS (Organizer Only)

Base URL

/api/v1/e-events/{eventId}/attendee-questions/analytics

Note: Only the event organizer can access analytics.


3.1 Get Summary Statistics

Endpoint:

GET /api/v1/e-events/{eventId}/attendee-questions/analytics/summary

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Summary retrieved",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "eventTitle": "Music Festival 2025",
    "totalStarted": 250,
    "totalDrafts": 45,
    "totalSubmitted": 180,
    "totalWithdrawn": 25,
    "completionRate": 72.0,
    "dropOffRate": 28.0,
    "averageCompletionTimeSeconds": 185.5,
    "fastestCompletionSeconds": 45,
    "slowestCompletionSeconds": 890,
    "submissionTrend": [
      {"date": "2025-01-01", "count": 0},
      {"date": "2025-01-02", "count": 5},
      {"date": "2025-01-03", "count": 12},
      {"date": "2025-01-04", "count": 8},
      {"date": "2025-01-05", "count": 15},
      {"date": "2025-01-06", "count": 22},
      {"date": "2025-01-07", "count": 18}
    ],
    "pageDropOff": [
      {
        "pageNumber": 1,
        "pageTitle": "Personal Information",
        "started": 250,
        "completed": 220,
        "dropOffRate": 12.0
      },
      {
        "pageNumber": 2,
        "pageTitle": "Dietary Requirements",
        "started": 220,
        "completed": 180,
        "dropOffRate": 18.2
      }
    ],
    "firstSubmissionAt": "2025-01-02T09:15:00",
    "lastSubmissionAt": "2025-01-23T10:50:00",
    "generatedAt": "2025-01-23T11:00:00"
  }
}

3.2 Get All Fields Analytics

Endpoint:

GET /api/v1/e-events/{eventId}/attendee-questions/analytics/fields

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Fields analytics retrieved",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "totalResponses": 180,
    "fields": [
      {
        "fieldId": "990e8400-e29b-41d4-a716-446655440004",
        "label": "Emergency Contact Name",
        "type": "TEXT",
        "pageNumber": 1,
        "required": true,
        "responseCount": 180,
        "skippedCount": 0,
        "responseRate": 100.0,
        "textStats": {
          "averageLength": 15,
          "minLength": 5,
          "maxLength": 45,
          "commonWords": ["john", "jane", "mary", "james", "david"]
        }
      },
      {
        "fieldId": "bb0e8400-e29b-41d4-a716-446655440006",
        "label": "T-Shirt Size",
        "type": "DROPDOWN",
        "pageNumber": 1,
        "required": true,
        "responseCount": 180,
        "skippedCount": 0,
        "responseRate": 100.0,
        "optionBreakdown": [
          {"value": "Medium", "count": 65, "percentage": 36.1},
          {"value": "Large", "count": 58, "percentage": 32.2},
          {"value": "Small", "count": 35, "percentage": 19.4},
          {"value": "X-Large", "count": 22, "percentage": 12.2}
        ]
      },
      {
        "fieldId": "dd0e8400-e29b-41d4-a716-446655440008",
        "label": "Dietary Restrictions",
        "type": "CHECKBOX",
        "pageNumber": 2,
        "required": false,
        "responseCount": 95,
        "skippedCount": 85,
        "responseRate": 52.8,
        "optionBreakdown": [
          {"value": "Vegetarian", "count": 42, "percentage": 44.2},
          {"value": "Gluten-free", "count": 28, "percentage": 29.5},
          {"value": "Vegan", "count": 18, "percentage": 18.9},
          {"value": "Halal", "count": 12, "percentage": 12.6},
          {"value": "Kosher", "count": 5, "percentage": 5.3}
        ]
      }
    ]
  }
}

3.3 Get Single Field Analytics

Endpoint:

GET /api/v1/e-events/{eventId}/attendee-questions/analytics/fields/{fieldId}?page=0&size=20

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Field analytics retrieved",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "fieldId": "bb0e8400-e29b-41d4-a716-446655440006",
    "label": "T-Shirt Size",
    "type": "DROPDOWN",
    "required": true,
    "totalResponses": 180,
    "responseCount": 180,
    "skippedCount": 0,
    "responseRate": 100.0,
    "optionBreakdown": [
      {"value": "Medium", "count": 65, "percentage": 36.1},
      {"value": "Large", "count": 58, "percentage": 32.2},
      {"value": "Small", "count": 35, "percentage": 19.4},
      {"value": "X-Large", "count": 22, "percentage": 12.2}
    ],
    "responses": [
      {
        "responseId": "resp-001",
        "value": "Large",
        "submittedAt": "2025-01-23T10:50:00"
      },
      {
        "responseId": "resp-002",
        "value": "Medium",
        "submittedAt": "2025-01-23T10:48:00"
      }
    ],
    "totalResponseCount": 180,
    "page": 0,
    "pageSize": 20
  }
}

3.4 Get All Responses (Spreadsheet View)

Endpoint:

GET /api/v1/e-events/{eventId}/attendee-questions/analytics/responses?page=0&size=20

Response (200 OK):

{
  "success": true,
  "httpStatus": "OK",
  "message": "Responses retrieved",
  "data": {
    "eventId": "660e8400-e29b-41d4-a716-446655440001",
    "totalResponses": 180,
    "page": 0,
    "pageSize": 20,
    "totalPages": 9,
    "columns": [
      {"fieldId": "990e8400-e29b-41d4-a716-446655440004", "label": "Emergency Contact Name", "type": "TEXT", "pageNumber": 1},
      {"fieldId": "aa0e8400-e29b-41d4-a716-446655440005", "label": "Emergency Contact Phone", "type": "PHONE", "pageNumber": 1},
      {"fieldId": "bb0e8400-e29b-41d4-a716-446655440006", "label": "T-Shirt Size", "type": "DROPDOWN", "pageNumber": 1},
      {"fieldId": "dd0e8400-e29b-41d4-a716-446655440008", "label": "Dietary Restrictions", "type": "CHECKBOX", "pageNumber": 2},
      {"fieldId": "ee0e8400-e29b-41d4-a716-446655440009", "label": "Other Dietary Notes", "type": "TEXTAREA", "pageNumber": 2}
    ],
    "responses": [
      {
        "responseId": "resp-001",
        "submittedById": "user-001",
        "submittedByName": "kibuti",
        "submittedByEmail": "kibuti@example.com",
        "status": "SUBMITTED",
        "startedAt": "2025-01-23T10:40:00",
        "submittedAt": "2025-01-23T10:50:00",
        "completionTimeSeconds": 600,
        "answers": {
          "990e8400-e29b-41d4-a716-446655440004": "John Doe",
          "aa0e8400-e29b-41d4-a716-446655440005": "+255712345678",
          "bb0e8400-e29b-41d4-a716-446655440006": "Large",
          "dd0e8400-e29b-41d4-a716-446655440008": ["Vegetarian", "Gluten-free"],
          "ee0e8400-e29b-41d4-a716-446655440009": "No nuts please"
        }
      },
      {
        "responseId": "resp-002",
        "submittedById": "user-002",
        "submittedByName": "john_doe",
        "submittedByEmail": "john@example.com",
        "status": "SUBMITTED",
        "startedAt": "2025-01-23T10:30:00",
        "submittedAt": "2025-01-23T10:45:00",
        "completionTimeSeconds": 900,
        "answers": {
          "990e8400-e29b-41d4-a716-446655440004": "Jane Smith",
          "aa0e8400-e29b-41d4-a716-446655440005": "+255798765432",
          "bb0e8400-e29b-41d4-a716-446655440006": "Medium",
          "dd0e8400-e29b-41d4-a716-446655440008": null,
          "ee0e8400-e29b-41d4-a716-446655440009": null
        }
      }
    ]
  }
}

3.5 Export to CSV

Endpoint:

GET /api/v1/e-events/{eventId}/attendee-questions/analytics/export/csv

Response: Downloads a CSV file

CSV Content:

Response ID,Submitted By,Email,Submitted At,Completion Time (seconds),Emergency Contact Name,Emergency Contact Phone,T-Shirt Size,Dietary Restrictions,Other Dietary Notes
resp-001,kibuti,kibuti@example.com,2025-01-23T10:50:00,600,John Doe,+255712345678,Large,Vegetarian; Gluten-free,No nuts please
resp-002,john_doe,john@example.com,2025-01-23T10:45:00,900,Jane Smith,+255798765432,Medium,,

3.6 Export to Excel

Endpoint:

GET /api/v1/e-events/{eventId}/attendee-questions/analytics/export/excel

Response: Downloads an Excel (.xlsx) file


PART 4: COMPLETE ENDPOINTS REFERENCE

Organizer Endpoints (Draft Events)

Method Endpoint Description
PUT /drafts/{draftId}/attendee-questions Enable questionnaire
PATCH /drafts/{draftId}/attendee-questions Update settings
GET /drafts/{draftId}/attendee-questions Get with full form
DELETE /drafts/{draftId}/attendee-questions Disable (delete)
POST /drafts/{draftId}/attendee-questions/pages Add page
PATCH /drafts/{draftId}/attendee-questions/pages/{pageId} Update page
DELETE /drafts/{draftId}/attendee-questions/pages/{pageId} Delete page
POST /drafts/{draftId}/attendee-questions/pages/reorder Reorder pages
POST /drafts/{draftId}/attendee-questions/pages/{pageId}/fields Add field
PATCH /drafts/{draftId}/attendee-questions/fields/{fieldId} Update field
DELETE /drafts/{draftId}/attendee-questions/fields/{fieldId} Delete field
POST /drafts/{draftId}/attendee-questions/pages/{pageId}/fields/reorder Reorder fields
POST /drafts/{draftId}/attendee-questions/fields/{fieldId}/options Add option
PATCH /drafts/{draftId}/attendee-questions/options/{optionId} Update option
DELETE /drafts/{draftId}/attendee-questions/options/{optionId} Delete option
POST /drafts/{draftId}/attendee-questions/fields/{fieldId}/options/reorder Reorder options

Attendee Endpoints (Published Events)

Method Endpoint Description
GET /{eventId}/attendee-questions Get form (page 1)
GET /{eventId}/attendee-questions/pages/{n} Get specific page
PATCH /{eventId}/attendee-questions/responses/pages/{n} Save page (auto-save)
POST /{eventId}/attendee-questions/responses/submit Submit (no body)
GET /{eventId}/attendee-questions/responses/status Get my status
DELETE /{eventId}/attendee-questions/responses Withdraw

Analytics Endpoints (Organizer Only)

Method Endpoint Description
GET /{eventId}/attendee-questions/analytics/summary Overall stats
GET /{eventId}/attendee-questions/analytics/fields All fields breakdown
GET /{eventId}/attendee-questions/analytics/fields/{fieldId} Single field detail
GET /{eventId}/attendee-questions/analytics/responses Spreadsheet view
GET /{eventId}/attendee-questions/analytics/export/csv Download CSV
GET /{eventId}/attendee-questions/analytics/export/excel Download Excel

PART 5: INSOMNIA TESTING GUIDE

Setup Environment Variables

base_url: http://localhost:8080/api/v1
jwt_token: <your_token>
draft_id: <your_draft_id>
event_id: <your_published_event_id>
page_id: <page_uuid>
field_id: <field_uuid>
option_id: <option_uuid>

Testing Flow

Step 1: Create Event Draft

POST {{base_url}}/e-events/drafts
Authorization: Bearer {{jwt_token}}
Content-Type: application/json

{
  "title": "Test Music Festival 2025",
  "categoryId": "{{category_id}}",
  "eventFormat": "IN_PERSON",
  "description": "Test event for questionnaire"
}

Step 2: Enable Attendee Questions

PUT {{base_url}}/e-events/drafts/{{draft_id}}/attendee-questions
Authorization: Bearer {{jwt_token}}
Content-Type: application/json

{
  "displayTime": "BEFORE_CHECKOUT",
  "isRequiredOnline": true,
  "applyToAtDoor": false
}

Step 3: Get Questionnaire (see default page)

GET {{base_url}}/e-events/drafts/{{draft_id}}/attendee-questions
Authorization: Bearer {{jwt_token}}

Step 4: Add Text Field

POST {{base_url}}/e-events/drafts/{{draft_id}}/attendee-questions/pages/{{page_id}}/fields
Authorization: Bearer {{jwt_token}}
Content-Type: application/json

{
  "type": "TEXT",
  "label": "Emergency Contact Name",
  "placeholder": "Full name",
  "required": true,
  "validation": {
    "minLength": 2,
    "maxLength": 100
  }
}

Step 5: Add Dropdown Field

POST {{base_url}}/e-events/drafts/{{draft_id}}/attendee-questions/pages/{{page_id}}/fields
Authorization: Bearer {{jwt_token}}
Content-Type: application/json

{
  "type": "DROPDOWN",
  "label": "T-Shirt Size",
  "required": true
}

Step 6: Add Options to Dropdown

POST {{base_url}}/e-events/drafts/{{draft_id}}/attendee-questions/fields/{{field_id}}/options
Authorization: Bearer {{jwt_token}}
Content-Type: application/json

{"label": "Small"}

Repeat for: Medium, Large, X-Large

Step 7: Publish Event

POST {{base_url}}/e-events/drafts/{{draft_id}}/publish
Authorization: Bearer {{jwt_token}}

Step 8: (As Attendee) Get Questionnaire

GET {{base_url}}/e-events/{{event_id}}/attendee-questions
Authorization: Bearer {{attendee_token}}

Step 9: (As Attendee) Save Page 1

PATCH {{base_url}}/e-events/{{event_id}}/attendee-questions/responses/pages/1
Authorization: Bearer {{attendee_token}}
Content-Type: application/json

{
  "answers": {
    "{{text_field_id}}": {
      "fieldId": "{{text_field_id}}",
      "value": "John Doe"
    },
    "{{dropdown_field_id}}": {
      "fieldId": "{{dropdown_field_id}}",
      "value": "Large"
    }
  }
}

Step 10: (As Attendee) Submit

POST {{base_url}}/e-events/{{event_id}}/attendee-questions/responses/submit
Authorization: Bearer {{attendee_token}}

Step 11: (As Organizer) View Analytics

GET {{base_url}}/e-events/{{event_id}}/attendee-questions/analytics/summary
Authorization: Bearer {{jwt_token}}

Step 12: (As Organizer) Export CSV

GET {{base_url}}/e-events/{{event_id}}/attendee-questions/analytics/export/csv
Authorization: Bearer {{jwt_token}}

This guide covers the complete Attendee Questions API. Ready to implement and test!