42 scenarios
(SUB) External Bot Enabled
Sends a webhook when externalBot is set to true on a chat — i.e. an external AI/automation just took over. Use this to start an AI session, light up a control panel, or sync state in an external system. Mirrors the trigger and condition used by the Q-AI handoff scenarios.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the chat payload when externalBot is enabled.
{
"version": "v1",
"name": "(SUB) External Bot Enabled",
"description": "Sends a webhook when externalBot is set to true on a chat.",
"triggerEvents": [
"domain.chat.updated.externalBot",
"app.bot.chat.setExternal"
],
"loaders": {},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "exists(externalBot) and externalBot",
"value": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "externalBotEnabled",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
Remember Last Agent on Chat Assigned
When an agent takes a chat, stores the agent's UID, display name, and email into the ChatsLastAgent data storage collection, keyed by chat ID. Use this as a building block: a bot can later read who the last agent was via a dataStorage func node and act on it — e.g. auto-assign the chat back to that agent the next time the customer messages, or include the agent in a webhook payload. Records expire after 1 day by default (max 7 days, server-enforced).
- Data Collection Nameoptional
actions[0].params.collectionThe data storage collection name. Default:
ChatsLastAgent. Customize for namespacing or to avoid collisions with other scenarios. Allowed characters:a-z,A-Z,0-9,_,-. Max 100 chars. - Record TTLoptional
actions[0].params.expiresIn, actions[0].params.expiresInUnitHow long each record lives before expiring. Default: 1 day. Units:
minutes,hours, ordays. Server-enforced maximum: 7 days (≈168 hours / 10080 minutes) — values above the cap are rejected. Pick a TTL that fits how long after a hand-off you still want to route follow-ups back to the same agent. - Stored Data Shapeoptional
actions[0].params.dataThe object written into storage. Defaults capture
latestAgentUid,latestAgentName,latestAgentEmail, and the assignment date. Add or remove fields per your use case — any data injection expression is supported.
{
"version": "v1",
"name": "Set last agent on assign chat",
"description": "when agent takes a chat, set ChatsLastAgent collection with the lastAgentUid",
"triggerEvents": [
"domain.chat.assigned"
],
"loaders": {
"afterConditions": [
{
"name": "user",
"alias": "user",
"params": {
"id": "%agent:_id%"
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "exists(agent.uid)",
"value": "%chat:chat%"
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "setData",
"params": {
"expiresInUnit": "days",
"collection": "ChatsLastAgent",
"key": "%chat:_id|toString%",
"data": {
"latestAgentUid": "%chat:agent.uid%",
"latestAgentName": "%user:displayName%",
"latestAgentEmail": "%user:email%",
"date": "%time:now(\"dd/MM/yyyy\")%"
},
"tags": [],
"expiresIn": 1
},
"confidentialData": false
}
],
"options": {
"unorderedActions": true
}
}
(SUB) Chat Resolved
Sends a webhook when a chat is resolved, with the full chat object (including the agent who resolved it and resolvedUpdateTime). Use this to close out tickets in external systems, log handling time, or trigger post-resolution follow-ups.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the chat payload when a chat is resolved.
{
"version": "v1",
"name": "(SUB) Chat Resolved",
"description": "Sends a webhook when a chat is resolved.",
"triggerEvents": [
"domain.chat.resolved"
],
"loaders": {},
"conditions": [],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "chatResolved",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SLA) Set Item On Set to pending
When a chat is set to pending status and no SLA record exists yet, writes one with the current timestamp and chat id so other SLA scenarios can later add/remove the SLA label.
- Data Collection Nameoptional
actions[0].params.collection, loaders.beforeConditions[0].params.collectionThe data store collection used to track SLA timestamps per chat. Keep the same value across all SLA scenarios. Default:
sla_chats_collection. - Record TTLoptional
actions[0].params.expiresIn, actions[0].params.expiresInUnitHow long the SLA record should live before expiring automatically (default: 24 hours).
{
"version": "v1",
"name": "(SLA) Set Item On Set to pending",
"description": "when customer sends a new message in a chat in pending or taken chat, add record to store",
"triggerEvents": [
"domain.chat.pending"
],
"loaders": {
"beforeConditions": [
{
"name": "getData",
"alias": "record",
"params": {
"collection": "sla_chats_collection",
"key": {
"##provide": {
"provider": "chat",
"key": "channelInfo.id"
}
}
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "empty(record.data.timestamp)",
"value": {
"record": "%record:record%"
}
},
"confidentialData": false
},
{
"name": "filtrex",
"params": {
"expression": "status in (1,2,3)",
"value": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "setData",
"params": {
"expiresInUnit": "hours",
"collection": "sla_chats_collection",
"data": {
"timestamp": "%time:now(\"x\")%",
"chatId": "%chat:_id%"
},
"tags": [],
"expiresIn": 24,
"key": {
"##provide": {
"provider": "chat",
"key": "channelInfo.id"
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SUB) Chat Assigned
Sends a webhook when a chat is taken by an agent, including the full chat and a narrowed agent profile (id, crmId, email, displayName, roles). Use this to sync assignment with CRMs, routing tools, or custom backends.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the chat and agent payload when a chat is assigned.
{
"version": "v1",
"name": "(SUB) Chat Assigned",
"description": "Sends a webhook when a chat is assigned, with full chat data and a narrowed agent object.",
"triggerEvents": [
"domain.chat.assigned"
],
"loaders": {},
"conditions": [],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "chatAssigned",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
},
"agent": {
"id": {
"##provide": {
"provider": "agent",
"key": "_id"
}
},
"crmId": {
"##provide": {
"provider": "agent",
"key": "crmId"
}
},
"email": {
"##provide": {
"provider": "agent",
"key": "email"
}
},
"displayName": {
"##provide": {
"provider": "agent",
"key": "displayName"
}
},
"roles": {
"##provide": {
"provider": "agent",
"key": "roles"
}
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SLA) Set Item On Incoming Message
When a customer sends an incoming message in an active chat (pending, assigned, or resolved), and no SLA record exists yet, writes one with the current timestamp and chat id so other SLA scenarios can later add/remove the SLA label.
- Data Collection Nameoptional
actions[0].params.collection, loaders.beforeConditions[1].params.collectionThe data store collection used to track SLA timestamps per chat. Keep the same value across all SLA scenarios. Default:
sla_chats_collection. - Record TTLoptional
actions[0].params.expiresIn, actions[0].params.expiresInUnitHow long the SLA record should live before expiring automatically (default: 24 hours).
{
"version": "v1",
"name": "(SLA) Set Item On Incoming Message",
"description": "when customer sends a new message in a chat in pending or taken chat, add record to store",
"triggerEvents": [
"domain.message.created"
],
"loaders": {
"beforeConditions": [
{
"name": "chat",
"alias": "chat",
"params": {
"id": {
"##provide": {
"provider": "message",
"key": "parent_chat"
}
}
},
"confidentialData": false
},
{
"name": "getData",
"alias": "record",
"params": {
"collection": "sla_chats_collection",
"key": {
"##provide": {
"provider": "message",
"key": "chatChannelInfo.id"
}
}
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "compare",
"params": {
"value": "%message:direction%",
"comparison": "Equal",
"compareTo": "incoming"
},
"confidentialData": false
},
{
"name": "filtrex",
"params": {
"expression": "empty(record.data.timestamp)",
"value": {
"record": "%record:record%"
}
},
"confidentialData": false
},
{
"name": "filtrex",
"params": {
"expression": "status in (1,2,3)",
"value": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "setData",
"params": {
"expiresInUnit": "hours",
"collection": "sla_chats_collection",
"data": {
"timestamp": "%message:timestamp%",
"chatId": "%chat:_id%"
},
"tags": [],
"expiresIn": 24,
"key": {
"##provide": {
"provider": "chat",
"key": "channelInfo.id"
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SUB) Chat Labels Updated
Sends a webhook whenever a chat's labels change. The payload includes the full chat, the previous label set (oldLabels), and a precomputed diff (addedLabels, removedLabels) so subscribers don't have to reconstruct the change themselves. Use this to sync label-driven workflows, CRM tags, or routing tables in real time.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the chat and label-diff payload.
{
"version": "v1",
"name": "(SUB) Chat Labels Updated",
"description": "Sends a webhook when a chat's labels change, with the chat, previous labels, and the added/removed diff.",
"triggerEvents": [
"domain.chat.labels"
],
"loaders": {},
"conditions": [],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "chatLabelsUpdated",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
},
"oldLabels": {
"##provide": {
"provider": "oldLabels",
"key": "labels"
}
},
"addedLabels": {
"##provide": {
"provider": "addedLabels",
"key": "labels"
}
},
"removedLabels": {
"##provide": {
"provider": "removedLabels",
"key": "labels"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
Q-AI: Turn On AI Bot
Part of the Q-AI suite. When externalBot is enabled on a chat, forwards the full chat object and current session messages to your AI service as a setExternalTrue event — the entry point of the AI handoff flow.
- AI Webhook URLrequired
actions[0].params.urlYour AI service webhook that receives the
setExternalTrueevent with the chat and session messages when AI mode is turned on.
{
"version": "v1",
"name": "Q-AI Turn On AI Bot",
"description": "When external bot is set to true, forward the chat and current session messages to AI",
"triggerEvents": [
"domain.chat.updated.externalBot",
"app.bot.chat.setExternal"
],
"loaders": {
"afterConditions": [
{
"name": "chatMessages",
"alias": "messages",
"params": {
"chatId": {
"##provide": {
"provider": "chat",
"key": "_id"
}
}
},
"confidentialData": false
},
{
"name": "environment",
"alias": "env",
"params": {},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "exists(externalBot) and externalBot",
"value": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourAIWebhookURL}}",
"method": "post",
"json": true,
"data": {
"projectId": "%env:projectId|replace(\"texter-\", \"\")%",
"eventName": "setExternalTrue",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
},
"messages": "%messages:botSession|map(\"type::type\",\"timestamp::timestamp\",\"text::text\",\"media::media\",\"direction::direction\",\"list::listOptions\",\"buttons::buttonsOptions\",\"special::specialExtraInfo\",\"postback::postback\")%"
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SUB) Messages with Attachments
Sends a webhook when an incoming message contains a media attachment — image, video, document, audio, or sticker. Useful for feeding media into processing pipelines or external storage.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the media message and chat payload.
{
"version": "v1",
"name": "(SUB) Messages with Attachments",
"description": "Sends a webhook when a new incoming message includes a media item (image / video / document / audio / sticker)",
"triggerEvents": [
"domain.message.created"
],
"loaders": {
"afterConditions": [
{
"name": "chat",
"alias": "chat",
"params": {
"id": {
"##provide": {
"provider": "message",
"key": "parent_chat"
}
}
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "direction == \"incoming\"",
"value": {
"##provide": {
"provider": "message",
"key": "message"
}
}
},
"confidentialData": false
},
{
"name": "filtrex",
"params": {
"expression": "type == \"media\"",
"value": {
"##provide": {
"provider": "message",
"key": "message"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "newMediaMessage",
"eventData": {
"message": {
"##provide": {
"provider": "message",
"key": "message"
}
},
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
Q-AI: Forward Incoming Message to AI
Part of the Q-AI suite. When a new incoming message arrives and externalBot is active, forwards the message and chat objects to the AI service as a newIncomingMessage event.
- AI Webhook URLrequired
actions[0].params.urlYour AI service webhook that receives the
newIncomingMessagepayload for each inbound message while AI mode is active.
{
"version": "v1",
"name": "Q-AI Forward Incoming Message to AI",
"description": "When a new incoming message is received and external bot is set to true, forward the message and the chat objects to AI",
"triggerEvents": [
"domain.message.created"
],
"loaders": {
"beforeConditions": [
{
"name": "chat",
"alias": "chat",
"params": {
"id": {
"##provide": {
"provider": "message",
"key": "parent_chat"
}
}
},
"confidentialData": false
}
],
"afterConditions": [
{
"name": "environment",
"alias": "env",
"params": {},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "exists(externalBot) and externalBot",
"value": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
},
"confidentialData": false
},
{
"name": "filtrex",
"params": {
"expression": "direction == \"incoming\"",
"value": {
"##provide": {
"provider": "message",
"key": "message"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourAIWebhookURL}}",
"method": "post",
"json": true,
"data": {
"projectId": "%env:projectId|replace(\"texter-\", \"\")%",
"eventName": "newIncomingMessage",
"eventData": {
"message": {
"##provide": {
"provider": "message",
"key": "message"
}
},
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SUB) Channel Health Problem Resolved
Sends a webhook when a previously detected channel health problem is resolved (the channel is healthy again). Pairs with (SUB) Channel Health Problem Created to close out incidents in your monitoring/paging system. The problem.resolvedAt field will be populated. See problem object for the payload schema.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the problem payload when a channel health issue is resolved.
{
"version": "v1",
"name": "(SUB) Channel Health Problem Resolved",
"description": "Sends a webhook when a previously detected channel health problem is resolved.",
"triggerEvents": [
"domain.channel.health.problem.resolved"
],
"loaders": {},
"conditions": [],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "channelHealthProblemResolved",
"eventData": {
"problem": {
"##provide": {
"provider": "problem",
"key": "problem"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
Q-AI: Disable External Bot After Manual Resolve
Part of the Q-AI suite. When a chat is resolved manually in Texter while AI mode is active, disables externalBot and notifies the AI service with setExternalFalse to end the session.
- AI Webhook URLrequired
actions[1].params.urlYour AI service webhook that receives the
setExternalFalseevent when a chat is manually resolved.
{
"version": "v1",
"name": "Q-AI Disable External Bot After Manual Resolve",
"description": "When chat is resolved within Texter and externalBot is true, set externalBot to false and forward the event",
"triggerEvents": [
"domain.chat.resolved"
],
"loaders": {
"afterConditions": [
{
"name": "environment",
"alias": "env",
"params": {},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "exists(externalBot) and externalBot",
"value": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "chatUpdateExternalBot",
"params": {
"externalBot": false,
"chatId": {
"##provide": {
"provider": "chat",
"key": "_id"
}
}
},
"confidentialData": false
},
{
"name": "request",
"params": {
"url": "{{yourAIWebhookURL}}",
"method": "post",
"json": true,
"data": {
"projectId": "%env:projectId|replace(\"texter-\", \"\")%",
"eventName": "setExternalFalse",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
End-of-Day Closing Message
Finds all pending chats active within the last ~9 hours at the end of the business day and sends a notification that a response will be provided the following business day, excluding those with the waiting_for_customer label. Runs on a custom cron schedule configured per customer in Nihul and sends up to 10 messages concurrently.
- Cron Schedulerequired
Nihul → Customer ConfigAdd to the
cron.schedulearray in the customer config in Nihul:{ "task": "ScenariosCustomTriggerCronTask", "expr": "30 18 * * 0-4", "params": { "name": "end-of-day-message-sending" } }The example runs Sun–Thu at 18:30 — adjust the cron expression per customer request.
- Exclude Labeloptional
loaders.afterConditions[0].params.filters[0].labels.exclude[0]Label ID to skip — chats tagged with this label won't receive the message. Default:
waiting_for_customer. - Time Windowoptional
loaders.afterConditions[0].params.filters[0].lastMessageTimestamp.afterHow far back to look for pending chats. Defaults to 9 hours (
now-9h). Can be adjusted per customer but must stay under 24 hours. - Message Textoptional
actions[0].params.message.textThe closing message body to send. Customize per customer. Supports the full message payload (text, media, template).
{
"version": "v1.1",
"name": "End-of-day closing message",
"description": "On cron trigger, find pending chats active in last ~9h and send a closing message.",
"triggerEvents": [
"app.scenarios.customTriggers.cron"
],
"loaders": {
"afterConditions": [
{
"name": "chatsList",
"alias": "chats",
"params": {
"limit": 1000,
"skip": 0,
"filters": [
{
"lastMessageTimestamp": {
"after": "%time:now-9h(\"x\")|parseInt%",
"before": "%time:now(\"x\")|parseInt%"
},
"status": [
"PENDING"
],
"channel": [],
"department": [],
"agent": [],
"labels": {
"include": [],
"exclude": [
"waiting_for_customer"
]
}
}
]
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "compare",
"params": {
"comparison": "Equal",
"compareTo": "end-of-day-message-sending",
"value": {
"##provide": {
"provider": "cron",
"key": "name"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "sendMessage",
"params": {
"message": {
"type": "text",
"text": "היי, ראינו את ההודעה אבל לא הספקנו לענות, נחזור אליכם ביום העסקים הבא"
},
"chat": {
"name": {
"##provide": {
"provider": "chat",
"key": "channelInfo.name"
}
},
"accountId": {
"##provide": {
"provider": "chat",
"key": "channelInfo.accountId"
}
},
"id": {
"##provide": {
"provider": "chat",
"key": "channelInfo.id"
}
}
}
},
"confidentialData": false
}
],
"loops": [
{
"loop": {
"type": "foreach",
"as": "chat",
"input": {
"##provide": {
"provider": "chats",
"key": "chats"
}
},
"confidentialData": false,
"foreachMode": "parallel",
"concurency": 10
},
"position": "beforeActions"
}
],
"options": {
"unorderedActions": false
}
}
Q-AI: End AI Session & Run Bot
Part of the Q-AI suite. When externalBot is disabled and the chat is in with bot status, resumes the Texter bot from a specified node and notifies the AI service with setExternalFalse. Handles the handoff back from AI to Texter.
- Bot Resume Noderequired
actions[0].params.nodeNameThe bot node name to resume from when returning from AI. Must match a node in your bot YAML (e.g.
back_to_texter). - AI Webhook URLrequired
actions[1].params.urlYour AI service webhook that receives the
setExternalFalseevent to close the AI session.
{
"version": "v1",
"name": "Q-AI End AI Session & Run Bot",
"description": "When externalBot is set to false and the chat status is 'with bot', close the AI session and run the bot",
"triggerEvents": [
"domain.chat.updated.externalBot",
"app.bot.chat.setExternal"
],
"loaders": {
"afterConditions": [
{
"name": "environment",
"alias": "env",
"params": {},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "compare",
"params": {
"comparison": "Equal",
"compareTo": false,
"value": {
"##provide": {
"provider": "chat",
"key": "externalBot"
}
}
},
"confidentialData": false
},
{
"name": "compare",
"params": {
"comparison": "Equal",
"compareTo": 0,
"value": {
"##provide": {
"provider": "chat",
"key": "status"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "runBot",
"params": {
"nodeName": "back_to_texter",
"chatId": {
"##provide": {
"provider": "chat",
"key": "_id"
}
}
},
"confidentialData": false
},
{
"name": "request",
"params": {
"url": "{{yourAIWebhookURL}}",
"method": "post",
"json": true,
"data": {
"projectId": "%env:projectId|replace(\"texter-\", \"\")%",
"eventName": "setExternalFalse",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": true
}
}
Q-AI: Disable External Bot On Pending Chat
Part of the Q-AI suite. When a chat is set to pending status (e.g. an agent manually reassigns the chat to a different agent while AI mode is active), disables externalBot and notifies the AI service with setExternalFalse. Covers the handoff case where the AI session should end because a human took over via the pending workflow.
- AI Webhook URLrequired
actions[1].params.urlYour AI service webhook that receives the
setExternalFalseevent when a chat is set to pending while AI mode was active.
{
"version": "v1",
"name": "Q-AI Disable External Bot On Pending Chat",
"description": "When chat is set to pending and externalBot is true, set externalBot to false and forward the event",
"triggerEvents": [
"domain.chat.pending"
],
"loaders": {
"afterConditions": [
{
"name": "environment",
"alias": "env",
"params": {},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "exists(externalBot) and externalBot",
"value": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "chatUpdateExternalBot",
"params": {
"externalBot": false,
"chatId": {
"##provide": {
"provider": "chat",
"key": "_id"
}
}
},
"confidentialData": false
},
{
"name": "request",
"params": {
"url": "{{yourAIWebhookURL}}",
"method": "post",
"json": true,
"data": {
"projectId": "%env:projectId|replace(\"texter-\", \"\")%",
"eventName": "setExternalFalse",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
Q-AI: Disable External Bot After Manual Assign
Part of the Q-AI suite. When an agent manually takes a chat while AI mode is active, disables externalBot and notifies the AI service with setExternalFalse. Ensures the AI stops handling a chat once a human steps in.
- AI Webhook URLrequired
actions[1].params.urlYour AI service webhook that receives the
setExternalFalseevent when a chat is manually assigned.
{
"version": "v1",
"name": "Q-AI Disable External Bot After Manual Assign",
"description": "When chat is assigned within Texter and externalBot is true, set externalBot to false and forward the event",
"triggerEvents": [
"domain.chat.assigned"
],
"loaders": {
"afterConditions": [
{
"name": "environment",
"alias": "env",
"params": {},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "exists(externalBot) and externalBot",
"value": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "chatUpdateExternalBot",
"params": {
"externalBot": false,
"chatId": {
"##provide": {
"provider": "chat",
"key": "_id"
}
}
},
"confidentialData": false
},
{
"name": "request",
"params": {
"url": "{{yourAIWebhookURL}}",
"method": "post",
"json": true,
"data": {
"projectId": "%env:projectId|replace(\"texter-\", \"\")%",
"eventName": "setExternalFalse",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
Message on Chat Assigned
Sends an automatic greeting message to the customer the moment an agent takes a chat — but only if there was incoming activity in the last 24 hours (avoids sending to stale chats). The message dynamically includes the assigned agent's name via data injection.
- Message Textrequired
actions[0].params.message.textThe greeting message to send. Supports data injection —
%chat:agent.displayName%is replaced with the assigned agent's name at send time.
{
"version": "v1",
"name": "Message on chat assigned",
"description": "Send message to chat when that chat is assigned",
"triggerEvents": [
"domain.chat.assigned"
],
"loaders": {},
"conditions": [
[
{
"name": "compare",
"params": {
"comparison": "Greater than",
"compareTo": "%time:now-1d(\"x\")|parseInt%",
"value": {
"##provide": {
"provider": "chat",
"key": "lastIncomingMessageTimestamp"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "sendMessage",
"params": {
"message": {
"text": "Hi, this is %chat:agent.displayName% — how can I help you?",
"type": "text"
},
"chat": {
"name": "whatsapp",
"##provide": {
"provider": "chat",
"key": "channelInfo"
},
"accountId": {
"##provide": {
"provider": "chat",
"key": "channelInfo.accountId"
}
},
"id": {
"##provide": {
"provider": "chat",
"key": "channelInfo.id"
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SUB) Messages Failed to Deliver
Sends a webhook when an outgoing message fails to deliver (blocked or rejected by Meta). Fires on status codes 4 and 5. Useful for alerting, retry logic, or audit trails.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the failed message status payload including error details.
{
"version": "v1",
"name": "(SUB) Messages Failed to Deliver",
"description": "Sends a webhook when an outgoing message fails to deliver (blocked by Meta)",
"triggerEvents": [
"app.message.statusRequest"
],
"loaders": {
"afterConditions": [
{
"name": "chat",
"alias": "chat",
"params": {
"name": {
"##provide": {
"provider": "messageStatusRequest",
"key": "chat.name"
}
},
"accountId": {
"##provide": {
"provider": "messageStatusRequest",
"key": "chat.accountId"
}
},
"idByChannel": {
"##provide": {
"provider": "messageStatusRequest",
"key": "chat.id"
}
}
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "compare",
"params": {
"comparison": "Equal",
"compareTo": 4,
"value": {
"##provide": {
"provider": "messageStatusRequest",
"key": "status"
}
}
},
"confidentialData": false
}
],
[
{
"name": "compare",
"params": {
"comparison": "Equal",
"compareTo": 5,
"value": {
"##provide": {
"provider": "messageStatusRequest",
"key": "status"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "messageFailed",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
},
"error": "%messageStatusRequest:error%",
"timestamp": "%messageStatusRequest:timestamp%",
"externalId": "%messageStatusRequest:ids%"
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
Assign Failed Label on Message Error
Adds a label to a chat whenever a sent message fails to deliver (status 4 or 5). Makes it easy to filter and follow up on chats with delivery failures from the Texter inbox.
- Label IDrequired
actions[0].params.labels[0]The label ID in Texter to apply when a message fails. Create this label in your Texter settings first. Default:
failed_message.
{
"version": "v1",
"name": "Assign Failed Label on Message Error",
"description": "Add the label failed_message to the chat whenever the sent message failed. Allows easy filtering",
"triggerEvents": [
"app.message.statusRequest"
],
"loaders": {
"afterConditions": [
{
"name": "chat",
"alias": "chat",
"params": {
"name": {
"##provide": {
"provider": "messageStatusRequest",
"key": "chat.name"
}
},
"accountId": {
"##provide": {
"provider": "messageStatusRequest",
"key": "chat.accountId"
}
},
"idByChannel": {
"##provide": {
"provider": "messageStatusRequest",
"key": "chat.id"
}
}
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "compare",
"params": {
"comparison": "Equal",
"compareTo": 4,
"value": {
"##provide": {
"provider": "messageStatusRequest",
"key": "status"
}
}
},
"confidentialData": false
}
],
[
{
"name": "compare",
"params": {
"comparison": "Equal",
"compareTo": 5,
"value": {
"##provide": {
"provider": "messageStatusRequest",
"key": "status"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "chatUpdateLabels",
"params": {
"operation": "add",
"labels": [
"failed_message"
],
"chatId": {
"##provide": {
"provider": "chat",
"key": "_id"
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
Run Bot on Agent Resolve
When an agent (not the bot) resolves a chat, automatically resumes the bot from a configurable node — for example close_chat to run a closing branch. Equivalent to the agent manually clicking "close and route to bot branch", but applied to every agent resolve.
Limitation: the resume node is the same for all chats, so the post-resolve flow is identical for everyone.
- Bot Resume Noderequired
actions[0].params.nodeNameThe bot node name to resume from after the agent resolves the chat. Must match a node in your bot YAML (e.g.
close_chat).
{
"version": "v1",
"name": "Run close_chat after agent resolve",
"triggerEvents": [
"domain.chat.resolved"
],
"loaders": {},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "exists(agent.uid)",
"value": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "runBot",
"params": {
"nodeName": "close_chat",
"chatId": {
"##provide": {
"provider": "chat",
"key": "_id"
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
Assign Chat on Echo Message
Automatically assigns a chat to a specific agent when an echo message is detected — a message sent directly from the WhatsApp Business App (not through Texter). This is a system scenario auto-generated during onboarding for WhatsApp Business accounts.
- Agent User IDrequired
actions[0].params.agentThe Texter internal user ID (
{{agentUserId}}) of the agent to assign the chat to. Find this in your Texter team settings.
{
"version": "v1",
"name": "Assign chat on echo message",
"description": "Assign chat to admin user when message was sent to chat directly from WhatsApp Business App",
"triggerEvents": [
"domain.message.created"
],
"loaders": {
"beforeConditions": [
{
"name": "channelAccount",
"alias": "channel",
"params": {
"name": {
"##provide": {
"provider": "message",
"key": "chatChannelInfo.name"
}
},
"accountId": {
"##provide": {
"provider": "message",
"key": "chatChannelInfo.accountId"
}
}
},
"confidentialData": false
},
{
"name": "chat",
"alias": "chat",
"params": {
"id": {
"##provide": {
"provider": "message",
"key": "parent_chat"
}
}
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "compare",
"params": {
"comparison": "Not equal",
"compareTo": true,
"value": {
"##provide": {
"provider": "channel",
"key": "botDisable"
}
}
},
"confidentialData": false
},
{
"name": "compare",
"params": {
"comparison": "Equal",
"compareTo": "outgoing",
"value": {
"##provide": {
"provider": "message",
"key": "direction"
}
}
},
"confidentialData": false
},
{
"name": "filtrex",
"params": {
"expression": "exists(special.isEchoMessage) and special.isEchoMessage",
"value": {
"##provide": {
"provider": "message",
"key": "message"
}
}
},
"confidentialData": true
},
{
"name": "compare",
"params": {
"comparison": "Not equal",
"compareTo": 2,
"value": {
"##provide": {
"provider": "chat",
"key": "status"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "chatAssign",
"params": {
"status": "Assigned",
"agent": "{{agentUserId}}",
"chatId": {
"##provide": {
"provider": "message",
"key": "parent_chat"
}
}
},
"confidentialData": false
}
],
"tags": [
"whatsapp-business-app-echo-assign"
],
"options": {
"unorderedActions": false
}
}
(SUB) All Messages
Sends a webhook POST for every new message — both incoming and outgoing. The simplest way to mirror all WhatsApp traffic to an external system in real time.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the message and chat payload on every message event.
{
"version": "v1",
"name": "(SUB) All Messages",
"description": "Sends a webhook for each new message (incoming & outgoing)",
"triggerEvents": [
"domain.message.created"
],
"loaders": {
"beforeConditions": [
{
"name": "chat",
"alias": "chat",
"params": {
"id": {
"##provide": {
"provider": "message",
"key": "parent_chat"
}
}
},
"confidentialData": false
}
]
},
"conditions": [],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "newMessage",
"eventData": {
"message": {
"##provide": {
"provider": "message",
"key": "message"
}
},
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SUB) Message Status Changed
Sends a webhook for every outgoing message status change — from Sent to Delivered, from Delivered to Seen, etc. Useful for tracking read receipts and delivery analytics in external systems.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the status update including the current status code, timestamp, and message ID.
{
"version": "v1",
"name": "(SUB) Messages Status Changed",
"description": "Sends a webhook for all outgoing messages status changes (e.g., from \"Delivered\" to \"Seen\")",
"triggerEvents": [
"app.message.statusRequest"
],
"loaders": {
"beforeConditions": [
{
"name": "chat",
"alias": "chat",
"params": {
"name": {
"##provide": {
"provider": "messageStatusRequest",
"key": "chat.name"
}
},
"accountId": {
"##provide": {
"provider": "messageStatusRequest",
"key": "chat.accountId"
}
},
"idByChannel": {
"##provide": {
"provider": "messageStatusRequest",
"key": "chat.id"
}
}
},
"confidentialData": false
}
]
},
"conditions": [],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "messageStatusChanged",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
},
"messageStatus": "%messageStatusRequest:status%",
"error": "%messageStatusRequest:error%",
"timestamp": "%messageStatusRequest:timestamp%",
"externalId": "%messageStatusRequest:ids%"
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SUB) Chat Resolved by Bot
Sends a webhook when a chat is resolved automatically by the bot — no human agent involved (chat.agent.uid is null/missing). Use this to track bot deflection rates, drive analytics on bot-only journeys, or trigger external follow-ups for unattended conversations.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the chat payload when the bot resolves a chat.
{
"version": "v1",
"name": "(SUB) Chat Resolved by Bot",
"description": "Sends a webhook when a chat is resolved automatically by the bot (no human agent assigned).",
"triggerEvents": [
"domain.chat.resolved"
],
"loaders": {},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "not exists(agent.uid)",
"value": "%chat:chat%"
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "chatResolvedByBot",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SLA) Set SLA Label For all Records
On a cron schedule, scans all stored SLA records and adds the sla label to chats whose timer exceeded the threshold (default: 20 minutes). This is the enforcement step that marks chats as breached/late.
- Cron Schedulerequired
Nihul → Customer ConfigAdd this entry to the customer config
cron.schedulearray in Nihul:{ "task": "ScenariosCustomTriggerCronTask", "expr": "*/10 * * * *", "params": { "name": "sla_scenario" } }The scenario uses the cron name to filter executions, so
params.namemust match exactly. - Cron Namerequired
conditions[0][0].params.compareTo (cron.name)Must match the cron
params.nameregistered in Nihul. Default in this template:sla_scenario. - SLA Thresholdrequired
conditions[0][1].params.expressionAdjust the time window by changing
now-20mto your desired threshold. Default is 20 minutes but should be set per customer — e.g.now-10m,now-30m. - Data Collection Nameoptional
loaders.beforeConditions[0].params.collectionThe data store collection used to track SLA timestamps per chat. Keep the same value across all SLA scenarios. Default:
sla_chats_collection.
{
"version": "v1.1",
"name": "(SLA) Set SLA Label For all Records",
"description": "set record for all records in store",
"triggerEvents": [
"app.scenarios.customTriggers.cron"
],
"loaders": {
"beforeConditions": [
{
"name": "listData",
"alias": "records",
"params": {
"limit": 50,
"skip": 0,
"collection": "sla_chats_collection",
"tags": []
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "compare",
"params": {
"value": "sla_scenario",
"comparison": "Equal",
"compareTo": {
"##provide": {
"provider": "cron",
"key": "name"
}
}
},
"confidentialData": false
},
{
"name": "filtrex",
"params": {
"expression": "not empty(record.data.chatId) and record.data.timestamp < timestamp",
"value": {
"timestamp": "%time:now-20m(\"x\")|parseInt%",
"record": {
"##provide": {
"provider": "item",
"key": "__item"
}
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "chatUpdateLabels",
"params": {
"chatId": "%item:data.chatId%",
"operation": "add",
"labels": [
"sla"
]
},
"confidentialData": false
}
],
"loops": [
{
"loop": {
"type": "foreach",
"as": "item",
"input": "%records:items%",
"confidentialData": false,
"foreachMode": "parallel",
"concurency": 5
},
"position": "beforeConditions"
}
],
"options": {
"unorderedActions": false
}
}
(SUB) Channel Health Problem Created
Sends a webhook when a new channel health problem is detected on a WhatsApp account (e.g. send/receive impairment, rate-limit warnings, account suspension). Forward to a monitoring system, on-call paging tool, or Slack/Teams to react to outages in real time. See problem object for the payload schema.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the problem payload when a new channel health issue is detected.
{
"version": "v1",
"name": "(SUB) Channel Health Problem Created",
"description": "Sends a webhook when a channel health problem is detected on a WhatsApp account.",
"triggerEvents": [
"domain.channel.health.problem.created"
],
"loaders": {},
"conditions": [],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "channelHealthProblemCreated",
"eventData": {
"problem": {
"##provide": {
"provider": "problem",
"key": "problem"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SUB) Messages with Specific Text
Sends a webhook only when an incoming message matches specific keywords. Configure the words list to trigger on exact phrases — useful for routing, escalation, or keyword-based integrations.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the matching message and chat payload.
- Keywords to matchrequired
conditions[0][1].params.expressionReplace
{{word1}},{{word2}}in the filtrex expression with the words you want to match (exact match on message text):text == "keyword1" or text == "keyword2"Add or remove
orclauses to match more or fewer keywords.
{
"version": "v1",
"name": "(SUB) Messages with Specific Text",
"description": "Sends a webhook when a new incoming message includes a specific word(s).",
"triggerEvents": [
"domain.message.created"
],
"loaders": {
"afterConditions": [
{
"name": "chat",
"alias": "chat",
"params": {
"id": {
"##provide": {
"provider": "message",
"key": "parent_chat"
}
}
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "direction == \"incoming\"",
"value": {
"##provide": {
"provider": "message",
"key": "message"
}
}
},
"confidentialData": false
},
{
"name": "filtrex",
"params": {
"expression": "text == \"{{word1}}\" or text == \"{{word2}}\"",
"value": {
"##provide": {
"provider": "message",
"key": "message"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "newMatchedMessage",
"eventData": {
"message": {
"##provide": {
"provider": "message",
"key": "message"
}
},
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
Handle Passive Marketing Chats
Runs once a day to find BULK chats from the previous day whose last message was one of the configured marketing templates. For each matching chat, assigns it to the sales department with Pending status and updates the lead status in Rapid CRM.
Designed for Rapid CRM customers using the Tyntec WhatsApp provider — see the configuration items below for the non-Tyntec variant.
- Cron Schedulerequired
Nihul → Customer ConfigAdd to the
cron.schedulearray in the customer config in Nihul:{ "task": "ScenariosCustomTriggerCronTask", "expr": "0 8 * * *", "params": { "name": "reassign-and-update-passive-bulk-chats" } }The example runs daily at 08:00 — adjust the cron expression per customer request.
- Rapid API URLrequired
actions[1].params.urlReplace the subdomain with the customer's Rapid subdomain. Example:
https://{{rapidSubdomain}}.rapid-image.net/api/import/leads/%chat:crmData.leadExternalId%Prerequisite: the chat's
crmDatamust containleadExternalId(populated when the bot creates the lead) andleadSource. Without these therequestaction silently fails — verifycrmDatais populated before enabling. - Marketing Template IDsrequired
conditions[0][1].params.expressionAsk the customer which templates should trigger this flow and update the ID list accordingly.
To match any template (no ID filtering), simplify the filtrex to:
exists(special.whatsappTyntec.template) - Sales Department IDoptional
actions[0].params.departmentIdThe department ID to assign matching chats to. Defaults to
sales. - Rapid Update Payloadoptional
actions[1].params.dataKey-value pairs to send to the Rapid API on the matched lead. Any fields the customer's Rapid API accepts — not limited to
status. - WhatsApp Provider (non-Tyntec)optional
conditions[0][1].params.expressionThis scenario is built for the Tyntec provider. For other providers, replace the filtrex expression with:
exists(special.whatsapp.template) and (special.whatsapp.template.name in ("template_name_1", "template_name_2"))Or to match any template:
exists(special.whatsapp.template)
{
"version": "v1.1",
"name": "Handle Passive Marketing Chats",
"description": "Once a day, check yesterdays chats that are still in bulk where the last template message sent fits one of the marketing messages, and assign to sales department + update lead status in Rapid",
"triggerEvents": [
"app.scenarios.customTriggers.cron"
],
"loaders": {
"beforeConditions": [
{
"name": "chatsList",
"alias": "chats",
"params": {
"limit": 1000,
"skip": 0,
"filters": [
{
"lastMessageTimestamp": {
"before": "%time:now-16h(\"x\")|parseInt%",
"after": "%time:now-41h(\"x\")|parseInt%"
},
"status": [
"BULK"
],
"channel": [],
"department": [],
"agent": [],
"labels": {
"include": [],
"exclude": []
}
}
]
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "compare",
"params": {
"comparison": "Equal",
"compareTo": "reassign-and-update-passive-bulk-chats",
"value": {
"##provide": {
"provider": "cron",
"key": "name"
}
}
},
"confidentialData": false
},
{
"name": "filtrex",
"params": {
"expression": "exists(special.whatsappTyntec.template) and (special.whatsappTyntec.template.templateId in (\"inbox_marketing_108\", \"inbox_utility_111\", \"inbox_marketing_109\", \"inbox_marketing_107\"))",
"value": {
"##provide": {
"provider": "chat",
"key": "lastMessage"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "chatAssign",
"params": {
"status": "Pending",
"departmentId": "sales",
"chatId": {
"##provide": {
"provider": "chat",
"key": "_id"
}
}
},
"confidentialData": false
},
{
"name": "request",
"params": {
"url": "https://{{rapidSubdomain}}.rapid-image.net/api/import/leads/%chat:crmData.leadExternalId%",
"method": "patch",
"json": true,
"headers": {
"Authorization": "RoAuth LeadSource=%chat:crmData.leadSource%"
},
"data": {
"status": 93
}
},
"confidentialData": false
}
],
"loops": [
{
"loop": {
"type": "foreach",
"as": "chat",
"input": {
"##provide": {
"provider": "chats",
"key": "chats"
}
},
"confidentialData": false,
"foreachMode": "parallel",
"concurency": 10
},
"position": "beforeConditions"
}
],
"options": {
"unorderedActions": true
}
}
(SUB) External Bot Disabled
Sends a webhook when externalBot is set to false on a chat — i.e. external AI/automation control was just released. Use this to close an AI session, archive context, or hand control back to your CRM/agent UI. Mirrors the trigger used by the Q-AI handoff scenarios.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the chat payload when externalBot is disabled.
{
"version": "v1",
"name": "(SUB) External Bot Disabled",
"description": "Sends a webhook when externalBot is set to false on a chat.",
"triggerEvents": [
"domain.chat.updated.externalBot",
"app.bot.chat.setExternal"
],
"loaders": {},
"conditions": [
[
{
"name": "compare",
"params": {
"comparison": "Equal",
"compareTo": false,
"value": {
"##provide": {
"provider": "chat",
"key": "externalBot"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "externalBotDisabled",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SLA) Remove Item On outgoing Message
When an agent sends an outgoing message in an active chat, clears the SLA tracking record and removes the sla label. Marks the chat as responded and resets SLA tracking until the next incoming message.
- Data Collection Nameoptional
actions[0].params.collection, loaders.beforeConditions[1].params.collectionThe data store collection used to track SLA timestamps per chat. Keep the same value across all SLA scenarios. Default:
sla_chats_collection.
{
"version": "v1",
"name": "(SLA) Remove Item On outgoing Message",
"description": "",
"triggerEvents": [
"domain.message.created"
],
"loaders": {
"beforeConditions": [
{
"name": "chat",
"alias": "chat",
"params": {
"id": {
"##provide": {
"provider": "message",
"key": "parent_chat"
}
}
},
"confidentialData": false
},
{
"name": "getData",
"alias": "record",
"params": {
"collection": "sla_chats_collection",
"key": {
"##provide": {
"provider": "message",
"key": "chatChannelInfo.id"
}
}
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "status in (1,2)",
"value": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
},
"confidentialData": false
},
{
"name": "compare",
"params": {
"value": "%message:direction%",
"comparison": "Equal",
"compareTo": "outgoing"
},
"confidentialData": false
},
{
"name": "filtrex",
"params": {
"expression": "not empty(record.data.timestamp)",
"value": {
"record": "%record:record%"
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "deleteData",
"params": {
"collection": "sla_chats_collection",
"key": {
"##provide": {
"provider": "message",
"key": "chatChannelInfo.id"
}
}
},
"confidentialData": false
},
{
"name": "chatUpdateLabels",
"params": {
"operation": "remove",
"labels": [
"sla"
],
"chatId": {
"##provide": {
"provider": "chat",
"key": "_id"
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": true
}
}
(SUB) Specific Label Added
Sends a webhook only when a specific label is added to a chat. Uses a filtrex condition that inspects the addedLabels diff so the webhook fires for additions of the target label only — other label changes (different label added, label removed) are filtered out. Use this to drive routing, alerting, or external automations keyed off a single label like vip, urgent, or escalated.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the chat and label-diff payload.
- Target Label IDrequired
conditions[0][0].params.expressionThe label ID to watch for. Replace
{{targetLabelId}}inside the filtrex expression (inArray(addedLabels, "{{targetLabelId}}")) with your actual label ID (e.g.vip,urgent). The scenario only fires when this exact label is in theaddedLabelsdiff.
{
"version": "v1",
"name": "(SUB) Specific Label Added",
"description": "Sends a webhook when a specific label is added to a chat.",
"triggerEvents": [
"domain.chat.labels"
],
"loaders": {},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "inArray(addedLabels, \"{{targetLabelId}}\")",
"value": {
"addedLabels": {
"##provide": {
"provider": "addedLabels",
"key": "labels"
}
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "chatSpecificLabelAdded",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
},
"oldLabels": {
"##provide": {
"provider": "oldLabels",
"key": "labels"
}
},
"addedLabels": {
"##provide": {
"provider": "addedLabels",
"key": "labels"
}
},
"removedLabels": {
"##provide": {
"provider": "removedLabels",
"key": "labels"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SUB) Chat Pending
Sends a webhook when a chat moves to pending status — waiting for a human agent to pick it up (e.g. after a bot handoff). Use this to alert routing tools, ticketing systems, or dashboards that a chat is ready to be claimed.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the chat payload when a chat moves to pending status.
{
"version": "v1",
"name": "(SUB) Chat Pending",
"description": "Sends a webhook when a chat moves to pending status (waiting for a human agent).",
"triggerEvents": [
"domain.chat.pending"
],
"loaders": {},
"conditions": [],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "chatPending",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SUB) New Incoming Messages
Sends a webhook POST for every new incoming customer message. Useful for CRMs, notification services, AI pipelines, or any external system that needs to react to inbound messages.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the message and chat payload on each incoming message.
{
"version": "v1",
"name": "(SUB) New Incoming Messages",
"description": "Sends a webhook for each new incoming message",
"triggerEvents": [
"domain.message.created"
],
"loaders": {
"afterConditions": [
{
"name": "chat",
"alias": "chat",
"params": {
"id": {
"##provide": {
"provider": "message",
"key": "parent_chat"
}
}
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "direction == \"incoming\"",
"value": {
"##provide": {
"provider": "message",
"key": "message"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "newIncomingMessage",
"eventData": {
"message": {
"##provide": {
"provider": "message",
"key": "message"
}
},
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
Close Service Request on Chat Resolved
When a chat is resolved in Texter, closes the linked Salesforce Service Request by updating its status field. Only fires if the chat has an associated CRM opportunity ID. Pairs well with Update Service Request on Chat Taken.
- Salesforce Instance URLrequired
actions[0].params.urlYour Salesforce instance URL with the object type. Replace
{{yourOrg}}and{{YourObject__c}}with your actual Salesforce setup. - Closed Status Valuerequired
actions[0].params.dataThe field name and value that marks the record as closed in Salesforce, e.g.
{ "Status__c": "Closed" }.
{
"version": "v1",
"name": "Close Service Request on resolve chat",
"triggerEvents": [
"domain.chat.resolved"
],
"loaders": {
"beforeConditions": [],
"afterConditions": [
{
"name": "oauth",
"alias": "oauth",
"params": {
"service": "salesforce"
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "exists(crmData.opportunityid)",
"value": "%chat:chat%"
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "request",
"params": {
"url": "https://{{yourOrg}}.my.salesforce.com/services/data/v62.0/sobjects/{{YourObject__c}}/%chat:crmData.opportunityid%",
"method": "patch",
"keepResponse": true,
"json": true,
"headers": {
"Authorization": "Bearer %oauth:accessToken%"
},
"data": {
"Status__c": "Closed"
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SUB) Chat Resolved by Agent
Sends a webhook when a chat is resolved by a human agent. Uses a filter on chat.agent.uid so only agent-driven resolutions fire — bot/auto-resolve events are excluded. Use this to log handling time, attribute resolutions, or trigger post-conversation surveys only for human interactions.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the chat payload when an agent resolves a chat.
{
"version": "v1",
"name": "(SUB) Chat Resolved by Agent",
"description": "Sends a webhook when a chat is resolved by a human agent.",
"triggerEvents": [
"domain.chat.resolved"
],
"loaders": {},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "exists(agent.uid)",
"value": "%chat:chat%"
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "chatResolvedByAgent",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SLA) Remove Item On Resolve Chat
When a chat is resolved, clears the SLA tracking record and removes the sla label (if present). Keeps the data store clean and ensures resolved chats are not shown as SLA-breached.
- Data Collection Nameoptional
actions[1].params.collection, loaders.beforeConditions[0].params.collectionThe data store collection used to track SLA timestamps per chat. Keep the same value across all SLA scenarios. Default:
sla_chats_collection.
{
"version": "v1",
"name": "(SLA) Remove Item On Resolve Chat",
"description": "",
"triggerEvents": [
"domain.chat.resolved"
],
"loaders": {
"beforeConditions": [
{
"name": "getData",
"alias": "record",
"params": {
"collection": "sla_chats_collection",
"key": {
"##provide": {
"provider": "chat",
"key": "channelInfo.id"
}
}
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "not empty(record.data.timestamp)",
"value": {
"record": "%record:record%"
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "chatUpdateLabels",
"params": {
"operation": "remove",
"labels": [
"sla"
],
"chatId": {
"##provide": {
"provider": "chat",
"key": "_id"
}
}
},
"confidentialData": false
},
{
"name": "deleteData",
"params": {
"collection": "sla_chats_collection",
"key": {
"##provide": {
"provider": "chat",
"key": "channelInfo.id"
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": true
}
}
Away-hours auto-reply
Auto-replies to customers who message outside business hours. On every incoming message to a taken (assigned) chat, if the time is outside the configured hours (default: Sun-Thu 08:00 to 16:15, closed all day Friday and Saturday) and no auto-reply has gone to this chat in the last hour, it sends a closed-office message and stores a 1-hour record (via setData) so the customer is not pinged again on every follow-up.
- Message Textoptional
actions[0].params.message.textThe closed-office reply. A complete Hebrew default is included as the prime example. If you change the hours gate below, update the hours quoted in this text too: the default text says 08:30 to 16:00 while the gate opens 08:00 to 16:15, so align both to your real hours.
- Business Hours Gateoptional
conditions[0][2].params.expressionA
filtrexexpression that decides what counts as outside hours.weekdayis the Luxon ISO weekday (1=Mon ... 7=Sun) andhhmmis the 24h time as an integer (e.g.1615= 16:15). Default: closed all day onweekday == 5(Fri) andweekday == 6(Sat), and on Sun-Thu whenhhmm < 800orhhmm >= 1615. Adjust to your business days and hours. - Re-send Throttle (TTL)optional
actions[1].params.expiresIn, actions[1].params.expiresInUnitHow long to suppress repeat auto-replies to the same chat. Default: 1 hour. Units:
minutes,hours, ordays. After each send a record is written to the data store, and the dedup condition skips sending while that record still exists. - Chat Status Gateoptional
conditions[0][1].params.compareToWhich chat status triggers the reply. Default:
2(taken/assigned), so only chats already handled by an agent get the away message. Change the value to target a different status, or replace thiscomparecondition with afiltrexlikestatus in (1,2)to cover more than one.
{
"version": "v1",
"name": "Away-hours auto-reply",
"description": "On every incoming message to a taken (assigned) chat, if outside business hours (Sun-Thu before 08:00 or from 16:15, or all day Fri/Sat) and no auto-reply was sent to this chat in the last hour, send the closed-office message and remember it for 1 hour.",
"triggerEvents": [
"domain.message.created"
],
"loaders": {
"beforeConditions": [
{
"name": "chat",
"alias": "chat",
"params": {
"id": {
"##provide": {
"provider": "message",
"key": "parent_chat"
}
}
},
"confidentialData": false
},
{
"name": "getData",
"alias": "awayRecord",
"params": {
"collection": "away_hours_auto_reply",
"key": "%message:parent_chat%_%message:chatChannelInfo.id%"
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "compare",
"params": {
"value": "%message:direction%",
"comparison": "Equal",
"compareTo": "incoming"
},
"confidentialData": false
},
{
"name": "compare",
"params": {
"value": "%chat:status%",
"comparison": "Equal",
"compareTo": 2
},
"confidentialData": false
},
{
"name": "filtrex",
"params": {
"expression": "(weekday == 5 or weekday == 6) or ((weekday == 7 or weekday <= 4) and (hhmm < 800 or hhmm >= 1615))",
"value": {
"weekday": "%time:now(\"c\",\"ist\")|parseInt%",
"hhmm": "%time:now(\"HHmm\",\"ist\")|parseInt%"
}
},
"confidentialData": false
},
{
"name": "filtrex",
"params": {
"expression": "not exists(rec.data)",
"value": {
"rec": "%awayRecord:awayRecord%"
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "sendMessage",
"params": {
"chat": {
"name": "%message:chatChannelInfo.name%",
"accountId": "%message:chatChannelInfo.accountId%",
"id": "%message:chatChannelInfo.id%"
},
"message": {
"type": "text",
"text": "היי,\n\nמשרדינו סגורים כעת. \n\nשעות המענה של המשרד הן בימים א-ה בין השעות 8:30 עד 16:00.\n\nניתן להשאיר לנו כאן הודעה ונעשה כל מאמץ לחזור אלייך בהקדם 🙏🏼"
}
},
"confidentialData": false
},
{
"name": "setData",
"params": {
"collection": "away_hours_auto_reply",
"key": "%message:parent_chat%_%message:chatChannelInfo.id%",
"data": {
"sentAt": "%time:now(\"iso\",\"ist\")%"
},
"expiresIn": 1,
"expiresInUnit": "hours"
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
Update Service Request on Chat Taken
When an agent takes a chat in Texter, updates the OwnerId of the linked Salesforce Service Request to match the agent's CRM ID. Requires the chat to have a CRM opportunity ID set via the Salesforce adapter. Uses OAuth for authentication.
- Salesforce Instance URLrequired
actions[0].params.urlYour Salesforce instance URL with the object type path. Replace
{{yourOrg}}(e.g.acme.my.salesforce.com) and{{YourObject__c}}with your actual Salesforce setup. - CRM Opportunity Fieldoptional
conditions[0][0].params.expressionThe dot-notation path to the CRM field holding the linked service request ID. Default:
crmData.opportunityid.
{
"version": "v1",
"name": "Update Service Request on chat taken",
"description": "When agent takes the chat in Texter, update the Owner ID in the service request in Salesforce",
"triggerEvents": [
"domain.chat.assigned"
],
"loaders": {
"beforeConditions": [],
"afterConditions": [
{
"name": "oauth",
"alias": "oauth",
"params": {
"service": "salesforce"
},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "exists(crmData.opportunityid)",
"value": "%chat:chat%"
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "request",
"params": {
"url": "https://{{yourOrg}}.my.salesforce.com/services/data/v62.0/sobjects/{{YourObject__c}}/%chat:crmData.opportunityid%",
"method": "patch",
"keepResponse": true,
"json": true,
"headers": {
"Authorization": "Bearer %oauth:accessToken%"
},
"data": {
"OwnerId": "%agent:crmId%"
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SUB) Chat Unsubscribed
Sends a webhook when a chat opts out of template messages — for example when the customer replies with an opt-out keyword such as "הסר". Use this to sync suppression lists or update consent in external systems.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the chat payload when the unsubscribe event fires.
{
"version": "v1",
"name": "(SUB) Chat Unsubscribed",
"description": "Sends a webhook when a chat unsubscribed from receiving template messages (e.g., by replying \"הסר\")",
"triggerEvents": [
"domain.chat.unsubscribed"
],
"loaders": {},
"conditions": [],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "chatUnsubscribed",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
(SUB) Chat Subscribed
Sends a webhook when a chat subscribes or opts back in to receiving template messages. Use this to refresh consent or resume outreach in external systems.
- Webhook URLrequired
actions[0].params.urlYour endpoint that will receive the chat payload when the subscribe event fires.
{
"version": "v1",
"name": "(SUB) Chat Subscribed",
"description": "Sends a webhook when a chat subscribes or opts back in to receiving template messages.",
"triggerEvents": [
"domain.chat.subscribed"
],
"loaders": {},
"conditions": [],
"actions": [
{
"name": "request",
"params": {
"url": "{{yourWebhookURL}}",
"method": "post",
"json": true,
"data": {
"eventName": "chatSubscribed",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
Q-AI: Disable External Bot After Template Message
Part of the Q-AI suite. If AI mode is active and a template message is sent (chat moves to bulk status), automatically disables externalBot and notifies the AI service with setExternalFalse. Prevents AI from handling a chat that was just contacted via a template.
- AI Webhook URLrequired
actions[1].params.urlYour AI service webhook that receives the
setExternalFalseevent.
{
"version": "v1",
"name": "Q-AI Disable External Bot after Template Message",
"description": "If external bot is true and a template message is sent (chat status = 'bulk'), set external bot to false and close AI session",
"triggerEvents": [
"domain.message.created"
],
"loaders": {
"beforeConditions": [
{
"name": "chat",
"alias": "chat",
"params": {
"id": {
"##provide": {
"provider": "message",
"key": "parent_chat"
}
}
},
"confidentialData": false
}
],
"afterConditions": [
{
"name": "environment",
"alias": "env",
"params": {},
"confidentialData": false
}
]
},
"conditions": [
[
{
"name": "filtrex",
"params": {
"expression": "exists(externalBot) and externalBot",
"value": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
},
"confidentialData": false
},
{
"name": "compare",
"params": {
"comparison": "Equal",
"compareTo": 4,
"value": {
"##provide": {
"provider": "chat",
"key": "status"
}
}
},
"confidentialData": false
}
]
],
"actions": [
{
"name": "chatUpdateExternalBot",
"params": {
"externalBot": false,
"chatId": {
"##provide": {
"provider": "chat",
"key": "_id"
}
}
},
"confidentialData": false
},
{
"name": "request",
"params": {
"url": "{{yourAIWebhookURL}}",
"method": "post",
"json": true,
"data": {
"projectId": "%env:projectId|replace(\"texter-\", \"\")%",
"eventName": "setExternalFalse",
"eventData": {
"chat": {
"##provide": {
"provider": "chat",
"key": "chat"
}
}
}
}
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}
Alert New Account Issue
Sends a formatted HTML email alert whenever a WhatsApp account health problem is detected. Includes the error code, severity, affected functionality, and remediation instructions. Useful for proactive monitoring without needing a separate alerting system.
- SMTP Emailrequired
actions[0].params.transport.auth.user, actions[0].params.from, actions[0].params.replyToThe Gmail address used to send the alert. Replace all three occurrences of
{{yourSmtpEmail}}. - SMTP App Passwordrequired
actions[0].params.transport.auth.passGmail App Password (not your account password). Generate one at Google Account → Security → App Passwords.
- Recipient Emailrequired
actions[0].params.toThe email address that should receive the alert.
{
"version": "v1",
"name": "Alert New Account Issue",
"description": "alert by mail when a new account error occurs on ",
"triggerEvents": [
"domain.channel.health.problem.created"
],
"loaders": {},
"conditions": [],
"actions": [
{
"name": "sendEmail",
"params": {
"cc": "",
"bcc": "",
"transport": {
"auth": {
"user": "{{yourSmtpEmail}}",
"pass": "{{yourSmtpAppPassword}}"
},
"service": "gmail"
},
"replyTo": "{{yourSmtpEmail}}",
"priority": "",
"textEncoding": "",
"from": "{{yourSmtpEmail}}",
"sender": "Texterchat",
"subject": "עדכון על בעיה שאותרה בחשבון הווטסאפ שלך",
"to": "{{recipientEmail}}",
"html": [
"<!doctype html>",
"<html lang=\"he\" dir=\"rtl\">",
"<head>",
" <meta charset=\"utf-8\">",
" <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">",
" <title>Texter — התראת WhatsApp</title>",
" <style>",
" body {",
" margin: 0;",
" padding: 0;",
" background-color: #f4f6f8;",
" font-family: \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;",
" direction: rtl;",
" }",
" table { border-collapse: collapse; }",
" .container {",
" width: 100%;",
" max-width: 640px;",
" margin: 0 auto;",
" background: #ffffff;",
" border-radius: 6px;",
" overflow: hidden;",
" box-shadow: 0 1px 4px rgba(0,0,0,0.06);",
" }",
" .header {",
" background: #0b67ff;",
" color: #ffffff;",
" padding: 16px 20px;",
" font-size: 17px;",
" font-weight: 600;",
" text-align: right;",
" }",
" .content {",
" padding: 20px;",
" color: #0f1724;",
" font-size: 15px;",
" line-height: 1.5;",
" text-align: right;",
" }",
" .kv { margin: 6px 0; }",
" .error-box {",
" background:#fff6f6;",
" border:1px solid #ffd6d6;",
"padding:10px;",
" border-radius:4px;",
" margin:12px 0;",
" color:#7a1b1b;",
" font-size:14px;",
" }",
" .footer {",
" padding:14px 20px;",
" font-size:13px;",
" color:#68707a;",
" background:#fbfcfd;",
" text-align: right;",
" }",
" </style>",
"</head>",
"<body>",
" <table width=\\\"100%\\\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">",
" <tr>",
" <td align=\"center\" style=\"padding:16px;\">",
" <table class=\"container\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\">",
" <!-- Header -->",
" <tr>",
" <td class=\"header\">התראת חשבון WhatsApp</td>",
" </tr>",
" <!-- Content -->",
" <tr>",
" <td class=\"content\">",
" <p><strong>נושא:</strong> התראה: זוהתה בעיה בחשבון ה-WhatsApp שלך</p>",
" <p>שלום,</p>",
" <p>זיהינו בעיה בחשבון ה-WhatsApp שלך. פרטי התקלה:</p>",
" <div class=\"kv\"><b>מספר חשבון:</b> %problem:accountId%</div>",
" <div class=\"kv\"><b>תאריך:</b> %problem:startedAt%</div>",
" <div class=\"kv\"><b>קוד שגיאה:</b> %problem:name%</div>",
" <div class=\"kv\"><b>חומרה:</b> %problem:severity%</div>",
" <div class=\"kv\"><b>סטטוס תפקוד:</b></div>",
" <div style=\"margin-right:12px;\">",
" <div class=\"kv\">• שליחת הודעות: %problem:impairedFunctionality|hbTpl(\"{{#when true 'eq' send}}מושבת{{else}}תקין{{/when}}\")%</div>",
" <div class=\"kv\">• קבלת הודעות: %problem:impairedFunctionality|hbTpl(\"{{#when true 'eq' receive}}מושבת{{else}}תקין{{/when}}\")%</div>",
" </div>",
" <div style=\"margin-top:12px;\">",
" <div><b>הודעת שגיאה:</b></div>",
" <div class=\"error-box\">%problem:message%</div>",
" </div>",
" ",
" <div style=\"margin-top:8px;\">",
" <div><b>הנחיות לטיפול:</b></div>",
" <div>%problem:instructions%</div>",
" </div>",
" ",
" <p style=\"margin-top:16px;\">",
" אנא בדוק את החשבון שלך ",
" <a href=\"https://business.facebook.com/\" target=\"_blank\">במנהל החשבונות של Meta</a> ",
" ונסה לפתור את הבעיה בהתאם להנחיות למעלה. ",
" במידה ואתה זקוק לעזרתנו, צוות התמיכה שלנו ישמח לסייע לך דרך WhatsApp: ",
" <a href=\"{whatsapp_support_link}\" target=\"_blank\">https://wa.me/972586640430</a>.",
" </p>",
" ",
" <p>בברכה,<br><strong>צוות Texter</strong></p>",
" ",
" <div style=\"margin-bottom: 20px;\">",
" <img src=\"https://texterchat.com/wp-content/uploads/2021/04/texter-logo.png\" alt=\"Texter Logo\" style=\"height: 50px;\" />",
" </div>",
" </td>",
" </tr>",
" <!-- Footer -->",
" <tr>",
" <td class=\"footer\">",
" מייל זה מכיל מידע חשוב לגבי החשבון שלך. אם קיבלת הודעה זו בטעות, אנא צור קשר עם התמיכה.",
" </td>",
" </tr>",
" </table>",
" </td>",
" </tr>",
" </table>",
"</body>",
"</html>"
],
"attachments": []
},
"confidentialData": false
}
],
"options": {
"unorderedActions": false
}
}