Everything you need to set up and run your WhatsApp SMM support bot. Includes command reference, role tables, verification flow, and API endpoints.
1. Sign up with your WhatsApp number
Create your account at /signup. Enter your phone number, verify via OTP sent to WhatsApp, and set a password. No email required — phone + password login only.
2. Connect your WhatsApp instance
Navigate to Dashboard → WhatsApp Numbers. Click "Connect" and scan the QR code with your WhatsApp. The bot goes live in under 30 seconds. No cables or third-party apps required.
3. Connect PerfectPanel API
Go to Bot Settings → Panel tab. Enter your PerfectPanel URL and Admin API key. The bot connects via PerfectPanel Admin API v2, enabling real-time order checks, refills, cancellations, speed-ups, balance queries, and service lookups from WhatsApp.
Panel URL: https://yourpanel.com API Key: your-admin-api-key-here
4. Choose your chat mode
Bot Settings → General tab. Three modes available: Manual (fixed hardcoded replies), AI (all replies reformatted through LLM), or Custom (replies from your message templates table, falls back to hardcoded if empty).
5. Add WhatsApp groups
Go to Groups in the dashboard. Groups appear automatically after the bot receives a message from them. Toggle Support (bot responds) and Marketing (bot broadcasts) per group. Silent mode lets the bot process and log without sending any replies.
Quick reference — customer commands
order / check <id>
Check order status. Returns service name, status (Pending/In Progress/Completed/etc.), start count, remains, charge, and provider. Supports comma-separated IDs for bulk lookup.
check 54321 order 54321, 54322, 54323
refill <id>
Submit a refill request. Bot auto-validates eligibility (order must be Partial or completed with appropriate status) before submitting. Supports multiple IDs. Returns service name, link, qty, and start count.
refill 54321 refill 54321 54322 54323
cancel <id>
Cancel an order. Checks eligibility before submitting. Bot confirms with next steps. Cooldown applies between cancel requests for the same order.
speed up <id>
Request order speed-up (resend). Validates active order status, submits priority flag, and confirms.
refund <id>
Submit a refund request. Eligibility check runs first. Logged with full provider context including Provider OID.
partial <id>
Request partial delivery for an oversized order. Validates and submits via panel API.
fake complete <id>
Force-complete a stalled order. Staff-level tool.
balance
Check your PerfectPanel account balance. Cooldown applies to prevent spam.
services
Get the panel service list URL for your account.
ticket <id>
Check the status of a support ticket in the panel.
my username
Show the panel username registered to your WhatsApp number.
help
Display the full command menu. Always hardcoded — identical in all chat modes.
Support Status Progression
Default on creation
Notifies provider group
Panel ticket opened
Issue closed
Update via !resolve <ids> <status> in WhatsApp or bulk-select rows in Dashboard → Message Logs.
Enabling Ticket AI
Go to Bot Settings → Panel tab. Enable the "Ticket AI" toggle. Set your ticket subject filter (default: "Orders Support- AI"). Customers must open tickets with this subject for AI handling.
ticket_ai_enabled = true ticket_poll_subject = "Orders Support- AI" ticket_poll_interval = 60 # seconds between polls ticket_signature = "Support Team" ticket_reply_staff_name = aisupport
Command tickets — automatic detection
Tickets containing action keywords (Speedup, Refill, Cancel, Refund, Partial Refund) plus one or more 4-12 digit order IDs are treated as commands. The bot fetches live order data from the panel API, logs the entry with serial number + provider + provider OID (exactly like a bot command), and posts an AI-generated reply confirming the action.
# Ticket message: "speedup my order 54321" # Bot detects: action=Speedup, order_ids=[54321] # Fetches: order status, provider, external_id # Logs: action=Speedup, serial=#1247, provider=smmcost.com, provider_oid=2323223 # Posts reply: "Speed-up request submitted for #54321..."
Support tickets — general questions
If no action keyword is found, AI generates a general support reply. Logged as "Ticket AI Reply" with any order context found in the message.
Duplicate prevention
Redis SET NX lock per ticket (TTL 5 min) prevents two Celery workers from replying to the same ticket simultaneously. A separate ticket_replied:{tenant_id} set (TTL 2 h) prevents re-processing within the same session.
Signature enforcement
The bot strips any AI-generated sign-off from the reply and appends your configured ticket_signature. Fallback: "Support Team". Ensures consistent branding in all ticket replies.
Verification Chat Flow
Step 1 — Greeting
Customer sends any greeting message ("hello", "hi", etc.) to the group or in DM. Bot sends the welcome message asking for their panel username.
Step 2 — Username lookup
Customer sends their PerfectPanel username. Bot validates the username via PerfectPanel API. If found, a 6-digit OTP code is created and sent to the customer via a panel support ticket.
Step 3 — OTP verification
Customer enters the 6-digit code. Bot verifies it (10-minute expiry, configurable max attempts). On success, the WhatsApp JID is permanently linked to the panel username in the tenant_users table.
verification_enabled = true verification_max_attempts = 3 verification_cooldown_seconds = 300 # 5 min after max attempts
Bulk verify — !verify-users
Admin command. Verifies all members in the current group under a given username at once. Useful when migrating an existing customer base.
!verify-users johndoe123
Managing customers from dashboard
Dashboard → Customers shows all verified users with their panel username and last active time. Actions: manually verify (skip OTP), block (prevents further commands), or delete (remove verification).
Full command cheat sheet — copy and share with your team:
| Command | Access | Description |
|---|---|---|
| !status | Admin | Show bot status, uptime, group count, AI provider |
| !broadcast <msg> | Admin | Send message to all support-enabled groups |
| !support enable|disable | Admin | Toggle bot responses for this group |
| !marketing enable|disable | Admin | Toggle marketing broadcasts for this group |
| !silent enable|disable | Admin | Toggle silent mode (process but no replies) |
| !resolve <ids> <status> | Admin+Staff | Update log status; escalated notifies provider group |
| !config set <key> <value> | Admin only | Live config update — persists to DB immediately |
| !config get <key> | Admin only | Read a config value |
| !config list | Admin only | List all bot_config keys and values |
| !verify-users <username> | Admin | Bulk verify all members in this group |
| !remove-users <username> | Admin | Unverify all users under this username |
| !users | Admin | List all verified users |
| !groups | Admin | List all whitelisted groups |
| refill verify <id…> | Admin+Staff | Live count vs panel data — refill analysis |
| <ids> provider status | Admin+Staff | Show Provider OID + Provider Status per order |
!status
Show bot status, uptime, verified user count, active group count, AI provider, and current chat mode. Works in DM or any group.
Status: Online | Uptime: 14h 32m Verified Users: 142 | Active Groups: 8 AI Provider: OpenAI GPT-4o-mini Chat Mode: ai
!broadcast <message>
Send a custom message immediately to all support-enabled groups. Useful for urgent announcements, service outages, or promotions.
!broadcast Maintenance scheduled tonight 11 PM - 1 AM UTC. Orders will process normally.
!support / !marketing / !silent enable|disable
Toggle group flags inside the target group. Takes effect immediately on the next message — no reload needed.
!support enable !marketing disable !silent enable
!resolve <order_id(s)> <status>
Update the support_status of a message log entry. When set to "escalated", the bot sends the provider order IDs to the mapped provider WhatsApp group for cross-panel follow-up.
!resolve 54321 escalated !resolve 54321 54322 resolved # Valid statuses: open | escalated | ticket created | resolved | ignored
!config set <key> <value>
Update a bot_config setting live without restarting. Changes persist to the database immediately. Admin-only command.
!config set chat_mode ai !config set cooldown_seconds 60 !config set marketing_interval_hours 4 !config list !config get chat_mode
refill verify <id…>
Admin + staff command. Shows live count vs panel data for each order ID — used to justify or dispute a refill request without the customer seeing. Run in DM or group.
refill verify 54321 54322 54323
<ids> provider status
Comma-separated order IDs followed by "provider status". Shows Provider OID and Provider Status per order. No ownership check — for staff use only.
54321,54322 provider status # Response: # #54321 | Provider OID: 2323223 | Provider Status: In Progress # #54322 | Provider OID: 6565655 | Provider Status: Canceled
Manual mode (default)
All bot replies use fixed hardcoded strings. Fast and completely predictable. No AI calls made for command replies. Dirty commands (order ID + action + frustrated text) still trigger AI consolation when AI is configured.
AI mode
All customer-facing command replies are reformatted through LLM. Unrecognised messages are routed to AI with full PerfectPanel context. Dirty commands always get a merged reply (action result + consolation). Auto language detection.
Custom mode
Replies served from your message_templates table (35+ keys covering every bot interaction). Falls back to hardcoded strings if a template is empty or missing. Changes to templates take effect on the next message — no restart.
# Template keys (sample) welcome_message verification_username_prompt verification_code_sent verification_success refill_submitted cancel_submitted speedup_submitted balance_cooldown ticket_signature
AI consolation — works in all modes
When a customer sends an order ID + action keyword + extra frustrated text (a "dirty command"), the bot always executes the action first and then generates a merged empathetic AI reply. This works regardless of chat_mode as long as LLM credentials are configured. The log is automatically flagged as priority.
Adding broadcast messages
Dashboard → Marketing. Click "Add Message" and write your promotional text. Supports full WhatsApp formatting (*bold*, _italic_, ~strike~, `mono`). Multiple messages rotate automatically.
Scheduling configuration
Bot Settings → Marketing tab. Set marketing_interval_hours (base interval). A random jitter of 0–60 minutes is added to each broadcast to avoid predictable patterns that trigger spam filters.
marketing_interval_hours = 4 scheduler_timezone = UTC+6 # Use UTC offset format
Timezone support
Set your timezone in Bot Settings using UTC offset format: UTC, UTC+6, UTC-5, etc. Do not use IANA timezone names (e.g. Asia/Dhaka) — use UTC offsets only. The dropdown in Bot Settings → Marketing shows UTC-12 through UTC+14.
Per-group targeting
Only groups with marketing_enabled = true receive broadcasts. Toggle per-group from Dashboard → Groups or via !marketing enable|disable in the target group.
Adding a provider
Dashboard → Providers → Add Provider. Enter the provider name, panel URL, and API key. Click Sync to fetch the initial service catalog and account balance.
Service catalog sync
Every sync fetches the full service list from the provider panel API (PerfectPanel Admin API v2). Services are upserted (updated or inserted). New services detected on subsequent syncs are tagged is_new and trigger a WhatsApp notification to admin-role numbers.
# First sync: baseline — nothing tagged new, no notification # Subsequent sync: new services tagged is_new # Notification sent to admin-role numbers only (not staff)
Balance tracking
Account balance is fetched alongside the service catalog on every sync and stored in smm_providers.balance. Best-effort — a sync succeeds even if the balance call fails.
Auto-sync and locking
Each provider has a configurable sync_interval. The Celery beat task runs auto-sync at this interval. A Redis NX lock (provider_sync_lock:{provider_id}, TTL 600s) prevents two workers from syncing the same provider simultaneously. Set is_active = false to disable auto-sync.
Provider escalation group
Map a WhatsApp group to a provider in the dashboard. When a log entry is escalated (!resolve <ids> escalated), the bot sends the provider order IDs to that provider group for cross-panel investigation.
Service search
Dashboard → Service Search. Search across all synced providers by service name or ID. Filter by provider. Paginated results.
| Permission | Owner | Staff Admin | Staff |
|---|---|---|---|
| All bot commands | — | — | |
| !config set/get/list | — | — | |
| !broadcast to all groups | — | ||
| Group flag toggles (!support / !marketing / !silent) | — | ||
| Bulk verify/remove users | — | ||
| !resolve <ids> <status> | |||
| refill verify <ids> | |||
| <ids> provider status | |||
| Dashboard — Bot Settings, Templates, Groups, Marketing | — | ||
| Dashboard — Customers, Providers, Service Search | — | ||
| Dashboard — Message Logs | |||
| Dashboard — Billing | — | — | |
| Dashboard — Admin & Staff, Settings | — | — |
Owner
Full bot and dashboard access. The phone number used to sign up becomes the owner. Authenticates with phone + password.
Staff Admin
Dashboard access: Bot Settings, Templates, Groups, Marketing, Customers, Message Logs, Providers, Service Search. Bot commands: all except !config set/get/list.
Staff
Dashboard access: Message Logs only. Bot commands: refill verify, <ids> provider status, !resolve.
Adding staff — OTP verified flow
Dashboard → Admin & Staff → Add Number. Enter the staff phone number. Bot sends a 6-digit OTP to their WhatsApp. They enter the code to verify. System auto-generates a random password and sends login credentials to their WhatsApp. LID is auto-resolved on their first group message.
POST /api/v1/admin-numbers/send-code → sends OTP to WhatsApp POST /api/v1/admin-numbers/verify → verifies OTP, saves to tenant_admins
Authentication — phone + password
No email. Phone-based OTP for signup, phone + password for login. Returns HttpOnly JWT cookies (separate secrets for tenant and admin panel).
# Signup (new phone only)
POST /api/v1/auth/phone/send { phone }
POST /api/v1/auth/phone/verify { phone, otp, password }
# Login
POST /api/v1/auth/login/phone { phone, password }
# Forgot password
POST /api/v1/auth/phone/forgot-password/send { phone }
POST /api/v1/auth/phone/forgot-password/reset { phone, otp, new_password }
# Session
GET /api/v1/auth/me
POST /api/v1/auth/logout
POST /api/v1/auth/refreshBot config — GET / PATCH
Fetch and update the bot_config table for the authenticated tenant. All saves trigger a live reload of the bot — no restart needed.
GET /api/v1/config
PATCH /api/v1/config { key: string, value: string }
GET /api/v1/config/ticket-webhook-info
POST /api/v1/config/regenerate-webhook-key
POST /api/v1/config/validate-panelMessage logs
Searchable log history with support status management. Bulk status update supported.
GET /api/v1/logs?date=&action=&status=&priority=&page=
PATCH /api/v1/logs/{id}/support-status { status }
POST /api/v1/logs/bulk-status { ids: [], status }Providers & services
Full CRUD for SMM providers plus sync and paginated service search.
GET /api/v1/providers
POST /api/v1/providers
PATCH /api/v1/providers/{id}
DELETE /api/v1/providers/{id}
POST /api/v1/providers/{id}/sync
GET /api/v1/providers/services?q=&provider_id=&sort=&limit=&offset=Groups
Manage whitelisted groups — toggle support, marketing, and silent flags.
GET /api/v1/groups
PATCH /api/v1/groups/{id} { support_enabled, marketing_enabled, silent_mode }
DELETE /api/v1/groups/{id}
POST /api/v1/groups/syncAdmin & Staff numbers
Two-step OTP-verified flow for adding admin/staff WhatsApp numbers.
GET /api/v1/admin-numbers
POST /api/v1/admin-numbers/send-code { phone }
POST /api/v1/admin-numbers/verify { phone, code, role }
DELETE /api/v1/admin-numbers/{id}Billing
Stripe-powered plan management with in-place upgrade/downgrade.
GET /api/v1/billing/plans
POST /api/v1/billing/checkout { plan_id }
POST /api/v1/billing/change-plan { plan_id }
GET /api/v1/billing/portal
GET /api/v1/billing/usage
GET /api/v1/billing/invoicesMessage templates
Read and update individual template keys. Reset to default is supported per key.
GET /api/v1/templates
PATCH /api/v1/templates/{key} { value }
POST /api/v1/templates/{key}/resetReady to get started?
Create your account