Campaigns
Campaigns send one message (template) to many contacts with an anti-ban expert's caution built in. You pick recipients straight from your contact base, compose the message, and bZapper handles the pacing, the warm-up and the protection of your numbers — on its own.
Campaigns are a Pro plan add-on and require at least 2 connected, warmed numbers (7+ days). Rotating across numbers is what dilutes the block risk — hence the minimum of 2.
Pick recipients from your base (no spreadsheet, no JSON)
Instead of pasting a list, you search and select contacts with filters:
- Text search (name, phone, email);
- Filter by contact tags and groups;
- or "select all" matching the filter.
Only valid contacts are added: the server forces status = active and never
includes blocked, opted-out, unreachable or pending-validation contacts — no matter what
is requested. Suppression is re-checked at send time. It is impossible, through the
tool, to message someone who opted out.
In the API, POST /campaigns/{id}/recipients accepts:
{ "contact_ids": ["<uuid>", "..."] } // explicit selection
{ "contact_filter": { "tags": ["vip"], "groups": ["sp"] } } // everyone matching
{ "contact_filter": { "search": "maria" }, "replace": true } // replace the list (draft)
Phones are resolved server-side, only among active contacts. replace: true swaps
the whole list (before the campaign starts).
Message: image + text, with variations
- Header image (optional): upload a PNG/JPEG/WebP (up to 5 MB) via
POST /campaigns/media— it returns a public URL to use invariations[].media. - Text with variables (
{name}) and spintax ({Hi|Hello|Hey}): use 3 variations to reduce the pattern and the block risk.
The builder shows a preview of how the message lands on WhatsApp and a real-time
summary: how many contacts will receive, how many numbers are eligible, and the
estimated send duration (GET /campaigns/estimate?recipients=&pacing=).
Trigger: manual or scheduled
- Manual — the campaign is saved as a draft; you click Start when you want to fire.
- Scheduled — pick a date and time; the campaign fires by itself at that time
(
start_atin the future).
While draft or scheduled, a campaign can be edited (name, pacing, schedule,
message and recipients) via PATCH /campaigns/{id}. Once started it becomes
view-only (409 if you try to edit).
Tracking
The campaign list shows, per campaign, live KPIs (sent, delivered, pending, failed) with a progress bar, plus a filter by status and by title.
Opening a running campaign shows the per-contact breakdown
(GET /campaigns/{id}/recipients): the contact name and the real delivery state —
sent, delivered and read (from WhatsApp receipts), plus failures (with reason)
and suppressed. Filter by Sent / Delivered / Read / Pending / Failed.
The safety autopilot (anti-ban)
Under the hood, every send goes through the anti-ban rail:
- Controlled pacing (conservative or normal) with jitter between sends;
- Mandatory warm-up — a new number (< 7 days) can't join;
- Number rotation (requires 2+ warmed) to spread the volume;
- Business-hours window;
- Smart auto-pause — if inferred blocking rises, the campaign pauses itself and the bad number is penalized.
You focus on the message and the list; bZapper protects your chips.