Skip to Content
AutomateWorkflows

Workflows

The workflow system provides state machine automation for any collection. Workflows control how items move between states (e.g., draft → review → published), who can trigger each transition, and what side effects run automatically.

Concepts

ConceptDescription
Workflow DefinitionJSON state machine stored in daas_wf_definition
Workflow AssignmentLinks a workflow to a collection + optional filter rule
Workflow InstanceCreated automatically when a matching item is created
TransitionMoving from one state to another via a named command
ActionAn event emitted after a successful transition

Workflow Definition Structure

{ "initial_state": "Draft", "states": [ { "name": "Draft", "commands": [ { "name": "Submit", "next_state": "Pending Approval", "policies": [], "actions": [] } ], "isEndState": false }, { "name": "Pending Approval", "commands": [ { "name": "Reject", "next_state": "Draft", "policies": [], "actions": [] }, { "name": "Approve", "next_state": "Published", "policies": ["550e8400-e29b-41d4-a716-446655440000"], "actions": [ { "name": "Publish", "event_name": "xtr.item.promote", "parameters": {} } ] } ], "isEndState": false }, { "name": "Published", "commands": [], "isEndState": true } ] }

State fields

FieldTypeDescription
namestringUnique state identifier
commandsarrayAvailable transitions from this state
isEndStatebooleanTerminal state — no further transitions

Command fields

FieldTypeDescription
namestringUnique command identifier
next_statestringState to transition to
policiesstring[]Required policy UUIDs — user must hold at least one
actionsarrayEvents to emit after transition

Action fields

FieldTypeDescription
namestringHuman-readable label
event_namestringEvent emitted — xtr.item.promote or custom
parametersobjectExtra data passed to the event handler

Automatic Instance Creation

When an item is created in a collection that has a Workflow Assignment, the system automatically:

  1. Checks daas_wf_assignment for matching assignments (by collection + filter rule)
  2. Creates a daas_wf_instance with current_state set to initial_state
  3. Updates the item’s workflow instance field and state field

Exactly one assignment must match per item. If zero match, the workflow is skipped. If multiple match, an error is logged and no instance is created.

Required collection fields

Two fields must exist in the collection: a Many-to-One link to daas_wf_instance and a Workflow State string field.

New collections — enable both switches in the collection creation wizard under System Fields → Workflow Fields:

SwitchField createdDetails
Workflow Instanceworkflow_instanceM2O to daas_wf_instance, nullable UUID
Workflow Stateworkflow_statextr-interface-workflow interface, read-only

Existing collections — add the fields manually via Data Model → [Your Collection] → New Field:

Field typeInterfacePurpose
Many-to-One → daas_wf_instanceM2OStores the workflow instance ID
Stringxtr-interface-workflow (Workflow State)Stores the current state name

Mark both as read-only in the field metadata — users should not edit them directly.

Execute a Transition

POST /api/workflow/transition
{ "workflowInstanceId": "uuid", "commandName": "Approve" }

Success (200):

{ "message": "Successfully transitioned workflow state" }

Unauthorized (403):

{ "message": "You are not authorized to perform this transition" }

The endpoint:

  1. Validates the command exists in the current state
  2. Checks the user holds at least one required policy UUID (directly or via role)
  3. Updates current_state in daas_wf_instance
  4. Records the transition in daas_wf_history
  5. Updates the workflow state field in the target collection or version
  6. Fires all configured actions in sequence

Built-in Actions

xtr.item.promote

Promotes a content version to the main item. Only runs when the workflow instance is linked to a version (version_key is not null).

{ "name": "Promote to Main", "event_name": "xtr.item.promote", "parameters": {} }

Custom actions

Register any event_name in a file-based extension or runtime extension:

export function register(sdk) { sdk.emitter.onAction('xtr.notification.send-email', async (meta, context) => { // action parameters are spread onto meta.payload[0] alongside workflow_instance const { recipient, workflow_instance } = meta.payload[0]; await sendEmail(recipient, 'Workflow state changed'); }); }

Workflow Assignments

Assignments connect a workflow definition to a collection with an optional filter rule:

{ "collection": "articles", "workflow": "workflow-definition-uuid", "filter_rule": { "category": { "_eq": "news" } } }

An empty filter_rule matches all items in the collection.

Version Workflows

Workflows can track content versions. When a version is created:

  • The filter rule is tested against the parent item (not the version itself)
  • The instance is linked with a version_key
  • The xtr.item.promote action applies the version delta to the main item

Best Practices

  1. One assignment per collection/filter combination — avoid overlapping filter rules
  2. Mark workflow fields as read-only — users should not manually edit workflow_instance or workflow_state
  3. Use empty policies arrays for commands that any authenticated user can trigger
  4. Test filter rules with Supabase queries before production

REST API

MethodPathDescription
GET/api/workflowsList workflow definitions
POST/api/workflowsCreate workflow definition
GET/api/workflows/:idGet workflow definition
PATCH/api/workflows/:idUpdate definition
DELETE/api/workflows/:idDelete definition
GET/api/workflow-instancesList instances
GET/api/workflow-instances/:idGet instance
GET/api/workflow-instances/:id/historyList transition history for an instance
GET/api/workflow-assignmentsList assignments
POST/api/workflow-assignmentsCreate assignment
GET/api/workflow-assignments/:idGet assignment
PATCH/api/workflow-assignments/:idUpdate assignment
DELETE/api/workflow-assignments/:idDelete assignment
POST/api/workflow/transitionExecute transition
Last updated on