Send a campaign
A campaign in Vibot is a one-shot send of one approved WhatsApp template to a list of recipients. This page walks the full wizard top-to-bottom, calls out the safety checks at each step, and explains exactly what every preflight verdict means.
Before you start
Five preconditions. If any one is missing, the wizard will block at the relevant step.
- Your WhatsApp number is Connected (green badge on the Connect page).
- You have at least one APPROVED template (the Templates page). PENDING and REJECTED templates are filtered out of the picker.
- Your account is on Lite plan or higher. Campaigns are not available on Free.
- Your wallet has enough credits to cover the send at your plan’s per-template rate. See Pricing.
- If this is your first send on the number, you’ve read Warm up a new number.
Step 0 — Open the wizard
Sidebar → Campaigns → top-right + New Campaign button.
Step 1 — Pick a template
Vibot lists every APPROVED template on your WABA. Each card shows:
- Template name (e.g.
welcome_v2). - Category pill —
Marketing/Utility/Authentication. The category determines wallet rate when sending. - Quality pill — Green / Yellow / Red / Unknown. Vibot reads this directly from Meta.
- Language — locale (
en,hi,en_IN). - Body preview — the first ~120 characters.
Click a card to select. The right-side preview pane fills with the full template content and a live preview of the message bubble.
Don’t blindly click the prettiest template. Pick the one whose category genuinely matches the message intent:
- Order shipped / appointment reminder → Utility
- Promotional offer / sale announcement → Marketing
- OTP / 2FA code → Authentication
Category mismatch is one of Meta’s top reasons for template rejection AND a frequent quality-rating-drop trigger.
Click Next to advance.
Step 2 — Choose recipients
Two paths:
Path A — From Contacts
If you’ve imported contacts into the Contacts page, this is the cleaner path. Vibot lets you filter by:
- Label — multi-select. Recipients matching ANY selected label are included.
- Opted-out — auto-excluded for Marketing templates; can be included for Utility/Authentication.
Below the filters, Vibot shows the live count of matching contacts.
Map template variables
If your template body has {{1}} {{2}} placeholders, Vibot prompts you to map each variable to a contact field:
| Variable | Maps to |
|---|---|
{{1}} | First name / Last name / Full name / a custom field |
{{2}} | Same |
If your template has no variables, this section doesn’t appear.
Path B — CSV upload
Upload a .csv or .xlsx file. Required columns:
phone— E.164 format with+(e.g.+919876543210). Vibot normalises common variants but+is required for unambiguous parsing.var1,var2, … — one column per template variable, in order.
Optional column: name — used for display only.
Vibot shows a preview of the first 5 rows so you can verify mapping before launching.
File-size limit: 5 MB. Recipient cap: depends on plan + tier. The 24-hour-tier ceiling (250 / 1,000 / 10,000 / etc.) is enforced regardless of file size.
Click Next to advance.
Step 3 — Review & Launch
This is where Vibot runs the preflight check and produces a traffic-light verdict.
Reading the preflight panel
The panel has three rows:
Verdict pill — one of:
- 🟢 Ready to send. No blockers, no warnings. Launch is enabled.
- 🟡 Review warnings before launch. Soft issues. Launch is enabled after you tick the “I’ve reviewed the warnings above and want to launch anyway” checkbox.
- 🔴 Sending blocked. Hard blockers — launch is disabled until you fix the source list.
Count pills — six numbers at a glance:
| Pill | What it counts |
|---|---|
| Accepted | Will actually be sent. The number on the Launch button. |
| Skip — length overflow | Rendered body > 1,024 chars (Meta’s limit). |
| Skip — opted out | Marketing campaigns only; recipients with optedOut: true are skipped. |
| Skip — not on WhatsApp | Cached 131026 (last 30d) or live-check confirmed invalid. |
| Skip — already received | Same template sent to this recipient within the dedupe window (default 7 days). |
| Warnings | Sendable but at risk (recently spam-blocked, dead-number warnings, tier-cap unverified). |
Warning list — full text of each soft warning, e.g.:
Verified the first 250 recipients against WhatsApp’s contact list — 4,750 more were not checked because that would exceed Meta’s per-day verification budget for this number. Your messaging tier is TIER_250. Those will be sent unverified.
The full list of blocker types
If the verdict is RED, one or more of these will be in the blockers list. Fix the source, then Back → Step 2 and re-import.
Recipient list is empty.— no recipients matched your filters or CSV.No sendable recipients — every row was filtered out.— common after a fresh sender’s first big import: all 100 rows were dead numbers + opt-outs.Your phone number's verification with Meta has expired.— the SMS-OTP re-verification has expired. Fix via Connect WhatsApp → Verify Number (see troubleshooting).Template '{name}' has a RED quality score on Meta.— the template itself has been quality-dropped. Recreate with cleaner copy under a new name, or pause for 24–72h.Insufficient wallet balance.— wallet check is the very last gate. Top up via Billing → Add Credits.
The launch warning modal (first-send heads-up)
If this is your first ever campaign on the number OR the first use of this specific template, Vibot pops the amber “First send on this WhatsApp number” modal before the actual launch.
Pick:
- Send slow on first launch ← recommended. Applies Conservative drip (5 → 10 → 25 → 50/h).
- Send normally, I accept the risk — bypasses drip, uses default 50-msg batches.
See Warm up a new number for why “send slow” is almost always the right answer.
Choose send time
Two options:
- Send now — campaign starts immediately on click.
- Schedule for later — pick a date + time. Vibot enqueues the launch as a delayed BullMQ job; recipients are not held in some staging table, they’re sent at the scheduled moment.
Name the campaign
The campaign name appears in your Campaigns list and in CSV exports. Use something descriptive — “Diwali Sale Push”, “Order Status Reminder Oct 12”, etc. Don’t use names that contain sensitive info (e.g. customer phone numbers).
Click Launch
Final click: Launch to N contacts. The button shows the Accepted count, not the total — so if your list has 1,000 rows but 200 are pre-skipped, the button says “Launch to 800”.
After click:
- Wallet balance check → debits the predicted cost.
- Campaign row created (status:
RUNNING). - Recipients inserted (
status: PENDINGfor sendable,status: SKIPPEDwithskipReasonfor pre-filtered). - First batch (or first canary cohort if eligible) enqueued.
You’re redirected to the campaign detail page.
After launch — what to watch
The campaign detail page is the single source of truth for live status.
Overview tab
Top of page: status pill (RUNNING / COMPLETED / CANCELLED) + canary banner (visible only when canary is in progress / failed / passed).
Below: six counters that auto-refresh every 4–6 seconds:
| Counter | Meaning |
|---|---|
| Total | Rows on the campaign. |
| Sent | Meta accepted the API call (returned a wamid). |
| Delivered | Meta’s delivery webhook fired. |
| Read | Customer opened the chat. |
| Failed | Meta returned an error (131026, 131049, etc.). |
| Skipped | Pre-filtered (opt-out, dead, dedup) — never sent. |
Send-progress bar shows (Sent + Failed + Skipped) / Total.
Recipients tab
Per-row view with status + (if failed) the Meta error code. Filter by status to focus on FAILED rows for retry.
Insights tab
After the campaign completes: funnel chart (Sent → Delivered → Read → Replied), top-10 reply messages, top-10 failure reasons (by code + count).
Cancelling a campaign mid-flight
There’s no UI button for customers to cancel a running campaign. If you need to halt one, the canary or 15% halt will catch most safety-critical issues automatically. If you need to force-stop:
- Contact
support@virtuo.inor use the in-dashboard Vibot Assistant — admins can issue a force-cancel. - Note: in-flight 50-msg batches may continue to completion before the cancel takes effect. Future batches will be drained as
SKIPPED, skipReason='admin_cancel'.
After a cancelled or partial campaign — Resume Skipped
If your campaign was cancelled (canary abort, manual cancel, 15% halt) or has FAILED recipients, you have two recovery paths from the campaign detail page:
Resume Skipped (N)
Re-targets recipients whose status is SKIPPED with a resumable skipReason. Opens a modal asking for the drip preset:
- Conservative — 5 → 10 → 25 → 50 per hour. Default after a canary abort. Recommended.
- Moderate — 10 → 25 → 50 every 30 min. Safe for known-clean lists.
- Aggressive — 25 → 50 every 15 min. Gated (≤ 200 recipients, no prior chain abort, requires acknowledgement).
- Custom — your own stages + delays.
The Resume button is disabled with a tooltip if a cool-off window is active (6h after a first abort, 24h after a second abort on the same chain).
Resume creates a NEW campaign row linked to the parent via resumedFromCampaignId. Conversation history with each recipient is preserved.
Retry Failed (N)
Re-targets recipients whose status is FAILED. Use sparingly — most FAILED rows are dead numbers or recipients globally spam-blocked, and retrying them costs you wallet credits to fail again. See Why sends fail.
Frequently asked
Q. Can I edit a campaign after launch? No. Campaigns are immutable once launched. To change message body or recipient list, cancel and create a new one.
Q. Can I A/B test two templates? Not via a single campaign. Launch two separate campaigns with different templates on different audience segments, compare reply rates in Insights.
Q. What’s the practical max recipients per campaign? 50,000 rows per campaign (Vibot’s CSV-import ceiling). Beyond that, split into multiple campaigns. Your 24h tier cap will limit how many actually send within a given day regardless.
Q. Why does my Accepted count not equal Total - Skipped?
Some warning categories (recently-spam-blocked-131049, dead-number-warnings) are still in Accepted because they’re warn-only, not skip-skip. They’ll appear in the campaign report as FAILED if Meta confirms.
Q. How is the cost calculated?
(Accepted count) × (per-template rate for your plan and the template category). Marketing / Utility / Authentication each have their own rate. Wallet is debited at launch as a prediction; if some sends are SKIPPED or FAILED, those refunds happen at campaign completion.
Next step
Sends failing in ways you don’t understand? → Why sends fail.