Bulk sends API

Send an approved template to a segment with every safeguard. 7 ops: list_campaigns, get_campaign, create_campaign, estimate_campaign, send_campaign, pause_campaign, cancel_campaign.

Send an approved template to a segment with every safeguard.

List campaigns · POST /api/v1/list_campaigns · scope campaigns:read or GET …?input=

Campaigns, newest first, with status, template, segment and stats.

curl -X POST https://getwabi.dev/api/v1/list_campaigns \  -H "Authorization: Bearer wabi_…"

Get a campaign · POST /api/v1/get_campaign · scope campaigns:read or GET …?input=

A campaign with its last estimate and live progress: recipients by status (pending, queued, excluded with reasons, refused, canceled) and messages sent, delivered, read and failed.

curl -X POST https://getwabi.dev/api/v1/get_campaign \  -H "Authorization: Bearer wabi_…" \  -H "Content-Type: application/json" \  -d '{"campaign":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}'

Create a campaign · POST /api/v1/create_campaign · scope campaigns:write

Creates a draft campaign: one approved template (name, language, components with the variable values) sent from one number to a segment (id or builtin:<name>). Marketing templates require granted consent for consent_purpose (default marketing; null only for utility templates the contacts expect). frequency_cap_hours skips contacts that got any campaign message that recently. Nothing is sent: call estimate_campaign (dry run and cost), then send_campaign.

curl -X POST https://getwabi.dev/api/v1/create_campaign \  -H "Authorization: Bearer wabi_…" \  -H "Content-Type: application/json" \  -d '{"name":"Support","phone_number_id":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10","segment":"segment","template":{"name":"Support","language":"es"}}'

Dry-run a campaign · POST /api/v1/estimate_campaign · scope campaigns:read or GET …?input=

Resolves the campaign's audience now without sending: how many would receive it, how many are excluded and why (opted_out, no_consent, consent_revoked, frequency_cap, duplicate, not_a_sandbox_contact, over_limit), sample recipients, and Meta's cost at the published per-message rates by market (shown at cost, billed by Meta to your WABA; the sandbox is free). Also says whether the plan allows the send.

curl -X POST https://getwabi.dev/api/v1/estimate_campaign \  -H "Authorization: Bearer wabi_…" \  -H "Content-Type: application/json" \  -d '{"campaign":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}'

Send a campaign · POST /api/v1/send_campaign · scope campaigns:write

Starts a draft campaign (or schedules it when scheduled_at is in the future): freezes the eligible audience and sends in batches through the messaging engine, whose safeguards apply to every message. Needs confirm: true after a person approved the estimate. Live numbers need the Growth plan; the sandbox works on every plan. Returns the campaign; follow progress with get_campaign.

curl -X POST https://getwabi.dev/api/v1/send_campaign \  -H "Authorization: Bearer wabi_…" \  -H "Content-Type: application/json" \  -d '{"campaign":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10","confirm":false}'

Pause or resume a campaign · POST /api/v1/pause_campaign · scope campaigns:write

Pauses a sending or scheduled campaign (messages already queued still go out) or resumes a paused one.

curl -X POST https://getwabi.dev/api/v1/pause_campaign \  -H "Authorization: Bearer wabi_…" \  -H "Content-Type: application/json" \  -d '{"campaign":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10","paused":false}'

Cancel a campaign · POST /api/v1/cancel_campaign · scope campaigns:write

Cancels a campaign: recipients not yet sent to are skipped. Messages already queued may still go out.

curl -X POST https://getwabi.dev/api/v1/cancel_campaign \  -H "Authorization: Bearer wabi_…" \  -H "Content-Type: application/json" \  -d '{"campaign":"6f1c2e0a-4b7d-4c2e-9a51-0d3b8e7f9a10"}'