Opbox

Submissions API

Manage form submissions, including listing, retrieving, updating, and tracking history. Submissions represent data entered by users through published forms. Each data change creates an immutable snapshot for audit and rollback.

Route Conventions (Current)

  • GET /api/submissions requires authentication and active workspace context.
  • POST /api/submissions requires a valid security token and validates the request body.
  • Submission payload strings are sanitized before persistence.
  • Error responses follow a standardized format: { success: false, error, code, details? }.

Submission JSON Output Contract

Submission payload values are persisted in submission.data and keyed by form field.key (not label text).

Example Submission Object

{
  "id": "SUB-8XQ2M7K9P1ZT",
  "formId": "cm_form_123",
  "status": "PENDING",
  "data": {
    "full_name": "Jane Smith",
    "email": "jane@example.com",
    "country": "US",
    "overall_rating": 4,
    "risk_flags": ["high_risk", "pep"],
    "section_shareholders_items": [
      { "shareholder_name": "Bob", "shareholder_address": "123 Main St" },
      { "shareholder_name": "Sarah", "shareholder_address": "456 Oak Ave" }
    ],
    "share_allocation": [
      { "name": "Bob", "shares": 500, "class": "ordinary" },
      { "name": "Sarah", "shares": 500, "class": "preference" }
    ]
  },
  "metadata": {
    "source": "client_form_link"
  },
  "formVersion": {
    "id": "cm...",
    "version": 2
  },
  "createdAt": "2026-02-12T09:15:00.000Z",
  "updatedAt": "2026-02-12T09:15:00.000Z"
}

Field Value Shapes

Field TypesStored Value TypeNotes
text, email, tel, url, textarea, date, time, datetime, select, radio, countrystringCountry stores ISO code values like US.
number, currency, ratingnumberRating is currently numeric (for example 1-5).
checkbox, multiselectstring[]Array of option value, not labels.
yesnobooleanTrue/false flag.
file, signatureimplementation-dependentTreat as opaque payload references unless endpoint-specific docs define a strict shape.
table_fillobject[]Array of row objects, each keyed by column key. Columns with sourceField are auto-populated from repeatable section data.
repeatable section itemsobject[]Keyed as {sectionId}_items. Each object contains field values for one instance of the repeatable section.

Behavior Guarantees

  • Submission IDs are prefixed with SUB-.
  • Conditional logic is enforced during submission create routes; hidden field values are stripped before persist.
  • API list responses include pagination as { page, limit, total, pages }.
  • Every data or status change creates an immutable snapshot for audit trail and rollback.
  • Submissions are linked to a specific form version via formVersionId.
  • List responses include a matters array on each submission containing linked matters (limited to the first linked matter). Each matter object has id, number, numberPrefix, and title. Empty array if no matter is linked.

Endpoints

MethodEndpointDescription
GET/api/submissionsList all submissions
POST/api/submissionsCreate a new submission
GET/api/submissions/:idGet a specific submission
PATCH/api/submissions/:idUpdate a submission (data, status, metadata)
DELETE/api/submissions/:idDelete a submission
POST/api/submissions/:id/submitSubmit a draft (DRAFT to PENDING)
GET/api/submissions/statsGet submission statistics
GET/api/submissions/:id/notesList notes on a submission
POST/api/submissions/:id/notesAdd a note to a submission
GET/api/submissions/:id/documentsList submission attachments
POST/api/submissions/:id/documentsAttach a document to a submission
DELETE/api/submissions/:id/documents?attachmentId=:attachmentIdRemove a submission attachment
POST/api/submissions/:id/shareGenerate a shareable link
POST/api/submissions/:id/share/emailShare submission via email
GET/api/submissions/draftsList draft submissions
GET/api/submissions/drafts/:idGet a specific draft
PATCH/api/submissions/drafts/:idUpdate a draft
DELETE/api/submissions/drafts/:idDelete a draft
GET/api/submissions/:id/historyGet submission activity timeline
GET/api/submissions/:id/snapshots/:snapshotIdGet a specific snapshot
POST/api/submissions/:id/snapshots/:snapshotId/rollbackRollback to a previous snapshot
GET/api/submissions/:id/visibilityGet visibility settings and member lists
PUT/api/submissions/:id/visibilityUpdate visibility settings (ADMIN/OWNER)

Create a Submission

Creates a new submission for a published form. The current implementation persists new submissions with COMPLETED status.

POST /api/submissions
Content-Type: application/json
{
  "formId": "cm_form_123",
  "data": {
    "full_name": "Jane Smith",
    "email": "jane@example.com"
  },
  "metadata": {
    "source": "api"
  }
}

Body Parameters

FieldTypeRequiredDescription
formIdstringYesThe form ID to create a submission for
dataobjectYesInitial field values keyed by field key
metadataobjectNoCustom metadata (source, tags, etc.)

List Submissions

Returns submissions for your active workspace. Supports filtering by form, status, date range, and submitter.

GET /api/submissions?formId=abc123&status=PENDING&dateFrom=2026-01-01&dateTo=2026-02-01

Query Parameters

ParameterTypeDescription
formIdstringFilter by form ID
statusstringFilter by status: DRAFT, PENDING, COMPLETED, EDITED
searchstringSearch by ID, form title, user name, or email
dateFrom / dateTostringFilter by date range (ISO date strings, inclusive)
submittedBystringFilter by submitter user ID
includeDraftsbooleanInclude DRAFT submissions (excluded by default)
sortBystringSort field: createdAt, updatedAt, status (default: createdAt)
sortOrderstringSort direction: asc or desc (default: desc)
page / limitnumberPagination (default: page 1, limit 10)

Response

{
  "submissions": [
    {
      "id": "SUB-8XQ2M7K9P1ZT",
      "formId": "cm_form_123",
      "status": "PENDING",
      "data": {
        "full_name": "Jane Smith",
        "email": "jane@example.com",
        "comments": "Great service!"
      },
      "metadata": {},
      "matters": [
        {
          "id": "cm...",
          "number": 1,
          "numberPrefix": "MAT",
          "title": "Client Onboarding - Acme Corp"
        }
      ],
      "createdAt": "2025-01-20T14:00:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 10,
    "total": 42,
    "pages": 5
  }
}

Update a Submission

Updates a submission's data, status, or metadata. Status transitions are validated - only valid values are accepted. If data is changed on a COMPLETED submission, the status is automatically set to EDITED. Every change creates a snapshot for the audit trail.

PATCH /api/submissions/:id
Content-Type: application/json
{
  "status": "COMPLETED",
  "data": {
    "full_name": "Jane Smith",
    "email": "jane@updated.com"
  },
  "metadata": { "reviewedBy": "admin" }
}

Body Parameters

FieldTypeDescription
statusstringNew status: DRAFT, PENDING, COMPLETED, or EDITED
dataobjectUpdated submission data (replaces existing data)
metadataobjectCustom key-value metadata
userIdstring | nullReassign the submission to a different user, or null to unassign

All fields are optional. A snapshot is created automatically when data or status changes, enabling full audit trail and rollback.

Add a Note

Adds an internal note to a submission. Notes are only visible to workspace members.

POST /api/submissions/:id/notes
Content-Type: application/json
{
  "content": "Followed up with client via email"
}

Submit a Draft

Transitions a DRAFT submission to PENDING. Validates all required fields before accepting the submission.

POST /api/submissions/:id/submit

Status Transitions

Transition submission state using PATCH /api/submissions/:id with a new status.

PATCH /api/submissions/:id
Content-Type: application/json
{
  "status": "COMPLETED"
}

Valid statuses are DRAFT, PENDING, COMPLETED, and EDITED.

Submission Documents

Manage file attachments on a submission.

GET    /api/submissions/:id/documents
POST   /api/submissions/:id/documents     { "fileId": "cm..." }
DELETE /api/submissions/:id/documents?attachmentId=cm_attachment_123

Sharing

Generate a shareable link or send a submission summary via email.

POST /api/submissions/:id/share

Response: { "shareUrl": "https://...share/:token" }

POST /api/submissions/:id/share/email
Content-Type: application/json
{
  "email": "reviewer@example.com",
  "message": "Please review this submission"
}

Draft Management

Manage individual draft submissions. Drafts are saved progress that haven't been submitted yet.

GET    /api/submissions/drafts
GET    /api/submissions/drafts/:id
PATCH  /api/submissions/drafts/:id
DELETE /api/submissions/drafts/:id

Snapshots & Rollback

Every submission data or status change creates an immutable snapshot. You can retrieve any snapshot and rollback to restore a previous state. Rollback is non-destructive - it creates a new snapshot rather than deleting history.

Get a Snapshot

GET /api/submissions/:id/snapshots/:snapshotId
{
  "id": "cm...",
  "version": 3,
  "status": "COMPLETED",
  "trigger": "edit",
  "changelog": { "summary": "Updated 2 fields" },
  "data": { "full_name": "Jane Smith", "email": "jane@example.com" },
  "createdBy": { "name": "Admin", "email": "admin@example.com" },
  "createdAt": "2026-02-13T10:00:00.000Z"
}

Rollback to a Snapshot

POST /api/submissions/:id/snapshots/:snapshotId/rollback
{
  "success": true,
  "rolledBackToVersion": 2,
  "submission": {
    "id": "cm...",
    "formId": "cm...",
    "data": {},
    "status": "PENDING"
  }
}

Rollback requires ADMIN or OWNER role. The submission's data is restored to the snapshot's data, and a new snapshot is created.

Submission Activity Timeline

Returns a unified activity timeline for a submission, merging snapshots and audit events. Events are sorted newest first (up to 100 entries).

GET /api/submissions/:id/history

Response

{
  "events": [
    {
      "id": "cm...",
      "type": "snapshot",
      "trigger": "edit",
      "description": "Submission data edited",
      "actor": { "name": "Admin", "email": "admin@example.com" },
      "snapshotId": "cm...",
      "changelog": { "summary": "Updated 2 fields" },
      "createdAt": "2026-02-13T14:00:00.000Z"
    },
    {
      "id": "cm...",
      "type": "snapshot",
      "trigger": "submit",
      "description": "Submission submitted",
      "actor": { "name": "Jane Smith" },
      "snapshotId": "cm...",
      "createdAt": "2026-02-12T10:00:00.000Z"
    },
    {
      "id": "cm...",
      "type": "snapshot",
      "trigger": "create",
      "description": "Submission created",
      "actor": { "name": "Jane Smith" },
      "snapshotId": "cm...",
      "createdAt": "2026-02-12T09:15:00.000Z"
    }
  ]
}

Submission Visibility

Control who can see a submission. Submissions support workspace (all members can view) or restricted (only granted users) visibility. Restricted mode supports three grant types: specific users, workspace roles, and oversight workspaces.

Get Visibility Settings

GET /api/submissions/:id/visibility
{
  "visibility": {
    "mode": "restricted",
    "grants": [
      { "targetType": "user", "targetId": "cm...", "accessLevel": "viewer" },
      { "targetType": "workspace_role", "targetId": "ADMIN", "accessLevel": "viewer" },
      { "targetType": "oversight_workspace", "targetId": "cm_ws_overseer", "accessLevel": "viewer" }
    ]
  },
  "members": [
    { "userId": "cm...", "name": "Jane Doe", "email": "jane@example.com", "role": "ADMIN" }
  ],
  "overseerWorkspaces": [
    {
      "workspaceId": "cm_ws_overseer",
      "workspaceName": "Regulator Workspace",
      "members": [
        { "userId": "cm...", "name": "Inspector", "email": "inspect@example.com", "role": "ADMIN" }
      ]
    }
  ]
}

Update Visibility Settings

PUT /api/submissions/:id/visibility
Content-Type: application/json
{
  "mode": "restricted",
  "grants": [
    { "targetType": "user", "targetId": "cm...", "accessLevel": "viewer" },
    { "targetType": "oversight_workspace", "targetId": "cm_ws_overseer", "accessLevel": "viewer" }
  ]
}

Requires ADMIN or OWNER role. Oversight workspace permissions are validated against active oversight relationships.

Grant Types

targetTypetargetIdDescription
userUser IDGrant to a specific user
workspace_roleRole name (OWNER, ADMIN, MEMBER, VIEWER)Grant to all users with the specified workspace role
oversight_workspaceWorkspace ID of the overseerGrant to all members of an overseer workspace (requires active oversight relationship)

Submission Statuses

StatusDescription
DRAFTSaved but not yet submitted
PENDINGSubmitted, awaiting review or processing
COMPLETEDReviewed and finalised
EDITEDData modified after completion (auto-set when a COMPLETED submission's data changes)