zavudev/zavu-skills

broadcast-campaign

Create and manage broadcast campaigns for bulk messaging across SMS, WhatsApp, Email, and Telegram.

First seen Mar 10, 2026

Installation

$ npx skills add zavudev/zavu-skills --skill broadcast-campaign

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from zavudev/zavu-skills · top by installs.

npx skills add zavudev/zavu-skills

Browse all from zavudev/zavu-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 1
License LICENSE
Default branch main
Open issues 0
Status Active

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 8,760 B
  • docs SUMMARY.md 3,764 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 211 installs

SKILL.md

Broadcast Campaign

When to Use

Use this skill when building code to send messages to multiple recipients in a campaign — including bulk email. Covers the full broadcast lifecycle from creation to monitoring.

Broadcast Lifecycle

draft -> pending_review -> pending_admin_review -> approved -> sending -> completed
                        -> rejected -> (edit) -> pending_review (retry, max 3)
                        -> rejected -> escalated (manual review by Zavu team)
                        -> rejected_final
         approved -> scheduled -> sending -> completed
         sending -> paused (can resume)
         (any active) -> cancelled
         (any) -> failed (permanent failure)

Step-by-Step Workflow

1. Create Broadcast

const result = await zavu.broadcasts.create({
  name: "Black Friday Sale",
  channel: "sms", // smart | sms | sms_oneway | whatsapp | telegram | email
  text: "Hi {{name}}, check out our Black Friday deals! Code: FRIDAY20",
});
const broadcastId = result.broadcast.id; // brd_xxx

Python:

result = zavu.broadcasts.create(
    name="Black Friday Sale",
    channel="sms",
    text="Hi {{name}}, check out our Black Friday deals! Code: FRIDAY20",
)
broadcast_id = result.broadcast.id

Go:

result, err := client.Broadcasts.Create(context.TODO(), zavudev.BroadcastCreateParams{
    Name:    zavudev.String("Black Friday Sale"),
    Channel: zavudev.String("sms"),
    Text:    zavudev.String("Hi {{name}}, check out our Black Friday deals! Code: FRIDAY20"),
})
broadcastID := result.Broadcast.ID

Ruby:

result = client.broadcasts.create(
    name: "Black Friday Sale",
    channel: "sms",
    text: "Hi {{name}}, check out our Black Friday deals! Code: FRIDAY20",
)
broadcast_id = result.broadcast.id

PHP:

$result = $client->broadcasts->create([
    'name' => 'Black Friday Sale',
    'channel' => 'sms',
    'text' => 'Hi {{name}}, check out our Black Friday deals! Code: FRIDAY20',
]);
$broadcastId = $result->broadcast->id;

Channel Options

Channel Description
smart Per-contact intelligent routing
sms SMS to all contacts
sms_oneway One-way SMS (no replies)
whatsapp WhatsApp (requires template for non-window contacts)
telegram Telegram
email Email (needs emailSubject) — recommended path for bulk email

Message Types

Type Description
text Plain text (default)
image Image with optional caption
video Video message
audio Audio message
document Document file
template WhatsApp pre-approved template

Email Broadcast (with HTML body)

For bulk email campaigns, use channel: "email" with an HTML body. This is the recommended way to send mass email through Zavu.

const result = await zavu.broadcasts.create({
  name: "Newsletter",
  channel: "email",
  emailSubject: "Special offer for {{name}}",
  text: "Hi {{name}}, check out our latest sale!",   // plain text fallback
  emailHtmlBody: "<h1>Hi {{name}}!</h1><p>Check out our latest sale.</p>",
  metadata: { campaign_id: "camp_123", region: "US" },
});

2. Add Contacts (batch, max 1000/request)

const result = await zavu.broadcasts.contacts.add({
  broadcastId: broadcastId,
  contacts: [
    { recipient: "+14155551234", templateVariables: { name: "John" } },
    { recipient: "+14155555678", templateVariables: { name: "Jane" } },
  ],
});
console.log(result.added, result.duplicates, result.invalid);

3. Send (triggers content review)

Sending requires the account to be past the unverified floor. Any one of these clears it, and they are not equally slow:

Route What it takes
Payment method Add a card, or settle the deposit — about half a minute
Paid plan Any paid subscription
Identity verification (KYC) A document and a selfie, a few minutes

Without one, the send is refused with 403 kyc_required and the message "Verify your identity, add a payment method, or upgrade before sending broadcasts. You can keep editing this draft in the meantime." (details.dashboardUrl is /kyc). Business verification (KYB) is not required to broadcast: it gates 10DLC registration, nothing here.

A whatsapp broadcast is exempt. It can only be built on a template, and Meta vets the business and the content when it approves that template, so the code is never returned for one. What is enforced instead is that the template is approved — an unapproved one is refused with 400 templatenotapproved, and since WhatsApp passes no other review, that is the only gate on it. smart is not exempt: it can route a contact to SMS or email.

Creating and editing drafts needs no check at all — everything above works unverified, and only this call is blocked.

// Send immediately
await zavu.broadcasts.send({ broadcastId });

// Or schedule
await zavu.broadcasts.send({
  broadcastId,
  scheduledAt: "2024-01-15T10:00:00Z",
});

A draft never goes straight out — what happens next depends on the channel:

Broadcast What this call does
WhatsApp on a Meta-approved template Skips review (Meta already vetted it) and starts sending
Email Automated review; sends as soon as it passes
SMS, Telegram, smart, everything else Automated review, then pendingadminreview — a person approves before it sends

So a 202 means accepted, not sending. Poll the status rather than assuming; only WhatsApp-template broadcasts move to sending immediately.

Calling send on a broadcast that is already approved or scheduled sends or reschedules it directly, since it has already been through review.

4. Monitor Progress

const progress = await zavu.broadcasts.progress({ broadcastId });
console.log(`${progress.percentComplete}% complete`);
console.log(`Delivered: ${progress.delivered}, Failed: ${progress.failed}, Skipped: ${progress.skipped}`);
console.log(`Estimated completion: ${progress.estimatedCompletionAt}`);

Per-contact statuses: pending, queued, sending, delivered, failed, skipped (excluded — opted out, duplicate, or invalid).

5. Handle Rejection (if content review fails)

// Check remaining review attempts
const broadcast = await zavu.broadcasts.get({ broadcastId });
console.log(`Review attempts: ${broadcast.reviewAttempts}/3`);

// Edit content
await zavu.broadcasts.update({
  broadcastId,
  text: "Updated message content with {{name}}",
});

// Retry review (max 3 attempts)
await zavu.broadcasts.retryReview({ broadcastId });

// Or escalate to manual review
await zavu.broadcasts.escalate({ broadcastId });

Other Operations

// Reschedule
await zavu.broadcasts.reschedule({
  broadcastId, scheduledAt: "2024-01-16T14:00:00Z",
});

// Cancel (pending contacts skipped, queued may still deliver)
await zavu.broadcasts.cancel({ broadcastId });

// List contacts in broadcast
const contacts = await zavu.broadcasts.contacts.list({
  broadcastId, status: "delivered", limit: 100,
});

// Delete (draft only)
await zavu.broadcasts.delete({ broadcastId });

Template Variables

Use {{variable_name}} in broadcast text. Override per-contact via templateVariables:

await zavu.broadcasts.contacts.add({
  broadcastId,
  contacts: [
    { recipient: "+14155551234", templateVariables: { name: "John", order_id: "ORD-001" } },
  ],
});

Constraints

  • Max 1000 contacts per add request (batch for larger lists)
  • Sending requires the account past the unverified floor — a payment method, a paid plan or KYC, any one of them (403 kyc_required otherwise) — on every channel except whatsapp, which is exempt because Meta's template approval stands in for it; smart is not exempt. KYB is not required. Drafting requires nothing
  • Each recipient counts against the channel's daily ceiling (see the send-message skill); once it is reached the remaining recipients are marked failed with errorCode: "DAILYLIMITEXCEEDED" and are not retried the next day
  • Content goes through review before sending, except WhatsApp on a Meta-approved template
  • Most channels also wait on a human (pendingadminreview) after the automated pass
  • Balance is reserved (estimated cost) when sending
  • Max 3 review retry attempts, then escalate
  • Can only update/delete broadcasts in draft status
  • Cancelling doesn't stop already-queued messages