🚀 Form Builder API

RESTful API Documentation v1.0

📋 Overview

The Form Builder API is a comprehensive RESTful API for creating, managing, and submitting dynamic forms. It provides complete backend functionality for form management systems with support for:

Base URL

https://your-domain.com/api/

Response Format

All API responses are returned in JSON format with the following structure:

Success Response:
{
  "status": "success",
  "message": "Operation successful",
  "data": { ... }
}
Error Response:
{
  "status": "error",
  "message": "Error description",
  "errors": { ... }
}

🔐 Authentication

The API uses Bearer Token authentication. After successful login or registration, you'll receive a token that must be included in the Authorization header of subsequent requests.

Using the Token

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Note: Public endpoints (register, login) do not require authentication. All other endpoints require a valid Bearer token.

Token Lifecycle

🎭 Role-Based Access Control

The API implements a three-tier role system with organization-scoped permissions:

🔷 Super Admin

  • Full system access across all organizations
  • Can create, view, update, and delete organizations
  • Can manage all users regardless of organization
  • Can create users with any role (including other super admins)
  • Can assign users to any organization

🔶 Admin (Organization-Scoped)

  • Administrator for a specific organization
  • Can view and manage only users within their organization
  • Can create new users and admins for their organization
  • Cannot access organization management endpoints
  • Cannot create super admins
  • Cannot change user organizations
  • Must be assigned to an organization

🔹 User (Regular)

  • Standard user with limited permissions
  • Can view users in their organization
  • Can update their own profile only
  • Cannot manage other users or organizations
💡 Important: When creating your first super admin, you'll need to manually update the database or promote an existing admin. See the migration documentation for details.

🔑 Authentication Endpoints

POST /register Public

Create a new user account and receive authentication token.

Request Body

{
  "name": "John Doe",
  "email": "john@example.com",
  "password": "secure_password_123"
}

Validation Rules

  • name: Required, string
  • email: Required, valid email format, must be unique
  • password: Required, minimum 8 characters

Success Response (201)

{
  "status": "success",
  "message": "Registration successful",
  "data": {
    "user": {
      "user_id": 1,
      "name": "John Doe",
      "email": "john@example.com",
      "role": "user",
      "org_id": null
    },
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  }
}

POST /login Public

Authenticate user and receive authentication token.

Request Body

{
  "email": "john@example.com",
  "password": "secure_password_123"
}

Success Response (200)

{
  "status": "success",
  "message": "Login successful",
  "data": {
    "user": {
      "user_id": 1,
      "name": "John Doe",
      "email": "john@example.com",
      "role": "user",
      "org_id": 5
    },
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  }
}

Error Response (401)

{
  "status": "error",
  "message": "Invalid credentials"
}

POST /logout Authenticated

Revoke authentication token and log out user.

Headers

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Success Response (200)

{
  "status": "success",
  "message": "Logout successful"
}

👥 User Management

GET /users Authenticated

Retrieve list of users. Results are filtered based on user role:

  • Super admins see all users in the system
  • Regular admins see only users from their organization
  • Regular users see users from their organization

Success Response (200)

{
  "status": "success",
  "data": {
    "users": [
      {
        "user_id": 1,
        "name": "John Doe",
        "email": "john@example.com",
        "role": "user",
        "org_id": 1
      },
      {
        "user_id": 2,
        "name": "Jane Smith",
        "email": "jane@example.com",
        "role": "admin",
        "org_id": 1
      }
    ]
  }
}

GET /users/{id} Authenticated

Get specific user details. Access is restricted by role:

  • Super admins can view any user
  • Regular admins can view users from their organization
  • Users can view themselves or users in their organization

Success Response (200)

{
  "status": "success",
  "data": {
    "user": {
      "user_id": 1,
      "name": "John Doe",
      "email": "john@example.com",
      "role": "user",
      "org_id": 1
    }
  }
}

POST /users Admin/Super Admin

Create a new user account. Permissions vary by role:

  • Super admins can create users with any role (user, admin, super_admin) for any organization
  • Regular admins can create users and admins (not super_admins) for their own organization only

Request Body

{
  "name": "Jane Smith",
  "email": "jane@example.com",
  "password": "secure_password_123",
  "role": "user",
  "org_id": 1
}
📝 Note:
  • Only admins and super admins can create users
  • Regular admins: role can be "user" or "admin" only
  • Super admins: role can be "user", "admin", or "super_admin"
  • For regular admins, org_id defaults to their organization if not provided
  • Regular admins cannot create users for other organizations
  • Password must be at least 8 characters
  • Email must be unique across all users

Success Response (201)

{
  "status": "success",
  "message": "User created successfully",
  "data": {
    "user": {
      "user_id": 2,
      "name": "Jane Smith",
      "email": "jane@example.com",
      "role": "user",
      "org_id": 1
    }
  }
}

PUT /users/{id} Authenticated

Update user information. Permissions vary by role:

  • Super admins can update any user, change any role, and modify organizations
  • Regular admins can update users in their organization (limited role changes)
  • Users can only update their own profile (name, email, password)

Request Body (partial update supported)

{
  "name": "John Updated",
  "email": "john.new@example.com",
  "role": "admin",
  "org_id": 2
}
📝 Note:
  • Regular users can update: name, email, password
  • Regular admins can update users in their org and change roles to "user" or "admin" only
  • Only super admins can change org_id and set role to "super_admin"
  • Regular admins cannot change user organizations
  • All fields are optional - only include fields you want to update

Success Response (200)

{
  "status": "success",
  "message": "User updated successfully",
  "data": {
    "user": {
      "user_id": 1,
      "name": "John Updated",
      "email": "john.new@example.com",
      "role": "admin",
      "org_id": 2
    }
  }
}

DELETE /users/{id} Admin/Super Admin

Delete a user account. Permissions vary by role:

  • Super admins can delete any user (except themselves)
  • Regular admins can delete users from their organization only
  • Regular admins cannot delete super admins
📝 Note:
  • Only admins and super admins can delete users
  • Users cannot delete their own account
  • Regular admins are restricted to their organization
  • All user tokens will be revoked upon deletion

Success Response (200)

{
  "status": "success",
  "message": "User deleted successfully"
}

GET /user Authenticated

Get current authenticated user details.

Success Response (200)

{
  "status": "success",
  "data": {
    "user": {
      "user_id": 1,
      "name": "John Doe",
      "email": "john@example.com",
      "role": "admin",
      "org_id": 1,
      "organizations": [
        {
          "org_id": 1,
          "name": "Acme Corp",
          "address": "123 Main St",
          "accent_color": "#FF5733"
        }
      ]
    }
  }
}

🏢 Organization Management

⚠️ Super Admin Only: All organization management endpoints require super admin role. Regular admins and users cannot access these endpoints.

GET /organizations Super Admin

Retrieve list of all organizations. Only accessible by super admins.

Success Response (200)

{
  "status": "success",
  "data": {
    "organizations": [
      {
        "org_id": 1,
        "name": "Acme Corp",
        "address": "123 Main St",
        "accent_color": "#FF5733"
      }
    ]
  }
}

GET /organizations/{id} Super Admin

Get specific organization details with member list. Only accessible by super admins.

Success Response (200)

{
  "status": "success",
  "data": {
    "organization": {
      "org_id": 1,
      "name": "Acme Corp",
      "address": "123 Main St",
      "accent_color": "#FF5733",
      "members": [
        {
          "user_id": 1,
          "name": "John Doe",
          "email": "john@example.com",
          "role": "admin"
        }
      ]
    }
  }
}

POST /organizations Super Admin

Create new organization. Only accessible by super admins. The creator is automatically added as a member.

Request Body

{
  "name": "New Corp",
  "address": "456 Oak Ave",
  "accent_color": "#3498DB"
}

Success Response (201)

{
  "status": "success",
  "message": "Organization created successfully",
  "data": {
    "organization": {
      "org_id": 2,
      "name": "New Corp",
      "address": "456 Oak Ave",
      "accent_color": "#3498DB"
    }
  }
}

PUT /organizations/{id} Super Admin

Update organization details. Only accessible by super admins.

Request Body (partial update supported)

{
  "name": "Updated Corp",
  "accent_color": "#E74C3C"
}

Success Response (200)

{
  "status": "success",
  "message": "Organization updated successfully",
  "data": {
    "organization": {
      "org_id": 1,
      "name": "Updated Corp",
      "address": "123 Main St",
      "accent_color": "#E74C3C"
    }
  }
}

📁 Folder Management

GET /folders Authenticated

Get all folders user has access to. Admins see all folders, users see folders they have permissions for.

Success Response (200)

{
  "status": "success",
  "data": {
    "folders": [
      {
        "folder_id": 1,
        "name": "HR Forms",
        "parent_folder_id": null,
        "org_id": 1
      },
      {
        "folder_id": 2,
        "name": "Onboarding",
        "parent_folder_id": 1,
        "org_id": 1
      }
    ]
  }
}

GET /folders/{id} Authenticated

Get specific folder with parent and organization information.

Success Response (200)

{
  "status": "success",
  "data": {
    "folder": {
      "folder_id": 2,
      "name": "Onboarding",
      "parent_folder_id": 1,
      "org_id": 1,
      "parent": {
        "folder_id": 1,
        "name": "HR Forms"
      },
      "organization": {
        "org_id": 1,
        "name": "Acme Corp"
      }
    }
  }
}

POST /folders Authenticated

Create new folder. Creator automatically gets admin permission for the folder.

Request Body

{
  "name": "Finance Forms",
  "org_id": 1,
  "parent_folder_id": null
}
Note: Set parent_folder_id to null for root-level folders, or specify a parent folder ID for nested folders.

Success Response (201)

{
  "status": "success",
  "message": "Folder created successfully",
  "data": {
    "folder": {
      "folder_id": 3,
      "name": "Finance Forms",
      "parent_folder_id": null,
      "org_id": 1
    }
  }
}

📝 Form Template Management

GET /forms Authenticated

Get all forms in user's organization.

Success Response (200)

{
  "status": "success",
  "data": {
    "forms": [
      {
        "form_id": 1,
        "template_id": 1,
        "name": "Employee Onboarding",
        "title": "Employee Onboarding",
        "description": "New employee intake form",
        "folder_id": 1,
        "concept_flag": false,
        "publication_date": "2025-10-15",
        "submission_type": 1,
        "status": "published",
        "version": 1,
        "created_at": "2025-10-10 14:30:00",
        "updated_at": "2025-10-15 09:20:00"
      }
    ]
  }
}

GET /forms/{id} Authenticated

Get specific form template details.

Success Response (200)

{
  "status": "success",
  "data": {
    "form": {
      "form_id": 1,
      "template_id": 1,
      "title": "Employee Onboarding",
      "description": "New employee intake form",
      "folder_id": 1,
      "concept_flag": false,
      "publication_date": "2025-10-15",
      "submission_type": 1,
      "status": "published",
      "version": 1
    }
  }
}

POST /forms Authenticated

Create new form template with optional field definitions.

Request Body

{
  "title": "Feedback Form",
  "folder_id": 1,
  "description": "Employee feedback survey",
  "concept_flag": 1,
  "submission_type": 1,
  "form_data": {
    "fields": [
      {
        "field_name": "name",
        "type": "text",
        "label": "Your Name",
        "required": true,
        "order_index": 1
      },
      {
        "field_name": "rating",
        "type": "number",
        "label": "Rating (1-5)",
        "required": true,
        "order_index": 2
      }
    ]
  }
}
Field Types: text, number, date, boolean, signature, file, image
concept_flag: 1 = draft, 0 = published

Success Response (201)

{
  "status": "success",
  "message": "Form created successfully",
  "data": {
    "form": {
      "form_id": 2,
      "title": "Feedback Form",
      "folder_id": 1,
      "concept_flag": true,
      "submission_type": 1
    }
  }
}

PUT /forms/{id} Authenticated

Update form template metadata.

Request Body (partial update supported)

{
  "title": "Updated Form Title",
  "description": "Updated description"
}

DELETE /forms/{id} Authenticated

Delete form template.

Success Response (200)

{
  "status": "success",
  "message": "Form deleted successfully"
}

POST /forms/{id}/publish Authenticated

Publish a draft form (changes concept_flag from 1 to 0).

GET /forms/{id}/fields Authenticated

Get all field definitions for a specific form.

Success Response (200)

{
  "status": "success",
  "data": {
    "fields": [
      {
        "field_id": 1,
        "template_id": 1,
        "field_name": "full_name",
        "type": "text",
        "label": "Full Name",
        "placeholder": "Enter your full name",
        "required": true,
        "order_index": 1
      },
      {
        "field_id": 2,
        "template_id": 1,
        "field_name": "email",
        "type": "text",
        "label": "Email Address",
        "required": true,
        "order_index": 2
      }
    ]
  }
}

PUT /forms/{id}/fields Authenticated

Update form field definitions (bulk update).

Request Body

{
  "fields": [
    {
      "field_id": 1,
      "label": "Updated Label",
      "required": false
    },
    {
      "field_id": 2,
      "placeholder": "New placeholder text"
    }
  ]
}

✅ Form Submissions

POST /submissions Authenticated

Submit form data or save as draft. Supports file uploads and various field types.

Request Body

{
  "form_id": 1,
  "submission_type": 1,
  "data": [
    {
      "field_id": 1,
      "value": "John Doe"
    },
    {
      "field_id": 2,
      "value": "john@example.com"
    },
    {
      "field_id": 3,
      "value": 42
    },
    {
      "field_id": 4,
      "value": true
    }
  ],
  "files": []
}
submission_type:
  • 0 = Draft (incomplete submission)
  • 1 = Complete (final submission)

Field Value Types

Field Type Value Format Example
text String "John Doe"
number Number 42 or 3.14
boolean Boolean true or false
date String (ISO date) "2025-10-28"
signature Base64 string "data:image/png;base64,..."
file/image File path or upload data Included in files array

Success Response (200)

{
  "status": "success",
  "message": "Submission created successfully",
  "data": {
    "submission": {
      "submission_id": 1,
      "form_id": 1,
      "version_id": 1,
      "user_id": 1,
      "submission_type": 1,
      "submitted_at": "2025-10-28 14:30:00"
    }
  }
}
Version Control: The API automatically creates or uses the latest form version when creating submissions.

GET /submissions Authenticated

Get list of all submissions with optional form filter.

Query Parameters

form_id (optional): Filter submissions by form ID

Success Response (200)

{
  "status": "success",
  "data": {
    "submissions": [
      {
        "submission_id": 1,
        "form_id": 1,
        "version_id": 1,
        "user_id": 1,
        "submission_type": 1,
        "submitted_at": "2025-10-28 14:30:00",
        "user_name": "John Doe",
        "user_email": "john@example.com"
      }
    ]
  }
}

GET /submissions/{id} Authenticated

Get detailed submission with all field data, including file paths and image references.

Success Response (200)

{
  "status": "success",
  "data": {
    "submission": {
      "submission_id": 1,
      "form_id": 1,
      "data": [
        {
          "field_id": 1,
          "field_title": "Full Name",
          "value": "John Doe"
        },
        {
          "field_id": 3,
          "field_title": "Photo",
          "value": "uploads/submissions/images/1_3_timestamp.jpg"
        }
      ]
    }
  }
}

PUT /submissions/{id} Authenticated

Update existing submission, change draft to complete, or modify field values.

Request Body

{
  "submission_type": 1,
  "data": [
    { "field_id": 1, "value": "Updated Value" }
  ]
}

GET /submissions/export/csv?form_id={id} Authenticated

Export all submissions for a form to CSV file for Excel or data analysis.

Query Parameters

  • form_id (required): Form ID to export submissions from

Response

  • Content-Type: text/csv
  • Filename: submissions_{form_id}_{date}.csv
  • Includes all submission data with field labels as headers

GET /submissions/{id}/export/pdf Authenticated

Export single submission as formatted HTML view (ready for PDF conversion or printing).

Note: Returns HTML that can be printed to PDF using browser print functionality.

GET /submissions/{id}/image/{field_id} Authenticated

Get image or signature data for a specific field in base64 format.

Success Response (200)

{
  "status": "success",
  "data": {
    "type": "image",
    "mime_type": "image/jpeg",
    "data": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEA...",
    "url": "/uploads/submissions/images/1_3_1698765432.jpg"
  }
}
Use Cases: Display signatures, show photos, download images for records, embed in exports

GET /submissions/files/{type}/{filename} Authenticated

Serve uploaded files directly. Images are displayed inline, other files are downloaded.

Parameters

  • type: images, signatures, or files
  • filename: Name of the file

Example URLs

/submissions/files/images/1_3_1698765432.jpg
/submissions/files/signatures/1_5_1698765433.png
/submissions/files/files/1_8_1698765434.pdf
Security: Access is verified - users can only access files from their own submissions or admins can access all.

🔔 Password Change Notifications

The Password Change Notification system allows users to request notifications for password changes. These requests must be approved by an administrator.

POST /api/password-notification/request

POST /api/password-notification/request

Request password change notification. Users provide their username and email to receive notifications. This endpoint does not require authentication.

Request Body

{
  "username": "johndoe",
  "email": "john@example.com"
}

Response (200 OK)

{
  "success": true,
  "message": "If the provided details match our records, your request has been submitted for admin approval."
}
Note: For security reasons, this endpoint always returns a success message regardless of whether the user exists or not.
Multiple Requests: Users can submit new requests over time, but only if their previous requests have been approved. If there's already a pending (unapproved) request for the same user, a new request will not be created to prevent duplicates.

GET /api/password-notification/pending

GET /api/password-notification/pending

Admin Only: Get all pending password change notification requests.

Headers

Authorization: Bearer YOUR_TOKEN_HERE

Response (200 OK)

{
  "success": true,
  "data": {
    "pending_requests": [
      {
        "id": 1,
        "user_id": 123,
        "username": "johndoe",
        "email_address": "john@example.com",
        "is_approved": "no"
      }
    ],
    "count": 1
  }
}

GET /api/password-notification/all

GET /api/password-notification/all

Admin Only: Get all password change notification requests (both pending and approved).

Headers

Authorization: Bearer YOUR_TOKEN_HERE

Response (200 OK)

{
  "success": true,
  "data": {
    "notifications": [
      {
        "id": 1,
        "user_id": 123,
        "username": "johndoe",
        "email_address": "john@example.com",
        "is_approved": "no"
      },
      {
        "id": 2,
        "user_id": 456,
        "username": "janedoe",
        "email_address": "jane@example.com",
        "is_approved": "yes"
      }
    ],
    "count": 2
  }
}

POST /api/password-notification/{id}/approve

POST /api/password-notification/{id}/approve

Admin Only: Approve a pending password change notification request.

Headers

Authorization: Bearer YOUR_TOKEN_HERE

Response (200 OK)

{
  "success": true,
  "message": "Notification request approved successfully"
}

DELETE /api/password-notification/{id}

DELETE /api/password-notification/{id}

Admin Only: Delete a password change notification request.

Headers

Authorization: Bearer YOUR_TOKEN_HERE

Response (200 OK)

{
  "success": true,
  "message": "Notification request deleted successfully"
}
Workflow:
  1. User submits notification request with username and email
  2. System verifies user exists with matching credentials
  3. Request is created with is_approved: 'no'
  4. Admin reviews pending requests
  5. Admin either approves or deletes the request

📊 Data Export

Export submission data in multiple formats for analysis, reporting, or archiving purposes.

GET /submissions/export Authenticated

Export all submissions for a specific form in CSV, Excel (XLSX), or OpenDocument (ODT) format.

Query Parameters

Parameter Type Required Description
form_id Integer Yes The ID of the form to export submissions from
format String No Export format: csv, xlsx, or odt (default: csv)

Supported Formats

  • CSV - Comma-separated values, compatible with Excel and Google Sheets
  • XLSX - Microsoft Excel format (.xlsx) with proper formatting
  • ODT - OpenDocument Text format (.odt), compatible with LibreOffice/OpenOffice

Example Requests

GET /api/submissions/export?form_id=26&format=csv
GET /api/submissions/export?form_id=26&format=xlsx
GET /api/submissions/export?form_id=26&format=odt

Response

File download with appropriate headers:

  • Filename format: {form_title}_{timestamp}.{extension}
  • Content-Type varies by format
  • Content-Disposition: attachment

Export Data Structure

Each exported file includes:

Column Description
Submission ID Unique identifier for the submission
Submitted At Date and time of submission (YYYY-MM-DD HH:MM:SS)
Status Complete or Draft
User Name Name of the submitting user
User Email Email of the submitting user
Organization Organization name (if applicable)
Form Fields Dynamic columns for each form field value

Field Value Formatting

Field Type Export Format
CHECKBOX Yes / No
FILE, PHOTO, SIGNATURE Filename only
NUMBER, PHONE Numeric value or formatted text
TEXT, TEXTAREA, EMAIL, etc. Text value
HEADER, DIVIDER Excluded from export
📝 Notes:
  • CSV exports include UTF-8 BOM for proper Excel compatibility
  • XLSX files are created using OpenXML format with proper structure
  • ODT files include proper document structure and table formatting
  • Decorative fields (HEADER, DIVIDER) are automatically excluded
  • Empty values are represented as blank cells
  • File uploads show only the filename, not the full path

Error Responses

Missing form_id (400):
{
  "status": "error",
  "message": "Form ID is required"
}
Invalid format (400):
{
  "status": "error",
  "message": "Invalid format. Supported formats: csv, xlsx, odt"
}
Form not found (404):
{
  "status": "error",
  "message": "Form not found"
}
Security: Only authenticated users can export data. Exports respect user permissions and organization boundaries.

⚠️ Error Codes & Responses

HTTP Status Codes

Code Status Description
200 OK Successful GET, PUT, DELETE operation
201 Created Successful POST operation (resource created)
400 Bad Request Invalid request format or missing required fields
401 Unauthorized Missing or invalid authentication token
403 Forbidden Valid token but insufficient permissions
404 Not Found Requested resource doesn't exist
422 Validation Error Request validation failed
500 Server Error Internal server error

Common Error Examples

Validation Error (422):
{
  "status": "error",
  "message": "Validation failed",
  "errors": {
    "email": "Valid email is required",
    "password": "Password must be at least 8 characters"
  }
}
Unauthorized (401):
{
  "status": "error",
  "message": "Unauthorized. Invalid or expired token."
}
Forbidden (403):
{
  "status": "error",
  "message": "You do not have permission to access this resource"
}
Not Found (404):
{
  "status": "error",
  "message": "Resource not found"
}

📚 Additional Information

Rate Limiting

Consider implementing rate limiting in production to prevent abuse. Recommended limits:

File Upload Limits

CORS Configuration

The API supports CORS for cross-origin requests. Configure allowed origins in public/api.php:

Access-Control-Allow-Origin: https://your-frontend-domain.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true

Security Best Practices

Database Backup

Regular database backups are essential. Recommended schedule: