SC ss-comms

Channels

loading...

Send text message

Send template

Message templates

loading...

Quick Sends

Pre-built messages agents fire in one tap. Pick a template, set the creative and preset values once — agents just choose it and the customer name auto-fills.

loading...
loading...
Drop files to upload

Import Contacts

Paste or upload a CSV of your customer list. Format: phone,name (one per line). Indian 10-digit numbers auto-prefix +91.

New Campaign

Broadcast a Quick Send to your contacts. Customer names auto-fill per recipient.

Only message contacts who opted in. Sending to cold lists can hurt your WhatsApp quality rating and get the number flagged.

Drip Sequences — multi-stage scheduled sends

A drip sequence fires multiple stages over days. For example: a welcome message on day 1, a follow-up on day 3, a final nudge on day 7. Each stage is an approved template (the customer's 24h window will be closed for later stages).

loading...

History

loading...

Automations

Auto-reply rules: when a customer's message matches a trigger, ss-comms fires an action automatically. Rules pause for 30 min after an agent replies, so the bot never talks over your team. Evaluated top to bottom — first match wins.

loading...

Activity log

ss-comms architecture

How the parts fit together. Read top-to-bottom on first visit; jump via the table of contents after.
Doc version

Contents

  1. The big picture — one diagram of everything
  2. Channels: customer-facing vs internal
  3. WhatsApp specifics — windows, templates, why so much machinery
  4. Telegram specifics — internal notifications
  5. Functional inboxes (Sales / Service / Hiring / ...)
  6. Notification engine
  7. Data model summary
  8. Decision flowcharts — common admin questions

1. The big picture

ss-comms is a single Node.js process on the VPS that brokers between external messaging platforms (Meta WhatsApp today, Telegram tomorrow) and the people who run the business (admins via this dashboard, agents via the inbox UI or mobile app, external systems via webhooks).

flowchart LR subgraph Customers["Customers"] direction TB PhoneWA["📱 WhatsApp"] end subgraph External["External systems"] direction TB Tally["Tally"] ArgonSR["Argon SR"] Other["Other apps"] end subgraph SSComms["ss-comms gateway (VPS)"] direction TB NodeApp["Node.js / Express"] SQLite[("SQLite DB")] Files[("Files on disk")] NodeApp --- SQLite NodeApp --- Files end subgraph Staff["Staff"] direction TB Admin["👤 Admin (this dashboard)"] Agent["👤 Agent (inbox / mobile app)"] TG["📨 Telegram (notifications — v1.44)"] end PhoneWA <-->|Cloud API + webhooks| NodeApp External -->|webhooks fire| NodeApp NodeApp -->|admin pages| Admin NodeApp <-->|inbox API| Agent NodeApp -.->|alerts| TG

Solid arrows = bidirectional message traffic (customer conversations, agent replies). Dotted arrows = one-way notifications (system alerts). The Node process is the only thing running — no Docker, no separate queue worker. Everything's in one place for ease of debugging.

2. Channels: customer-facing vs internal

A "channel" is a transport for messages. ss-comms has two categories of channels and they behave differently — keeping them mentally separate is the first step to understanding why things work the way they do.

📞 Customer-facing
Today: WhatsApp. Two-way conversations with customers. Every message becomes a row in messages; conversations land in the inbox. Strict rules from Meta (24h window, templates, quality rating). High operational cost per send.
🔔 Internal (staff-only)
Tomorrow: Telegram. One-way alerts FROM ss-comms TO staff. No customer ever sees these. Used for "new lead arrived", "send failed", "quality rating dropped". No conversation history stored — the messages live in Telegram itself.

Key consequence: customers will never message you on Telegram, and your staff will never reply to customers from Telegram. If you need to reply to a customer, open the inbox UI. Telegram is read-only for customer matters.

3. WhatsApp specifics

The 24-hour window rule

Meta's most important constraint: you can free-text-reply to a customer ONLY within 24 hours of their last message to you. After that, only pre-approved templates work.

flowchart LR A["Customer messages you"] --> B["24h window OPEN"] B -->|Reply with anything
(text, image, free-form)| C["Window stays open for 24h
from last customer message"] B -.->|24h passes with no inbound| D["Window CLOSED"] D -->|Want to reach out?| E["Must use approved template"] E --> F["Customer responds → window reopens"] F --> B

Why we have webhooks + Quick Sends + Campaigns + Drips

Each maps to a different real-world need within Meta's rules:

Tool Used by Purpose
WebhooksExternal systemsArgon SR fires "service booking made" → ss-comms sends the customer a confirmation template automatically
Quick SendsAgents in the inboxAgent picks a curated template from a dropdown to reply to a customer — used most when the 24h window is closed
CampaignsAdmins (one-shot blast)"Send Diwali greeting template to all 1,200 customers tagged Sales" — single point-in-time send
DripsAdmins (scheduled sequence)"After a customer takes a test drive: send a thank-you on day 1, brochure on day 3, finance offer on day 7" — multi-step over time

Quality rating + common failures

Meta scores each business number 1-10. Drops if customers block you, mark spam, or report. A low score throttles your sends per recipient. Some common error codes and what they mean:

CodeMeaningWhat to do
131026Recipient unreachable (no WA / blocked / stale account)No fix; suppress the number after repeats
13104724h window closed — used free textUse a template instead
131049Quality-throttle (Meta deliberately not delivering)Improve quality rating, space out sends
132012Template parameter mismatchFix the webhook/QS payload mapping

The apology workflow (out-of-window mitigation)

The Cloud API has NO message recall/delete. Once a wrong message is sent, the customer has it. The only honest mitigation: send an apology. If the window's open, free-text apology; if closed, the configured apology template. ss-comms logs the link between original + apology so a supervisor can see what happened.

4. Telegram specifics — internal notifications, staff-only

Telegram fills the gap WhatsApp leaves: low-cost staff alerts that don't compete for customer-facing message slots. One bot, one supergroup, multiple topics inside the group — each topic corresponds to a functional inbox.

flowchart LR SS["ss-comms"] -->|posts to topic| TG["Telegram supergroup"] TG --> T1["📌 Sales topic"] TG --> T2["📌 Service topic"] TG --> T3["📌 Hiring topic"] TG --> T4["📌 Admin alerts topic"] T1 -->|👀| Agent1["Sales staff"] T2 -->|👀| Agent2["Service staff"] T3 -->|👀| Agent3["HR staff"] T4 -->|👀| Adm["Admins only"]

What Telegram CAN do that WhatsApp can't

  • Edit/delete bot messages in-place — useful for "claim this lead" buttons that update after someone clicks
  • No per-message cost or quality rating — send as much as you want
  • Native topic muting per agent (each person silences what they don't need)
  • Inline buttons that trigger commands without typing

What Telegram CAN'T do

  • Reach customers (they're not in your Telegram group)
  • Replace WhatsApp templates or webhooks
  • Provide delivery receipts the way WhatsApp does (Telegram considers a message delivered if it lands in the group; what users do with it is opaque)

5. Functional inboxes (Sales / Service / Hiring / ...)

One WhatsApp number, multiple business buckets. Each conversation belongs to ONE inbox (or Triage if unclassified). The inbox is set at the first touchpoint (webhook fire / Quick Send) and stable thereafter unless an admin moves it.

flowchart TB Cust["📱 Customer messages you"] --> Q{"First touchpoint?"} Q -->|via Sales webhook| S["app = Sales"] Q -->|via Service QS| Sv["app = Service"] Q -->|cold inbound| T["app = NULL → Triage"] S --> Inbox["Inbox view → Sales tab"] Sv --> Inbox2["Inbox view → Service tab"] T --> Inbox3["Inbox view → Triage tab"] Inbox3 -.->|Agent picks 'Move to'| Sv

Agents see only the inboxes their permissions allow (Settings → Agent permissions). Triage is always visible to everyone — that's where unclassified inbound lands and someone has to route it.

6. Notification engine — routes events to channels

When a system event fires (a cold inbound arrives, a send fails, a campaign finishes), the dispatcher looks up matching rules, renders their templates with the event payload, and posts to the configured channel. Rules are admin-managed in Settings → Notification rules.

flowchart LR E["Event fires
e.g. conversation.new_cold"] --> Match{"Rules match?"} Match -->|Yes| Render["Render template
with event variables"] Match -->|No| Drop["Ignored"] Render --> Route["Route to channel(s)"] Route --> TG1["Telegram: Sales topic"] Route --> TG2["Telegram: admin alerts"] Route -.->|future| Email["Email"] Route -.->|future| SMS["SMS"]

Events currently wired

EventFires whenDefault rule
conversation.new_coldFirst inbound from an unknown contact (no prior conversation, no app tag)→ Triage topic
conversation.waiting_longScanner-driven (v1.46). Fires once per conversation per threshold crossing: 4h, 12h, 24h, 72h.→ App's topic (waitingHours ≥ 4h)
send.failedMeta returned status:failed on an outbound message→ Admin alerts
webhook.failedA webhook fire's send returned an error→ Admin alerts
campaign.finishedBlast or carousel campaign completed→ Campaign's app topic

Templates + escaping

Templates use {{name}} for substitution (auto-escaped for Telegram MarkdownV2), {{{name}}} for raw (already-formatted) content, and {{#name}}...{{/name}} for conditional blocks. All user-supplied text is escaped so a customer name like "K.S. Kumar" doesn't break the rendering.

Every fire — sent, skipped, or failed — is recorded in notification_deliveries. Recent deliveries visible in Settings → Notification rules → Recent deliveries.

7. Data model summary

Tables grouped by what they're for. Schemas live in store.js.

Customer messaging
contacts
conversations
messages
files
media_library
Business config
webhooks
webhook_docs_versions
quick_sends
campaigns
campaign_stages
campaign_drip_sends
carousels
automations
settings
Agent control
agents
canned_responses
push_tokens
Audit + logs
webhook_fires
log files on disk
(daily JSONL in /logs)

8. Decision flowcharts

"I want to message a customer — which tool?"

flowchart TB Q1{"Known customer
OR cold lead?"} Q1 -->|Known| Q2{"24h window open?
(replied in last 24h)"} Q1 -->|Cold| Tpl1["Use a template
(Quick Send or webhook)"] Q2 -->|Yes| Free["Free text or any media
in the inbox"] Q2 -->|No| Tpl2["Use a template
(Quick Send)"] Q3{"Sending to many
at once?"} Tpl1 --> Q3 Tpl2 --> Q3 Q3 -->|Just this one| Now["Send from inbox"] Q3 -->|Many, one-shot| Camp["Campaigns tab"] Q3 -->|Many, sequenced over days| Drip["Drips tab"]

"Something went wrong — where do I look?"

flowchart TB Sym{"What's broken?"} Sym -->|Customer didn't get message| L1["Open conversation → ⓘ on the bubble
Shows error code + reason"] Sym -->|Webhook stopped firing| L2["Integrations → Run health check"] Sym -->|Many sends failing| L3["Settings → Logs → filter by 'wa_status' with 'failed'"] Sym -->|Quality rating dropping| L4["Meta Business Manager →
WhatsApp Manager → Phone Numbers"] Sym -->|Need historical search| L5["Settings → Logs → Download all"]

"I want to add a new functional inbox"

flowchart LR S1["Settings →
Functional inboxes"] --> S2["Add 'New Inbox'"] S2 --> S3["Webhooks tab →
assign relevant webhooks to it"] S3 --> S4["Quick Sends tab →
assign relevant QS to it"] S4 --> S5["Settings → Agent permissions →
grant access to relevant agents"] S5 --> S6["New inbox tab visible
to those agents"]

Agent compose mode

Controls what agents see when replying. Palette = curated messages first (90% from dropdown). Traditional = free text box first. Set per role.

Optional modules

Enable add-on capabilities for this deployment.

Inbox display

Business hours — wait-time clock

When on, the "waiting on us" clock and overdue highlighting only count time inside store hours, so overnight messages don't all show red by morning. When off, the clock runs 24/7.

Functional inboxes — split conversations into Sales / Service / Hiring / etc.

One WhatsApp number, multiple business functions. Each conversation belongs to ONE inbox tag. Webhooks and Quick Sends set the tag at the first touchpoint; cold inbound goes to Triage. Agents see only the inboxes they're permitted to handle (set below). Conversations can be moved between inboxes any time.

Don't rename existing inboxes lightly — any conversation already tagged with the old name will become invisible until you migrate it. Removing an inbox doesn't delete its conversations; they keep the tag but become uncategorised.

Agent permissions — which inboxes each agent can see

By default an agent sees every inbox. Restrict access by ticking only the boxes you want them to handle. Triage is always visible to everyone — that's where unclassified inbound lands and someone has to route it. Admins always see everything regardless of their settings here.

loading…

Maintenance — admin-only cleanup tools

Delete by phone number

Removes conversations, messages, attached files, and the contact entry for the given numbers. Pending drip enrolments for those numbers are cancelled. Webhook fire history (audit) is kept.

Use case: clearing test data so the same wa_id can be re-tested from scratch. Irreversible. Always run Preview first.

Telegram — internal notifications, staff-only

Not yet connected

One-way alerts from ss-comms to a Telegram supergroup. Customers never see these; staff use them to know when a lead lands, a send fails, or a campaign finishes. See Architecture → Telegram for the full model.

Step 1: Bot token

Step 2: Admin alerts destination

Where admin-only alerts land (webhook failures, quality drops, etc.). Often a small private group with just admins.

Step 3: Per-app routing

Which chat/topic receives alerts for each functional inbox. If you're using one supergroup with Topics, each app maps to a topic in it.

Setup walkthrough (open me if you're just starting)
Bot token: On Telegram, message @BotFather/newbot → follow the prompts (name, username) → copy the token it gives you. Paste in Step 1 and click Test.

Groups + Topics: Create a supergroup on Telegram. Group settings → Edit → toggle Topics on. Add topic threads for Sales / Service / Hiring / Test as you need. Add your bot to the group as an admin (so it can post to topics).

Chat + Topic IDs: Rather than hunting through JSON, use the Detect chats button in Step 3:
  1. In the group's General/Main topic, mention the bot (e.g. @your_bot_name hi)
  2. In each other topic you want routed to, mention the bot too
  3. Come back here and click Detect chats — the picker lists everything the bot has seen
  4. Click "Use for X" next to each row to map it to an app

Admin group (optional but recommended): if you want admin-only alerts (send failures, webhook errors, quality drops) in a smaller private group, create a separate group + add the bot; then paste that group's chat ID in Step 2.

Gotcha: if getUpdates ever fails with "webhook already set", visit https://api.telegram.org/bot<YOUR_TOKEN>/deleteWebhook in a browser. ss-comms doesn't use webhooks for Telegram.

Notification rules — which alerts fire when

Each rule watches for a system event and posts a formatted message to a channel. Default rules cover the common cases; add custom rules for anything else.

loading…

Apology template — for mistaken sends outside the 24h window

WhatsApp's Cloud API can't delete or recall a sent message — once delivered, the customer has it. When an agent sends something by mistake, ss-comms can send an apology message. Inside the 24-hour window: free-form text. Outside the window: the apology must be a Meta-approved template. Enter that template's name here.

Recommended template content (utility category): "Apologies — please ignore our previous message, it was sent in error." with no body variables. Submit through WhatsApp Manager or via the regular template creation flow.

Carousels

Swipeable multi-card marketing messages (2–10 cards). Each must be approved by Meta before sending — approval takes anywhere from a minute to 24 hours. Use them in campaigns to showcase models or offers.

loading…

Team

Agents, supervisors, and admins who can sign in to ss-comms. (Also available from the Team link in the inbox.)

loading…

Agent Performance

Speed and coverage per agent. This measures how fast and how much — not reply quality (use the knowledge test and spot-checks for that).

loading…

Team Knowledge Test — results

Who has taken the agent knowledge test, their best score, and proctoring snapshots from each attempt.

loading…
All attempts

Integrations — webhook triggers

External systems (CRM, booking tools) POST an event here → ss-comms transforms the data and sends a WhatsApp template. The message lands in the Campaigns inbox (or main inbox) and follows the customer's reply.

File info
Webhook documentation
Carousel defaults