Skip to content
Splashify Pro
Docs

Broadcasts

The broadcasts (plural) and broadcast (singular) commands mirror the /broadcasts and /broadcasts/<id> pages. From the terminal you can list every campaign, drill into one, see per-message delivery, cancel an in-flight broadcast, send a scheduled one immediately, restart a partially failed run, and rebroadcast a cohort.

Every write command runs the same subscription + wallet preflight that the page does before submitting; the backend still enforces both at send time. A broadcast that fails preflight prints why and exits non-zero without burning a wallet hold.

Quick start

bash
splashify broadcasts                                 # list every campaign
splashify broadcast stats                            # overall stats card
splashify broadcast <broadcast_id>                   # campaign detail

splashify broadcast create \
  --name "May Sale" \
  --template may_offer \
  --audience-type segment \
  --audience-id <segment_id> \
  --schedule 2026-06-01T10:00:00Z

Command reference

splashify broadcasts — list campaigns

bash
splashify broadcasts                                 # all

Response shape (per row):

json
{
  "broadcast_id":   "uuid",
  "name":           "May Sale",
  "template_name":  "may_offer",
  "audience_type":  "segment",      // segment | tag | all
  "audience_id":    "...",
  "status":         "scheduled",    // draft | scheduled | running | completed | cancelled | failed
  "schedule_at":    "2026-06-01T10:00:00Z",
  "started_at":     null,
  "completed_at":   null,
  "created_at":     "...",
  "total_recipients":  1245,
  "sent_count":     0,
  "delivered_count":0,
  "read_count":     0,
  "failed_count":   0
}

splashify broadcast stats — global stats

bash
splashify broadcast stats

Returns counts across every broadcast (total / completed / running / failed) plus aggregate delivery metrics.

splashify broadcast <broadcast_id> — campaign detail

bash
splashify broadcast 7a32bce6-…

Returns the full broadcast row plus the cohort counts and progress breakdown shown on the detail page.

splashify broadcast create — schedule a new campaign

bash
splashify broadcast create \
  --name "May Sale" \
  --template may_offer \
  --audience-type segment \
  --audience-id <segment_id> \
  --schedule 2026-06-01T10:00:00Z

Preflight checks before the round-trip:

  1. Subscription — the account must have an active plan OR unexpired trial. A subscription_expired refusal points to /settings/subscriptions.
  2. Balance — the wallet must cover the estimated cost (recipients × per-message rate for the template's category). If short, the CLI surfaces the shortfall and the recharge link.

If either fails the CLI exits with the friendly error and does not create the broadcast. Once submitted, the backend's broadcast worker enforces both again at send time (defence in depth).

Lifecycle actions

Per-id actions live after the broadcast id — splashify broadcast <id> <action>.

bash
splashify broadcast <broadcast_id> cancel            # stop a scheduled/running broadcast
splashify broadcast <broadcast_id> send-now          # send a `scheduled` broadcast immediately
splashify broadcast <broadcast_id> restart           # retry the failed cohort on a `failed`/partial broadcast
splashify broadcast <broadcast_id> rebroadcast \
  --cohort failed|sent|delivered|read|all            # re-target a specific cohort on a fresh row

All four run the same preflight as create. cancel is irreversible — once a broadcast moves to cancelled, you re-broadcast or create a new one.

Per-message inspection

bash
splashify broadcast <broadcast_id> messages [--page N] [--limit N] [--status sent|delivered|read|failed]
splashify broadcast <broadcast_id> progress          # live SSE stream of progress events
splashify broadcast <broadcast_id> progress --once   # print the first event and exit
splashify broadcast <broadcast_id> progress --max 10 # stop after N events
splashify broadcast <broadcast_id> cohorts           # cohort counts (failed / sent / delivered / read)
splashify broadcast <broadcast_id> --recompute       # refresh the local rollup (Refresh button)

--recompute is the page's "Refresh" button — it re-aggregates the per-message rows into the broadcast row's counters. Use it if the totals look stale. progress streams Server-Sent Events the same way the /broadcasts/<id>/progress page does; the loop ends when the broadcast reaches a terminal state (completed, cancelled, failed) or when --max / --once is satisfied.

CSV export

bash
splashify broadcast <broadcast_id> export > campaign.csv

# Filter by message status before exporting
splashify broadcast <broadcast_id> export --status FAILED > failed.csv
splashify broadcast <broadcast_id> export --csv         # force the CSV content-type

Streams the same CSV the page's Export CSV button produces — one row per recipient with phone, status, sent_at, delivered_at, failed_reason, etc. The CLI writes the raw response to stdout so you can redirect or pipe.

Live progress (SSE)

bash
splashify broadcast <broadcast_id> progress              # follow until terminal status
splashify broadcast <broadcast_id> progress --once       # snapshot (first event, then exit)
splashify broadcast <broadcast_id> progress --max 10     # stop after N events

Mirrors the /broadcasts/<id>/progress page. The CLI connects to the SSE stream, prints one JSON object per event (running counts + status), and exits cleanly when the broadcast reaches a terminal state (COMPLETED, CANCELLED, or FAILED). Aliases: watch, stream.

Each event has the shape:

json
{
  "broadcast_id": "uuid",
  "status":       "SENDING",
  "pct":          42.3,
  "counts": {
    "pending":   100,
    "sent":      850,
    "delivered": 820,
    "read":      612,
    "failed":    13
  }
}

Common workflows

List broadcasts that need attention

bash
splashify broadcasts | jq '.broadcasts[] |
  select(.status == "failed" or .failed_count > 0) |
  {broadcast_id, name, status, failed_count, total_recipients}'

Watch a broadcast finish

bash
# Recommended: follow the SSE stream and exit on terminal status
splashify broadcast 7a32bce6-… progress

Need a polling loop instead (e.g. logging snapshots every 30s)?

bash
BID=7a32bce6-…
while : ; do
  STATUS=$(splashify broadcast "$BID" | jq -r '.status // .broadcast.status')
  PROG=$(splashify broadcast "$BID" progress --once | jq -c '.counts // .')
  echo "$(date -u +%H:%M:%S)  $STATUS  $PROG"
  [ "$STATUS" = "completed" ] || [ "$STATUS" = "cancelled" ] || [ "$STATUS" = "failed" ] && break
  sleep 30
done

Send to every "VIP" contact

bash
SEGMENT_ID=$(splashify segments --search "VIP" | jq -r '.segments[0].id')
splashify broadcast create \
  --name "VIP exclusive — May" \
  --template vip_may_offer \
  --audience-type segment \
  --audience-id "$SEGMENT_ID"

Cancel every scheduled broadcast (e.g. emergency stop)

bash
splashify broadcasts | \
  jq -r '.broadcasts[] | select(.status == "scheduled") | .broadcast_id' | \
  xargs -I{} splashify broadcast {} cancel

Rebroadcast to recipients who failed

bash
splashify broadcast <broadcast_id> rebroadcast --cohort failed
# Backend re-targets only the recipients whose message status is `failed`,
# at the same template, on a fresh broadcast row.

Troubleshooting

subscription_expired on create — the account has no active paid plan and the trial is over. Open /settings/subscriptions or run splashify subscription for status + upgrade URL.

insufficient_balance on create — wallet won't cover the estimated cost. The error includes the shortfall amount and a recharge link. splashify wallet shows the current balance; recharge from the app.

Template not found / not approved — --template takes the template name, not the ID. The template must be APPROVED on Meta — run splashify templates sync to refresh status, then splashify template <id> to confirm.

audience_id ignored — required only when --audience-type is segment or tag. For all, omit it.

Counts look wrong on the detail view — run splashify broadcast recompute-stats <id>. The page's per-row counts come from a rollup that can lag during heavy bursts.

Cancelled but still receiving deliveries — cancellation stops scheduling of new messages. Messages already in Meta's outbound queue get delivered; webhook updates land normally. Wait ~1 minute after cancel to see the final counts settle.

See also