-
Notifications
You must be signed in to change notification settings - Fork 15
REST API Forms
The complete usage guide for the Forms module of the REST API β custom forms, their version chains, and submissions. Mirrors the interactive documentation at System β API β Documentation (with its live "Try it" tester).
Note
New to the API? The basics table on REST API: Tickets covers base URL, authentication, the response envelope, error codes, rate limits and PATCH semantics β identical across all modules.
What's distinctive about Forms:
| π Version chains | A form's history is a chain of rows β each new version points back at its predecessor, the leaf is the only editable version, older ones are frozen snapshots. GET /forms lists one row per chain (the current version); PATCH/fork/delete on a frozen version is a 409. |
βοΈ The form.submitted workflow event
|
Submitting via the API fires the exact same workflow dispatch as the UI, with the label-keyed answers map β so the marquee "new starter form β tickets in IT/HR/Facilities" automation works identically whether a human or a script submits. |
| 𧬠Field ids survive edits | Updating fields uses the module's positional sync: existing field ids are reused in order, so historical submission data stays mapped. Removed fields lose their submission data β fork a new version instead if you need to restructure without losing history. |
π is_active, finally settable
|
Nothing in the UI writes is_active today β the API is currently the only way to retire a form (stop submissions) without deleting it. |
| π¦ Native JSON values | Submit checkbox booleans as booleans and multi-select answers as arrays β no pre-encoding. Answers come back with checkboxes decoded to arrays too. |
B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_β¦"
# Create a form
FORM=$(curl -s -X POST "$B/forms" -H "$K" -H "Content-Type: application/json" -d '{
"title": "New starter",
"fields": [
{ "field_type": "text", "label": "Full name", "is_required": true },
{ "field_type": "email", "label": "Manager email", "is_required": true },
{ "field_type": "dropdown", "label": "Department", "options": ["IT", "HR", "Finance"] },
{ "field_type": "checkboxes", "label": "Equipment", "options": ["Laptop", "Phone"] }
]}' | jq '.data')
ID=$(echo "$FORM" | jq -r '.id')
# Submit it (field ids from the create response; arrays and booleans are fine as-is)
curl -s -X POST "$B/forms/$ID/submissions" -H "$K" -H "Content-Type: application/json" -d '{
"data": { "1": "Sam Jones", "2": "manager@example.com", "3": "IT", "4": ["Laptop", "Phone"] }}'
# Read the answers back, labels attached
curl -s "$B/forms/$ID/submissions" -H "$K"One row per version chain β the current version, with field_count and submission_count. is_active=true|false filters; q searches titles.
title required; fields is an ordered array of {field_type, label, options?, is_required?}.
Field types: text, textarea, email, number, checkbox (single yes/no), checkboxes (multi-select), dropdown, radio. The last three take an options array. Unknown types and empty labels are a 422 (the UI silently stores/drops them).
The form with its fields and version info:
{ "data": { "id": 7, "title": "New starter", "is_active": true,
"version": { "number": 2, "parent_form_id": 6, "is_current": true },
"fields": [ { "id": 31, "field_type": "text", "label": "Full name", "options": null,
"is_required": true, "sort_order": 0 } ] } }In-place save of the current version (a frozen historical version is a 409). Send only what changes β title, description, is_active, and/or the full fields array (positional sync: existing ids reused in order, extras appended, trailing leftovers deleted with their submission data).
Deletes one version and its submissions β leaf only. Beware: deleting the leaf resurfaces the previous version as current (that's the UI's behaviour too). A mid-chain id is a 409. Pass ?chain=true to delete the entire version chain and every submission, transactionally β the "actually delete the form" verb.
Every version in the chain containing this form (any member's id works), oldest first β version.is_current marks the editable leaf.
Fork the current version: clones title, description and fields into a new editable version (version_number + 1); the source freezes. Forking from a non-leaf is a 409. Use this instead of PATCH when restructuring a form whose submission history you want to keep intact.
data maps field id β value. Validation matches the UI exactly: required fields (a required checkbox must be truthy, required checkboxes must tick at least one), email format, numeric check. Improvements for machines: unknown field ids are a 422 (the UI inserts them blindly), an inactive form is a 409, and booleans/arrays are accepted natively.
On success (201) the form.submitted workflow event fires with the label-keyed answers map and the first email-type answer surfaced as submission.email β identical to a UI submission.
Newest first, paginated; submitted_since / submitted_before bound the window. Each submission carries its answers joined to field definitions:
{ "data": [ { "id": 12, "form": { "id": 7, "title": "New starter" },
"submitted_by": { "id": 1, "name": "Administrator" }, "submitted_at": "2026-07-03T09:15:00Z",
"answers": [
{ "field_id": 31, "label": "Full name", "field_type": "text", "value": "Sam Jones" },
{ "field_id": 34, "label": "Equipment", "field_type": "checkboxes", "value": ["Laptop", "Phone"] } ] } ] }One submission (404 if it doesn't belong to that form). DELETE removes it and its answers transactionally.
| Group | Actions |
|---|---|
Forms (forms) |
read Β· create (incl. version forks) Β· update Β· delete
|
Form submissions (form_submissions) |
read Β· create (the submit verb) Β· delete
|
Forms are install-wide β no company scoping (matches the UI) β and the module has no audit trail. The AI form-generation endpoints stay UI-only.
FreeITSM β an open-source IT Service Management platform Β· github.com/edmozley/freeitsm Β· MIT licence
- Installation
- β° Scheduled tasks (cron jobs)
- Architecture
- AI Providers
- Internationalisation (i18n)
- Timezones & Time Handling
- Theming & Dark Mode
- β¨οΈ Command palette (βK)
- π Searching inside tickets
- π Attached documents
- MobileβFriendly
-
Security
- Layer 1 β which modules you can enter
- β³ π§© Module Access Control
- β³ π οΈ Module Access β Developer Guide
- Layer 2 β what you can administer
- β³ π Roles & Permissions
- β³ π οΈ Roles β Developer Guide
- β³ π€ Why capabilities are constants
- Layer 3 β the System module
- β³ π Admin Access Control
- Hardening
- β³ π Security review response 2026-08
- β³ π‘οΈ Security hardening 2026-08
- β³ π οΈ Security hardening 2026-08 β Developer Guide
- β³ π‘οΈ Round three β plain English
- β³ π οΈ Round three β Developer Guide
- Single Sign-On (SSO)
- ποΈ LDAP & Active Directory
- Browser Extension
- API Reference
-
π REST API β how it works
- β³ π« REST API: Tickets
- β³ π» REST API: Assets
- β³ π΄ REST API: Problems
- β³ π REST API: Changes
- β³ π REST API: Knowledge
- β³ β REST API: Tasks
- β³ ποΈ REST API: CMDB
- β³ π REST API: Contracts
- β³ ποΈ REST API: Calendar
- β³ πΏ REST API: Software
- β³ π¦ REST API: Service Status
- β³ βοΈ REST API: Morning Checks
- β³ π REST API: Forms
- β³ βοΈ REST API: Workflow
- β³ πΊοΈ REST API: Network Mapper
- β³ π§ Using the API docs page
- β³ π OpenAPI specification
- β³ β OpenAPI: kept correct
- β³ π οΈ Maintaining the catalogue
- Watchtower
-
Tickets
- β³ Mailbox Authentication
- β³ π€ Email send log
- β³ Basic IMAP mailboxes
- β³ Email rendering & images
- β³ SLA Management
- β³ WhatsApp channel
- β³ π¬ Web chat channel
- β³ π£ Slack channel
- β³ π Linking tickets
- β³ ποΈ Canned responses
- β³ βοΈ Limiting replies to particular senders
- β³ βοΈ Email signatures
- β³ π The public web address
- β³ π’ Ticket numbering
- β³ π Raising a ticket for someone else
- β³ π Merging tickets
- β³ β Splitting tickets
- β³ β Selecting several tickets
- β³ π οΈ Snoozing tickets β Developer Guide
- β³ π₯ Collision detection
- β³ β±οΈ Time tracking
- Problem Management
- Tasks
- Assets
- Knowledge
- Change Management
- Calendar
- Morning Checks
- Reporting
- Software
- Forms
- Contracts
- Service Status
- π Notifications
- π¨ War Room
- Self-Service Portal
- LMS
- Process Mapper
- CMDB
- Network Mapper
- Workflows
- Issue trackers (Jira, Azure DevOps)
- System
-
Overview
- β³ π Progress tracker
- β³ Concepts & vocabulary
- β³ Email routing & mailboxes
- β³ Settings: global vs per-company
- β³ Users & self-service
- β³ Staff cross-company access
- β³ Worked examples
- β³ Pitfalls & gotchas
- β³ Scope: what it's for
- β³ π οΈ Developer Guide (make a module multi-company)
- β³ ποΈ Case study: CMDB (a linked graph)
- β³ π§ͺ Test harness (prove it's isolated)