$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 enabledFrom: 09:00:00 enabledTo: 18:00:00 enabledDays: - MONDAY - SUNDAY - THURSDAY - example-description: |- old style - will be removed soon wait until Monday at 5 pm type: .configuration.action.Delay transitionTo: ResumeExecutionNode waitForDay: MONDAY waitForTime: 17:00:00 allOf: - type: object properties: enabledDays: description: Enabled only one specified days type: array items: $ref: "#/$defs/DayOfWeek" enabledFrom: examples: - 23:59:59 description: Restrict to be run only after specified time additionalProperties: false type: string format: time enabledTo: examples: - 23:59:59 description: Restrict to be run only before specified time additionalProperties: false type: string format: time description: Restricts the days of week and time interval when node is active or delayed to additionalProperties: false ".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://eztexting.com/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://eztexting.com/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: 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/.configuration.condition.Transition" 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: 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: - transitionTo: NextTrueNode name: VIP client condition: js: | contact.vipClient falseTransition: NextFalseNode - example-description: "based on the contact groups ids we can branch the workflow, both contains and notContains operations could be used" type: .configuration.condition.If transitions: - transitionTo: Send Message 1 name: Path 1 condition: op: contains dataType: list value: 123 variable: contact.groupIds falseTransition: Send Message 2 - example-description: "branching based on the date, we'll make sure customers will go other branch after some date" type: .configuration.condition.If transitions: - transitionTo: After 2030 Branch name: 2030 condition: js: | new Date().getYear() > 2030 falseTransition: Before 2030 Branch - example-description: branching based on multiple variables type: .configuration.condition.If transitions: - transitionTo: After 2030 Branch name: 2030 condition: and: - or: - js: | new Date().getYear() > 2030 - op: eq value: value variable: variableName - js: | contact.vipClient falseTransition: Before 2030 Branch - example-description: multiple branches type: .configuration.condition.If transitions: - transitionTo: After 2030 Branch name: 2030 condition: js: | new Date().getYear() > 2030 - transitionTo: Vip Client Branch name: VIP condition: js: | contact.vipClient 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.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 to transition to after executing current configuration type: const: .configuration.condition.Transition 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 transitionTo: NextTrueNode name: Vip Branch condition: js: | contact.vipClient - example-description: "branching based on the date, we'll make sure customers will go other branch after some date" transitionTo: After 2030 Branch name: 2030 condition: js: | new Date().getYear() > 2030 - example-description: branching based on multiple variables transitionTo: After 2030 Branch name: 2030 condition: and: - or: - js: | new Date().getYear() > 2030 - op: eq value: value variable: variableName - js: | contact.vipClient ".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 recurringConfig: $ref: "#/$defs/RecurringConfig" 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: 2035-12-31 scheduledTime: 20:00:00 listIds: - 123 - example-description: will trigger for 123 list on Dec 31 20:00 in account's time zone every year starting from 2025. type: .configuration.trigger.ListOnDateTime transitionTo: next node name triggerType: STATIC scheduledDate: 2035-12-31 scheduledTime: 20:00:00 listIds: - 123 recurringConfig: period: ANNUALLY - 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 - OUTBOUND - INTEGRATION_NATION_BUILDER - INTEGRATION_ZOHO - INTEGRATION_NETSUITE - INTEGRATION_SALES_GENIE - 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 - list OperationType: type: string enum: - eq - ne - contains - notContains - startsWith - endsWith - gt - lt - exist - notExist RecurringConfig: type: object properties: endsOn: type: string format: date-time description: Optional cut-off datetime after which no further occurrences will be scheduled period: $ref: "#/$defs/RecurringPeriod" description: Recurrence cadence/pattern that determines the interval between successive executions description: Defines how often the node repeats and optional stop conditions additionalProperties: false RecurringPeriod: type: string const: ANNUALLY RelativeTriggerType: type: string enum: - BEFORE - AFTER - ON_DATE Restriction: type: object properties: 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 allOf: - type: object properties: enabledDays: description: Enabled only one specified days type: array items: $ref: "#/$defs/DayOfWeek" enabledFrom: examples: - 23:59:59 description: Restrict to be run only after specified time additionalProperties: false type: string format: time enabledTo: examples: - 23:59:59 description: Restrict to be run only before specified time additionalProperties: false type: string format: time description: Restricts the days of week and time interval when node is active or delayed to additionalProperties: false RestrictionType: type: string enum: - DATE - WEEKDAY 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 - PAUSED_ACCOUNT_BLOCKED - 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