19 scenarios
Q-AI: End AI Session & Run Bot
Part of the Q-AI suite. When external bot is disabled and the chat is in "with bot" status, resumes the Texter bot from a specified node and notifies the AI service to close the session. 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 "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
}
}
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 value in the example is "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
}
}
(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
}
}
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
}
}
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 the external bot flag and notifies the AI service to end the session.
- AI Webhook URLrequired
actions[1].params.urlYour 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
}
}
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 the external bot and notifies the AI service. 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 "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
}
}
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 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
}
}
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 in 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.resolved"
],
"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
}
}
(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: Turn On AI Bot
Part of the Q-AI suite. When external bot is enabled on a chat, forwards the full chat object and current session messages to your AI service. This is the entry point of the AI handoff flow.
- AI Webhook URLrequired
actions[0].params.urlYour AI service webhook that receives 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
}
}
Q-AI: Forward Incoming Message to AI
Part of the Q-AI suite. When a new incoming message arrives and external bot is active, forwards the message and chat objects to the AI service for processing.
- AI Webhook URLrequired
actions[0].params.urlYour AI service webhook that receives each incoming 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
}
}
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 the external bot flag and notifies the AI service. 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 "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
}
}
Update Service Request on Chat Taken
When an agent takes a chat in Texter, updates the Owner ID 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 the domain (e.g. "yourorg.my.salesforce.com") and object type 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) 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
}
}
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. The task runs on a custom cron schedule configured per customer in Nihul, sending up to 10 messages concurrently.
- Cron Schedulerequired
Nihul → Customer ConfigAdd to the 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.
- 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 to send. Can be customized per customer.
{
"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
}
}
(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
}
}
(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). Add or remove conditions 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
}
}
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 the domain and object name 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) 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
}
}