POST /api/actions is the workspace mutation boundary. Clients send an array of typed operations, the exact expectedRevision they reviewed, and confirmed:true when the batch requires confirmation. Manual edits and reviewed AI drafts pass through the same validation and persistence boundary. Proposing an operation is separate from applying it.

json
{
  "operations": [
    {
      "action": "update_item",
      "spaceId": "sheet_projects",
      "itemId": "record_example",
      "notes": "Approved for the next review."
    }
  ],
  "expectedRevision": 7
}

This example changes only notes on an existing synthetic record. Read actual sheet/record IDs and the current revision first. A successful result contains authoritative workspace data, a summary, historyId, and runs. With external workers, runs is empty because background scheduling occurs separately. Use paged response mode when you want metadata rather than a fully loaded workspace.

Supported operation names#

ActionPayload besides action
create_insightdocument: InsightDocument
update_insightinsightId; changes with name, description and/or blocks
delete_insightinsightId
create_rulerule: RecordRule
update_ruleruleId; changes (excluding id and createdAt)
delete_ruleruleId
create_workbookworkbook: Workbook
update_workbookworkbookId; changes with name, description, color and/or archived
move_spacespaceId; workbookId:string|null; optional index
reorder_workbooksworkbookIds:string[]
create_workflowworkflow: Workflow
update_workflowworkflowId; changes with name, description, trigger, conditions, steps, instructions, mode and/or enabled
delete_workflowworkflowId
create_spacespace: Space
rename_spacespaceId; name
create_itemspaceId; item: Item
start_timerspaceId; itemId; fieldId
stop_timerspaceId; itemId; fieldId
update_itemspaceId; itemId; values and/or notes
delete_itemspaceId; itemId
archive_itemspaceId; itemId
restore_itemspaceId; itemId
create_fieldspaceId; field: Field
update_fieldspaceId; fieldId; optional name/type/options/optionColors/width/relation/formula/rollup/format
move_fieldspaceId; fieldId; index
delete_fieldspaceId; fieldId
create_viewspaceId; view: View
update_viewspaceId; viewId; optional name/type/filters/sorts/groupBy/config
bulk_updatespaceId; itemIds:string[]; values
bulk_archivespaceId; itemIds:string[]

The table follows the current Operation union and engine. It is exhaustive for operation names, but nested objects still require their own valid fields, references, and constraints. There is no generic arbitrary-property mutation, SQL endpoint, predicate-based bulk write, delete_space action, or delete_view action. Bulk edits identify concrete, unique records in a specific sheet.

Use IDs and typed values#

Item.values is keyed by field ID, not a displayed column name. A CellValue is a string, number, boolean, string array, timer object, or null, with the permitted choice determined by the field. Relation values reference real records; Person values reference real members. Formula and rollup fields are computed and cannot be treated as ordinary stored editable values. Timer actions let the server control start timestamps rather than trusting a client-written start time.

  • Field types: text, long_text, number, duration, timer, rating, phone, checkbox, date, status, select, multi_select, person, url, email, attachment, relation, formula, rollup.
  • View types: table, board, calendar, timeline, flow, gallery, list, chart, form, workload. The UI may use a friendlier label such as Pipeline for flow.
  • Choice colors: slate, blue, indigo, violet, pink, red, orange, amber, green, teal.
  • Creating an Item requires id, values, notes, archived, createdAt, and updatedAt; nested IDs/references must be valid in the proposed workspace.

Validate the whole batch#

The route accepts at most 500 operations within a 4 MiB JSON body. Later operations can reference entities created earlier in the same batch. Validation, references, permissions, record rules, and optimistic revision checks all apply before commit. A failed batch does not leave its earlier operations partially applied. Confirmation is an explicit reviewed choice; do not automatically add confirmed:true to every failing request.

When applying a saved AI proposal, include its aiJobId and use that proposal’s baseRevision as expectedRevision. The server checks ownership, completed/unapplied state, and the saved proposal against the requested operation batch. The mutation and job application receipt commit together. An arbitrary job ID cannot authorize a change.

Read the result and preserve history semantics#

After a successful write, replace or reconcile local state with the authoritative response. Do not treat an old local snapshot as current simply because the HTTP request was sent. POST /api/history accepts direction undo or redo and an expectedRevision; history operations advance the workspace revision. They respect top-of-history actor checks and do not perform selective merging over teammates’ later edits.