Skip to main content

Scenario Marketplace

Browse ready-made automations. Click any scenario to see what it does, what you need to configure, and copy the JSON directly into Texter.

Filter:

42 scenarios

External Bot ChangedSend Webhook

(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.

on-external-botwebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
Chat AssignedSet Data Item

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).

on-assigndata-storage
  • Data Collection Nameoptional
    actions[0].params.collection

    The 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.expiresInUnit

    How long each record lives before expiring. Default: 1 day. Units: minutes, hours, or days. 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.data

    The 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
}
}
Chat ResolvedSend Webhook

(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.

on-resolvewebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
Chat PendingSet Data Item

(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.

slaon-pendingdata-storage
  • Data Collection Nameoptional
    actions[0].params.collection, loaders.beforeConditions[0].params.collection

    The 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.expiresInUnit

    How 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
}
}
Chat AssignedSend Webhook

(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.

on-assignwebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
Message CreatedSet Data Item

(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.

slaon-messagedata-storage
  • Data Collection Nameoptional
    actions[0].params.collection, loaders.beforeConditions[1].params.collection

    The 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.expiresInUnit

    How 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
}
}
Chat Labels UpdatedSend Webhook

(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.

on-labelswebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
External Bot ChangedSend Webhook

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.

on-external-botwebhookai-bot
  • AI Webhook URLrequired
    actions[0].params.url

    Your AI service webhook that receives the setExternalTrue event 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
}
}
Message CreatedSend Webhook

(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.

on-messagewebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
Message CreatedSend Webhook

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.

on-messagewebhookai-bot
  • AI Webhook URLrequired
    actions[0].params.url

    Your AI service webhook that receives the newIncomingMessage payload 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
}
}
Channel Health RecoveredSend Webhook

(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.

on-channel-eventwebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
Chat ResolvedSet External BotSend Webhook

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.

on-resolvewebhookai-bot
  • AI Webhook URLrequired
    actions[1].params.url

    Your AI service webhook that receives the setExternalFalse event 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
}
}
ScheduledSend Message

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.

scheduledsend-message
  • Cron Schedulerequired
    Nihul → Customer Config

    Add to the cron.schedule array 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.after

    How 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.text

    The 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
}
}
External Bot ChangedRun BotSend Webhook

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.

on-external-botwebhookrun-botai-bot
  • Bot Resume Noderequired
    actions[0].params.nodeName

    The 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.url

    Your AI service webhook that receives the setExternalFalse event 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
}
}
Chat PendingSet External BotSend Webhook

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.

on-pendingwebhookai-bot
  • AI Webhook URLrequired
    actions[1].params.url

    Your AI service webhook that receives the setExternalFalse event 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
}
}
Chat AssignedSet External BotSend Webhook

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.

on-assignwebhookai-bot
  • AI Webhook URLrequired
    actions[1].params.url

    Your AI service webhook that receives the setExternalFalse event 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
}
}
Chat AssignedSend Message

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.

on-assignsend-message
  • Message Textrequired
    actions[0].params.message.text

    The 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
}
}
Message Status UpdateSend Webhook

(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.

on-message-status-changewebhooksubscriptionfailed-message
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
Message Status UpdateUpdate Labels

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.

on-message-status-changeadd-labelfailed-message
  • 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
}
}
Chat ResolvedRun Bot

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.

on-resolverun-bot
  • Bot Resume Noderequired
    actions[0].params.nodeName

    The 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
}
}
Message CreatedAssign Chat

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.

on-messageassign-chat
  • Agent User IDrequired
    actions[0].params.agent

    The 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
}
}
Message CreatedSend Webhook

(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.

on-messagewebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
Message Status UpdateSend Webhook

(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.

on-message-status-changewebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
Chat ResolvedSend Webhook

(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.

on-resolvewebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
ScheduledUpdate Labels

(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.

slascheduledadd-labeldata-storage
  • Cron Schedulerequired
    Nihul → Customer Config

    Add this entry to the customer config cron.schedule array in Nihul:

    {  
      "task": "ScenariosCustomTriggerCronTask",  
      "expr": "*/10 * * * *",  
      "params": { "name": "sla_scenario" }  
    }  
    

    The scenario uses the cron name to filter executions, so params.name must match exactly.

  • Cron Namerequired
    conditions[0][0].params.compareTo (cron.name)

    Must match the cron params.name registered in Nihul. Default in this template: sla_scenario.

  • SLA Thresholdrequired
    conditions[0][1].params.expression

    Adjust the time window by changing now-20m to 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.collection

    The 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
}
}
Channel Health AlertSend Webhook

(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.

on-channel-eventwebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
Message CreatedSend Webhook

(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.

on-messagewebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your endpoint that will receive the matching message and chat payload.

  • Keywords to matchrequired
    conditions[0][1].params.expression

    Replace {{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 or clauses 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
}
}
ScheduledAssign ChatSend Webhook

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.

scheduledassign-chatcrm-updatewebhookrapid
  • Cron Schedulerequired
    Nihul → Customer Config

    Add to the cron.schedule array 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.url

    Replace the subdomain with the customer's Rapid subdomain. Example:

    https://{{rapidSubdomain}}.rapid-image.net/api/import/leads/%chat:crmData.leadExternalId%  
    

    Prerequisite: the chat's crmData must contain leadExternalId (populated when the bot creates the lead) and leadSource. Without these the request action silently fails — verify crmData is populated before enabling.

  • Marketing Template IDsrequired
    conditions[0][1].params.expression

    Ask 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.departmentId

    The department ID to assign matching chats to. Defaults to sales.

  • Rapid Update Payloadoptional
    actions[1].params.data

    Key-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.expression

    This 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
}
}
External Bot ChangedSend Webhook

(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.

on-external-botwebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
Message CreatedDelete Data ItemUpdate Labels

(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.

slaon-messageadd-labeldata-storage
  • Data Collection Nameoptional
    actions[0].params.collection, loaders.beforeConditions[1].params.collection

    The 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
}
}
Chat Labels UpdatedSend Webhook

(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.

on-labelswebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your endpoint that will receive the chat and label-diff payload.

  • Target Label IDrequired
    conditions[0][0].params.expression

    The 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 the addedLabels diff.

{
"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
}
}
Chat PendingSend Webhook

(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.

on-pendingwebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
Message CreatedSend Webhook

(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.

on-messagewebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
Chat ResolvedSend Webhook

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.

on-resolvecrm-updatesalesforce
  • Salesforce Instance URLrequired
    actions[0].params.url

    Your Salesforce instance URL with the object type. Replace {{yourOrg}} and {{YourObject__c}} with your actual Salesforce setup.

  • Closed Status Valuerequired
    actions[0].params.data

    The 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
}
}
Chat ResolvedSend Webhook

(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.

on-resolvewebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
Chat ResolvedUpdate LabelsDelete Data Item

(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.

slaon-resolveadd-labeldata-storage
  • Data Collection Nameoptional
    actions[1].params.collection, loaders.beforeConditions[0].params.collection

    The 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
}
}
Message CreatedSend MessageSet Data Item

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.

on-messagesend-messagedata-storage
  • Message Textoptional
    actions[0].params.message.text

    The 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.expression

    A filtrex expression that decides what counts as outside hours. weekday is the Luxon ISO weekday (1=Mon ... 7=Sun) and hhmm is the 24h time as an integer (e.g. 1615 = 16:15). Default: closed all day on weekday == 5 (Fri) and weekday == 6 (Sat), and on Sun-Thu when hhmm < 800 or hhmm >= 1615. Adjust to your business days and hours.

  • Re-send Throttle (TTL)optional
    actions[1].params.expiresIn, actions[1].params.expiresInUnit

    How long to suppress repeat auto-replies to the same chat. Default: 1 hour. Units: minutes, hours, or days. 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.compareTo

    Which 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 this compare condition with a filtrex like status 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
}
}
Chat AssignedSend Webhook

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.

on-assigncrm-updatesalesforce
  • Salesforce Instance URLrequired
    actions[0].params.url

    Your 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.expression

    The 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
}
}
Chat UnsubscribedSend Webhook

(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.

on-unsubscribewebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
Chat SubscribedSend Webhook

(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.

on-subscribewebhooksubscription
  • Webhook URLrequired
    actions[0].params.url

    Your 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
}
}
Message CreatedSet External BotSend Webhook

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.

on-messagewebhookai-bot
  • AI Webhook URLrequired
    actions[1].params.url

    Your AI service webhook that receives the setExternalFalse event.

{
"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
}
}
Channel Health AlertSend Email

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.

on-channel-eventsend-email
  • SMTP Emailrequired
    actions[0].params.transport.auth.user, actions[0].params.from, actions[0].params.replyTo

    The Gmail address used to send the alert. Replace all three occurrences of {{yourSmtpEmail}}.

  • SMTP App Passwordrequired
    actions[0].params.transport.auth.pass

    Gmail App Password (not your account password). Generate one at Google Account → Security → App Passwords.

  • Recipient Emailrequired
    actions[0].params.to

    The 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
}
}