Built-in Steps
The steps and triggers MindCloud runs itself (Loop, If/Else, Code, HTTP request, Schedule, Webhook and more): each one's settings, their types and examples, and what it outputs.
Set a built-in step up with Update Workflow Step Configuration: its settings go in arguments and the ones marked option in options. Get Workflow Step Schema answers the same for a step you have added. A template is text that may hold references (Workflow References); a condition is an If/Else condition tree.
Steps
Loop
Add it with "app": "iterate" in Add Workflow Step.
| Setting | Type | Required | Default | Choices | Example | What it is |
|---|---|---|---|---|---|---|
source | template | yes | "{{ steps.<stepId>.output }}" | What to loop through: "{{ steps.<stepId>.output }}" (every record) or "{{ steps.<stepId>.output[0].<field> }}" (an array in the first record). | ||
delayMs | integer | no | 100 | 500 | A pause after each item, in milliseconds: 1 or more. Left out, 100. |
Options: parallel (Run loop items in parallel: { adaptive, window, maxWindow }. Example: {"window":5}).
Output. The list it loops through. Inside the loop, each pass sees the Loop's output as a one-item list holding the current item, so steps in its body read {{ steps.<loopStepId>.output[0].<field> }}. A Loop is not tested on its own: give the step it loops over a sample (Test Workflow Step or Update Workflow Step Output) and the Loop's sample is that sample's first record.
If/Else
Add it with "app": "ifElse" in Add Workflow Step.
| Setting | Type | Required | Default | Choices | Example | What it is |
|---|---|---|---|---|---|---|
condition | condition | yes | {"conjunction":"and","where":[{"field":"{{ steps.<loopStepId>.output[0].realName }}","operator":"startsWith","value":"D","type":"string"},{"field":"{{ steps.<loopStepId>.output[0].isBot }}","operator":"eq","value":"false","type":"boolean"}]} | A condition tree: one condition { field, operator, value, type } or a group { conjunction, where }. Sending one in place of the other replaces it whole. It is stored as a group, so reads always answer { conjunction, where }: a single condition reads back as a group of one. |
Output. One record: which lane ran and each condition as it was evaluated. The then lane runs when the condition holds, the else lane otherwise.
| Field | Type | Holds |
|---|---|---|
conclusion | string | then or else: the lane that ran. |
conditions | object | The condition tree as evaluated: { conjunction, filterSet }, where filterSet lists each condition as { field, operator, value, conclusion, disabled } with its field and value resolved and conclusion true or false, and each nested group as { type: "nested", conjunction, filterSet, conclusion }. An If still on the older single condition answers field, operator and value on the record itself instead. |
Transform
Add it with "app": "transform" in Add Workflow Step.
| Setting | Type | Required | Default | Choices | Example | What it is |
|---|---|---|---|---|---|---|
source | template | yes | "{{ steps.<stepId>.output }}" | The output to transform: "{{ steps.<stepId>.output }}". |
Options: postProcess (Filter, sort and slice the output: { filter, sort: [{ field, direction }], slice: { from, to } } (from 0, to excluded). Example: {"slice":{"from":0,"to":10}}).
Output. Transform filters, sorts or slices one earlier output without code (to reshape records with JavaScript, use Map). It answers the source's records after the postProcess option's filter, sort and slice.
Wait
Add it with "app": "wait" in Add Workflow Step.
| Setting | Type | Required | Default | Choices | Example | What it is |
|---|---|---|---|---|---|---|
delayMs | integer | no | 1000 | 5000 | How long to wait, in milliseconds: 1 or more. Left out, 1000. |
Output. One record with the pause it took.
| Field | Type | Holds |
|---|---|---|
delay | integer | The pause, in milliseconds. |
Continue or Break
Add it with "app": "continue" or "app": "break" in Add Workflow Step.
No settings.
Output. No output: Continue moves a loop to its next item, Break ends the loop.
Map
Add it with "app": "map" in Add Workflow Step.
| Setting | Type | Required | Default | Choices | Example | What it is |
|---|---|---|---|---|---|---|
code | string | yes | "return input['<key>'].map((user) => ({ name: 'Mr. ' + user.realName }));" | The JavaScript, a function body that returns the output: input['<key>'] is each input's output, always a list. Required before the step can run, not to save it: a Map step added without code is kept and shows as not set up yet, which is how one that reads a step created in the same Set Workflow Definition call is added before its key is known. | ||
inputs | array | yes | [{"stepId":"<stepId>","grouped":false}] | The steps whose outputs the code reads: [{ stepId, grouped }]. grouped (for a step inside a loop) collects that step's records from every pass of the loop instead of the current pass's. Each input answers its key, the name the code reads it by (input['<key>']): for an app step it is the app's slug, then the action's slug with a capital first letter, then Group when grouped, then the last four characters of the step id in capitals (slackListUsers7K2Q); for a built-in step it is the built-in's slug, then Group when grouped, then those four characters (iterateFVNN). It cannot be set. | ||
allowLargeOutput | boolean | no | false | Allow an output row over 500 KB. |
Options: batching (Run the code once per batch of an input: { size, inputKey }. Example: {"size":100,"inputKey":"<key>"}).
Output. Map runs your JavaScript over earlier steps' outputs (to filter, sort or slice one output without code, use Transform). It answers the records the code returns: return an array for several records. The code is the body of a JavaScript function that gets one argument, input, whose keys are the inputs' keys (each input's key is answered with it, before and after a save). Each input['<key>'] is always a list: a step's records, the current item of a loop as a one-item list, or with grouped every pass's records of a step inside a loop. It runs in MindCloud's code runner.
Group results
Add it with "app": "groupResults" in Add Workflow Step.
| Setting | Type | Required | Default | Choices | Example | What it is |
|---|---|---|---|---|---|---|
inputs | array | yes | ["<stepId>","<stepId>"] | The steps whose outputs are grouped, in order. | ||
flatten | boolean | no | true | Flatten nested lists into one. | ||
hideEmpty | boolean | no | true | Leave out empty results of steps inside an If. |
Output. The records of its inputs collected into one output, in input order; a step inside a loop contributes its records from every pass. flatten merges them into one list of records.
Memory
Add it with "app": "memory" in Add Workflow Step.
No settings.
Options: memory (Values to remember after the step runs: [{ key, value, scope, saveOn, expiresAfterMs }]. Example: [{"key":"lastSync","value":"{{ system.now }}","scope":"workflow","saveOn":"success"}]).
Output. One record per value its memory option saved.
| Field | Type | Holds |
|---|---|---|
key | string | The name the value is saved under. |
value | dynamic | The value saved. |
scope | string | Where it is kept: workflow, allWorkflows, environment or installation. |
Flow control
Add it with "app": "flowControl" in Add Workflow Step.
| Setting | Type | Required | Default | Choices | Example | What it is |
|---|---|---|---|---|---|---|
action | string | no | "endAsSuccess" | doNothing, continue or break (in a loop), endAsSuccess, or endAsFailure. | ||
log | object | no | {"level":"info","message":"Synced {{ steps.<stepId>.output[0].id }}"} | Write to the run log: { level: info | warn | error, message }. | ||
email | object | no | {"to":"[email protected]","subject":"Order failed","body":"Order {{ steps.<stepId>.output[0].id }} failed."} | Send an e-mail: { to (comma-separated), subject, body, html, toEndUser }. | ||
slack | object | no | {"channel":"C0123456789","message":"Order {{ steps.<stepId>.output[0].id }} failed."} | Send a Slack message: { channel (a channel id), message }. |
Output. One record: the action taken and what each notice did.
| Field | Type | Holds |
|---|---|---|
action | string | The action it took. |
log | object | sent: whether it wrote to the run log. |
email | object | sent, sentTo and any recipients skipped for rate limits. |
slack | object | sent, and Slack's answer. |
HTTP request
Add it with "app": "httpRequest" in Add Workflow Step.
| Setting | Type | Required | Default | Choices | Example | What it is |
|---|---|---|---|---|---|---|
url | template | yes | "https://api.example.com/orders/{{ steps.<stepId>.output[0].id }}" | The URL, which may hold templates. | ||
method | string | no | "POST" | GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS. Left out, GET. | ||
query | array | no | [{"name":"status","value":"open","type":"string"}] | Query parameters: [{ name, value, type }]. | ||
headers | array | no | [{"name":"Accept","value":"application/json","type":"string"}] | Headers: [{ name, value, type }]. | ||
auth | object | no | {"type":"bearer","token":"{{ workflow.inputs.apiToken }}"} | Authentication: { type: basic, username, password }, { type: bearer, token }, or { type: apiKey, name, value, in: header (the default) or query }; null for none. | ||
body | object | no | {"format":"json","fields":[{"name":"orderId","value":"{{ steps.<stepId>.output[0].id }}","type":"string"}]} | The body: { format: json | formData | urlencoded, fields: [{ name, value, type }] } or { format: raw, content, contentType }; null for none. | ||
followRedirects | boolean | no | false | Follow redirects (up to 10). Left out, true. | ||
acceptEncoding | string | no | "gzip" | The Accept-Encoding to ask for: gzip, deflate, gzip, deflate, br. | ||
connectionPooling | boolean | no | true | Reuse connections. Left out, true. | ||
retries (option) | object | no | {"count":3,"delayMs":1000,"multiplier":2,"onStatusCodes":[429,503]} | Retries, as on every step: { count, delayMs, multiplier, onStatusCodes, onAnyError }. |
Options: onFailure (What to do when the step fails: { action, logLevel }. Example: {"action":"continue","logLevel":"warn"}); onNoResults (What to do when it finds nothing: { action, logLevel }. Example: {"action":"break"}); onSuccess (What to do when it succeeds: { action: stop }. Example: {"action":"stop"}).
Output. The response body as records: an array body gives one record per item, anything else one record. The response's status and headers are in the step's meta.response.
Run workflow
Add it with "app": "runWorkflow" in Add Workflow Step.
| Setting | Type | Required | Default | Choices | Example | What it is |
|---|---|---|---|---|---|---|
workflowId | string | yes | "Wq3kZ8pLx2Nb" | The workflow to run, from List Workflows. | ||
version | string | no | "published" | published (the default once it has one) or draft. | ||
inputs | object | no | {"orderId":"{{ steps.<stepId>.output[0].id }}"} | Values for the workflow's variables, by key; they may be templates. | ||
environments | array | no | ["Ev8kT3nW5qLz"] | Environment ids to run it in, one run each; left out, one run in the default environment. |
Output. One record per run it queued, with the message the queue answered; a run that could not be queued adds a record with its error.
| Field | Type | Holds |
|---|---|---|
message | string | What the queue answered. |
error | string | Why a run could not be queued. |
Triggers
Schedule
Add it with "app": "schedule" in Add Workflow Trigger.
| Setting | Type | Required | Default | Choices | Example | What it is |
|---|---|---|---|---|---|---|
type | string | no | "interval" | interval, fixed | "fixed" | interval: every everyMinutes; fixed: at each of times, in timeZone. |
everyMinutes | integer | no | 60 | 10, 15, 30, 60, 180, 360, 720, 1440, 2880, 4320, 10080, 20160 | 60 | Interval schedules: how often it runs, in minutes, one of the choices. Days are read in the company time zone. |
days | array | no | [0,1,2,3,4,5,6] | 0, 1, 2, 3, 4, 5, 6 | [1,2,3,4,5] | Weekdays it runs on, 0 (Sunday) to 6. Left out, every day; an empty list never runs. |
times | array | no | ["09:00","17:00"] | Fixed schedules: the times it runs at, HH:MM in 24-hour time, at least one, each at least 10 minutes from the next (across midnight too). Stored once each, in order. | ||
timeZone | string | no | "America/New_York" | Fixed schedules: the IANA time zone of times and days ("America/New_York"). | ||
environments | array | no | ["Ev8kT3nW5qLz"] | Environment ids to run in, one run each; left out, the default environment. Not for Embedded workflows. |
Output. It starts a run at each scheduled time; steps read the time as {{ system.now }}.
Webhook
Add it with "app": "webhook" in Add Workflow Trigger.
| Setting | Type | Required | Default | Choices | Example | What it is |
|---|---|---|---|---|---|---|
url | string | no | "https://webhook.mindcloud.co/v1/webhook/<id>" | The URL that starts the workflow, made by MindCloud. Read-only. Add Workflow Trigger answers it as webhookUrl too. | ||
waitForCompletion | boolean | no | false | false | true: a call waits for the workflow to finish (the answer comes from a Respond to webhook step, if any); false: the call is queued and answered at once, with the custom response when one is set and otherwise { success, message, requestId, runId }, where runId is the run it started (Get a Run; null when processInOrder is on, since that run starts later). A new Webhook trigger starts false (queued), as in the editor; adding a Respond to webhook step turns it true. Settings apply after publish. | |
processInOrder | boolean | no | true | Queued calls only: run one at a time, in the order they came. Each run starts when its turn comes, so the answer has no runId. | ||
forwardHeaders | boolean | no | false | Queued calls only: answer with the call's own request headers. | ||
customUrl | string | no | "orders/:orderId" | A path of your own after https://webhook.mindcloud.co/v1/webhook/<company slug>/, such as "orders/:orderId" (":name" captures a part). Applies at once, published or not; unique in the company. null turns it off. | ||
response | object | no | {"status":["200","201","202","204","301","304","400","401","403","404","418","429","500","502","503","504"]} | {"status":"202","body":{"received":"true"}} | Queued calls only: the answer, { status, headers, body, redirectUrl }. status is one of the choices (default "200"); headers are names and values; body is fields and values, or one text value; templates may read only this trigger's call, {{ trigger.<triggerId>.output[0].body.<field> }}. null answers the default. | |
environments | array | no | ["Ev8kT3nW5qLz"] | Queued calls only: environment ids to run in, one run each; left out, the default environment. Not for Embedded workflows. |
Output. One record per call, read as {{ trigger.<triggerId>.output[0].<part>.<field> }}. Listen Workflow Trigger saves a real call as the sample.
| Field | Type | Holds |
|---|---|---|
body | object | The call's body. |
query | object | The call's query parameters. |
headers | object | The call's headers. |
When called
Add it with "app": "runWorkflow" in Add Workflow Trigger.
| Setting | Type | Required | Default | Choices | Example | What it is |
|---|---|---|---|---|---|---|
allowConcurrentRuns (option) | boolean | no | true | Start a run for every call, even while another run of this workflow is going. Left out, a call made during a run is skipped. |
Output. It starts a run when another workflow's Run workflow step calls this one; the values that step sends set this workflow's variables, read as {{ workflow.inputs.<key> }}.