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/submissionsrequires authentication and active workspace context.POST /api/submissionsrequires 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 Types | Stored Value Type | Notes |
|---|---|---|
| text, email, tel, url, textarea, date, time, datetime, select, radio, country | string | Country stores ISO code values like US. |
| number, currency, rating | number | Rating is currently numeric (for example 1-5). |
| checkbox, multiselect | string[] | Array of option value, not labels. |
| yesno | boolean | True/false flag. |
| file, signature | implementation-dependent | Treat as opaque payload references unless endpoint-specific docs define a strict shape. |
| table_fill | object[] | Array of row objects, each keyed by column key. Columns with sourceField are auto-populated from repeatable section data. |
| repeatable section items | object[] | 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
mattersarray on each submission containing linked matters (limited to the first linked matter). Each matter object hasid,number,numberPrefix, andtitle. Empty array if no matter is linked.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET | /api/submissions | List all submissions |
POST | /api/submissions | Create a new submission |
GET | /api/submissions/:id | Get a specific submission |
PATCH | /api/submissions/:id | Update a submission (data, status, metadata) |
DELETE | /api/submissions/:id | Delete a submission |
POST | /api/submissions/:id/submit | Submit a draft (DRAFT to PENDING) |
GET | /api/submissions/stats | Get submission statistics |
GET | /api/submissions/:id/notes | List notes on a submission |
POST | /api/submissions/:id/notes | Add a note to a submission |
GET | /api/submissions/:id/documents | List submission attachments |
POST | /api/submissions/:id/documents | Attach a document to a submission |
DELETE | /api/submissions/:id/documents?attachmentId=:attachmentId | Remove a submission attachment |
POST | /api/submissions/:id/share | Generate a shareable link |
POST | /api/submissions/:id/share/email | Share submission via email |
GET | /api/submissions/drafts | List draft submissions |
GET | /api/submissions/drafts/:id | Get a specific draft |
PATCH | /api/submissions/drafts/:id | Update a draft |
DELETE | /api/submissions/drafts/:id | Delete a draft |
GET | /api/submissions/:id/history | Get submission activity timeline |
GET | /api/submissions/:id/snapshots/:snapshotId | Get a specific snapshot |
POST | /api/submissions/:id/snapshots/:snapshotId/rollback | Rollback to a previous snapshot |
GET | /api/submissions/:id/visibility | Get visibility settings and member lists |
PUT | /api/submissions/:id/visibility | Update 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
| Field | Type | Required | Description |
|---|---|---|---|
formId | string | Yes | The form ID to create a submission for |
data | object | Yes | Initial field values keyed by field key |
metadata | object | No | Custom 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
| Parameter | Type | Description |
|---|---|---|
formId | string | Filter by form ID |
status | string | Filter by status: DRAFT, PENDING, COMPLETED, EDITED |
search | string | Search by ID, form title, user name, or email |
dateFrom / dateTo | string | Filter by date range (ISO date strings, inclusive) |
submittedBy | string | Filter by submitter user ID |
includeDrafts | boolean | Include DRAFT submissions (excluded by default) |
sortBy | string | Sort field: createdAt, updatedAt, status (default: createdAt) |
sortOrder | string | Sort direction: asc or desc (default: desc) |
page / limit | number | Pagination (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
| Field | Type | Description |
|---|---|---|
status | string | New status: DRAFT, PENDING, COMPLETED, or EDITED |
data | object | Updated submission data (replaces existing data) |
metadata | object | Custom key-value metadata |
userId | string | null | Reassign 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
| targetType | targetId | Description |
|---|---|---|
user | User ID | Grant to a specific user |
workspace_role | Role name (OWNER, ADMIN, MEMBER, VIEWER) | Grant to all users with the specified workspace role |
oversight_workspace | Workspace ID of the overseer | Grant to all members of an overseer workspace (requires active oversight relationship) |
Submission Statuses
| Status | Description |
|---|---|
DRAFT | Saved but not yet submitted |
PENDING | Submitted, awaiting review or processing |
COMPLETED | Reviewed and finalised |
EDITED | Data modified after completion (auto-set when a COMPLETED submission's data changes) |