Workflow actions
data.config.actionType of an action node. Fields marked tpl accept {{ placeholders }} from the payload (see Triggers). Every action reports what it did in the execution result (see Executions).
send_sms
Sends an SMS.
{ "id": "reply", "type": "actionNode",
"data": { "title": "Auto-reply", "config": { "actionType": "send_sms", "messageType": "reply_message",
"message": "Thanks for your message, we are closed right now and will reply tomorrow." } } }
{ "id": "notify", "type": "actionNode",
"data": { "title": "Notify sales", "config": { "actionType": "send_sms", "messageType": "new_message",
"sender": "SMSTools", "receiver": "32470123456", "message": "New lead: {{ contact.phone }} wrote {{ message.body }}" } } }
| Key | Values | Description |
|---|---|---|
messageType | new_message (default) / reply_message / trigger_contact | new_message: to receiver (or contact.phone) with sender. reply_message: reply to the triggering message from the inbox number it arrived on. trigger_contact: to contact.phone with sender. |
sender | max. 17 characters | Sender ID or number. |
receiver | phone number, optional | Empty = contact.phone of the payload. |
message | tpl, required, max. 1600 characters | Text of the message. |
channel | optional | Channel hint from the builder. |
send_whatsapp_template
Sends an approved WhatsApp Business template; works outside the 24-hour window.
{ "id": "welcome", "type": "actionNode",
"data": { "title": "Welcome template", "config": { "actionType": "send_whatsapp_template",
"wabaId": "123456789012345", "sender": "32460123456",
"templateName": "welcome_message", "templateLanguage": "en_US", "templateCategory": "utility",
"templateParameterFormat": "POSITIONAL", "headerType": "none",
"bodyParams": [ { "variable": "1", "value": "{{ contact.firstname }}" } ] } } }
| Key | Values | Description |
|---|---|---|
wabaId | WhatsApp Business account ID | The account the template belongs to. |
sender | WhatsApp number of that account | Number to send from. |
receiver | phone number, optional | Empty = contact.phone. |
templateName | required | Name of the template. |
templateId, templateLanguage, templateCategory | e.g. en_US; utility / marketing / authentication | Template details as in List WhatsApp templates. |
templateParameterFormat | POSITIONAL (default) / NAMED | How the template expects its parameters. |
headerType, headerUrl | none (default) / text / image / video / document | Header of the template and the media URL for media headers. |
bodyParams | list of { variable, value } (tpl) | Values for the body parameters. |
messageType | optional | Same meaning as for send_sms. |
send_whatsapp_message
Sends a free-form WhatsApp message to contact.phone. Only possible inside the 24-hour customer service window; outside it the message is not sent and the fallback handle is followed, so you can connect a send_whatsapp_template or send_sms node there.
{ "id": "wa_reply", "type": "actionNode",
"data": { "title": "WhatsApp reply", "config": { "actionType": "send_whatsapp_message",
"message": "Hi {{ contact.firstname }}, thanks for reaching out!" } } }
"edges": [
{ "id": "e4", "source": "wa_reply", "sourceHandle": "out", "target": "assign" },
{ "id": "e5", "source": "wa_reply", "sourceHandle": "fallback", "target": "welcome" }
]
| Key | Values | Description |
|---|---|---|
message | tpl, required, max. 4096 characters | Text of the message. |
forward
Forwards the triggering inbound message.
{ "id": "forward", "type": "actionNode",
"data": { "title": "Forward to support", "config": { "actionType": "forward", "forwardMethod": "email", "receiver": "[email protected]" } } }
| Key | Values | Description |
|---|---|---|
forwardMethod | email (default) / sms / sms_group | Forward by e-mail, by SMS to one number or by SMS to a group. |
receiver | e-mail address or phone number | For email and sms. |
groupid | gid_... | For sms_group. |
inboxMessageId | optional | Inbound message to forward; empty = the triggering message. |
http_webhook
Calls a URL of your own with the payload data. The request times out after 15 seconds.
{ "id": "crm", "type": "actionNode",
"data": { "title": "Push to CRM", "config": { "actionType": "http_webhook",
"method": "POST", "url": "https://crm.example.com/api/leads",
"authType": "bearer", "authToken": "my-secret-token",
"headers": [ { "key": "X-Source", "value": "smstools" } ],
"bodyType": "form",
"bodyFields": [ { "key": "phone", "value": "{{ contact.phone }}" }, { "key": "message", "value": "{{ message.body }}" } ] } } }
| Key | Values | Description |
|---|---|---|
method | GET / POST (default) / PUT / PATCH / DELETE | HTTP method. |
url | tpl, required, http(s) | The URL to call. |
authType | none (default) / bearer / basic / api_key_header / api_key_query | Authentication. |
authToken | tpl | Token for bearer. |
authUsername, authPassword | tpl | Credentials for basic. |
authKeyName, authKeyValue | tpl | Header or query parameter for the API-key types. |
headers, queryParams | lists of { key, value } (tpl) | Extra headers and query parameters. |
bodyType | json (default) / form | How the body is encoded. |
bodyJson | raw JSON string, tpl | Body for json. |
bodyFields | list of { key, value } (tpl) | Body for form. |
contact
Adds, loads, updates or removes the contact with contact.phone in one of your groups. get loads the contact into the payload for the nodes that follow.
{ "id": "save", "type": "actionNode",
"data": { "title": "Save as lead", "config": { "actionType": "contact", "editMethod": "add",
"groupid": "gid_3520a1ec234dbabe1232def67e858855",
"updateFields": { "firstname": "{{ contact.firstname }}", "extra1": "{{ message.body }}" } } } }
| Key | Values | Description |
|---|---|---|
editMethod | add (default) / get / update / remove | What to do. |
groupid | gid_... | Required for add, update and remove. |
updateFields | object | Any of firstname, lastname, extra1 .. extra8, birthdate (YYYY-MM-DD or DD/MM/YYYY) for add and update. |
opt_out
Opts the contact with contact.phone out (or back in).
{ "id": "opt_out", "type": "actionNode",
"data": { "title": "Opt out", "config": { "actionType": "opt_out", "editMethod": "opt_out" } } }
| Key | Values | Description |
|---|---|---|
editMethod | opt_out (default) / opt_in / add / remove | add = opt out, remove = opt back in. |
groupid | gid_..., optional | Limit the opt-out to one group. |
get_contact
Loads a contact into the payload (contact.*), for example at the start of a cron workflow or to enrich an inbound message with the contact's name and extra fields.
{ "id": "load", "type": "actionNode",
"data": { "title": "Load contact", "config": { "actionType": "get_contact", "lookupBy": "phone_from_payload" } } }
{ "id": "pick", "type": "actionNode",
"data": { "title": "Random winner", "config": { "actionType": "get_contact", "lookupBy": "group_random", "groupId": "gid_3520a1ec234dbabe1232def67e858855" } } }
| Key | Values | Description |
|---|---|---|
lookupBy | phone_from_payload (default) / phone_from_payload_in_group / phone / group_first / group_random | By the phone number of the payload, by that number within a group, by a fixed number, or the first / a random contact of a group. |
phoneValue | phone number | For phone. |
groupId | gid_... | For the group variants. |
wait
Parks the execution (status waiting) and resumes it later with the same version of the workflow, for example to send a follow-up the next morning.
{ "id": "wait", "type": "actionNode",
"data": { "title": "Wait until morning", "config": { "actionType": "wait", "waitMode": "until_time", "untilTime": "09:00", "timezone": "Europe/Brussels" } } }
{ "id": "wait", "type": "actionNode",
"data": { "title": "Wait 2 days", "config": { "actionType": "wait", "waitMode": "duration", "durationValue": 2, "durationUnit": "days" } } }
| Key | Values | Description |
|---|---|---|
waitMode | duration (default) / until_time | Wait a fixed time, or until a time of day. |
durationValue | integer, 1 or more, default 30 | How long, for duration. |
durationUnit | seconds / minutes (default) / hours / days / weeks / months | Unit of durationValue. |
untilTime | HH:MM | For until_time. |
timezone | IANA name, default Europe/Brussels | Time zone of untilTime. |
assign_conversation
Hands the conversation of contact.phone to a team member, exactly like the Conversations endpoints do. Meant for the inbound_message and delivery_report triggers; without contact.phone in the payload the action is skipped.
{ "id": "assign", "type": "actionNode",
"data": { "title": "Assign to support", "config": { "actionType": "assign_conversation",
"assignMode": "round_robin",
"teamMembers": [ "sub_3520a1ec234dbabe1232def67e858855", "sub_9b74c9897bac770ffc029102a200c5de" ],
"onlyIfUnassigned": true, "status": "open" } } }
| Key | Values | Description |
|---|---|---|
assignMode | fixed (default) / round_robin | fixed always assigns to teamMember. round_robin takes turns over teamMembers: the member whose most recent assignment is the oldest is next; members without any assignment come first, in list order. |
teamMember | sub_... | Required for fixed. |
teamMembers | list of sub_... | At least one for round_robin. |
onlyIfUnassigned | boolean, default false | When true and the conversation already has an assignee, the action is skipped and reports the current assignee. |
status | open / pending / null | Also set the conversation status after assigning; null leaves it as it is. |