API and MCP

Surface parity

How each resource maps across the REST API, MCP tools and CLI commands — generated from the parity table.

<!-- Generated from lib/surface-parity.ts by npm run openapi:gen; __tests__/surface-parity.test.ts fails when it drifts. -->

Every configurable resource can be listed, read, created, edited and deleted from all three surfaces, and each resource's key extra operations are available everywhere. MCP tools and REST routes call the same service in lib/services; the CLI commands are generated from the REST registry. — marks an operation that is deliberately not offered (see Notes).

Edit round trip. Every update endpoint accepts its own GET response as the body: usertasks <resource> get <id> -o json > x.json, edit, usertasks <resource> update <id> -f x.json. The { <item>: {...} } wrapper is unwrapped, read-only fields (ids, timestamps, counts) are ignored, null for a field that cannot be null means "unchanged" and __SECRET__ keeps a stored credential. Workflows, decision tables, objects and webhooks report changed: false when nothing differs. For workflows, GET /workflows/{id}/definition returns exactly the author payload; edits save the draft and publish makes them live.

Workflows

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /workflowsworkflows_listworkflows list
getGET /workflows/{id}workflows_getworkflows get
get definitionGET /workflows/{id}/definitionworkflows_get_definitionworkflows definition
createPOST /workflowsworkflows_createworkflows create
updatePATCH /workflows/{id}workflows_updateworkflows update
deleteDELETE /workflows/{id}workflows_deleteworkflows delete
publishPOST /workflows/{id}/publishworkflows_publishworkflows publish
activatePOST /workflows/{id}/activateworkflows_toggleworkflows activate
deactivatePOST /workflows/{id}/deactivateworkflows_toggleworkflows deactivate
list versionsGET /workflows/{id}/versionsworkflows_versions_listworkflows versions
get versionGET /workflows/{id}/versions/{versionId}workflows_version_getworkflows version
startPOST /workflows/startworkflows_startworkflows start
get inputsGET /workflows/{id}/inputsworkflows_inputs_getworkflows inputs
list runsGET /workflows/runsworkflows_runs_listruns list
get runGET /workflows/runs/{id}workflows_run_getruns get
run actionPOST /workflows/runs/{id}/actionworkflows_run_actionruns action
list live instancesGET /workflows/{id}/instancesworkflows_instances_listworkflows instances
migrate live instancesPOST /workflows/{id}/instances/migrateworkflows_instances_migrateworkflows migrate-instances
exportGET /config/exportconfig_exportconfig exportone workflow: config export with ids=<id>
importPOST /config/applyconfig_applyconfig applyconfig apply of the exported workflow (dry run first)

Webhooks

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /workflows/{id}/webhookswebhooks_listwebhooks list
getGET /webhooks/{id}webhooks_getwebhooks get
createPOST /workflows/{id}/webhookswebhooks_createwebhooks create
updatePATCH /webhooks/{id}webhooks_updatewebhooks update
deleteDELETE /webhooks/{id}webhooks_deletewebhooks delete
rotate secretPOST /webhooks/{id}/rotatewebhooks_rotatewebhooks rotate

Integrations

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /integrationsintegrations_listintegrations list
getGET /integrations/{id}integrations_getintegrations get
createPOST /integrationsintegrations_createintegrations create
updatePATCH /integrations/{id}integrations_updateintegrations update
deleteDELETE /integrations/{id}integrations_deleteintegrations delete
testPOST /integrations/{id}/testintegrations_testintegrations test
import OpenAPIPOST /integrations/import-openapiintegrations_import_api_specintegrations import-openapi
exportGET /config/exportconfig_exportconfig exportone integration (with its references and objects): config export with ids=<id>
importPOST /config/applyconfig_applyconfig applyconfig apply of the exported integration (dry run first)

References

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /integrations/{id}/referencesreferences_listreferences list
getGET /references/{id}references_getreferences get
createPOST /integrations/{id}/referencesreferences_createreferences create
updatePATCH /references/{id}references_updatereferences update
deleteDELETE /references/{id}references_deletereferences delete
bulk deletePOST /references/bulk-deletereferences_bulk_deletereferences bulk-delete
executePOST /references/{id}/executeintegrations_execute_referencereferences execute

Objects

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /objectsobjects_listobjects list
getGET /objects/{id}objects_getobjects get
createPOST /objectsobjects_createobjects create
updatePATCH /objects/{id}objects_updateobjects update
deleteDELETE /objects/{id}objects_deleteobjects delete

Connectors

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
catalogGET /connectors/catalogconnectors_listconnectors catalog
listGET /connectorsconnectors_list_installedconnectors list
getGET /connectors/{id}connectors_getconnectors get
createPOST /connectorsconnectors_createconnectors create
updatePATCH /connectors/{id}connectors_updateconnectors update
deleteDELETE /connectors/{id}connectors_deleteconnectors delete
testPOST /connectors/{id}/testconnectors_testconnectors test
enablePOST /connectors/{id}/enableconnectors_updateconnectors enableMCP: connectors_update { enabled: true }
disablePOST /connectors/{id}/disableconnectors_updateconnectors disableMCP: connectors_update { enabled: false }
regenerate referencesPOST /connectors/{id}/regenerate-referencesconnectors_updateconnectors regenerate-referencesMCP: connectors_update { regenerate_references: true }
exportGET /config/exportconfig_exportconfig exportone connector (credentials never travel): config export with ids=<id>
importPOST /config/applyconfig_applyconfig applyconfig apply of the exported connector (dry run first)

Decision tables

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /decision-tablesdecision_tables_listdecision-tables list
getGET /decision-tables/{id}decision_tables_getdecision-tables get
createPOST /decision-tablesdecision_tables_createdecision-tables create
updatePUT /decision-tables/{id}decision_tables_updatedecision-tables updatePATCH is accepted too
deleteDELETE /decision-tables/{id}decision_tables_deletedecision-tables delete
testPOST /decision-tables/{id}/testdecision_tables_testdecision-tables test
exportGET /decision-tables/{id}/exportdecision_tables_exportdecision-tables export
importPOST /decision-tables/importdecision_tables_importdecision-tables import

Email templates

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /email-templatesemail_templates_listemail-templates list
getGET /email-templates/{id}email_templates_getemail-templates get
createPOST /email-templatesemail_templates_createemail-templates create
updatePATCH /email-templates/{id}email_templates_updateemail-templates update
deleteDELETE /email-templates/{id}email_templates_deleteemail-templates delete
previewPOST /email-templates/{id}/previewemail_templates_previewemail-templates preview
exportGET /config/exportconfig_exportconfig exportone email template: config export with ids=<id>
importPOST /config/applyconfig_applyconfig applyconfig apply of the exported email template (dry run first)

Workflow activities

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /workflow-activitiesworkflow_activities_listactivities list
getGET /workflow-activities/{id}workflow_activities_getactivities get
createPOST /workflow-activitiesworkflow_activities_createactivities create
updatePATCH /workflow-activities/{id}workflow_activities_updateactivities update
deleteDELETE /workflow-activities/{id}workflow_activities_deleteactivities delete
exportGET /workflow-activities/{id}/exportworkflow_activities_exportactivities export
importPOST /workflow-activities/importworkflow_activities_importactivities import

Data tables

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /data-tablesdata_tables_listtables list
getGET /data-tables/{id}data_tables_gettables get
createPOST /data-tablesdata_tables_createtables create
updatePATCH /data-tables/{id}data_tables_update_schematables update
deleteDELETE /data-tables/{id}data_tables_deletetables delete
exportGET /config/exportconfig_exportconfig exportone data table (include_rows for its rows): config export with ids=<id>
importPOST /config/applyconfig_applyconfig applyconfig apply of the exported data table (dry run first)

Data rows

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /data-tables/{id}/rowsdata_rows_queryrows list
getGET /data-tables/{id}/rows/{rowId}data_rows_getrows get
createPOST /data-tables/{id}/rowsdata_rows_upsertrows upsertinsert or update (row_id) in one call
updatePATCH /data-tables/{id}/rows/{rowId}data_rows_upsertrows updateMCP: data_rows_upsert { row_id }
deleteDELETE /data-tables/{id}/rows/{rowId}data_rows_deleterows delete
bulk deletePOST /data-tables/{id}/rows/bulk-deletedata_rows_bulk_deleterows bulk-delete

Reports

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /reportsreports_listreports list
getGET /reports/{id}reports_getreports get
createPOST /reportsreports_createreports create
updatePUT /reports/{id}reports_updatereports updatePATCH is accepted too
deleteDELETE /reports/{id}reports_deletereports delete
previewPOST /reports/previewreports_previewreports preview
sourcesGET /reports/sourcesreports_sources_listreports sources
exportGET /reports/{id}/exportreports_exportreports export
importPOST /reports/importreports_importreports import

Agents

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /agentsagents_listagents list
getGET /agents/{id}agents_getagents get
createPOST /agentsagents_createagents create
updatePUT /agents/{id}agents_updateagents updatePATCH is accepted too
deleteDELETE /agents/{id}agents_deleteagents delete
executePOST /agents/{id}/executeagents_executeagents execute
exportGET /config/exportconfig_exportconfig exportone agent: config export with ids=<id>
importPOST /config/applyconfig_applyconfig applyconfig apply of the exported agent (dry run first)

Retention policies

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /retention-policiesretention_policies_listretention list
getGET /retention-policies/{id}retention_policies_getretention get
createPOST /retention-policiesretention_policies_createretention create
updatePUT /retention-policies/{id}retention_policies_updateretention updatePATCH is accepted too
deleteDELETE /retention-policies/{id}retention_policies_deleteretention delete
list assetsGET /retention-policies/{id}/assetsretention_policies_list_assetsretention assets
assignPOST /retention-policies/assignretention_policies_assignretention assign
exportGET /config/exportconfig_exportconfig exportone retention policy: config export with ids=<id>
importPOST /config/applyconfig_applyconfig applyconfig apply of the exported retention policy (dry run first)

Roles

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /rolesroles_listroles list
getGET /roles/{id}roles_getroles get
createPOST /rolesroles_manageroles createMCP: roles_manage { action: create_role }
updatePATCH /roles/{id}roles_manageroles updateMCP: roles_manage { action: update_role }
deleteDELETE /roles/{id}roles_manageroles deleteMCP: roles_manage { action: delete_role }
assign to userPUT /users/{id}/roles/{roleId}roles_manageusers add-roleMCP: roles_manage { action: assign_role }
remove from userDELETE /users/{id}/roles/{roleId}roles_manageusers remove-roleMCP: roles_manage { action: remove_role }
exportGET /config/exportconfig_exportconfig exportone custom role: config export with ids=<id>
importPOST /config/applyconfig_applyconfig applyconfig apply of the exported custom role (dry run first)

Teams

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /teamsteams_listteams list
getGET /teams/{id}teams_getteams get
createPOST /teamsteams_createteams create
updatePATCH /teams/{id}teams_updateteams update
deleteDELETE /teams/{id}teams_deleteteams delete
add memberPUT /teams/{id}/members/{userId}teams_add_memberteams add-member
remove memberDELETE /teams/{id}/members/{userId}teams_remove_memberteams remove-member

Invitations

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /invitationsinvitations_listinvitations list
get———the list returns every field; there is nothing more to fetch per invitation
createPOST /invitationsinvitations_sendinvitations send
update———invitations are immutable: revoke and send again (resend refreshes the link)
deleteDELETE /invitations/{id}invitations_revokeinvitations revoke
resendPOST /invitations/{id}/resendinvitations_resendinvitations resend

Api keys

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /api-keysapi_keys_listapi-keys list
get———the list returns every stored field; the key itself is only shown at creation
createPOST /api-keysapi_keys_createapi-keys create
update———credentials are immutable by design: create a new key with the new permissions/scopes and revoke the old one
deleteDELETE /api-keys/{id}api_keys_deleteapi-keys delete
revokePOST /api-keys/{id}/revokeapi_keys_revokeapi-keys revoke

Log destinations

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /log-destinationslog_destinations_listlog-destinations list
getGET /log-destinations/{id}log_destinations_getlog-destinations get
createPOST /log-destinationslog_destinations_createlog-destinations create
updatePATCH /log-destinations/{id}log_destinations_updatelog-destinations update
deleteDELETE /log-destinations/{id}log_destinations_deletelog-destinations delete
statusGET /log-destinations/{id}/statuslog_destinations_statuslog-destinations status
reset cursorPOST /log-destinations/{id}/reset-cursorlog_destinations_reset_cursorlog-destinations reset-cursor
testPOST /log-destinations/{id}/testlog_destinations_testlog-destinations test
exportGET /config/exportconfig_exportconfig exportone log destination (no credentials): config export with ids=<id>
importPOST /config/applyconfig_applyconfig applyconfig apply of the exported log destination (dry run first)

Directory connections

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /directory-sync/connectionsdirectory_sync_listdirectory-sync list
getGET /directory-sync/connections/{provider}directory_sync_getdirectory-sync get
createPOST /directory-sync/connectionsdirectory_sync_connectdirectory-sync connectverified before it is saved
updatePATCH /directory-sync/connections/{provider}directory_sync_updatedirectory-sync update
deleteDELETE /directory-sync/connections/{provider}directory_sync_disconnectdirectory-sync disconnectlinks and accounts are kept
testPOST /directory-sync/connections/{provider}/testdirectory_sync_testdirectory-sync test
sync nowPOST /directory-sync/connections/{provider}/syncdirectory_sync_startdirectory-sync sync
list runsGET /directory-sync/runsdirectory_sync_runs_listdirectory-sync runs

Scim tokens

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /directory-sync/scim-tokensscim_tokens_listscim-tokens list
get———the list returns every stored field; the token itself is only shown at creation and rotation
createPOST /directory-sync/scim-tokensscim_tokens_createscim-tokens create
update———tokens are immutable: rotate for a new secret, or create one with other scopes
deleteDELETE /directory-sync/scim-tokens/{id}scim_tokens_deletescim-tokens delete
rotatePOST /directory-sync/scim-tokens/{id}/rotatescim_tokens_rotatescim-tokens rotate

Workspace theme

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
list———one theme per workspace: get returns it
getGET /workspace-themeworkspace_theme_getworkspace-theme get
create———every workspace always has a theme (new workspaces start from the default template)
updatePUT /workspace-themeworkspace_theme_updateworkspace-theme update
delete———a theme cannot be removed; apply a template to reset it
list presetsGET /workspace-theme/presetsworkspace_theme_presets_listworkspace-theme presets
apply presetPOST /workspace-theme/apply-presetworkspace_theme_apply_presetworkspace-theme apply-preset
upload fontPOST /workspace-theme/fontsworkspace_theme_font_uploadworkspace-theme upload-font

Packages

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /packagespackages_listpackages list
getGET /packages/{id}packages_getpackages get
createPOST /packagespackages_createpackages create
updatePATCH /packages/{id}packages_updatepackages updateCLI also: packages add / remove <type:id>…
deleteDELETE /packages/{id}packages_deletepackages delete
preview contentsPOST /packages/previewpackages_previewpackages preview
contentsGET /packages/{id}/contentspackages_contentspackages contents
list versionsGET /packages/{id}/versionspackages_versions_listpackages versions
build versionPOST /packages/{id}/versionspackages_buildpackages buildCLI saves the .utpkg (--out)
get versionGET /packages/{id}/versions/{versionId}packages_version_getpackages version
download versionGET /packages/{id}/versions/{versionId}/downloadpackages_downloadpackages download
inspect filePOST /packages/inspectpackages_inspectpackages inspectthe CLI verifies offline

Package installs

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /package-installspackages_installs_listpackages installs
getGET /package-installs/{id}packages_installs_getpackage-installs get
createPOST /package-installspackages_installpackages installinstall; upgrades in place when installed already
updatePOST /package-installs/{id}/upgradepackages_upgradepackages upgrade
deletePOST /package-installs/{id}/uninstallpackages_uninstallpackages uninstalldry_run lists what is removed
plan (dry run)POST /package-installs/planpackages_install_planpackages installCLI: packages install --dry-run
complete setupPOST /package-installs/{id}/completepackages_complete_setuppackages complete

Package history

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /package-eventspackages_historypackages historyfilters: package, action, status, channel, actor, since / until; CSV export in the app
getGET /package-events/{id}packages_history_getpackage-events getwith the applied plan / diff
create———events are recorded by installs, upgrades, complete setup and uninstalls (failed attempts too)
update———the history is append-only
delete———the history is append-only; events go with the workspace

Events

OperationREST (/api/v1)MCP toolCLI (usertasks …)Notes
listGET /eventsevents_listevents listcursor paged (after / next_cursor); audit and security also need settings.view
get———events are immutable and the list carries every field; filter by run_id / task_id / trace_id
create———events are written by the platform (database triggers), never by callers
update———the event stream is append-only
delete———events expire with the stream retention (72h default)

Single-surface operations

SurfaceOperationsWhy
MCPworkflows_catalog, workflows_preflight, workflows_resolve_dependenciesprompt-authoring aids for agents (node catalog, dependency checks); REST/CLI users read the docs and get validation errors from create/update
MCPintegrations_create_bundlecreates an integration and its references in one prompt step; REST/CLI do it with integrations create + references create, or config apply
MCPreports_query, reports_source_get, reports_remediate_config, data_rows_searchagent-oriented read helpers
MCPintegration_calls_, agent_runs_, trace_get, object_audit_log_queryobservability reads, not configuration
CLIconfig diff / newfolder helpers over POST /config/apply (dry run) and local scaffolding; config export / apply themselves are on every surface (MCP: config_export / config_apply, single-manifest form)
CLItasks completeergonomic wrapper over POST /tasks/{id}/action
CLIlogs tail, logs exportlive tail over the SSE endpoint GET /events/stream (auto-reconnect, NDJSON with -o json) and cursor export over GET /events; MCP clients poll events_list with after

Gaps closed (October 2026)

GapFix
Export coverage (Oct 2026): no single-asset export/import for workflows, data tables, integrations, connectors, email templates, agents, retention policies, roles or log destinations on REST/MCP/CLI; no MCP config export/apply; CLI config export without ids; data-table rows exportable nowhereconfig export ids + with_dependencies + include_rows (table_rows section, data-rows/ folder) and config apply rows_mode on every surface (MCP config_export / config_apply, CLI --ids / --with-dependencies / --include-rows / --rows-mode); see docs/export-coverage.md
Workflows: GET /workflows/{id} output could not be sent back to update (different shape, id in the body, no trigger_config/description; REST stripped unknown node keys)GET /workflows/{id}/definition returns the author payload; PATCH /workflows/{id} takes it (and the include_definition GET response); nodes/edges are loose; MCP workflows_get_definition + workflows_update { definition }
Workflows: no REST/CLI publish; three different publish implementations (UI, REST author flag, MCP)POST /workflows/{id}/publish and workflows publish; REST and MCP share lib/services/workflows (audit, sync, workflows.activate)
Workflows: MCP could not read one published versionworkflows_version_get
Webhooks: no MCP tools; no get/update on any surfacewebhooks_* MCP tools; GET/PATCH /webhooks/{id}; service getWebhook/updateWebhook
Objects: no update on any surfaceupdateObject service, PATCH /objects/{id}, objects_update, objects update
Connectors: MCP could only list the catalog, not installed connectorsconnectors_list_installed
References: no MCP bulk deletereferences_bulk_delete
Data tables / rows: no MCP table delete, row get or bulk row delete; a fetched schema (with system columns) was rejected on updatedata_tables_delete, data_rows_get, data_rows_bulk_delete; system columns in an update are ignored
Decision tables: REST and MCP had separate CRUD code (REST unaudited, hard delete, required ids)lib/services/decision-tables CRUD + test used by both; PATCH alias; ids generated when missing
Reports: export/import were MCP-onlyGET /reports/{id}/export, POST /reports/import (lib/services/reports), reports export|import
Agents, reports, retention: PUT only, and a GET response sent back was silently ignored (no fields matched)PATCH accepted too; the { agent|report|retention_policy: {...} } wrapper is unwrapped
Integrations: MCP integrations_get hid the config, so MCP could not edit it from a readmasked config returned (as REST)
Every update: the { <item>: {...} } GET wrapper and null optional fields were rejected or silently ignoredroundTrip handling in apiRoute (prepareRoundTripBody) for every update endpoint
API keys / roles / teams: no MCP delete (keys) or get (roles, teams)api_keys_delete, roles_get, teams_get

Verified end to end by scripts/e2e-surfaces.ts (create → get → edit file → update → get → delete per resource; workflows add a node and edge, publish, list versions and run the new version).