Campaigns

Campaigns reach a list of recipients with one of your AI agents over voice, SMS, or WhatsApp, at a carrier-safe rate, with automatic retries for no-answer/busy voice calls. You create a campaign, upload recipients, then start it — Voicebip paces the dispatch per carrier and records the outcome of every recipient. This guide leads with voice; SMS and WhatsApp use the same flow with a different config.

The lifecycle is: draft → running ⇄ paused → completed | cancelled.

1. Create a campaign

A new campaign starts in draft. config carries the per-call template (caller-id, optional webhook, optional call window). retry_policy is optional — omit it for no retries.

curl -X POST "https://api.voicebip.com/v1/campaigns" \
-H "Authorization: Bearer pk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"channel": "voice",
"agent_id": "agt_abc123",
"config": {
"from_number": "+2348001234567",
"call_window_start": "09:00",
"call_window_end": "18:00",
"call_window_timezone": "Africa/Lagos"
},
"retry_policy": {
"max_attempts": 3,
"backoff_seconds": 300,
"backoff_multiplier": 2.0
}
}'

Response (201):

{
"id": "camp_abc123",
"channel": "voice",
"agent_id": "agt_abc123",
"status": "draft",
"config": { "from_number": "+2348001234567", "...": "..." },
"retry_policy": { "max_attempts": 3, "backoff_seconds": 300, "backoff_multiplier": 2.0 },
"counters": { "total": 0, "queued": 0, "dispatched": 0, "succeeded": 0, "failed": 0 },
"created_at": "2026-06-11T12:00:00Z"
}

Retry policy

FieldDefaultMeaning
max_attempts3Total dial attempts per recipient (including the first).
backoff_seconds300Base wait before the first retry.
backoff_multiplier2.0Exponential factor: wait = backoff_seconds × multiplier^(attempt-1), capped at 6 hours.

Only transient failures (no_answer, busy) are retried. completed and hard failed outcomes are terminal. Omit retry_policy entirely to disable retries — every recipient is dialed once.

2. Add recipients

Upload recipients in bulk (up to 10,000 per request). Invalid E.164 numbers and in-campaign duplicates are skipped, not fatal — the response reports the counts. params are optional per-recipient template variables.

curl -X POST "https://api.voicebip.com/v1/campaigns/camp_abc123/targets" \
-H "Authorization: Bearer pk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"targets": [
{ "to_address": "+2348031234567", "params": { "first_name": "Ada" } },
{ "to_address": "+2348039876543", "params": { "first_name": "Bola" } }
]
}'

Response (200):

{ "added": 2, "skipped_duplicate": 0, "rejected_invalid": 0 }

3. Start, pause, resume, cancel

# Begin paced dialing (draft → running)
curl -X POST "https://api.voicebip.com/v1/campaigns/camp_abc123/start" \
-H "Authorization: Bearer pk_live_your_key"
# Halt new dials; in-flight calls finish (running → paused)
curl -X POST "https://api.voicebip.com/v1/campaigns/camp_abc123/pause" \
-H "Authorization: Bearer pk_live_your_key"
# Re-seed the remaining recipients (paused → running)
curl -X POST "https://api.voicebip.com/v1/campaigns/camp_abc123/resume" \
-H "Authorization: Bearer pk_live_your_key"
# Stop and discard the backlog (any non-terminal status → cancelled)
curl -X POST "https://api.voicebip.com/v1/campaigns/camp_abc123/cancel" \
-H "Authorization: Bearer pk_live_your_key"

A campaign auto-completes (running → completed) once every recipient has a terminal outcome and no retries remain.

4. Track progress

Poll the campaign for live counters, or list per-recipient outcomes.

# Campaign-level progress
curl "https://api.voicebip.com/v1/campaigns/camp_abc123" \
-H "Authorization: Bearer pk_live_your_key"
{
"id": "camp_abc123",
"status": "running",
"counters": { "total": 500, "queued": 120, "dispatched": 3, "succeeded": 340, "failed": 37 }
}

total = queued + dispatched + succeeded + failed always holds:

  • queued — waiting to be dialed (first attempt or a scheduled retry).
  • dispatched — currently in flight, awaiting outcome.
  • succeeded — call completed.
  • failed — hard failure, or a transient failure that exhausted its retries.
# Per-recipient outcomes (filter by disposition, paginate)
curl "https://api.voicebip.com/v1/campaigns/camp_abc123/targets?disposition=no_answer" \
-H "Authorization: Bearer pk_live_your_key"
{
"targets": [
{
"id": "tgt_xyz789",
"to_address": "+2348031234567",
"disposition": "no_answer",
"attempt_count": 2,
"next_attempt_at": "2026-06-11T12:10:00Z",
"last_exec_id": "call_def456"
}
],
"next_page_token": ""
}

Every campaign-dialed call also appears in GET /v1/calls with its campaign_id set, so transcripts and recordings flow through the usual call APIs.

5. SMS and WhatsApp campaigns

Campaigns aren’t voice-only. Set channel to sms or whatsapp and Voicebip paces the sends the same way it paces dials — per carrier for SMS, per sender + template-category for WhatsApp. The lifecycle, target upload, tracking, and pagination are identical to voice; only config changes per channel.

Channelconfig fieldsPaced byNotes
voicefrom_number, optional call-windowper-carrier concurrencyretries apply (no_answer/busy).
smsfrom_number, bodyper-carrier throughputone campaign = one message body; per-recipient override via target params.body.
whatsappfrom_number, phone_number_id, template_name, language_code, category, optional parametersper-sender daily conversation capWhatsApp campaigns are template campaigns; category is marketing/utility/authentication. Per-recipient template variables via target params.parameters.

SMS campaign:

curl -X POST "https://api.voicebip.com/v1/campaigns" \
-H "Authorization: Bearer pk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"channel": "sms",
"agent_id": "agt_abc123",
"config": { "from_number": "+2348001234567", "body": "Hi {{first_name}}, your order shipped." }
}'

WhatsApp campaign (one approved template, one sender, one category):

curl -X POST "https://api.voicebip.com/v1/campaigns" \
-H "Authorization: Bearer pk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"channel": "whatsapp",
"agent_id": "agt_abc123",
"config": {
"from_number": "+2348001234567",
"phone_number_id": "1234567890",
"template_name": "order_update",
"language_code": "en",
"category": "utility"
}
}'

Recipients who have opted out are suppressed automatically — per-category or blanket for WhatsApp, blanket for SMS — and recorded with disposition opted_out; they are never submitted to the carrier. A messaging recipient is marked sent once the provider accepts the submit. For SMS, the carrier delivery receipt then upgrades that to delivered, or to undeliv on a hard delivery failure. For WhatsApp, Meta upgrades it to delivered / read, or failed. All of this is visible on the target’s disposition.

Notes

  • Pacing and the per-carrier concurrency cap are managed by Voicebip — you don’t set a dial rate; the platform stays within carrier limits.
  • config, schedule, and retry_policy are free-form JSON objects. The voice, sms, and whatsapp channels are supported for campaigns; automatic retries apply to the voice channel today.
  • List endpoints use opaque-cursor pagination (next_page_token).