supabase
Handles the full Supabase workflow from schema changes to deployment, with built-in security guardrails that catch common traps like RLS...
chat-notifyer
Live chat operations for Notifyer by WhatsAble. Enables AI agents to operate the WhatsApp chat interface: list and search conversations, send text/template/ attachment messages, assign labels, control AI bot vs. human handoff, schedule messages, and manage recipient notes. Use this skill when you...
Full skill instructions
Live chat operations for the Notifyer platform (chat.notifyer-systems.com).
This skill covers Phase 3 of the Notifyer agent-skills suite:
| Phase | Skill | Coverage |
|---|---|---|
| 1 | setup-notifyer | Account, WhatsApp connection, Plans, Team, Labels, API Key |
| 2 | automate-notifyer | Templates, AI Bots, Broadcasts, Analytics, Webhooks |
| 3 | chat-notifyer | Recipients, Messaging, Labels, Handoff, Scheduling, Notes |
Set these before running any script:
| Variable | Required | Default | Description |
|---|---|---|---|
NOTIFYER_API_BASE_URL | yes | — | Backend API base URL (e.g. https://api.insightssystem.com) |
NOTIFYER_API_TOKEN | yes | — | JWT token from setup-notifyer/login.js |
NOTIFYER_CHAT_ORIGIN | no | https://chat.notifyer-systems.com | CORS Origin header for chat endpoints |
export NOTIFYER_API_BASE_URL="https://api.insightssystem.com"
export NOTIFYER_API_TOKEN="eyJhbGciOi..." # from setup-notifyer/login.js
This skill uses Chat Auth Mode: Authorization: <token> (raw JWT, NO Bearer prefix).
This is different from setup-notifyer and automate-notifyer which use Authorization: Bearer <token>.
The same JWT token works for both modes — only the header format differs.
The token is obtained from setup-notifyer/scripts/login.js and stored as NOTIFYER_API_TOKEN.
Several endpoints run Xano's /cors_origin_web_chat function which allows requests from:
https://chat.notifyer-systems.com (primary)https://console.notifyer-systems.comhttps://api.insightssystem.comhttps://preview-chat-notifyer.vercel.apphttp://localhost:5173, http://localhost:3000, http://127.0.0.1:5173Scripts automatically send Origin: https://chat.notifyer-systems.com.
Optional: set NOTIFYER_CHAT_ORIGIN if you need a different Origin header.
Endpoints that do NOT require CORS: /chatapp/* endpoints, send/text.
| Group | Path Prefix | Covers |
|---|---|---|
| Auth | /api:-4GSCDHb | /auth/me — resolves user_id for chatapp endpoints |
| Chat Web | /api:bVXsw_FD | Recipients, messaging, schedules (primary group for this skill) |
| Media Upload | /api:ox_LN9zX | File upload for attachments |
| AI Config | /api:Sc_sezER | List bots (console auth) |
WhatsApp policy: Free-text messages and attachments can only be sent within 24 hours of the recipient's last inbound message.
Window open: recipient.expiration_timestamp > Date.now()
Window closed: recipient.expiration_timestamp == null OR < Date.now()
| Window State | Allowed Messages |
|---|---|
| Open | Text ✓, Template ✓, Attachment ✓ |
| Closed | Template only ✓ |
Before sending text or attachments, verify the 24-hour window:
node scripts/get-recipient.js --phone 14155550123 --pretty
node scripts/list-recipients.js --pretty
node scripts/list-recipients.js --search "John" --pretty
node scripts/list-recipients.js --search "14155550123" --pretty
node scripts/get-recipient.js --phone 14155550123 --pretty
node scripts/filter-recipients-by-label.js --labels "Support" --status unread --pretty
Label matching is case-sensitive. If the API returns 0 results, the script automatically retries with case-insensitive client-side filtering and flags used_case_insensitive_fallback: true in the output.
node scripts/list-recipients.js --all --pretty
node scripts/send-text.js --phone 14155550123 --text "Hello! How can I help?"
send-text.js automatically checks the 24h messaging window before sending. If the window is closed it exits with ok: false and a clear message explaining the options (use a template, or wait for the contact to message first). No manual pre-check with get-recipient.js is needed.
# By template name (recommended — easier than looking up the ID):
node scripts/send-template.js --phone 14155550123 --name order_confirm
node scripts/send-template.js --phone 14155550123 --name order_confirm \
--variables '{"body1":"John","body2":"#12345"}'
# List all available templates:
node scripts/send-template.js --list
# Preview what would be sent without actually sending:
node scripts/send-template.js --phone 14155550123 --name order_confirm --dry-run
# By template ID (legacy):
node scripts/send-template.js --phone 14155550123 --template tmpl_abc123
# Single file — no caption
node scripts/send-attachment.js --phone 14155550123 --file /path/to/invoice.pdf --pretty
# Single file — with caption
node scripts/send-attachment.js --phone 14155550123 --file /path/to/photo.jpg --caption "Your order photo"
# Multiple files — shared caption for all
node scripts/send-attachment.js --phone 14155550123 \
--files "/path/to/photo.jpg,/path/to/invoice.pdf,/path/to/video.mp4" \
--caption "See the attached files" --pretty
# Multiple files — per-file captions (JSON array, positional)
node scripts/send-attachment.js --phone 14155550123 \
--files "/path/to/photo.jpg,/path/to/invoice.pdf,/path/to/video.mp4" \
--captions '["Great photo","Your invoice",""]'
# Mixed — per-file captions with a fallback for unspecified positions
node scripts/send-attachment.js --phone 14155550123 \
--files "/path/to/photo.jpg,/path/to/invoice.pdf,/path/to/video.mp4" \
--captions '["Great photo"]' \
--caption "See attached"
Files are uploaded 3 at a time concurrently, then sent sequentially. Max 10 files per call.
--captions is a JSON string array — one entry per file by position. Use "" for no caption on a specific file. If the array is shorter than the file list, remaining files use --caption (or no caption if --caption is also omitted). --caption and --captions can be combined.
node scripts/send-text.js \
--phone 14155550123 \
--text "Your appointment is tomorrow at 10am!" \
--schedule "25/01/2025 09:00"
node scripts/send-template.js \
--phone 14155550123 \
--template tmpl_abc123 \
--schedule "25/01/2025 14:00"
node scripts/list-scheduled.js --pretty
node scripts/list-scheduled.js --phone 14155550123
node scripts/delete-scheduled.js --id 7 --confirm
node scripts/assign-label.js --phone 14155550123 --label "Support" --pretty
Labels must exist — create them first via setup-notifyer/create-label.js.
node scripts/remove-label.js --phone 14155550123 --label "Support" --pretty
node scripts/filter-recipients-by-label.js --labels "VIP,Support" --pretty
This is the primary escalation workflow. Use it whenever the contact expresses a desire to speak with a human — even implicitly (e.g. "I need help", "can someone call me", "talk to a person", "agent please", "representative").
The correct method is to assign the bot's handoff_label to the conversation.
Notifyer automatically sets is_ai_assistant = false when this label is assigned,
stopping the bot and routing the conversation to human agents in one step.
# Step 1 — confirm the bot's configured handoff label (do this once; remember the value)
node ../automate-notifyer/scripts/list-bots.js --pretty
# Look for: handoff_label — e.g. "Human"
# Step 2 — assign the handoff label (this stops the bot AND routes to humans)
node scripts/assign-label.js --phone 14155550123 --label "Human" --pretty
What happens automatically after Step 2:
label = handoff_label on the recipientis_ai_assistant = false — bot stops responding immediately"Human" labelDo NOT call set-handoff.js separately — the label assignment already triggers
the handoff. Calling both would be redundant.
If the handoff_label is not configured on the bot, fall back to:
# Fallback — manual handoff without label routing
node scripts/set-handoff.js --phone 14155550123 --mode human --pretty
This stops the bot but does not route to a label-scoped agent queue.
When running as an AI bot in a conversation, monitor for these signals and trigger the human handover workflow above:
Before escalating, optionally send an acknowledgement message:
node scripts/send-text.js --phone 14155550123 \
--message "I'm connecting you with a human agent now. Someone will be with you shortly."
Then immediately assign the handoff label.
node scripts/set-handoff.js --phone 14155550123 --mode human --pretty
node scripts/set-handoff.js --phone 14155550123 --mode bot --pretty
# Step 1: list available bots
node scripts/list-bots.js --pretty
# Step 2: assign bot and enable AI mode
node scripts/assign-bot.js --phone 14155550123 --bot-id 5 --pretty
# Last 30 messages (both sides of the conversation):
node scripts/get-conversation.js --phone 14155550123 --pretty
# Page through history:
node scripts/get-conversation.js --phone 14155550123 --page 1 --per-page 50 --pretty
# Last 20 outbound-only messages with delivery status:
node scripts/get-conversation-log.js --phone 14155550123 --pretty
# All messages ever sent to this contact:
node scripts/get-conversation-log.js --phone 14155550123 --all --pretty
Note: get-conversation.js returns the full bidirectional thread (both sides). get-conversation-log.js returns outbound-only sends with delivery analytics (from the console log API).
node scripts/update-recipient.js --phone 14155550123 --name "John Doe" --pretty
node scripts/get-notes.js --phone 14155550123 --pretty
node scripts/add-note.js --phone 14155550123 --note "VIP customer — apply 15% discount"
node scripts/add-note.js --phone 14155550123 --append "Requested callback on 15 Feb"
node scripts/add-note.js --phone 14155550123 --note "" # clear note
If you encounter an error, find something unclear, want to request a feature, or spot a security concern while using this skill, send feedback to the Notifyer team:
node ../setup-notifyer/scripts/send-feedback.js \
--feedback "your message here" \
--type error|request|unclear|security|improvement|general \
--skill chat-notifyer \
--script <script-name.js>
Requires NOTIFYER_API_TOKEN (same token used by all scripts).
Auth mode: Use raw JWT (Authorization: <token>, no Bearer prefix) for all chat endpoints in this skill, except list-bots.js, which uses console auth.
Phone numbers: Send phone numbers as integers (no + prefix). Parse with parseInt(phone.replace(/^\+/, ""), 10).
24h window: send-text.js auto-checks the window and refuses to send if it is closed — no pre-check needed. For attachments, check expiration_timestamp via get-recipient.js. If window closed, use send-template.js.
Fetch before patch: For label changes, note changes, and bot assignment — fetch the recipient first to get current state, then PATCH with the full intended state.
Labels are strings: global_label is a string[] of label names (not IDs). Send ["Support", "Billing"] — not [1, 2].
CORS endpoints: All /web/* endpoints require Origin: https://chat.notifyer-systems.com. Scripts handle this automatically.
user_id for chatapp endpoints: get-recipient.js and set-handoff.js call /auth/me internally to resolve the user_id UUID. No manual action needed.
Page numbering: Xano uses 0-based page numbers internally. Scripts expose 1-based page numbers to users (--page 1 = page_number=0 in API).
Template scheduling: scheduled_time: 0 = immediate send. 0 is NOT a null/empty — it is the explicit "immediate" signal.
list-bots.js uses console auth: This is intentional — the AI config endpoint is in the console API group. Both Bearer and raw token use the same JWT, just different formats.
Human handover = assign the handoff_label, not set-handoff.js: When a contact requests a human, use assign-label.js --label "<handoff_label>". This assigns the label AND automatically flips is_ai_assistant = false in one step. Calling set-handoff.js alone stops the bot but does NOT route the conversation into the human agent's label queue. Always prefer the label-based path. If handoff_label is unknown, run list-bots.js once to retrieve it.
Proactive handover: If the bot has failed to resolve the contact's issue after 3 attempts, or if the contact repeats the same question more than twice, proactively offer a human handover without waiting to be asked explicitly.
| Script | Description | Auth Mode |
|---|---|---|
scripts/list-recipients.js | List/search conversation recipients with pagination | Chat |
scripts/get-recipient.js | Get single recipient by phone number | Chat |
scripts/filter-recipients-by-label.js | List recipients filtered by label(s) | Chat |
scripts/send-text.js | Send a free-text message (auto-checks 24h window; refuses if closed) | Chat |
scripts/send-template.js | Send a template message (no window required; supports --name, --list, --dry-run) | Chat |
scripts/send-attachment.js | Upload 1–10 files then send as image/video/audio/document (auto-detects type per file; concurrent upload, sequential send) | Chat |
scripts/assign-label.js | Assign a label to a recipient | Chat |
scripts/remove-label.js | Remove a label from a recipient | Chat |
scripts/set-handoff.js | Toggle AI bot vs. human mode | Chat |
scripts/assign-bot.js | Assign specific AI bot to recipient | Chat |
scripts/list-bots.js | List all AI bots (for bot ID lookup) | Console |
scripts/list-scheduled.js | List all scheduled messages | Chat |
scripts/delete-scheduled.js | Cancel a scheduled message | Chat |
scripts/add-note.js | Set or append to manual note on recipient | Chat |
scripts/get-notes.js | Read manual + AI-generated notes for recipient | Chat |
scripts/get-conversation.js | Read full bidirectional chat thread (sent + received messages) | Chat |
scripts/get-conversation-log.js | Read outbound-only send history with delivery status (console log API) | Console |
scripts/update-recipient.js | Update recipient display name | Chat |
| File | Description |
|---|---|
lib/notifyer-api.js | loadConfig, requestJson, AUTH_MODE_CHAT, AUTH_MODE_CONSOLE |
lib/args.js | parseArgs, getFlag, getBooleanFlag, getNumberFlag |
lib/result.js | ok, err, printJson — standardised JSON output |
lib/schedule-response.js | validateScheduledSendResponse — detects silent schedule failures (status: not_passed, id: null) |
| File | Coverage |
|---|---|
../../AUTHENTICATION.md | All three auth surfaces — curl examples, decision guide, header formats, error diagnostics |
references/recipients-reference.md | Recipient object, GET/PATCH endpoints, 24h window, label routing |
references/messaging-reference.md | Text, template, attachment send APIs — all parameters and side effects |
references/labels-handoff-reference.md | Label assignment, keyword auto-labelling, handoff modes, bot assignment |
references/scheduling-notes-reference.md | Scheduled messages, chat_schedule table, note fields |
| File | Description |
|---|---|
assets/send-template-example.json | Example --variables payloads for common template patterns |
setup-notifyer/get-connection-status.js. Re-connecting a fully revoked WABA requires the browser-based embedded signup — it cannot be scripted.get-conversation.js reads the full thread; get-conversation-log.js is outbound-only. Use get-conversation.js (Chat API, /web/conversations) to read both sides of a conversation. Use get-conversation-log.js (Console API, /api:ereqLKj6/log) for outbound delivery analytics only.automate-notifyer skill). Scripts cannot subscribe to or poll for new inbound messages.send-template.js — free-text sends will be rejected by Meta.automate-notifyer/create-broadcast.js.APPROVED status from Meta. Manage template creation and status via automate-notifyer/create-template.js and list-templates.js./auth/me internally. This adds one extra API round-trip on each invocation. If the token is expired, both the auth/me call and the main call will fail — re-run setup-notifyer/login.js to refresh.PATCH /api:bVXsw_FD/web/conversations ({ phone_number, message_id, status }) updates message read/delivery status. This is triggered automatically by the chat UI when a conversation is opened — there is no script for it, and AI agents do not need to call it manually.GET /api:bVXsw_FD/recipient_download_csv returns a binary CSV stream. Use raw fetch with response.text() or response.blob() in a custom workflow if you need to export the full recipient list.Handles the full Supabase workflow from schema changes to deployment, with built-in security guardrails that catch common traps like RLS...
Comprehensive guides and best practices for Neon Serverless Postgres, covering setup, connection methods, authentication, and platform APIs.
Guide for setting up and using Firebase Authentication. Use this skill when the user's app requires user sign-in, user management, or secure data access using auth rules.
A skill to evaluate how secure Firestore security rules are. Use this when Firestore security rules are updated to ensure that the generated rules are extremely secure and robust.
Official skill for integrating Firebase AI Logic (Gemini API) into web applications. Covers setup, multimodal inference, structured output, and security.
Complete Better Auth server and client setup with database adapters, session management, plugins, and security configuration.
Deploy and manage projects on Vercel using token-based authentication. Use when working with Vercel CLI using access tokens rather than interactive login — e.g. "deploy to vercel", "set up vercel", "add environment variables to vercel".
Complete Cloudflare platform integration with decision trees for compute, storage, AI, networking, security, and infrastructure-as-code.
Run Azure compliance and security audits with azqr plus Key Vault expiration checks. Covers best-practice assessment, resource review, policy/compliance validation, and security posture checks. WHEN: compliance scan, security audit, BEFORE running azqr (compliance cli tool), Azure best practices, Key Vault expiration check, expired certificates, expiring secrets, orphaned resources, compliance assessment.
Send, read, and manage Gmail messages, drafts, labels, and account settings.
Comprehensive website auditing across 230+ rules in 21 categories including SEO, performance, security, and accessibility.
Shared authentication, CLI syntax, and output formatting patterns for gws Google Workspace commands.
Discover your celebrity doppelgänger with StarByFace!
GeoSpy: Pricing, Features, FAQs, and Alternatives for AI Teams
Detect AI-generated voices to protect against audio fraud.
Ensure Your Content's Originality with AI Plagiarism Checker
Upscale images by 400% without quality loss
Protect your social media from copyright disputes
Accurately Detect AI-Generated Content with TheChecker.AI
Chrome extension that detects and flags AI-generated content