← Help centre

Automation nodes and triggers

Every block you can drop on the automation canvas, what it does, the fields it takes and where it can continue to. This page is generated from the same table the visual builder and the MCP server read, so it cannot drift from the product.

How a flow runs

A flow starts at a trigger and walks from node to node along its outputs. A node that waits for a reply pauses the flow until the contact answers; a terminal node ends it. If a node needs something the network does not support, it is skipped at runtime rather than breaking the flow.

Triggers

What starts a flow.

TriggerWhat starts it
keywordFires when an incoming direct message matches one of the keywords.
commentFires on a comment on your posts. Instagram and Facebook only — they are the ones that allow answering a comment by direct message.
storyFires when someone replies or reacts to a story, which arrives as a direct message.
welcomeFires once, on the contact's first ever conversation.
manualNever fires on its own. For flows reached from another one with a goto_flow node (keep it active).

Nodes

start

Entry point of the flow. Every graph has exactly one.

Outputs: next (Node to continue to.)

message

Send a plain text message.

FieldWhat it does
text · text · requiredMessage body. Every text a flow sends (messages, captions, button and question texts, public comment replies, handoff notices) accepts variables: {{first_name}}, {{last_name}}, {{name}}, {{username}} (of whoever wrote or commented), {{email}}, any custom field by its slug ({{phone}}), or a question node's variable. A fallback goes after "": {{first_namethere}}. A variable with no value and no fallback is left out.

Outputs: next (Node to continue to.)

image

Send an attachment (image, video, audio or file) with an optional caption.

Needs the dmAttachments capability on the target network.
FieldWhat it does
url · string · requiredPublic https URL of the file.
caption · textText sent alongside the attachment.
mediaType · select · one of: image, video, audio, file · default imageKind of attachment.
mediaButtonTitle · stringLabel of the link button used to deliver a document (mediaType "file") on Instagram and Facebook, where an attached document opens behind a Meta interstitial. Defaults to the file extension.

Outputs: next (Node to continue to.)

button_message

Message with up to 3 buttons. Each button either opens a URL or branches the flow. With media it renders as a rich card, without it as a bubble with buttons. This is the button node to use.

Waits for the contact to reply before continuing. Needs the dmButtons capability on the target network.
FieldWhat it does
text · text · requiredMessage body.
buttons · messageButton[] · required · max 3Each: {title, kind:"url""reply", url (when url), payload (when reply), next (branch of THIS button, reply only)}.
mediaUrl · stringPublic https URL of an attachment sent with the message.
mediaType · select · one of: image, video, audio, file · default imageKind of attachment. Networks differ: check dmAttachments in get_network_rules.
mediaButtonTitle · stringLabel of the link button used to deliver a document (mediaType "file"). On Instagram and Facebook a message with buttons only carries an image, so documents travel as a link button to their public URL. Defaults to the file extension.

Outputs: next (Continuation / fallback: no reply buttons, or an unmatched tap.) · buttons[].next (Branch taken when that specific reply button is tapped.)

buttons

Legacy node: text plus 1-3 link buttons. Does not branch.

Needs the dmButtons capability on the target network. Superseded by button_message; still runs, but prefer the newer one.
FieldWhat it does
text · text · requiredMessage body.
buttons · linkButton[] · required · max 3Each: {title, url}.
mediaUrl · stringPublic https URL of an attachment sent with the message.
mediaType · select · one of: image, video, audio, file · default imageKind of attachment. Networks differ: check dmAttachments in get_network_rules.
mediaButtonTitle · stringLabel of the link button used to deliver a document (mediaType "file"). On Instagram and Facebook a message with buttons only carries an image, so documents travel as a link button to their public URL. Defaults to the file extension.

Outputs: next (Node to continue to.)

reply_buttons

Legacy node: text plus up to 3 reply buttons; waits for a tap and stores it.

Waits for the contact to reply before continuing. Needs the dmButtons capability on the target network. Superseded by button_message; still runs, but prefer the newer one.
FieldWhat it does
text · text · requiredMessage body.
replies · quickReply[] · required · max 3Each: {title, payload}. Without payload the title is used.
variable · stringStore the answer under this name.
mediaUrl · stringPublic https URL of an attachment sent with the message.
mediaType · select · one of: image, video, audio, file · default imageKind of attachment. Networks differ: check dmAttachments in get_network_rules.
mediaButtonTitle · stringLabel of the link button used to deliver a document (mediaType "file"). On Instagram and Facebook a message with buttons only carries an image, so documents travel as a link button to their public URL. Defaults to the file extension.

Outputs: next (Node to continue to.)

carousel

Horizontal carousel of cards. Instagram and Facebook only.

Needs the carousel capability on the target network.
FieldWhat it does
elements · card[] · required · max 10Each: {title, subtitle, imageUrl, buttons:[{title,url}] (max 3 link buttons per card)}.

Outputs: next (Node to continue to.)

catalog

Show the workspace catalogue as a carousel. Items come from the catalogue itself, not from the node — manage them with manage_catalog.

Needs the carousel capability on the target network.
FieldWhat it does
category · stringFree-text SEARCH, not an exact filter: it matches as a substring against item name, description or category.

Outputs: next (Node to continue to.)

booking

Book an appointment with buttons, without AI: service → (person, if the business lets people choose) → day → time → the required details, then the appointment is created (Google Calendar event included) and the flow continues. Services, hours and what to ask are configured in Appointments in the app (get_booking_settings), not here. Needs appointments in the plan (Blaze and up) and turned on.

Waits for the contact to reply before continuing. Needs the dmButtons capability on the target network.
FieldWhat it does
serviceIds · string[]Restrict to these service ids. Empty = every bookable service.

Outputs: next (Taken once the appointment is booked.) · noSlotsNext (Taken when there is nothing to offer (no free slots, appointments off or not in the plan) or the person keeps writing instead of tapping. Falls back to next.)

delay

Pause the flow, then resume: for a number of minutes, or until a date (fixed, or taken from a field or answer). Optionally only within some days and hours.

FieldWhat it does
minutes · number · requiredMinutes to wait (mode "duration"; ignored with mode "until", pass 0). Decimals allowed: 0.5 = 30 seconds, 99 = 1.65 hours.
mode · select · one of: duration, until · default duration"until" waits until a date instead: untilDate (YYYY-MM-DD) or the date in untilField (a contact field slug or a question variable), at untilTime (HH:MM, default 09:00), plus offsetMinutes (negative = before, e.g. -1440 = one day before). If that moment has passed or there is no valid date, the flow continues at once.
untilDate · stringFixed date, YYYY-MM-DD.
untilField · stringField slug or question variable holding the date.
untilTime · stringTime of day, HH:MM, in the organization time zone.
offsetMinutes · numberShift from that date; negative = before.
window · window{"days":[1-7, 1=Monday],"from":"09:00","to":"18:00"} in the organization time zone. If the wait ends outside it, the flow continues at the start of the next window. from > to crosses midnight.

Outputs: next (Node to continue to.)

delay_random

Pause a random number of minutes between two bounds, so replies do not look automated.

FieldWhat it does
minMinutes · number · requiredLower bound in minutes, inclusive. Decimals allowed (0.5 = 30 seconds).
maxMinutes · number · requiredUpper bound in minutes, inclusive. Decimals allowed (99 = 1.65 hours).

Outputs: next (Node to continue to.)

question

Ask something and wait for the answer, optionally validating and storing it.

Waits for the contact to reply before continuing.
FieldWhat it does
text · text · requiredThe question.
variable · stringStore the answer under this name.
validate · select · one of: email, phone, number, url, dateRequire a valid answer of that kind. On a bad answer it resends retryText and asks again, then gives up and keeps whatever came so the user is never trapped. The answer is stored normalized: number with a dot and no thousands separator ("1.234,5" → 1234.5), url with https://, date as YYYY-MM-DD (typed day first: 15/3/26). That is what lets a later condition compare it with gt/lt.
retryText · textMessage sent when validation fails.
timeoutMinutes · numberMinutes to wait for an answer before taking the timeout branch. Without it, someone who never answers stays waiting forever and the flow ends there in silence — and not answering is the normal case, so this branch is usually the difference between capturing a contact and losing it.
timeoutNext · nodeRefNode to continue to when the wait runs out. Needed for timeoutMinutes to do anything. Typically a message that asks again. If the person answers before the time is up, this branch never fires.

Outputs: next (Node to continue to.) · timeoutNext (Taken when nobody answered within timeoutMinutes.)

condition

Branch on the user's last answer, the contact's tags and custom fields, the network, or the day and time. Takes the first branch that matches.

FieldWhat it does
branches · branch[] · requiredEach: {keywords:[…], rules?:[…], match?:"all""any", next}. keywords checks the last answer (case and accents ignored, substrings hit, a leading "-" excludes). rules adds checks, combined with the keywords by match (default "all"): {"kind":"tag","op":"has""has_not","tag":"vip"} · {"kind":"field","slug":"email","op":"is""is_not""contains""not_contains""is_set""is_empty""gt""lt","value":"…"} (email and name also read the native contact data; gt/lt compare numbers or dates) · {"kind":"platform","op":"is""is_not","platform":"instagram"} · {"kind":"time","days":[1-7, 1=Monday],"from":"09:00","to":"18:00"} (organization time zone; from > to crosses midnight) · {"kind":"text","op":"contains""not_contains""is""starts_with","value":"yes, ok"} (comma-separated list: contains = any of them, "-word" excludes; not_contains = none of them; same as keywords, which is the older way to write text·contains) · {"kind":"seen","op":"yes""no","scope"?:"post"} (had this person already been through THIS flow before this time — on this same post with scope "post"; counted like oncePerContact on the trigger, so you can send something else instead of staying silent). Without a contact, tags and fields count as empty. With no answer (after a delay) keywords never match but rules are still checked.

Outputs: branches[].next (Branch whose keywords matched.) · fallbackNext (Taken when nothing matched.)

follower

Branch on whether the person follows the account. Instagram only exposes this; anywhere else it takes the yes branch.

Outputs: yesNext (Follows, or unknown. Unknown counts as yes so nobody gets stuck.) · noNext (Only when Instagram explicitly confirms they do not follow.)

ab_split

Split runs between two branches at random and count each one, for real A/B stats.

FieldWhat it does
percentage · number · default 50Percentage going to branch A, 0-100. The rest go to B.

Outputs: aNext (Branch A.) · bNext (Branch B.)

randomize

Send one of several text variants at random, to avoid sounding repetitive.

FieldWhat it does
texts · string[] · requiredVariants. Empty ones are ignored.

Outputs: next (Node to continue to.)

tag

Add tags to the contact, or remove them. Silent: nothing is sent to the user.

FieldWhat it does
tags · string[] · requiredTags to add or remove. Adding merges with the existing ones, it does not replace them. Removing ignores case and accents.
mode · select · one of: add, remove · default add"add" adds the tags; "remove" takes them off the contact if present.

Outputs: next (Node to continue to.)

field

Set a custom field on the contact, or clear it. Silent.

FieldWhat it does
slug · string · requiredField slug, from list_custom_fields.
value · stringValue to store. Accepts variables, e.g. {{size}} from an earlier question.
valueFromAnswer · boolean · default falseStore the user's LAST answer instead of value: the usual question → field pattern.
mode · select · one of: set, clear · default set"clear" empties the field on the contact (the field definition stays); value is ignored. Clearing email also empties the native email.

Outputs: next (Node to continue to.)

subscribe

Enrol the contact in a drip sequence, or take them out of it. Silent.

FieldWhat it does
sequenceId · string · requiredSequence id, from list_sequences.
mode · select · one of: subscribe, unsubscribe · default subscribe"unsubscribe" removes the contact from the sequence: no further steps are sent.

Outputs: next (Node to continue to.)

handoff

Hand the conversation to a human and STOP the bot for it. Terminal: no automation runs on that conversation again until someone clears it.

Ends the conversation: it has no outputs.
FieldWhat it does
message · textOptional notice sent to the user.
assignMode · select · one of: auto, user, team · default autoauto lets Ignix route it; user or team forces an owner.
assignUserId · stringRequired when assignMode is user.
assignTeamId · stringRequired when assignMode is team.

ai

Answer ONCE with the AI, using the workspace knowledge base and the contact's memory, then carry on with the flow.

FieldWhat it does
instructions · textExtra steer for THIS point of the flow, e.g. "focus on booking a visit".
fallbackText · textSent when the AI is unavailable or over its fair-use ceiling.
retrieveLimit · numberHow many knowledge passages to retrieve.
escalateOnUnknown · boolean · default falseTake escalateNext when the AI could not answer from knowledge.

Outputs: next (Node to continue to.) · fallbackNext (Taken when the AI was unavailable.) · escalateNext (Taken when the user asks for a human, or on unknown if enabled. Wire it to a handoff node.)

ai_agent

Hand the conversation to the AI and let it answer EVERY incoming message, turn after turn, until it escalates. Use this instead of ai for open-ended conversations.

Waits for the contact to reply before continuing.
FieldWhat it does
instructions · textStanding steer for the conversation.
fallbackText · textSent when the AI is unavailable.
retrieveLimit · numberHow many knowledge passages to retrieve.
escalateOnUnknown · boolean · default falseEscalate when the AI could not answer from knowledge.

Outputs: escalateNext (Taken when the user asks for a human, or on unknown if enabled. Without escalation the node keeps waiting for the next message.)

comment_reply

Post a PUBLIC reply to the comment that triggered the flow. Only does anything on comment triggers.

Needs the commentReply capability on the target network.
FieldWhat it does
text · text · requiredThe public reply.
texts · string[]Variants; one is picked at random per comment. Falls back to text.

Outputs: next (Node to continue to.)

random_split

Send each person down one of 2–6 paths at random, by weight. With sticky the same person always gets the same path, also on later runs. No stats: use ab_split to measure.

FieldWhat it does
paths · string[] · required[{"weight":50,"next":"n1"},{"weight":50,"next":"n2"}]. Weights are relative (they do not need to add up to 100).
sticky · boolean · default falseSame person → same path every time (deterministic by node and contact).

Outputs: paths[].next (The path drawn.)

team

A team action, nothing is sent to the user: notify the team, change the conversation status in the inbox, or pause the bot for this contact.

FieldWhat it does
action · select · required · one of: notify, stage, pause"notify" emails/pushes message (accepts variables) to the conversation owner (or OWNER/ADMIN), or to notifyUserId / notifyTeamId with notifyMode "user"/"team". "stage" sets the inbox status to stage. "pause" silences the bot for this contact for pauseHours (none = until someone turns it back on); the rest of the current pass still runs.
message · textFor notify.
notifyMode · select · one of: auto, user, team · default autoFor notify.
notifyUserId · stringFor notify with notifyMode "user", from list_team.
notifyTeamId · stringFor notify with notifyMode "team".
stage · select · one of: open, pending, resolvedFor stage.
pauseHours · numberFor pause. Empty = until turned back on.

Outputs: next (Node to continue to.)

http

Call an external service (Zapier, Make, a webhook, an API) and continue. Silent for the user. Only https, never internal addresses; 8 s timeout, no redirects.

FieldWhat it does
method · select · required · one of: GET, POST, PUT, PATCH, DELETEHTTP method.
url · string · requiredhttps URL. Accepts variables ({{email}}), URL-encoded.
headers · string[][{"key":"Authorization","value":"Bearer …"}]. Values accept variables.
body · textRequest body for POST/PUT/PATCH, usually JSON. Variables are escaped for JSON: {"email":"{{email}}","name":"{{first_name}}"}. Content-Type defaults to application/json.
save · string[][{"path":"data.order.status","variable":"order_status","field":"order_status"}]: copies a value from the JSON response into a run variable (usable later as {{order_status}}) and/or a contact field.

Outputs: next (Got a 2xx response.) · errorNext (Anything else (error status, timeout, blocked URL). Without it, the flow goes on through next.)

goto_flow

Jump to ANOTHER automation and continue there, in the same conversation. Terminal: what happens next is up to the target. Only ACTIVE automations run (an inactive target ends the flow); its trigger, accounts and once-per-person setting are ignored — automations with a "manual" trigger exist to be reached this way.

Ends the conversation: it has no outputs.
FieldWhat it does
flowId · string · requiredId of the target automation, from list_automations (same workspace).

end

End the flow.

Ends the conversation: it has no outputs.
Automation nodes and triggers — Ignix Help