Skip to content

Form configuration

A form configuration is a JSON document that defines pages, fields, validation, translations, and integration flags. Instances created later must match this shape.

This guide walks the configuration part by part, then assembles a complete template you can copy and adapt. When you are ready, validate and persist it with the configuration endpoints at the end.

Contract version covered here: 1.0.0.

Layer Role
Structure (pages, fields, options) IDs, keys, types, rules — no user-facing copy
Translations All display strings (titles, labels, placeholders, …)
$ references Structure points at translation paths (e.g. $.pages.p1.fields.p1_k1.label)

Literals must not be hard-coded on pages/fields. Put them under translations, then reference them with $-prefixed paths.

Every id (form, page, field, dropdown option) must be a UUID v4. Stable string **key**s (e.g. p1, p1_k1) are what you use elsewhere (including workflow view field maps).


{
"version": "1.0.0",
"id": "12c8aa13-88f6-40de-b7c0-4b1bef48bb51"
}
Property Purpose
version Configuration schema version (semver). Use 1.0.0 for the current contract.
id UUID of this configuration. Generate your own for production; keep it stable across updates.

Part 2 — Controls, metadata, integrations

Section titled “Part 2 — Controls, metadata, integrations”
{
"controls": {
"enableLogging": false
},
"metadata": {
"captureTimestamp": true,
"captureTags": true,
"captureSummary": true,
"captureLocation": false
},
"integrations": {
"allowSpaceAssociations": true,
"allowWorkflowStarts": true
}
}
Block Property Purpose
controls enableLogging When true, audit logging is enabled for instance updates (as supported by the deployment).
metadata captureTimestamp Capture a timestamp with the instance.
captureTags Capture tags (comma-separated string on instances when enabled).
captureSummary Capture a free-text summary.
captureLocation Capture location metadata.
integrations allowSpaceAssociations Allow associating filled forms with Spaces.
allowWorkflowStarts Allow starting a workflow from instances of this form. Set true if you will pair with a workflow configuration.

Translations hold all human-readable copy. Structure elsewhere only stores $ paths into this tree.

{
"translations": {
"defaultLanguage": "en",
"en": {
"details": {
"title": "Field Snapshot",
"description": "Capture a summary snapshot of a field inspection."
},
"common": {
"buttons": {
"next": "Next",
"back": "Back",
"submit": "Submit"
}
},
"pages": {
"p1": {
"title": "Site details",
"description": "General information about the inspection site.",
"fields": {
"p1_k1": {
"label": "Name",
"placeholder": "Enter field name",
"tooltip": "Field name",
"description": "Short name for this inspection."
}
}
}
}
},
"fr": {
"details": {
"title": "Instantané de terrain",
"description": "Capturez un résumé d’une inspection de terrain."
}
}
}
}
Property Purpose
defaultLanguage Language code used when resolving $ refs if no other language is selected (must exist as a sibling key, e.g. en).
Language keys (en, fr, …) Open map of locale bundles. Add only the languages you need.
details Form-level title and description.
common.buttons Shared UI button labels.
pages.<pageKey>... Per-page and per-field copy. Page/field keys here must match the key values on structural pages / fields.
Dropdown option labels Live under fields.<fieldKey>.options.<optionKey>.label (see Part 5).

How $ refs work: a structural property such as "label": "$.pages.p1.fields.p1_k1.label" means “resolve pages.p1.fields.p1_k1.label inside the active language bundle (falling back via defaultLanguage).” The leading $. marks a translation path — do not put the literal string on the field.

Incomplete locale bundles are fine for languages you only partially translate; ensure every $ path you reference exists under defaultLanguage.


Supported field type values: text, textarea, date, dropdown, file.

Common field properties:

Property Purpose
id UUID v4 for the field.
key Stable key (used in translations and workflow listFields / detailFields).
order Display order within the page.
type One of the supported types above.
value Default shown in the UI. Empty string = start blank; non-empty = pre-fill.
label, placeholder, tooltip, description $ paths into translations.
validation Regex applied to submitted answers, not to the config file itself.
minLength / maxLength Length bounds for text-like fields.
format For date fields (e.g. YYYY-MM-DD HH:mm:ss).
visible / editable / required UI and submit rules.

Example page with a text field:

{
"pages": [
{
"id": "dce7622a-73c0-466d-8c2c-85362589a754",
"key": "p1",
"order": 1,
"title": "$.pages.p1.title",
"description": "$.pages.p1.description",
"fields": [
{
"id": "28837e41-7f0b-4f01-a2b1-794da82e124b",
"key": "p1_k1",
"order": 1,
"type": "text",
"value": "",
"label": "$.pages.p1.fields.p1_k1.label",
"placeholder": "$.pages.p1.fields.p1_k1.placeholder",
"tooltip": "$.pages.p1.fields.p1_k1.tooltip",
"description": "$.pages.p1.fields.p1_k1.description",
"validation": "^(?!\\s*$).+",
"minLength": 1,
"maxLength": 120,
"visible": true,
"editable": true,
"required": true
}
]
}
]
}

Dropdown option labels live in translations; the structure lists option id / key / value / $ label refs.

Translations excerpt:

"p1_k3": {
"label": "Status",
"placeholder": "Select inspection status",
"tooltip": "Inspection status",
"description": "Current status of the field inspection.",
"options": {
"status_open": { "label": "Open" },
"status_in_progress": { "label": "In progress" },
"status_closed": { "label": "Closed" }
}
}

Structure excerpt:

{
"type": "dropdown",
"value": "open",
"validation": "^(open|in_progress|closed)$",
"options": [
{
"id": "b1b2c3d4-e5f6-4a89-8123-111111111111",
"key": "status_open",
"order": 1,
"value": "open",
"label": "$.pages.p1.fields.p1_k3.options.status_open.label"
}
]
}

value on the field is the option value (e.g. open), not the option key.


When type is file, include a file object:

Property Purpose
accept MIME type(s) and/or extensions the picker should allow (string or array).
maxBytes Max size per file in bytes.
multiple Allow more than one attachment.
maxFiles Cap when multiple is true.

At instance time, file fields are submitted as [], then binaries are uploaded via Media — see Form with file.

{
"type": "file",
"value": "",
"required": false,
"file": {
"accept": ["image/jpeg", "image/png", "image/heic"],
"maxBytes": 10485760,
"multiple": true,
"maxFiles": 3
}
}

Full configuration combining the parts above — all field types, translation $ refs, dropdown options, file metadata, metadata flags, and workflow-friendly integrations. Replace UUIDs with your own before creating in production.

{
"version": "1.0.0",
"id": "12c8aa13-88f6-40de-b7c0-4b1bef48bb51",
"controls": {
"enableLogging": false
},
"metadata": {
"captureTimestamp": true,
"captureTags": true,
"captureSummary": true,
"captureLocation": false
},
"integrations": {
"allowSpaceAssociations": true,
"allowWorkflowStarts": true
},
"translations": {
"defaultLanguage": "en",
"en": {
"details": {
"title": "Field Snapshot",
"description": "A form to quickly capture a summary snapshot of a field inspection."
},
"common": {
"buttons": {
"next": "Next",
"back": "Back",
"submit": "Submit"
}
},
"pages": {
"p1": {
"title": "Page 1",
"description": "General information about the inspection site.",
"fields": {
"p1_k1": {
"label": "Name",
"placeholder": "Enter field name.",
"tooltip": "Field Name",
"description": "Something about a name."
},
"p1_k2": {
"label": "Date",
"placeholder": "Enter today's date",
"tooltip": "Today's date",
"description": "Something about a date."
},
"p1_k3": {
"label": "Status",
"placeholder": "Select inspection status",
"tooltip": "Inspection status",
"description": "Current status of the field inspection.",
"options": {
"status_open": { "label": "Open" },
"status_in_progress": { "label": "In progress" },
"status_closed": { "label": "Closed" }
}
}
}
},
"p2": {
"title": "Page 2",
"description": "Findings and supporting attachments.",
"fields": {
"p2_k1": {
"label": "Summary",
"placeholder": "Enter a summary of your findings.",
"tooltip": "Summary Findings",
"description": "Support field snapshot information and observations."
},
"p2_k2": {
"label": "Site photo",
"placeholder": "Attach photos from the site",
"tooltip": "Site photo",
"description": "Optional photographic evidence."
}
}
}
}
},
"fr": {
"details": {
"title": "Instantané de terrain",
"description": "Capturez un résumé d’une inspection de terrain."
}
}
},
"pages": [
{
"id": "dce7622a-73c0-466d-8c2c-85362589a754",
"key": "p1",
"order": 1,
"title": "$.pages.p1.title",
"description": "$.pages.p1.description",
"fields": [
{
"id": "28837e41-7f0b-4f01-a2b1-794da82e124b",
"key": "p1_k1",
"order": 1,
"type": "text",
"value": "",
"label": "$.pages.p1.fields.p1_k1.label",
"placeholder": "$.pages.p1.fields.p1_k1.placeholder",
"tooltip": "$.pages.p1.fields.p1_k1.tooltip",
"description": "$.pages.p1.fields.p1_k1.description",
"validation": "^(?!\\s*$).+",
"minLength": 1,
"maxLength": 120,
"visible": true,
"editable": true,
"required": true
},
{
"id": "d8c9eb00-3cb5-488c-8c1e-a0fa565212e2",
"key": "p1_k2",
"order": 2,
"type": "date",
"value": "",
"label": "$.pages.p1.fields.p1_k2.label",
"placeholder": "$.pages.p1.fields.p1_k2.placeholder",
"tooltip": "$.pages.p1.fields.p1_k2.tooltip",
"description": "$.pages.p1.fields.p1_k2.description",
"validation": "^(?!\\s*$).+",
"format": "YYYY-MM-DD HH:mm:ss",
"visible": true,
"editable": true,
"required": true
},
{
"id": "a1b2c3d4-e5f6-4a89-a012-3456789abcde",
"key": "p1_k3",
"order": 3,
"type": "dropdown",
"value": "open",
"label": "$.pages.p1.fields.p1_k3.label",
"placeholder": "$.pages.p1.fields.p1_k3.placeholder",
"tooltip": "$.pages.p1.fields.p1_k3.tooltip",
"description": "$.pages.p1.fields.p1_k3.description",
"validation": "^(open|in_progress|closed)$",
"visible": true,
"editable": true,
"required": true,
"options": [
{
"id": "b1b2c3d4-e5f6-4a89-8123-111111111111",
"key": "status_open",
"order": 1,
"value": "open",
"label": "$.pages.p1.fields.p1_k3.options.status_open.label"
},
{
"id": "c2b3c4d5-e6f7-4b90-9123-222222222222",
"key": "status_in_progress",
"order": 2,
"value": "in_progress",
"label": "$.pages.p1.fields.p1_k3.options.status_in_progress.label"
},
{
"id": "d3c4d5e6-f7a8-4c01-8234-333333333333",
"key": "status_closed",
"order": 3,
"value": "closed",
"label": "$.pages.p1.fields.p1_k3.options.status_closed.label"
}
]
}
]
},
{
"id": "1d2c8430-2a58-451a-a930-49ab8c219dfa",
"key": "p2",
"order": 2,
"title": "$.pages.p2.title",
"description": "$.pages.p2.description",
"fields": [
{
"id": "542abbf1-efc7-429e-9ca6-69d5d36f521a",
"key": "p2_k1",
"order": 1,
"type": "textarea",
"value": "",
"label": "$.pages.p2.fields.p2_k1.label",
"placeholder": "$.pages.p2.fields.p2_k1.placeholder",
"tooltip": "$.pages.p2.fields.p2_k1.tooltip",
"description": "$.pages.p2.fields.p2_k1.description",
"validation": "^(?!\\s*$).+",
"minLength": 1,
"maxLength": 4000,
"visible": true,
"editable": true,
"required": true
},
{
"id": "e4f5a6b7-c8d9-4e12-a345-67890abcdef0",
"key": "p2_k2",
"order": 2,
"type": "file",
"value": "",
"label": "$.pages.p2.fields.p2_k2.label",
"placeholder": "$.pages.p2.fields.p2_k2.placeholder",
"tooltip": "$.pages.p2.fields.p2_k2.tooltip",
"description": "$.pages.p2.fields.p2_k2.description",
"validation": "^(?!\\s*$).+",
"visible": true,
"editable": true,
"required": false,
"file": {
"accept": ["image/jpeg", "image/png", "image/heic"],
"maxBytes": 10485760,
"multiple": true,
"maxFiles": 3
}
}
]
}
]
}

Adapt pages, fields, and copy for your use case — keep the same conventions (UUID ids, $ refs, matching keys).


Request bodies wrap your JSON under config (optional top-level id / roles as supported by the API):

{
"id": "12c8aa13-88f6-40de-b7c0-4b1bef48bb51",
"config": { }
}

Replace { } with the full configuration document from above.

Method Path Purpose
POST /v0/forms/configurations/validate Validate without persisting
POST /v0/forms/configurations Create (persists; typically 201)
PUT /v0/forms/configurations/{configurationId} Update an existing configuration
GET /v0/forms/configurations/{configurationId} Fetch one
GET /v0/forms/configurations List (filterable by language / states)

Suggested order: authenticate → POST .../validate until clean → POST .../configurations to create → continue with Forms (instances) and optionally Form with file.

Exact request/response schemas: API reference.