Workflows
A workflow is an automation: a trigger (a reservation is created, a task is completed, a schedule fires), optional conditions, and the actions to run. The SuiteOp app calls them agents. Over the API you describe a workflow in plain language and SuiteOp’s AI builds the steps, then you choose where it runs and publish it. This guide covers the five workflow operations. Every field is listed on the operation’s page in the API Reference.
| Operation | Request | Permission |
|---|---|---|
create_workflow | POST /workflows | manage_workflows |
modify_workflow | POST /workflows/{workflowId}/modify | manage_workflows |
set_workflow_scopes | POST /workflows/{workflowId}/scopes | manage_workflows |
publish_workflow | POST /workflows/{workflowId}/publish | manage_workflows |
update_workflow | PATCH /workflows/{workflowId} | manage_workflows |
Paths are relative to your region’s base URL, for example https://api-us.suiteop.com/api/v1. See Authentication for permissions.
The API can’t list, read or delete workflows, and it can’t connect the integrations a workflow uses. Keep the workflowId that create_workflow returns: it is the only handle you get, and you check a workflow’s steps in the app.
Lifecycle
Section titled “Lifecycle”A workflow goes live in three steps. Skipping one leaves it unable to fire.
- Create.
create_workflowsaves the workflow as an inactive, unscoped draft. - Scope.
set_workflow_scopeschooses the properties, property groups or tags it runs on. A workflow with no scope never runs, and publishing one is refused. - Publish.
publish_workflowmakes the draft live and switches the workflow on.
Later edits with modify_workflow land on a new draft. The live version keeps running unchanged until you publish again. update_workflow renames, pauses, resumes or refiles a workflow without touching its steps.
Creating a workflow
Section titled “Creating a workflow”POST /workflows takes one field, description: the whole automation in plain language, up to 20,000 characters. The AI sees this text and nothing else, so name the trigger, the timing, the conditions and each action explicitly.
curl -X POST https://api-us.suiteop.com/api/v1/workflows \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Idempotency-Key: 9c4e2a1b-7d3f-4b8e-a5c6-0f1d2e3b4a57" \ -H "Content-Type: application/json" \ -d '{"description": "When a reservation is created, create a cleaning task in the Housekeeping department due on the check-out day at 11:00, and send a Slack message to #ops."}'{ "data": { "success": true, "workflowId": "d8b3f1a2-6c4e-4f7a-9b2d-1e0c3a5f7b64", "nodeCount": 3, "edgeCount": 2 }, "meta": { "requestId": "…" }}missingPluginis set when the workflow needs an integration your organization hasn’t connected. It is an integration ID such asslack, orunknown. Connect it in the app, then send the request again.refusalCodeandrefusalMessageare set when the description can’t be built as asked.refusalMessagesays what to change. Rewrite the description and resend.- A request the AI can’t express with an existing trigger, such as a schedule SuiteOp has no trigger for, returns
success: falsewith neither field. Don’t assume an explanation is present; rephrase the description around a trigger that exists.
The AI can build a different graph from the same text on two calls, and a call can take up to about 50 seconds. Set your HTTP client’s timeout accordingly. The response doesn’t include the workflow’s title or its steps.
Changing the steps
Section titled “Changing the steps”POST /workflows/{workflowId}/modify applies a plain-language instruction to an existing workflow. The response has the same fields as create, without workflowId.
curl -X POST "https://api-us.suiteop.com/api/v1/workflows/d8b3f1a2-6c4e-4f7a-9b2d-1e0c3a5f7b64/modify" \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"instruction": "Create the cleaning task and send the Slack message to #ops, and also email the guest the Welcome template two days before check-in."}'- State the end state, not a delta. The AI rewrites the complete graph, so steps you don’t mention can change. The API can’t read the current steps, so describe the whole workflow you want.
- Edits land on the draft. A published workflow keeps running its previous version until you call
publish_workflowagain. - Hidden values stay put. Values SuiteOp masks, such as HTTP headers, query parameters, request bodies and URLs, can’t be changed this way. When the instruction tried to change one, the edit is saved without that change and
hiddenValuesNotChangedlists each one bynodeIdandfield(url,body,header,queryorparameter).cleared: truemeans the field was saved without its value and must be re-entered in the app. - A deleted workflow, or one in another organization, returns
404 not_found_error. If someone saves the workflow while the AI is working, the call returns409 conflict_error; send it again.
Scoping a workflow
Section titled “Scoping a workflow”POST /workflows/{workflowId}/scopes sets where the workflow runs, one scopeType at a time: property, property_group or tag.
curl -X POST "https://api-us.suiteop.com/api/v1/workflows/d8b3f1a2-6c4e-4f7a-9b2d-1e0c3a5f7b64/scopes" \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"scopeType": "property_group", "entityIds": ["2e6d0f5b-8a1c-4d3e-9b7f-6c0a2e4d8f13"]}'{ "data": { "success": true }, "meta": { "requestId": "…" } }- It replaces one type.
entityIdsis the complete list for thatscopeType: anything you leave out is removed, and[]clears it. The other two types are untouched. - IDs must match
scopeTypeand be yours. IDs from another organization return400 validation_errorwith the messagevalidation.scope_ids_not_in_org. - A live workflow can’t lose its last scope. Clearing it returns
400 validation_error. Pause the workflow withupdate_workflowfirst. - The response doesn’t echo the scopes. These are workflow scopes, separate from the entity scopes of portal content.
Publishing
Section titled “Publishing”POST /workflows/{workflowId}/publish takes an empty body. It makes the current draft the live version and switches the workflow on.
curl -X POST "https://api-us.suiteop.com/api/v1/workflows/d8b3f1a2-6c4e-4f7a-9b2d-1e0c3a5f7b64/publish" \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{}'{ "data": { "success": true, "publishedVersionId": "71c0e9d4-3a2b-4c5f-8e6d-9b1a0f2c3d48", "activeVersionId": "71c0e9d4-3a2b-4c5f-8e6d-9b1a0f2c3d48", "isActive": true }, "meta": { "requestId": "…" }}Publishing checks the draft first. It returns 400 validation_error when the workflow has no scope (message validation.workflow.publish_unscoped), no trigger, steps missing required settings, or a trigger that is no longer offered. It returns 404 when there is no draft to publish, and 409 conflict_error when the workflow changed during the call.
Renaming, pausing and refiling
Section titled “Renaming, pausing and refiling”PATCH /workflows/{workflowId} changes a workflow’s settings, never its steps. Send only the fields that change.
curl -X PATCH "https://api-us.suiteop.com/api/v1/workflows/d8b3f1a2-6c4e-4f7a-9b2d-1e0c3a5f7b64" \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"isActive": false}'isActive:falsepauses the workflow,trueresumes it. Switching on a workflow with no scope returns400 validation_error. To put new steps live, usepublish_workflow.title: a new name, 1 to 200 characters.folderId: moves the workflow to a folder in your organization, ornulltakes it out of its folder. Folders are created in the app.
The response is { "success": true }.
Pitfalls
Section titled “Pitfalls”- Unknown fields are rejected. Every workflow operation rejects fields it doesn’t define with
400 validation_error. There is nopropertyIds,isActiveorpublishon create or modify. - AI rate limit.
create_workflowandmodify_workflowcount toward the per-organization budget for AI-backed operations, shared by every key in the organization (see Rate limits). An AI outage returns502or503; retry later. - Idempotency. Send an
Idempotency-Keyon thePOSToperations so a retried create doesn’t make a second workflow (see Idempotency).PATCHignores the header. An AI call can run close to a minute, so wait for the first request to finish before retrying with the same key, or the retry returns409. - Property-limited callers. An OAuth token carries its member’s property access. For such a caller,
set_workflow_scopesreplaces only the scopes the member can reach and keeps the rest, so a200doesn’t mean the workflow runs exactly where you asked. An ID outside the member’s access returns404. - Raw error keys. Most workflow errors carry a message key such as
validation.workflow.publish_unscopedrather than a sentence. Match on it, and onerror.code, rather than on English text. - No webhooks. Creating, publishing or running a workflow doesn’t send a webhook event.