Forms API
Create, retrieve, update, and delete forms. Forms are the core building block of Opbox - they define the fields and structure that users fill out.
Form JSON Contract
A form's runtime structure lives in schema. Submissions then persist values in submission.data keyed by each field's field.key.
{
"title": "Client Onboarding",
"description": "Collect client and shareholder details",
"version": "1.0",
"sections": [
{
"id": "section_abc123",
"title": "Client Details",
"fields": [
{
"id": "field_name",
"key": "full_name",
"type": "text",
"label": "Full Name",
"validation": { "required": true }
},
{
"id": "field_country",
"key": "country",
"type": "country",
"label": "Country"
}
]
},
{
"id": "section_shareholders",
"title": "Shareholders",
"repeatable": true,
"repeatableConfig": {
"singularLabel": "Shareholder",
"pluralLabel": "Shareholders",
"minItems": 1,
"maxItems": 10
},
"fields": [
{
"id": "field_sh_name",
"key": "shareholder_name",
"type": "text",
"label": "Name",
"validation": { "required": true }
},
{
"id": "field_sh_address",
"key": "shareholder_address",
"type": "textarea",
"label": "Address"
}
]
},
{
"id": "section_shares",
"title": "Share Allocation",
"fields": [
{
"id": "field_shares_table",
"key": "share_allocation",
"type": "table_fill",
"label": "Shares",
"tableColumns": [
{ "key": "name", "label": "Name", "type": "text",
"sourceField": "shareholder_name" },
{ "key": "shares", "label": "Shares", "type": "number" },
{ "key": "class", "label": "Class", "type": "select",
"options": [
{ "label": "Ordinary", "value": "ordinary" },
{ "label": "Preference", "value": "preference" }
] }
]
}
]
}
],
"settings": {
"submitButtonText": "Submit",
"allowSaveDraft": true
}
}
Supported Field Types
text, email, phone, tel, url, number, currency, textarea, select, multiselect, radio, checkbox, yesno, rating, country, date, time, datetime, file, document, signature, table_fill, heading, paragraph, divider, document_embed
Contract Notes
| Topic | Expectation |
|---|---|
| Schema storage | Stored in form.schema as JSON. |
| Save Draft default | settings.allowSaveDraft defaults to true when omitted. |
| Country values | country stores ISO country code values like US, AE, GB. |
| Repeatable sections | Set section.repeatable: true to allow users to add multiple instances. Data stored as {sectionId}_items: array of objects keyed by field key. Configure with repeatableConfig (singularLabel, pluralLabel, minItems, maxItems). |
| Table fill | table_fill fields define columns via tableColumns. Each column has key, label, type (text/number/select/date), and optional sourceField to auto-populate from a repeatable section. Stored as array of row objects. |
| Document embed | document_embed is a layout-only field (no submission data). Set documentId to render a document inline in the form. |
| Questions and labels | Use field.question for human-readable prompt text and field.label for stable technical identifiers (for example adgm_spv.company_details.entity_name). |
| Section visibility | Sections support conditional visibility through section.conditional (builder format) and legacy visibilityConditions rules in imported JSON templates. |
| Forward compatibility | Schema parsing is passthrough-friendly; unknown keys may be preserved. |
Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET | /api/forms | List all forms |
GET | /api/forms/:id | Get a specific form |
POST | /api/forms | Create a new form |
PATCH | /api/forms/:id | Update a form |
DELETE | /api/forms/:id | Delete a form |
GET | /api/forms/:id/versions | List form version history |
GET | /api/forms/:id/versions/:versionId | Get a specific version with full schema |
POST | /api/forms/:id/versions/:versionId/rollback | Rollback form to a previous version |
POST | /api/forms/:id/send | Send form to a client via email |
List Forms
Returns all forms belonging to your active workspace.
GET /api/forms
Response
[
{
"id": "cm_form_123",
"title": "Customer Feedback",
"description": "Collect feedback from customers",
"status": "PUBLISHED",
"schema": {
"version": "1.0",
"sections": []
},
"workspaceId": "cm_ws_123",
"createdById": "cm_user_123",
"createdAt": "2026-02-12T09:00:00.000Z",
"updatedAt": "2026-02-12T09:05:00.000Z",
"_count": {
"submissions": 12
}
}
]
Get a Form
Returns a single form by ID, including all fields and configuration.
GET /api/forms/:id
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | The form's unique identifier |
Create a Form
Creates a new form in your active workspace.
POST /api/forms
Content-Type: application/json
{
"title": "Customer Feedback",
"description": "Collect feedback from customers",
"status": "DRAFT",
"schema": {
"version": "1.0",
"sections": [
{
"id": "section_client_details",
"title": "Client Details",
"fields": [
{
"id": "field_client_name",
"key": "client_name",
"type": "text",
"label": "adgm_spv.client_details.client_name",
"question": "Client name",
"validation": { "required": true }
}
]
}
]
}
}
Body Parameters
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | The form title |
description | string | No | Form description |
schema | object | No | Full form schema object containing sections and fields |
status | string | No | One of DRAFT, PUBLISHED, or ARCHIVED. Defaults to DRAFT. |
Update a Form
Updates an existing form. Only the provided fields are updated.
PATCH /api/forms/:id
Content-Type: application/json
{
"title": "Updated Form Title",
"description": "Updated description"
}
Version History
Every save creates a new version with a computed changelog. You can view the full history and rollback to any previous version. Rollback is non-destructive - it creates a new version (N+1) with the restored schema.
List Versions
GET /api/forms/:id/versions
{
"versions": [
{
"id": "cm...",
"version": 3,
"changelog": {
"summary": "Added 2 fields, removed 1 field",
"entries": [
{ "type": "added", "target": "field", "description": "Added field \"Phone Number\"" },
{ "type": "removed", "target": "field", "description": "Removed field \"Fax\"" }
]
},
"createdBy": { "name": "Admin" },
"createdAt": "2026-02-13T10:00:00.000Z"
}
]
}
Get a Version
GET /api/forms/:id/versions/:versionId
Response includes full schema snapshot:
{
"id": "cm...",
"version": 2,
"schema": { "sections": [], "settings": {} },
"title": "Client Intake",
"changelog": {},
"createdAt": "2026-02-12T09:00:00.000Z"
}
Rollback
POST /api/forms/:id/versions/:versionId/rollback
Creates version N+1 with the target version's schema.
{
"success": true,
"version": 4,
"message": "Rolled back to version 2"
}
Rollback requires ADMIN or OWNER role.
Send Form to Client
Sends a form to a client via email with a secure link. Creates a DRAFT submission and generates a secure token for the recipient. The form must be PUBLISHED.
POST /api/forms/:id/send
Content-Type: application/json
{
"email": "client@example.com",
"name": "Jane Smith",
"message": "Please complete this form at your earliest convenience."
}
Body Parameters
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Recipient email address |
name | string | No | Recipient name |
message | string | No | Custom message included in the email |
Requires an active email integration. The recipient receives a link to /c/:token where they can fill out and submit the form.
Delete a Form
Permanently deletes a form and all its associated data. This action cannot be undone.
DELETE /api/forms/:id
Warning: Deleting a form also removes all submissions, the associated form table, and shared links.