EZ Texting Workflows Schema
$schema: https://json-schema.org/draft/2020-12/schema
$defs:
".condition.And":
type: object
properties:
and:
description: List of conditions to check against
type: array
items:
anyOf:
- $ref: "#/$defs/.condition.And"
- $ref: "#/$defs/.condition.Or"
- $ref: "#/$defs/.condition.Not"
- $ref: "#/$defs/.condition.JS"
- $ref: "#/$defs/.condition.Variable"
- $ref: "#/$defs/.condition.Operation"
description: |
Logical "and" to check against the conditions provided in the children. Must have at least 2 conditions.
additionalProperties: false
examples:
- example-description: will be true if all of the js and variable condition evaluates to true
and:
- js: |
some code here
- op: eq
value: check-against-this-value
variable: check-against-this-variable
".condition.JS":
type: object
properties:
js:
type: string
description: Custom java script to evaluate to calculate if the value is true
description: |
Custom java script to evaluate to calculate if the value is true.
To succeed must return true boolean or any of the strings: 'true', 'on', 'y', 't' or 'yes'. Otherwise will evaluate to false.
additionalProperties: false
examples:
- example-description: will evaluate to true
js: |
true
- example-description: will evaluate to true
js: |
'12356'.length == 5
- example-description: will evaluate based on the value in contact custom field
js: |
contact.vipClient
".condition.Not":
type: object
properties:
not:
anyOf:
- $ref: "#/$defs/.condition.And"
description: Condition to negate
- $ref: "#/$defs/.condition.Or"
description: Condition to negate
- $ref: "#/$defs/.condition.Not"
description: Condition to negate
- $ref: "#/$defs/.condition.JS"
description: Condition to negate
- $ref: "#/$defs/.condition.Variable"
description: Condition to negate
- $ref: "#/$defs/.condition.Operation"
description: Condition to negate
description: |
Negates the evaluation result of the child condition.
additionalProperties: false
examples:
- example-description: will evaluate to false as a result
not:
js: |
true
".condition.Operation":
type: object
properties:
dataType:
$ref: "#/$defs/OperationDataType"
description: The type of the data the operation is working with
operation:
$ref: "#/$defs/OperationType"
description: Operation to perform on the provided input
value:
type: string
description: the value to compare with
description: |
The operation to perform on the provided input. Will evaluate to true or false based on the input
additionalProperties: false
examples: []
".condition.Or":
type: object
properties:
or:
description: List of conditions to check against
type: array
items:
anyOf:
- $ref: "#/$defs/.condition.And"
- $ref: "#/$defs/.condition.Or"
- $ref: "#/$defs/.condition.Not"
- $ref: "#/$defs/.condition.JS"
- $ref: "#/$defs/.condition.Variable"
- $ref: "#/$defs/.condition.Operation"
description: |
Logical "or" to check against the conditions provided in the children. Must have at least 2 conditions.
additionalProperties: false
examples:
- example-description: will be true if one of the js or variable condition evaluates to true
or:
- js: |
some code here
- op: eq
value: check-against-this-value
variable: check-against-this-variable
".condition.Variable":
type: object
properties:
dataType:
$ref: "#/$defs/OperationDataType"
description: The type of the data the operation is working with
op:
$ref: "#/$defs/OperationType"
description: Operation to perform on the variable
value:
type: string
description: "Value to check against. Optional for some types of operations, like 'exists'"
variable:
type: string
description: Name of the variable to check against
minLength: 1
pattern: "^([a-zA-Z][-a-zA-Z0-9\\.]*)$"
required:
- op
- variable
description: |
Variable condition to check against.
Takes a variable and checks operation on that.
additionalProperties: false
examples:
- example-description: "will evaluate to true, assuming \"theVariable\" variable has text 'hello world'"
op: contains
dataType: text
value: world
variable: theVariable
- example-description: "will evaluate to false, assuming \"theVariable\" variable has text 'hello world'"
op: eq
dataType: text
value: world
variable: theVariable
- example-description: "will evaluate to true, assuming \"theDateVariable\" variable has date value of '2025-01-01T15:49:51'"
op: gt
dataType: date
value: 2024-12-01T05:39:00
variable: theDateVariable
".configuration.action.Delay":
type: object
properties:
amount:
type: integer
description: The amount of units to delay execution for
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
units:
$ref: "#/$defs/DelayUnit"
description: Units to delay execution for
waitForDate:
examples:
- 2030-12-31
description: Specific date to wait for
additionalProperties: false
type: string
format: date
waitForDay:
$ref: "#/$defs/DayOfWeek"
description: Day of week to wait for
waitForTime:
examples:
- 23:59:59
description: Specific time to wait for
additionalProperties: false
type: string
format: time
type:
const: .configuration.action.Delay
description: |
Delay the execution for specified configurable time.
One can specify one of the setting: units, waitForDay or waitForDate.
Additional setting waitForTime can be added to the above.
The calculations will be done in account time zone, specified in settings.
additionalProperties: false
examples:
- example-description: wait for 3 days AND until 14:00
type: .configuration.action.Delay
transitionTo: ResumeExecutionNode
amount: 3
units: DAY
waitForTime: 14:00:00
- example-description: wait until specified date and 3 pm
type: .configuration.action.Delay
transitionTo: ResumeExecutionNode
waitForDate: 2025-12-31
waitForTime: 15:00:00
- example-description: wait until Monday at 5 pm
type: .configuration.action.Delay
transitionTo: ResumeExecutionNode
waitForDay: MONDAY
waitForTime: 17:00:00
".configuration.action.DeleteContact":
type: object
properties:
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
type:
const: .configuration.action.DeleteContact
description: |
Deletes a contact from account with all the values.
Note: even after deleting workflow can still resume for a phone number.
additionalProperties: false
examples:
- example-description: deletes a contact and will resume execution to the next node named "The next execution"
type: .configuration.action.DeleteContact
transitionTo: The next execution
".configuration.action.HttpRequest":
type: object
properties:
errorTransition:
type: string
description: Next node name when execution fails
headers:
$ref: "#/$defs/Map(String,String)"
description: Headers to send along with request
jsonKeyValues:
$ref: "#/$defs/JsonNode"
description: Json key values to use as body object to send. Supports variable replacements in values
method:
$ref: "#/$defs/Method"
description: HTTP method to use
requestBodyVariable:
type: string
description: Request body variable to use to send body as. Will be sent as String entity.
successTransition:
type: string
description: Next node name when execution succeeds
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
url:
type: string
description: Url to send request to. Supports variable replacements
type:
const: .configuration.action.HttpRequest
description: |
Perform http request to an external endpoint and evaluate expression based on the response.
Can variables based on the execution result.
The body of the request will be sent only for HTTP calls that support that by specification, otherwise it will be ignored.
Use requestBodyVariable or jsonKeyValues to populate the body that the request will be sent with.
Passes "responseBody" variable to expression to evaluate the result on.
additionalProperties: false
examples:
- example-description: |-
Perform GET request and extract isVipClient from response, and set it to the vipClient variable.
Transition to next node named "Next Node"
type: .configuration.action.HttpRequest
transitionTo: Next Node - Deprecated for HttpRequest
method: GET
url: "https://example.endpoint/get-info-about?phoneNumber=${contact.phoneNumber}"
headers:
Accept: application/json
Custom-Header: test
requestBodyVariable: theVariableThatContainsBodyToSend
variable: vipClient
expression: |
JSON.parse(responseBody).isVipClient
successTransition: Next node when execution succeeds
errorTransition: Next node when execution fails
- example-description: example shows usage of jsonKeyValues replacements - vipClient is populated with field of the contact.
type: .configuration.action.HttpRequest
transitionTo: Next Node - Deprecated for HttpRequest
method: POST
url: "https://example.endpoint/update-info-about?phoneNumber=${contact.phoneNumber}"
headers:
Accept: application/json
Custom-Header: test
jsonKeyValues:
vipClient: "${contact.isVipClient}"
info: hello!
variable: vipClient
expression: |
JSON.parse(responseBody).isVipClient
successTransition: Next node when execution succeeds
errorTransition: Next node when execution fails
allOf:
- type: object
properties:
expression:
type: string
description: Expression to evaluate the value to set. Supports JavaScript.
variable:
type: string
description: Name of the variable to set the result of the evaluation of the expression. May be empty if the result is returning map or object with key values.
pattern: "^([a-zA-Z][-a-zA-Z0-9\\.]*)$"
description: combination of variable with expression to reuse in configurations that require that
additionalProperties: false
".configuration.action.OptOut":
type: object
properties:
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
type:
const: .configuration.action.OptOut
description: |
Opts out the contact from the further communication.
Note: you can still resume execution. For example to do some http request to make sure you update the contact info on third party side.
additionalProperties: false
examples: []
".configuration.action.SendMessage":
type: object
properties:
campaignId:
type:
- string
- number
description: Campaign id that you'll see messages on the dashboard. Auto generated upon first save.
readOnly: true
containsSuspiciousWords:
type: boolean
description: "An indicator if this message contains suspicious words. If so, you'll have to wait until we work it out or contact customer support to unblock it."
readOnly: true
fileId:
type:
- string
- number
description: The file id to send.
message:
type: string
description: The message text to send. Supports variable replacements. Can use emojis ?
messageType:
$ref: "#/$defs/MessageType"
description: "Type of the message to send. Note: setting this to MMS doesn't guarantee it will be sent as MMS, since some of the carriers doesn't support it. It may be transformed to SMS automatically."
subject:
type: string
description: Subject of the message
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
variable:
type: string
description: the variable name to use to set the resulting delivery state and delivery category to
pattern: "^([a-zA-Z][-a-zA-Z0-9\\.]*)$"
type:
const: .configuration.action.SendMessage
description: |
Sends a message to the contact supporting variable replacements from the instance execution.
additionalProperties: false
examples:
- example-description: "the variables will be saved into sendMessage variable for the execution and can be later accessed like: sendMessage.deliveryState or sendMessage.deliveryCategory"
type: .configuration.action.SendMessage
transitionTo: SomeOtherNode
subject: Your Company Name
messageType: MMS
message: |
Hello, very nice to see you're using workflows from EzTexting! ?
The message you're composing supports variable replacements.
You can use same notation as in sending group texts like ${FirstName} or ${URL=https://example.com}
or even variable replacements with workflow style: ${contact.firstName} or even with space ${contact.custom Field}
fileId: 100
campaignId: 123456789
containsSuspiciousWords: false
variable: sendMessage
".configuration.action.SetVariable":
type: object
properties:
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
type:
const: .configuration.action.SetVariable
description: |
Sets a variable for the current instance during its execution.
Use this to run custom JavaScript and assign the returned value to an instance variable in flow execution context.
The returned result can be a string, number, date, boolean, or an object with properties.
additionalProperties: false
examples:
- example-description: Assigns a static numerical value to the variable.
type: .configuration.action.SetVariable
transitionTo: OtherNode
variable: numericVariableName
expression: |
42
- example-description: Assigns a string literal to the variable.
type: .configuration.action.SetVariable
transitionTo: Send Other Message
variable: strGreeting
expression: |
'Hello, world!'
- example-description: Calculates a simple math expression and assigns the result.
type: .configuration.action.SetVariable
transitionTo: Send Other Message
variable: numericVariableName
expression: |
(2 + 5) * 10
- example-description: |-
Calculates a math expression using variables from the execution context and assigns the result.
For example, given a context variable TWO=2, the expression (TWO + 5) * 10 would result in 70.
type: .configuration.action.SetVariable
transitionTo: Send Other Message
variable: numericVariableName
expression: |
(TWO + 5) * 10
- example-description: |-
Constructs a new object by reusing variables from previous steps using JavaScript object notation.
The resulting object can also be reused in subsequent steps.
In this example, it maps the contact's phone number, which is stored in the 'contact' variable as 'phoneNumber' property, to a key 'theValueFromPreviousSteps' in the resulting object.
type: .configuration.action.SetVariable
transitionTo: Send Other Message
variable: evaluateToSomeMap
expression: |
({greeting: 'Hello, world!', e: 2.71828, pi: Math.PI, theValueFromPreviousSteps: contact.phoneNumber})
- example-description: |-
Evaluates an expression using values from previous steps.
In this case, it gets the length of a phone number for the contact.
type: .configuration.action.SetVariable
transitionTo: Send Other Message
variable: phoneNumberLength
expression: |
contact.phoneNumber.length
- example-description: |-
Evaluates a multiline expression using values from previous steps.
In this case, it converts a phone number retrieved from 'store.phoneNumber' context variable to MSISDN.
type: .configuration.action.SetVariable
transitionTo: Send Other Message
variable: phoneNumberLength
expression: |
const phoneToMSISDN = (phone) => {
if (phone.startsWith("+")) return phone;
return "+" + phone;
};
phoneToMSISDN(store.phoneNumber);
allOf:
- type: object
properties:
expression:
type: string
description: Expression to evaluate the value to set. Supports JavaScript.
variable:
type: string
description: Name of the variable to set the result of the evaluation of the expression. May be empty if the result is returning map or object with key values.
pattern: "^([a-zA-Z][-a-zA-Z0-9\\.]*)$"
description: combination of variable with expression to reuse in configurations that require that
additionalProperties: false
".configuration.action.UpdateContact":
type: object
properties:
fieldExpressions:
description: update a field with an expression value
type: array
items:
$ref: "#/$defs/FieldExpression"
listIds:
description: contact list IDs to add/remove
type: array
items:
type:
- string
- number
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
updateContactType:
$ref: "#/$defs/UpdateContactType"
description: update a field or contact groups
type:
const: .configuration.action.UpdateContact
description: |
Updates a contact's groups or field values.
Performs one of the following actions:
ADD_TO_GROUPS adds a contact to the specified groups,
REMOVE_FROM_GROUPS removes a contact from the specified groups,
UPDATE_FIELD update a contact's field value
Note: phoneNumber is not allowed to be updated by the workflow.
additionalProperties: false
examples:
- example-description: updates a contact's groups and move to the next node
type: .configuration.action.UpdateContact
transitionTo: The next execution
listIds:
- 123
updateContactType: ADD_TO_GROUPS
- example-description: updates a contact's field value and move to the next node
type: .configuration.action.UpdateContact
transitionTo: The next execution
fieldExpressions:
- fieldName: custom1
expression: |
${myReply.messageText}
updateContactType: UPDATE_FIELD
".configuration.condition.If":
type: object
properties:
condition:
anyOf:
- $ref: "#/$defs/.condition.And"
description: condition to evaluate against to determine to which branch to go
- $ref: "#/$defs/.condition.Or"
description: condition to evaluate against to determine to which branch to go
- $ref: "#/$defs/.condition.Not"
description: condition to evaluate against to determine to which branch to go
- $ref: "#/$defs/.condition.JS"
description: condition to evaluate against to determine to which branch to go
- $ref: "#/$defs/.condition.Variable"
description: condition to evaluate against to determine to which branch to go
- $ref: "#/$defs/.condition.Operation"
description: condition to evaluate against to determine to which branch to go
falseTransition:
type: string
description: the name of the node that will be executed if condition evaluates to false
transitions:
description: the first node in the list whose condition evaluates to true will be executed
type: array
items:
$ref: "#/$defs/Transition"
trueTransition:
type: string
description: the name of the node that will be executed if condition evaluates to true
type:
const: .configuration.condition.If
description: |
Branch the workflow based on some condition.
If condition evaluates to true then "true" node will be executed next, "false" node will execute otherwise.
additionalProperties: false
examples:
- example-description: |-
old style - will be removed soon
based on the previously set variable (or contact custom field) we can branch the workflow. In this use case we're branching vip clients to specific scenario
type: .configuration.condition.If
trueTransition: NextTrueNode
falseTransition: NextFalseNode
condition:
js: |
contact.vipClient
- example-description: |-
old style - will be removed soon
branching based on the date, we'll make sure customers will go other branch after some date
type: .configuration.condition.If
trueTransition: After 2030 Branch
falseTransition: Before 2030 Branch
condition:
js: |
new Date().getYear() > 2030
- example-description: |-
old style - will be removed soon
branching based on multiple variables
type: .configuration.condition.If
trueTransition: After 2030 Branch
falseTransition: Before 2030 Branch
condition:
and:
- or:
- js: |
new Date().getYear() > 2030
- op: eq
value: value
variable: variableName
- js: |
contact.vipClient
- example-description: based on the previously set variable (or contact custom field) we can branch the workflow. In this use case we're branching vip clients to specific scenario
type: .configuration.condition.If
transitions:
- name: VIP client
condition:
js: |
contact.vipClient
transitionTo: NextTrueNode
falseTransition: NextFalseNode
- example-description: "branching based on the date, we'll make sure customers will go other branch after some date"
type: .configuration.condition.If
transitions:
- name: 2030
condition:
js: |
new Date().getYear() > 2030
transitionTo: After 2030 Branch
falseTransition: Before 2030 Branch
- example-description: branching based on multiple variables
type: .configuration.condition.If
transitions:
- name: 2030
condition:
and:
- or:
- js: |
new Date().getYear() > 2030
- op: eq
value: value
variable: variableName
- js: |
contact.vipClient
transitionTo: After 2030 Branch
falseTransition: Before 2030 Branch
- example-description: multiple branches
type: .configuration.condition.If
transitions:
- name: 2030
condition:
js: |
new Date().getYear() > 2030
transitionTo: After 2030 Branch
- name: VIP
condition:
js: |
contact.vipClient
transitionTo: Vip Client Branch
falseTransition: New Client Branch
".configuration.condition.InList":
type: object
properties:
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
type:
const: .configuration.condition.InList
description: |
Checks if the contact is in the list and branch based on the result.
This node is not currently supported. Stay tuned.
additionalProperties: false
".configuration.condition.OptOut":
type: object
properties:
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
type:
const: .configuration.condition.OptOut
description: |
Checks if the contact is opted out.
This node is not currently supported. Stay tuned.
additionalProperties: false
".configuration.condition.RandomSplit":
type: object
properties:
buckets:
description: A list of named ranges to branch contact based on the random value
type: array
items:
$ref: "#/$defs/.configuration.condition.RandomSplit$NamedRange"
type:
const: .configuration.condition.RandomSplit
description: |
Branch the workflow based random probability.
Specify a range of probabilities to branch contact based on the random value.
The sum of the probabilities must be 100.
additionalProperties: false
examples:
- example-description: split based on 2 ranges
type: .configuration.condition.RandomSplit
buckets:
- transitionTo: SomeOtherNode
name: A
probability: 30
- transitionTo: SomeOtherNodeWith70%Probability
name: B
probability: 70
".configuration.condition.RandomSplit$NamedRange":
type: object
properties:
name:
type: string
description: The name of the bucket
probability:
type: integer
description: The probability of the bucket to be selected
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
type:
const: .configuration.condition.RandomSplit$NamedRange
description: A range of probabilities to branch contact based on the random value
additionalProperties: false
examples: []
".configuration.condition.Time":
type: object
properties:
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
type:
const: .configuration.condition.Time
description: |
Checks if the time has come.
This node is not currently supported. Stay tuned.
additionalProperties: false
".configuration.condition.WaitForClick":
type: object
properties:
amount:
type: integer
description: The amount of units to delay execution for
noLinkClickTransition:
type: string
description: the name of the node that will be executed if no click received
nodeWithUrl:
type: string
description: the name of the send message node that contains the url
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
units:
$ref: "#/$defs/DelayUnit"
description: Units to delay execution for
url:
type: string
description: The url from a send message node that is expected to be clicked
type:
const: .configuration.condition.WaitForClick
description: |
A workflow node that waits for a provided url to be clicked.
If no click is received within a specified time, the defined fallback node is executed.
additionalProperties: false
examples:
- example-description: wait for 3 days until the provided url is clicked
type: .configuration.condition.WaitForClick
transitionTo: ResumeExecutionNode
amount: 3
units: DAY
noLinkClickTransition: ifNoClickNodeName
nodeWithUrl: SendMessageNode
url: https://example.com/click
".configuration.condition.WaitForReply":
type: object
properties:
amount:
type: integer
description: The amount of units to delay execution for
noReplyReceivedTransition:
type: string
description: the name of the node that will be executed if no reply received
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
units:
$ref: "#/$defs/DelayUnit"
description: Units to delay execution for
type:
const: .configuration.condition.WaitForReply
description: |
Wait for reply after sending a message.
Can branch based on no matching condition.
Sets a reply variable based on the reply received.
additionalProperties: false
examples:
- example-description: wait for 3 days until customer texts in text that contains word EXAMPLE ignoring case
type: .configuration.condition.WaitForReply
transitionTo: ResumeExecutionNode
amount: 3
units: DAY
noReplyReceivedTransition: ifNoReplyReceivedNodeName
condition:
js: |
input.messageText.toUpperCase().includes('EXAMPLE')
variable: replyFromCustomer
allOf:
- type: object
properties:
condition:
anyOf:
- $ref: "#/$defs/.condition.And"
description: |-
Condition to evaluate, must result in boolean or to evaluate to true to have string value (case insensitive): 'true', 'on', 'y', 't' or 'yes'.
The value is usually passed as 'input'. Might contain key values. Check the corresponding containing class info for detailed variables passed to the computation
- $ref: "#/$defs/.condition.Or"
description: |-
Condition to evaluate, must result in boolean or to evaluate to true to have string value (case insensitive): 'true', 'on', 'y', 't' or 'yes'.
The value is usually passed as 'input'. Might contain key values. Check the corresponding containing class info for detailed variables passed to the computation
- $ref: "#/$defs/.condition.Not"
description: |-
Condition to evaluate, must result in boolean or to evaluate to true to have string value (case insensitive): 'true', 'on', 'y', 't' or 'yes'.
The value is usually passed as 'input'. Might contain key values. Check the corresponding containing class info for detailed variables passed to the computation
- $ref: "#/$defs/.condition.JS"
description: |-
Condition to evaluate, must result in boolean or to evaluate to true to have string value (case insensitive): 'true', 'on', 'y', 't' or 'yes'.
The value is usually passed as 'input'. Might contain key values. Check the corresponding containing class info for detailed variables passed to the computation
- $ref: "#/$defs/.condition.Variable"
description: |-
Condition to evaluate, must result in boolean or to evaluate to true to have string value (case insensitive): 'true', 'on', 'y', 't' or 'yes'.
The value is usually passed as 'input'. Might contain key values. Check the corresponding containing class info for detailed variables passed to the computation
- $ref: "#/$defs/.condition.Operation"
description: |-
Condition to evaluate, must result in boolean or to evaluate to true to have string value (case insensitive): 'true', 'on', 'y', 't' or 'yes'.
The value is usually passed as 'input'. Might contain key values. Check the corresponding containing class info for detailed variables passed to the computation
variable:
type: string
description: the variable name to use to set the resulting input value to after successful condition evaluation
pattern: "^([a-zA-Z][-a-zA-Z0-9\\.]*)$"
description: "Condition to evaluate, and variable to set the result to combination. Used in nodes when both are present."
additionalProperties: false
".configuration.trigger.ExternalWebhook":
type: object
properties:
authKey:
type: string
description: Authentication key for the webhook. Must be populated if authType is set
authType:
$ref: "#/$defs/WebhookAuthType"
description: Authentication type for the webhook. Might be empty to use no authentication
authValue:
type: string
description: "Authentication value for the webhook to check against. Must be populated if authType is set. The value will be encrypted and hidden after save. To change the value - update it, otherwise populate with 'hidden' keyword to leave the same."
jsExtractor:
type: string
description: |
Java Script extractor function that accepts 'body' variable as string that is passed to this webhook and transforms it one of the 2 ways:
* return a plain phone number value
* return a map/object with one of the keys as 'phoneNumber' to launch an execution for. All other values will be saved into execution variables and can be reused later in execution
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
webhookId:
type: string
description: Webhook ID to trigger for this trigger
readOnly: true
type:
const: .configuration.trigger.ExternalWebhook
description: |
External webhook trigger to allow triggering execution for a contact based on the external trigger.
Having a webhookId of "111-222-333" you can trigger POST request to https://a.eztexting.com/open/workflow/trigger/111-222-333 with the body that will be passed to the jsExtractor as a "body" variable.
jsExtractor may parse or transform the body and extract phoneNumber at which the trigger will execute. The result of the trigger may be a string, map or object that will be saved into initial variables for the execution.
Passing a "test" query parameter value as "true" will initiate test execution for that trigger.
For authentication authKey and authValue should be used. authValue is encoded to be saved and cannot be further read, only rewritten.
additionalProperties: false
examples:
- example-description: |-
example for a webhook with header authentication that extracts just a phone number from body via parsing a json
note - webhookId will be provided upon save
type: .configuration.trigger.ExternalWebhook
transitionTo: next node name
webhookId: 111-222-333
authType: HEADER
authKey: some-secret-header
authValue: some-secret-value-to-check-against
jsExtractor: |
JSON.parse(body).phoneNumber
- example-description: |-
example for a webhook with basic authentication that extracts a phoneNumber and someOtherKey from body via parsing a json, a phoneNumber will not be saved to execution variables, other values will be populated to execution variables
note - webhookId will be provided upon save
type: .configuration.trigger.ExternalWebhook
transitionTo: next node name
webhookId: 111-222-333
authType: BASIC
authKey: username
authValue: password-will-be-hidden
jsExtractor: |
let json = JSON.parse(body);
({phoneNumber: JSON.parse(body).phoneNumber, someOtherKey: json.someOtherValue})
".configuration.trigger.InboundMessage":
type: object
properties:
numbers:
description: "trigger fires only if the message was sent to one of these numbers. If empty, applies to all numbers"
type: array
items:
type: string
restrictions:
description: restrictions for trigger to restrict when this trigger will apply
type: array
items:
$ref: "#/$defs/Restriction"
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
type:
const: .configuration.trigger.InboundMessage
description: |
Trigger a workflow on a inbound message from a contact
Condition is matched against the text. Variable name: input.messageText.
Detailed examples for restrictions can be found in corresponding type.
additionalProperties: false
examples:
- example-description: |-
will trigger workflow for a contact which just texted to account number 14243335551 with word HELP in the text ignoring case
the result of the variables will be saved into inboundTextInput variable for the execution and can be later accessed like: inboundTextInput.messageText
one restriction added to trigger only on weekends
type: .configuration.trigger.InboundMessage
transitionTo: next node
condition:
js: |
input.messageText.toUpperCase().includes('HELP')
variable: inboundTextInput
restrictions:
- enabledFrom: 00:00:00
enabledTo: 23:59:00
enabledDays:
- SATURDAY
- SUNDAY
type: WEEKDAY
numbers:
- 14243335551
allOf:
- type: object
properties:
condition:
anyOf:
- $ref: "#/$defs/.condition.And"
description: |-
Condition to evaluate, must result in boolean or to evaluate to true to have string value (case insensitive): 'true', 'on', 'y', 't' or 'yes'.
The value is usually passed as 'input'. Might contain key values. Check the corresponding containing class info for detailed variables passed to the computation
- $ref: "#/$defs/.condition.Or"
description: |-
Condition to evaluate, must result in boolean or to evaluate to true to have string value (case insensitive): 'true', 'on', 'y', 't' or 'yes'.
The value is usually passed as 'input'. Might contain key values. Check the corresponding containing class info for detailed variables passed to the computation
- $ref: "#/$defs/.condition.Not"
description: |-
Condition to evaluate, must result in boolean or to evaluate to true to have string value (case insensitive): 'true', 'on', 'y', 't' or 'yes'.
The value is usually passed as 'input'. Might contain key values. Check the corresponding containing class info for detailed variables passed to the computation
- $ref: "#/$defs/.condition.JS"
description: |-
Condition to evaluate, must result in boolean or to evaluate to true to have string value (case insensitive): 'true', 'on', 'y', 't' or 'yes'.
The value is usually passed as 'input'. Might contain key values. Check the corresponding containing class info for detailed variables passed to the computation
- $ref: "#/$defs/.condition.Variable"
description: |-
Condition to evaluate, must result in boolean or to evaluate to true to have string value (case insensitive): 'true', 'on', 'y', 't' or 'yes'.
The value is usually passed as 'input'. Might contain key values. Check the corresponding containing class info for detailed variables passed to the computation
- $ref: "#/$defs/.condition.Operation"
description: |-
Condition to evaluate, must result in boolean or to evaluate to true to have string value (case insensitive): 'true', 'on', 'y', 't' or 'yes'.
The value is usually passed as 'input'. Might contain key values. Check the corresponding containing class info for detailed variables passed to the computation
variable:
type: string
description: the variable name to use to set the resulting input value to after successful condition evaluation
pattern: "^([a-zA-Z][-a-zA-Z0-9\\.]*)$"
description: "Condition to evaluate, and variable to set the result to combination. Used in nodes when both are present."
additionalProperties: false
".configuration.trigger.KeywordJoined":
type: object
properties:
keywordIds:
description: keyword ids to trigger for
type: array
items:
type:
- string
- number
numbers:
description: "trigger fires only if the message was sent to one of these numbers. If empty, applies to all numbers"
type: array
items:
type: string
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
variable:
type: string
description: the variable name to use to set the keyword and number value to
pattern: "^([a-zA-Z][-a-zA-Z0-9\\.]*)$"
type:
const: .configuration.trigger.KeywordJoined
description: |
Trigger a workflow when a contact joins a keyword via texting to it and receives auto replies.
additionalProperties: false
examples:
- example-description: |-
will trigger workflow for a contact which received autoreply for a number 14243335551 keyword with ids: 123, 345
the variables will be saved into keywordJoinedInput variable for the execution and can be later accessed like: keywordJoinedInput.number or keywordJoinedInput.keyword
type: .configuration.trigger.KeywordJoined
transitionTo: next node name
keywordIds:
- 123
- 345
numbers:
- 14243335551
variable: keywordJoinedInput
".configuration.trigger.ListJoined":
type: object
properties:
contactSource:
$ref: "#/$defs/ContactSource"
description: Contact source to trigger on
listIds:
description: Contact list IDs to trigger on
type: array
items:
type:
- string
- number
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
variable:
type: string
description: the variable name to use to set the contacts source value to
pattern: "^([a-zA-Z][-a-zA-Z0-9\\.]*)$"
type:
const: .configuration.trigger.ListJoined
description: |
Trigger a workflow when contact joins a contact list/group, based on the contact source this contact has joined via.
additionalProperties: false
examples:
- example-description: will trigger webhook whenever someone joins contact list 123 via keyword.
type: .configuration.trigger.ListJoined
transitionTo: next node
contactSource: KEYWORD
listIds:
- 123
- example-description: |-
will trigger webhook whenever someone uploads contacts into 123 list.
the result of the variables will be saved into listJoinedInput variable for the execution and can be later accessed like: listJoinedInput.contactSource
type: .configuration.trigger.ListJoined
transitionTo: next node
contactSource: UPLOAD
listIds:
- 123
variable: listJoinedInput
".configuration.trigger.ListOnDateTime":
type: object
properties:
field:
type: string
description: Field to calculate relativity based on
listIds:
description: Contact list IDs to trigger for
type: array
items:
type:
- string
- number
relativeAmount:
type: integer
description: The number of units to delay before/after trigger launch
relativeUnits:
$ref: "#/$defs/DelayUnit"
description: Units to use in conjunction with amount to calculate the trigger time
relativityType:
$ref: "#/$defs/RelativeTriggerType"
description: Which time direction should a trigger calculate relative to contact field
scheduledDate:
examples:
- 2030-12-31
description: Date to trigger on. Used for static type
additionalProperties: false
type: string
format: date
scheduledTime:
examples:
- 23:59:59
description: Time to trigger on. Used for both static and dynamic types
additionalProperties: false
type: string
format: time
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
triggerType:
$ref: "#/$defs/DateTimeTriggerType"
description: Trigger type to use when calculating trigger time. Choose static to specify a date and time in the future and dynamic to calculate based on the contact field.
type:
const: .configuration.trigger.ListOnDateTime
description: |
Trigger a workflow for a contact list/group when a date and time is reached.
additionalProperties: false
examples:
- example-description: will trigger for 123 list on a last day of the 2025 year at 20:00 in account's time zone.
type: .configuration.trigger.ListOnDateTime
transitionTo: next node name
triggerType: STATIC
scheduledDate: 2025-12-31
scheduledTime: 20:00:00
listIds:
- 123
- example-description: will trigger execution 1 day before contact has a birthday date time field in list 123
type: .configuration.trigger.ListOnDateTime
transitionTo: next node name
triggerType: DYNAMIC
listIds:
- 123
field: appointment
relativeAmount: 1
relativeUnits: DAY
relativityType: BEFORE
- example-description: will trigger execution on the date contact has a birthday date field at 13:00 in the account's time zone in list 123
type: .configuration.trigger.ListOnDateTime
transitionTo: next node name
triggerType: DYNAMIC
scheduledTime: 13:00:00
listIds:
- 123
field: birthday
relativityType: ON_DATE
".configuration.trigger.ShopifyAbandonedCheckout":
type: object
properties:
lookBackMinutes:
type:
- string
- number
description: Enter the number of minutes you want the system to look back when finding abandoned Shopify shopping carts.
shopifySite:
type: string
description: "Shopify shop name. You can find it in the url For example, if the URL is https://example.myshopify.com/admin, then your shop name is 'example'"
shopifyToken:
type: string
description: Shopify Admin Access Token. Obtain via Settings -> Apps -> Develop apps -> Create an App -> Install app. See detailed description in trigger description.
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
type:
const: .configuration.trigger.ShopifyAbandonedCheckout
description: |
Trigger for Shopify abandoned checkout.
Monitors the abandoned carts and trigger the execution based on the new values.
Note: since Shopify doesn't provide a webhook notifications the system is polling for new abandoned checkouts, and they are not triggered immediately.
To configure:
You can find your shop name in the URL. For example, if the URL is https://example.myshopify.com/admin, then your shop name is example.
Set it as a value for 'shopifySite' field in node configuration.
Admin Token:
* Login to Shopify account
* Go to Settings -> Apps -> Develop apps -> Create an App
* Fill the app name
* Click on Configure Admin API Scopes and select:
** 'read_orders'
** 'write_orders'
** 'write_customers'
** 'read_customers'
** 'write_products'
** 'read_products'
** 'write_draft_orders'
** 'read_draft_orders'
* Click on Install app and copy the Admin Access Token
'shopifyToken' is encoded on save and can't be further read; only rewritten.
Available Variables:
* 'shopifyFirstName': Customer's first name
* 'shopifyLastName': Customer's last name
* 'shopifyFirstItemTitle': Title of the first item in cart
* 'shopifyFirstItemPrice': Price of the first item in cart
* 'shopifyTotalItemsCount': Total number of items in cart
* 'shopifyAdditionalItemsCount': Total number of items minus 1
* 'shopifySmsConsent': Customer's SMS consent status
* 'shopifyEmailConsent': Customer's email consent status
* 'shopifyCartToken': Unique token for the abandoned checkout cart
* 'shopifyAbandonedCheckoutUrl': Direct link to the abandoned checkout cart
additionalProperties: false
examples: []
allOf:
- type: object
properties:
accepted:
type: boolean
description: Indicates whether the user has accepted the agreement.
acceptedAt:
type: string
format: date-time
description: Timestamp when the agreement was accepted.
description: |
User agreement configuration for abandoned checkout processing.
This agreement must be accepted before the system can process abandoned checkouts.
The acceptance is tracked with a timestamp for audit purposes.
Once accepted, the agreement cannot be modified through API requests to maintain
data integrity and compliance requirements.
additionalProperties: false
".configuration.trigger.SignupFormCompleted":
type: object
properties:
transitionTo:
type: string
description: The name of the node to transition to after executing current configuration
variable:
type: string
description: the variable name to use to set the signup form name value to
pattern: "^([a-zA-Z][-a-zA-Z0-9\\.]*)$"
widgetIds:
description: signup form ids to trigger for
type: array
items:
type: string
type:
const: .configuration.trigger.SignupFormCompleted
description: |
Triggers for when a contact completes a signup form
additionalProperties: false
examples:
- example-description: |-
will trigger workflow for a contact which just completed a sign up form 123
the variables will be saved into signupFormInput variable for the execution and can be later accessed like: signupFormInput.signupForm
type: .configuration.trigger.SignupFormCompleted
transitionTo: next node name
widgetIds:
- 123
variable: signupFormInput
ContactSource:
type: string
enum:
- UNKNOWN
- WEBINTERFACE
- UPLOAD
- WEBWIDGET
- API
- WORKFLOW
- KEYWORD
- INTEGRATION_MAILCHIMP
- INTEGRATION_HIGHRISE
- INTEGRATION_AWEBER
- INTEGRATION_CONSTANTCONTACT
- INTEGRATION_EVENTBRITE
- INTEGRATION_ICONTACT
- INTEGRATION_SALESFORCE
- INTEGRATION_INFUSION
- INCOMING
- INTEGRATION_ZAPIER
- INTEGRATION_SQUARESPACE
- INTEGRATION_HUBSPOT
- INTEGRATION_NATION_BUILDER
- INTEGRATION_ZOHO
- INTEGRATION_NETSUITE
- INTEGRATION_SALES_GENIE
- OUTBOUND
- INTEGRATION_SHOPIFY
DateTimeTriggerType:
type: string
enum:
- STATIC
- DYNAMIC
DayOfWeek:
type: string
enum:
- MONDAY
- TUESDAY
- WEDNESDAY
- THURSDAY
- FRIDAY
- SATURDAY
- SUNDAY
DelayUnit:
type: string
enum:
- MINUTE
- HOUR
- DAY
FieldExpression:
type: object
properties:
expression:
type: string
description: The result of JS expression is assigned to a field value.
fieldName:
type: string
description: "Field name. Can be name of a predefined fields like firstName or custom1, or a name of a custom field"
description: |
An expression to update contact field, can be JS compatible expression including variables and string literals.
additionalProperties: false
examples:
- example-description: updates a contact's field value
fieldName: firstName
expression: customer
JsonNode:
type: object
additionalProperties: false
Map(String,String):
type: object
additionalProperties: false
MessageType:
type: string
enum:
- SMS
- MMS
- DID_SMS
- RCS_RBM
- RCS_ABC
Method:
type: string
enum:
- GET
- HEAD
- POST
- PUT
- DELETE
- CONNECT
- TRACE
- OPTIONS
- PATCH
Node(Configuration):
type: object
properties:
config:
anyOf:
- $ref: "#/$defs/.configuration.action.Delay"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.action.DeleteContact"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.action.HttpRequest"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.action.OptOut"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.action.SendMessage"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.action.SetVariable"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.action.UpdateContact"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.condition.InList"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.condition.OptOut"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.condition.RandomSplit"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.condition.Time"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.condition.If"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.condition.WaitForReply"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.condition.WaitForClick"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.trigger.ListJoined"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.trigger.KeywordJoined"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.trigger.ListOnDateTime"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.trigger.InboundMessage"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.trigger.SignupFormCompleted"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.trigger.ExternalWebhook"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
- $ref: "#/$defs/.configuration.trigger.ShopifyAbandonedCheckout"
description: "the configuration of the node. May be any of the supported configurations (triggers, conditions, actions)"
created:
type: string
format: date-time
description: node creation date
readOnly: true
frontConfig:
$ref: "#/$defs/JsonNode"
description: technical UI configuration for the node. stores the placements on the UI and can safely be ignored/deleted
id:
type:
- string
- number
description: the unique identifier of the node
modified:
type: string
format: date-time
description: node last modification date
readOnly: true
name:
type: string
description: the name of the node. must be unique within a workflow
minLength: 1
action.Delay:
description: |-
the configuration of the node of type: .configuration.action.Delay. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.action.Delay"
action.DeleteContact:
description: |-
the configuration of the node of type: .configuration.action.DeleteContact. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.action.DeleteContact"
action.HttpRequest:
description: |-
the configuration of the node of type: .configuration.action.HttpRequest. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.action.HttpRequest"
action.OptOut:
description: |-
the configuration of the node of type: .configuration.action.OptOut. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.action.OptOut"
action.SendMessage:
description: |-
the configuration of the node of type: .configuration.action.SendMessage. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.action.SendMessage"
action.SetVariable:
description: |-
the configuration of the node of type: .configuration.action.SetVariable. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.action.SetVariable"
action.UpdateContact:
description: |-
the configuration of the node of type: .configuration.action.UpdateContact. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.action.UpdateContact"
condition.InList:
description: |-
the configuration of the node of type: .configuration.condition.InList. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.condition.InList"
condition.OptOut:
description: |-
the configuration of the node of type: .configuration.condition.OptOut. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.condition.OptOut"
condition.RandomSplit:
description: |-
the configuration of the node of type: .configuration.condition.RandomSplit. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.condition.RandomSplit"
condition.Time:
description: |-
the configuration of the node of type: .configuration.condition.Time. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.condition.Time"
condition.If:
description: |-
the configuration of the node of type: .configuration.condition.If. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.condition.If"
condition.WaitForReply:
description: |-
the configuration of the node of type: .configuration.condition.WaitForReply. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.condition.WaitForReply"
condition.WaitForClick:
description: |-
the configuration of the node of type: .configuration.condition.WaitForClick. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.condition.WaitForClick"
trigger.ListJoined:
description: |-
the configuration of the node of type: .configuration.trigger.ListJoined. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.trigger.ListJoined"
trigger.KeywordJoined:
description: |-
the configuration of the node of type: .configuration.trigger.KeywordJoined. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.trigger.KeywordJoined"
trigger.ListOnDateTime:
description: |-
the configuration of the node of type: .configuration.trigger.ListOnDateTime. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.trigger.ListOnDateTime"
trigger.InboundMessage:
description: |-
the configuration of the node of type: .configuration.trigger.InboundMessage. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.trigger.InboundMessage"
trigger.SignupFormCompleted:
description: |-
the configuration of the node of type: .configuration.trigger.SignupFormCompleted. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.trigger.SignupFormCompleted"
trigger.ExternalWebhook:
description: |-
the configuration of the node of type: .configuration.trigger.ExternalWebhook. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.trigger.ExternalWebhook"
trigger.ShopifyAbandonedCheckout:
description: |-
the configuration of the node of type: .configuration.trigger.ShopifyAbandonedCheckout. This can be used as alternative to 'config' property, for a content assist and strong typing validation.
One can omit the child type if using this property name.
$ref: "#/$defs/.configuration.trigger.ShopifyAbandonedCheckout"
required:
- name
description: |
A named node holding some configuration.
Node is referenced by its name.
Node names must be unique within a workflow.
additionalProperties: false
examples:
- example-description: shows example of config configuration (possible)
id: 123
name: Some mnemonic and unique node name
created: 2030-01-31T15:00:00Z
modified: 2030-01-31T15:00:00Z
config:
type: .configuration.action.SendMessage
transitionTo: SomewhereNext
subject: Your Company Name
messageType: MMS
message: |
Message to send
containsSuspiciousWords: false
frontConfig: something not important for code editing
- example-description: shows example of typed configuration (also possible)
id: 123
name: Some mnemonic and unique node name
created: 2030-01-31T15:00:00Z
modified: 2030-01-31T15:00:00Z
config:
type: .configuration.action.SendMessage
transitionTo: SomewhereNext
subject: Your Company Name
messageType: SMS
message: |
Message to send
containsSuspiciousWords: false
oneOf:
- required:
- config
- required:
- action.Delay
- required:
- action.DeleteContact
- required:
- action.HttpRequest
- required:
- action.OptOut
- required:
- action.SendMessage
- required:
- action.SetVariable
- required:
- action.UpdateContact
- required:
- condition.InList
- required:
- condition.OptOut
- required:
- condition.RandomSplit
- required:
- condition.Time
- required:
- condition.If
- required:
- condition.WaitForReply
- required:
- condition.WaitForClick
- required:
- trigger.ListJoined
- required:
- trigger.KeywordJoined
- required:
- trigger.ListOnDateTime
- required:
- trigger.InboundMessage
- required:
- trigger.SignupFormCompleted
- required:
- trigger.ExternalWebhook
- required:
- trigger.ShopifyAbandonedCheckout
OperationDataType:
type: string
enum:
- text
- number
- date
OperationType:
type: string
enum:
- eq
- ne
- contains
- notContains
- startsWith
- endsWith
- gt
- lt
- exist
- notExist
RelativeTriggerType:
type: string
enum:
- BEFORE
- AFTER
- ON_DATE
Restriction:
type: object
properties:
enabledDays:
description: Enabled only on a specified days
type: array
items:
$ref: "#/$defs/DayOfWeek"
enabledFrom:
examples:
- 23:59:59
description: Restrict to be enabled only after specified time. If a from time specified after to time - inner time frame will be excluded
additionalProperties: false
type: string
format: time
enabledTo:
examples:
- 23:59:59
description: Restrict to be enabled only before specified time
additionalProperties: false
type: string
format: time
fromDate:
examples:
- 2030-12-31
description: Restrict to run from a specific date
additionalProperties: false
type: string
format: date
toDate:
examples:
- 2030-12-31
description: Restrict to run until a specific date
additionalProperties: false
type: string
format: date
type:
$ref: "#/$defs/RestrictionType"
description: Type of restriction
description: |
Restriction for an inbound message to configure time constraints at which a trigger should start.
additionalProperties: false
examples:
- example-description: restrict to trigger between 10:00 and 18:00 and from 2025-01-01 to 2025-02-28
enabledFrom: 10:00:00
enabledTo: 18:00:00
fromDate: 2025-01-01
toDate: 2025-02-28
type: DATE
- example-description: restrict to trigger on weekends
enabledFrom: 00:00:00
enabledTo: 23:59:00
enabledDays:
- SATURDAY
- SUNDAY
type: WEEKDAY
- example-description: restrict to trigger on weekdays from 00:00 to 9:00 and from 18:00 to 24:00
enabledFrom: 18:00:00
enabledTo: 09:00:00
enabledDays:
- MONDAY
- TUESDAY
- WEDNESDAY
- THURSDAY
- FRIDAY
type: WEEKDAY
RestrictionType:
type: string
enum:
- DATE
- WEEKDAY
Transition:
type: object
properties:
condition:
anyOf:
- $ref: "#/$defs/.condition.And"
description: a condition to be evaluated
- $ref: "#/$defs/.condition.Or"
description: a condition to be evaluated
- $ref: "#/$defs/.condition.Not"
description: a condition to be evaluated
- $ref: "#/$defs/.condition.JS"
description: a condition to be evaluated
- $ref: "#/$defs/.condition.Variable"
description: a condition to be evaluated
- $ref: "#/$defs/.condition.Operation"
description: a condition to be evaluated
name:
type: string
description: a branch name
transitionTo:
type: string
description: the name of the node that will be executed if condition evaluates to true
description: |
A single branch of If node.
If condition of on one of the transitions evaluates to true then execution proceeds to transitionTo node.
additionalProperties: false
examples:
- example-description: based on the previously set variable (or contact custom field) we can branch the workflow. In this use case we're branching vip clients to specific scenario
name: Vip Branch
condition:
js: |
contact.vipClient
transitionTo: NextTrueNode
- example-description: "branching based on the date, we'll make sure customers will go other branch after some date"
name: 2030
condition:
js: |
new Date().getYear() > 2030
transitionTo: After 2030 Branch
- example-description: branching based on multiple variables
name: 2030
condition:
and:
- or:
- js: |
new Date().getYear() > 2030
- op: eq
value: value
variable: variableName
- js: |
contact.vipClient
transitionTo: After 2030 Branch
UpdateContactType:
type: string
enum:
- ADD_TO_GROUPS
- REMOVE_FROM_GROUPS
- UPDATE_FIELD
WebhookAuthType:
type: string
enum:
- BASIC
- HEADER
WorkflowStatus:
type: string
enum:
- PUBLISHED
- UNPUBLISHED
- PAUSED
- BLOCKED_SUSPICIOUS
- APPROVED
- INSUFFICIENT_FUNDS
- PAUSED_API_FAILURES
- ARCHIVE
type: object
properties:
cooldownAmount:
type: integer
description: "specifies the amount of time after which the contact can re-enter the workflow. If the time didn't pass, then the contact will not enter to the workflow."
exclusiveMinimum: 0
cooldownUnit:
$ref: "#/$defs/DelayUnit"
description: units in which cooldown amount will be calculated
created:
type: string
format: date-time
description: date when the workflow was created
readOnly: true
description:
type: string
maxLength: 200
id:
type:
- string
- number
description: the unique identifier of the workflow
readOnly: true
lastStructureModified:
type: string
format: date-time
description: indicates when the workflow structure was last modified
readOnly: true
modified:
type: string
format: date-time
description: date when the workflow was last modified
readOnly: true
name:
type: string
minLength: 1
maxLength: 200
nodes:
description: the list of the nodes for this workflow with references between them
type: array
items:
$ref: "#/$defs/Node(Configuration)"
runOnlyOnce:
type: boolean
description: a setting to indicate whether a contact may enter only once into this workflow
status:
$ref: "#/$defs/WorkflowStatus"
description: the status of the workflow
timeZone:
type: string
description: time zone for a workflow. leave empty to populate time zone from account
required:
- name
- status
description: |
# Workflows
A main entrypoint for the workflow engine to execute a sequence of nodes.
## Description
Workflow is a sequence of the actions that are executed one by one to achieve specific logic that is leading to algorithm evaluation in EzTexting.
## Workflow nodes
##
Node is an entity that contains configuration of the action that will be executed during the workflow evaluation.
There are 3 types of nodes:
1. triggers: those having types that contain '.trigger.'. Triggers are intended to be a starting point of a workflow and can trigger execution for one or multiple contacts. For example when a contact joins a contact list (or someone adds it to the list) an execution for that contact is triggered.
2. actions: those having types that contain '.action.'. Actions are intended to perform some action during the workflow execution.
Example action would be a http request to third party service that is transmitting some data from the EzTexting system, like contact information.
3. conditions: those having types that contain '.configuration.'. Conditions are intended to evaluate condition of the execution and branch the execution based on that.
Example condition is there 'wait for link click' condition that is branching based on the fact that contact clicked or not clicked the link.
By combining all three types of nodes one can configure algorithm through which contact will be provided through a steps to achieve desired result, like reminding of a birthday for a contact,
gathering info into contact, making polls etc.
## Workflow execution
A workflow execution is an invocation of the workflow for a contact or a phone number that is transitioning through the nodes.
A workflow will execute instances/executions if one (or multiple) is triggered via one of the Trigger nodes, resuming execution by transitioning through the tree of the nodes.
When three reversal is finished, and there is no next nodes to go to a contact will exit the workflow with the status of DONE.
One configure workflow to accept the same contact multiple times or to accept it after some period of time which is called cool down period.
## Variables
An important part of the workflow execution is a variables that can persist information between nodes and execution invocations.
They can be in form of the key values, including nested objects/maps. Variables can be reused in a JavaScript evaluations:
1. one can set a variable to later reuse by SetVariable action
2. JavaScript code can reference variable same way as a JavaScript is accessing local/global variables as per JavaScript language specification
3. there are places where variable substitution is in place and can substitute values by the variable keys. Places like HTTP request url, JSON body in http call, message in send message node and other.
For example, 'send message' node can have message substituted both variables and replacements already known from a Group message composing dialog.
Below is the example JavaScript that access contact variables and evaluates based on the logic and returns an object as a result, that may be saved to a variable (e.g. in ExternalWebhook trigger):
```
let greeting = 'Hello, ' + (contact.sex == 'M' ? 'Sir' : 'Madam') + contact.lastName';
let sir = greeting.toUpperCase().includes('SIR');
let blankLastName = contact.lastName.trim() === "";
({isSir: sir, blankLastName: blankLastName, greetVia: greeting})
```
Here is another example that evaluates to true based on the input variables. Assuming input has an object with 2 fields: messageText and requestBody (that also has json with same messageText):
```
JSON.parse(requestBody).messageText === messageText
```
additionalProperties: false
Workflows are sequences of automated steps that respond to triggers (like receiving a keyword, inbound SMS, or Shopify abandoned cart), perform actions (like sending a message, making an HTTP request, updating a contact), and check conditions (like waiting for replies, splitting traffic randomly, or evaluating variables).
Key Concepts:
Triggers (
.configuration.trigger.*) – Define what starts the workflow.
Examples:KeywordJoined: When someone texts a keyword.InboundMessage: When a customer replies.ExternalWebhook: When a webhook call is received.ShopifyAbandonedCheckout: When a cart is abandoned.
Actions (
.configuration.action.*) – Steps that “do something.”
Examples:SendMessage: Send an SMS/MMS.HttpRequest: Call an external API.UpdateContact: Change a contact’s group or custom field.Delay: Wait for a certain time before continuing.
Conditions (
.configuration.condition.*) – Logic checks and branching.
Examples:If: Branch flow based on JavaScript or variable conditions.WaitForReply: Pause until a customer replies.WaitForClick: Pause until a link is clicked.RandomSplit: Send contacts down different branches by probability.
Nodes:
Each workflow is made of nodes, and each node has a name and a config that describes whether it’s a trigger, action, or condition. Nodes connect bytransitionTo, which points to the next step.Workflow Properties:
name,description,status(Published, Paused, etc.)cooldown(how often a contact can re-enter)timeZonenodes(the actual steps of the workflow).