Skip to content

Workflow triggers ​

A trigger starts a workflow automatically. Each trigger belongs to one workflow, has a name and a configuration, and can be enabled or disabled without deleting it. In the console, you manage triggers in the workflow's editor.

Besides triggers, a workflow can be started by hand from the console or with the executeWorkflow mutation (see Running a workflow). Each execution records how it was started in its triggerType, for example MANUAL or SCHEDULED. The API's TriggerType enum does not yet include edge app event and folder watch triggers, so don't select triggerType on executions those triggers started.

Trigger types ​

TypeFires whenWorkflow input
ScheduledA CRON schedule is dueEmpty
EventA record of a given kind is created, updated or deletedThe result of the optional data query, under data
Device MQTTA device publishes an MQTT message on a matching topicThe message under mqtt, with the fields of a JSON payload also copied to the top level
Edge app eventAn edge app on a controller publishes an eventThe event under edgeAppEvent
Folder watchA new file appears in a FolderfolderId and the file's key

Scheduled ​

FieldMeaning
cronExpressionCRON expression with 5 or 6 fields: minute, hour, day of month, month, weekday and an optional year
timezoneIANA time zone the schedule is evaluated in, for example Europe/Berlin. Optional.
overlapPolicyALLOW, SKIP or CANCEL. Required, but not applied at run time: what happens when a previous run is still going is decided by the trigger's concurrency policy.

Event ​

FieldMeaning
topicThe change to react to, as <resource>.<action>, for example job.created, order.updated or preflightReport.created
dataQueryOptional GraphQL query run when the event fires. The ID of the changed record is passed as $id, and the result appears in the workflow input under data.

The listDataChangeEventTopics query returns every available topic. Not every listed topic fires yet, so test a trigger before you rely on it:

graphql
query EventTopics {
  listDataChangeEventTopics {
    topics { topic verb description }
  }
}

The event itself only identifies the record that changed and carries none of its fields, so use dataQuery to load the fields you need:

graphql
query DataQuery($id: JobID!) {
  getJob(id: $id) {
    id
    name
    status
    quantity
  }
}

A workflow started this way reads the job as input.data.getJob.status, and so on.

Device MQTT ​

FieldMeaning
topicTopic filter relative to the device, with the MQTT wildcards + and #. Do not include the tenant or device prefix; a topic starting with t/ is rejected.
deviceIdOptional. Limits the trigger to one device (dev_...); without it, messages from every device in the tenant match.
filterOptional JSON Logic rule evaluated against the message envelope

The workflow input contains mqtt with topic, relativeTopic, deviceId, qos, retain, receivedAt, payload (the parsed JSON payload) and payloadRaw. If the payload is a JSON object, its fields are also copied to the top level of the input. A filter that starts the workflow only when the payload's state is open:

json
{ "==": [{ "var": "mqtt.payload.state" }, "open"] }

A new Device MQTT trigger starts listening within a few seconds. A change to the topic, device or filter of a trigger that is already enabled is not picked up on its own: disable the trigger, wait a few seconds, and enable it again.

For the MQTT side, see Getting started with MQTT.

Edge app event ​

All fields are optional. Leave them out to match every event in the tenant.

FieldMeaning
controllerIdOnly events from this controller (ctl_...)
edgeAppHandleOnly events from this edge app
topicOnly events published on this topic (exact match, no wildcards)

The workflow input contains edgeAppEvent with controllerId, edgeAppHandle, topic, emittedAt and payload.

Folder watch ​

FieldMeaning
folderIdThe Folder to watch (fld_...)
prefixFolder-relative path to watch for new files. Only files directly under the prefix are picked up, not files in subdirectories.

Folders are polled, so a new file starts the workflow after a short delay rather than instantly. Folder-watch triggers must use the concurrency policy ALLOW and no execution cap.

Concurrency ​

Every trigger has a concurrencyPolicy that decides what happens when it fires while an execution of the workflow is still pending or running (from any trigger or a manual run):

PolicyBehaviour
ALLOWStart another execution (default)
QUEUEQueue the firing and start it when an execution finishes (at most 100 waiting; a firing waiting longer than an hour is dropped). The queued run does not get the original firing's input, such as the MQTT message.
SKIPSkip the new execution
CANCELCancel the workflow's pending and running executions and start the new one

With ALLOW, maxConcurrentExecutions caps how many executions of the workflow may be pending or running when the trigger fires; beyond that the firing is skipped. Leave it out for no cap.

A trigger runs the workflow's active version. Set versionId to pin it to one specific version instead.

Managing triggers with the API ​

graphql
mutation NightlyReport($input: CreateWorkflowTriggerInput!) {
  createWorkflowTrigger(input: $input) {
    trigger { id name isEnabled }
    errors { path message }
  }
}
json
{
  "input": {
    "workflowId": "wfl_...",
    "name": "nightly-report",
    "config": {
      "scheduled": {
        "cronExpression": "0 2 * * *",
        "timezone": "Europe/Berlin",
        "overlapPolicy": "SKIP"
      }
    }
  }
}

config takes exactly one of scheduled, event, deviceMqtt, edgeAppEvent or folderWatch. List a workflow's triggers, and turn one off or on:

graphql
query Triggers($workflowId: WorkflowID!) {
  workflowTriggers(workflowId: $workflowId) {
    id
    name
    isEnabled
    concurrencyPolicy
    config {
      __typename
      ... on ScheduledTriggerConfig { cronExpression timezone overlapPolicy }
      ... on EventTriggerConfig { topic filter dataQuery }
    }
  }
}

mutation Disable($id: WorkflowTriggerID!) {
  disableWorkflowTrigger(input: { id: $id }) {
    trigger { id isEnabled }
    errors { path message }
  }
}

enableWorkflowTrigger, updateWorkflowTrigger and deleteWorkflowTrigger work the same way.

Connect machines, automate workflows, and build custom apps for print production.