SalesMsg Hub
SalesMsg is the primary outbound/inbound SMS platform for all acquisition and dispo agent messaging. It handles local-presence dialing across 12 inboxes (163,199+ contacts), OAuth-authenticated API calls, and webhook delivery for real-time message routing. Read this hub before modifying any SMS workflow, webhook handler, blast configuration, or inbox assignment. Owned by Henry Hill; managed by acquisitions + dispo agents.
⚠️ P0 Security Alert (PF-A)
/etc/systemd/system/salesmsg-gateway.service hardcodes ANTHROPIC_API_KEY=sk-ant-api03-C4A75YcCl... as plaintext in a system-level unit file. This is a G-NO-PLAINTEXT-CREDS violation. Rotation is pending. Until rotated, do NOT redeploy this unit without first replacing the hardcoded key with op://Aurora/anthropic/api-key reference and updating the unit to use EnvironmentFile=/run/secrets/anthropic.env or equivalent 1Password CLI injection. See 1password for op run pattern.
Quick reference
| Field | Value |
|---|---|
| Vendor | SalesMsg (salesmessage.com) |
| URL | https://api.salesmessage.com/pub/v2.2 |
| KB doc | API · WEBHOOKS · CREDENTIALS |
| Auth method | OAuth 2.0 Bearer Token (access token + refresh token auto-rotated every 6h) |
| Auth credential | op://Aurora/salesmsg/api-key — do NOT use plaintext |
| Cred-proxy port | n/a (until B1-B6 ratified in openclaw-fragmentation-fix-2026-05-01) |
| Webhook port | :18793 |
| Webhook handler | salesmessage-handler-v4-complete |
| Webhook auth | ⚠️ query-param token ?secret= — NOT HMAC (KB WEBHOOKS.md once said HMAC; KB was wrong; live is ?secret= query param only) |
| Webhook dedup table | processed_webhook_events (24h TTL) |
| Tunnel path (canonical) | https://webhook.reri.co/webhook/salesmessage · alt: /webhooks/salesmessage |
| Tunnel path (fallback) | https://srv1347501.tailb025a7.ts.net/webhook/salesmessage |
| Outbound API base | https://api.salesmessage.com/pub/v2.2 |
| Rate limits | Not documented; treat as standard SaaS (avoid burst >10 req/s) |
| Rate-limit action | 429 → exponential backoff (3 retries), Discord ops alert |
| Organization ID | 96638 |
| Primary inbox | Dispo | A (ID: 128279) — 16 numbers, local presence enabled |
| OAuth token file | /home/opsadmin/.openclaw/workspace/data/salesmessage-oauth.json (current access + refresh tokens) |
| Token refresh cron | sm-token-refresh every 6h |
| Cost | Per-message SMS pricing (see SalesMsg billing) |
| Backup/recovery | Vendor-owned (no local backup of message history) |
| Discord alert channel | ops |
| Drift cadence | Weekly (security-audit-funnel.timer) |
| Status | production |
Components
webhooks/salesmessage-handler-v4-complete.js— inbound webhook handler on :18793; routesmessage.created,message.updated,conversation.*,contact.*,call.*events/home/opsadmin/.openclaw/workspace/data/salesmessage-oauth.json— live OAuth access + refresh tokens; read this first before any API call/home/opsadmin/.openclaw/workspace/data/salesmessage-credentials.json— client ID (1395) + client secret; do NOT commit/home/opsadmin/.openclaw/workspace/data/salesmessage-aurora-oauth.json— Aurora-specific token for posting internal notesscripts/sm-token-refresh.js— token refresh worker invoked by cron every 6h/etc/systemd/system/salesmsg-gateway.service— ⚠️ CONTAINS PLAINTEXT ANTHROPIC KEY — see P0 alert abovesystemd unit: salesmsg-webhook (PM2)— process manager for handler on :18793
Inbox map
| ID | Name | Nums | Primary Number | Use case |
|---|---|---|---|---|
| 128279 | Dispo | A | 16 | (949) 776-5077 | Default list blasts (CRMLS agents) |
| 143887 | End Buyer/Cash Buyer | 1 | (949) 558-2868 | InvestorBase CH3 CA blasts |
| 160031 | End Buyer (FL) | 1 | (407) 250-1332 | InvestorBase CH3 FL blasts |
| 153323 | Dispo A (FL) | 1 | (407) 904-9008 | FL dispo outreach |
| 210192 | Dispo (AZ) | 1 | (480) 400-5187 | AZ dispo outreach |
Local presence (is_geomatch: true) is enabled on all 12 inboxes — SalesMsg auto-selects the outbound number matching the recipient’s area code. No per-message number selection needed.
How it’s used
- Trigger: Inbound SMS fires
message.createdwebhook →salesmessage-handler-v4-complete.js→ Supabase write + agent dispatch via OpenClaw gateway (:18789) - Outbound workflow: Acquisitions or dispo agent calls
POST /conversationswithteam_id(inbox ID) → SalesMsg selects local-presence number automatically - Agents involved: acquisitions agent (CH outreach Stages 1-4), dispo agent (buyer comms), Aurora (orchestration + note posting)
- Blast workflow:
dispo-blast-engine.jscoordinates 4-channel blast; SalesMsg handles CRMLS agent list channel and InvestorBase end-buyer channels — see dispo-blast - Failure mode: OAuth token expiry → 401 on all API calls →
sm-token-refreshauto-recovers within 6h; manual refresh:node scripts/sm-token-refresh.js --force - Success criteria:
message.createdwebhook received within 5s of outbound send; Supabaseopenphone_messages(or equivalent table) row created; no 429s in handler logs
Cross-links
Agents that touch this
- _summary — Stage 1-4 outreach, inbound reply classification (A-G)
- _summary — orchestration, posting internal notes via Aurora OAuth token
- _summary — buyer-side SMS comms post-blast
Skills that invoke this
- acquisitions-outreach — Stage 1 initial CH outreach (compliance-gated)
- acquisitions-followup — Stage 2-4 follow-up cadence + inbound reply handler
- dispo-blast — 4-channel buyer blast; SalesMsg handles CRMLS + InvestorBase channels
Plans that govern this
- openclaw-fragmentation-fix-2026-05-01 — Phase 1.7 per-gate feedback files; Phase 4.5 MEMORY split
- openclaw-self-improvement-layer-2026-05-03 — OSIL conversational SMS tiers gated on 10DLC (see twilio)
Feedback rules
- feedback_salesmsg_api_first — always use the SalesMsg API, not direct DB writes, for sending messages
- feedback_salesmsg_mention_syntax — @mention syntax for agent routing in SalesMsg notes
- feedback_blast_inbox_required — blast must specify inbox ID explicitly; default inbox fallback is forbidden
- feedback_action_gate_violation_repeated — service restarts require explicit Henry auth; do not restart salesmsg-webhook without confirmation
KB / source docs
- API — full API reference, OAuth flow, inbox/contact/conversation endpoints
- WEBHOOKS — event types, payload schemas,
?secret=auth pattern - CREDENTIALS — token storage, refresh flow, Aurora token
System maps
- vm-integrations-overview — full integration topology
- sms-inbound-flow — inbound SMS routing diagram
Related: SMS/Carrier compliance cluster
This hub is part of the SMS/Carrier compliance cluster. All three SMS/voice channels must be considered together for TCPA compliance, 10DLC registration, and blast safety.
- salesmsg — SalesMsg (this hub) — primary blast channel
- openphone-quo — Quo/OpenPhone — acquisitions voice + SMS
- twilio — Twilio — voice + A2P 10DLC anchor; ⚠️ 10DLC repeat-denial active — blocks ALL OSIL SMS tiers (see osil-twilio-10dlc-resubmission-2026-05-03 B14)
- compliance-gates — 5-gate pre-send enforcement (gate-computer, compliance-gate, blast-safety, thread-context, response-generator)
Related: Webhook/tunnel cluster
- cloudflare — tunnel + WAF governing this endpoint; FUNNEL-REGISTRY.md is authoritative
- openphone-quo — sibling webhook handler on :18792
- twilio — sibling webhook handler on :18797
- hubspot — sibling webhook handler on :18790
Open issues / TODOs
- P0 SECURITY: Rotate
ANTHROPIC_API_KEYin/etc/systemd/system/salesmsg-gateway.service— replace hardcodedsk-ant-api03-C4A75YcCl...with 1Password-injected reference (per G-NO-PLAINTEXT-CREDS) - Verify SalesMsg webhook
?secret=token value matches FUNNEL-REGISTRY; auditprocessed_webhook_eventsdedup TTL still 24h - Confirm
feedback_salesmsg_mention_syntaxapplies to Aurora note-posting viasalesmessage-aurora-oauth.json - Document all 12 inboxes in this hub (currently 5 of 12 documented above)
- Add SalesMsg to cred-proxy rotation plan when B1-B6 ratified
Recent activity
- 2026-05-03: hub created (W1-S2)