Opbox

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

TopicExpectation
Schema storageStored in form.schema as JSON.
Save Draft defaultsettings.allowSaveDraft defaults to true when omitted.
Country valuescountry stores ISO country code values like US, AE, GB.
Repeatable sectionsSet 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 filltable_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 embeddocument_embed is a layout-only field (no submission data). Set documentId to render a document inline in the form.
Questions and labelsUse field.question for human-readable prompt text and field.label for stable technical identifiers (for example adgm_spv.company_details.entity_name).
Section visibilitySections support conditional visibility through section.conditional (builder format) and legacy visibilityConditions rules in imported JSON templates.
Forward compatibilitySchema parsing is passthrough-friendly; unknown keys may be preserved.

Endpoints

MethodEndpointDescription
GET/api/formsList all forms
GET/api/forms/:idGet a specific form
POST/api/formsCreate a new form
PATCH/api/forms/:idUpdate a form
DELETE/api/forms/:idDelete a form
GET/api/forms/:id/versionsList form version history
GET/api/forms/:id/versions/:versionIdGet a specific version with full schema
POST/api/forms/:id/versions/:versionId/rollbackRollback form to a previous version
POST/api/forms/:id/sendSend 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

ParameterTypeDescription
idstringThe 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

FieldTypeRequiredDescription
titlestringYesThe form title
descriptionstringNoForm description
schemaobjectNoFull form schema object containing sections and fields
statusstringNoOne 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

FieldTypeRequiredDescription
emailstringYesRecipient email address
namestringNoRecipient name
messagestringNoCustom 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.