Skip to content
Dashboard

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.

OperationRequestPermission
create_workflowPOST /workflowsmanage_workflows
modify_workflowPOST /workflows/{workflowId}/modifymanage_workflows
set_workflow_scopesPOST /workflows/{workflowId}/scopesmanage_workflows
publish_workflowPOST /workflows/{workflowId}/publishmanage_workflows
update_workflowPATCH /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.

A workflow goes live in three steps. Skipping one leaves it unable to fire.

  1. Create. create_workflow saves the workflow as an inactive, unscoped draft.
  2. Scope. set_workflow_scopes chooses the properties, property groups or tags it runs on. A workflow with no scope never runs, and publishing one is refused.
  3. Publish. publish_workflow makes 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.

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.

Terminal window
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": "…" }
}
  • missingPlugin is set when the workflow needs an integration your organization hasn’t connected. It is an integration ID such as slack, or unknown. Connect it in the app, then send the request again.
  • refusalCode and refusalMessage are set when the description can’t be built as asked. refusalMessage says 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: false with 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.

POST /workflows/{workflowId}/modify applies a plain-language instruction to an existing workflow. The response has the same fields as create, without workflowId.

Terminal window
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_workflow again.
  • 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 hiddenValuesNotChanged lists each one by nodeId and field (url, body, header, query or parameter). cleared: true means 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 returns 409 conflict_error; send it again.

POST /workflows/{workflowId}/scopes sets where the workflow runs, one scopeType at a time: property, property_group or tag.

Terminal window
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. entityIds is the complete list for that scopeType: anything you leave out is removed, and [] clears it. The other two types are untouched.
  • IDs must match scopeType and be yours. IDs from another organization return 400 validation_error with the message validation.scope_ids_not_in_org.
  • A live workflow can’t lose its last scope. Clearing it returns 400 validation_error. Pause the workflow with update_workflow first.
  • The response doesn’t echo the scopes. These are workflow scopes, separate from the entity scopes of portal content.

POST /workflows/{workflowId}/publish takes an empty body. It makes the current draft the live version and switches the workflow on.

Terminal window
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.

PATCH /workflows/{workflowId} changes a workflow’s settings, never its steps. Send only the fields that change.

Terminal window
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: false pauses the workflow, true resumes it. Switching on a workflow with no scope returns 400 validation_error. To put new steps live, use publish_workflow.
  • title: a new name, 1 to 200 characters.
  • folderId: moves the workflow to a folder in your organization, or null takes it out of its folder. Folders are created in the app.

The response is { "success": true }.

  • Unknown fields are rejected. Every workflow operation rejects fields it doesn’t define with 400 validation_error. There is no propertyIds, isActive or publish on create or modify.
  • AI rate limit. create_workflow and modify_workflow count toward the per-organization budget for AI-backed operations, shared by every key in the organization (see Rate limits). An AI outage returns 502 or 503; retry later.
  • Idempotency. Send an Idempotency-Key on the POST operations so a retried create doesn’t make a second workflow (see Idempotency). PATCH ignores 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 returns 409.
  • Property-limited callers. An OAuth token carries its member’s property access. For such a caller, set_workflow_scopes replaces only the scopes the member can reach and keeps the rest, so a 200 doesn’t mean the workflow runs exactly where you asked. An ID outside the member’s access returns 404.
  • Raw error keys. Most workflow errors carry a message key such as validation.workflow.publish_unscoped rather than a sentence. Match on it, and on error.code, rather than on English text.
  • No webhooks. Creating, publishing or running a workflow doesn’t send a webhook event.