Campaigns
Campaigns send one message (template) to many contacts with the care of respecting who receives it, caution built in. You pick recipients straight from your contact base, compose the message, and bZapper handles the pacing, the ramp-up and the health of your numbers — on its own.
Campaigns are a Pro plan add-on and require at least 1 connected number past ramp-up (7+ days). With 2 or more, bZapper rotates sends across numbers and further reduces the block risk.
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}): personalize per contact — use up to 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 sending controls
Under the hood, every send goes through the same controls:
- Controlled pacing (conservative or normal) with an interval between sends;
- Mandatory ramp-up — a new number (< 7 days) can't join;
- Load spreading (with 2+ numbers) to distribute 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 handles pacing and distribution.