Skip to Content
splashify CLIWhatsApp Calling

WhatsApp Calling

The calling command mirrors the /calling page and call is its per-id sibling. Together they cover everything the page does except the browser-only WebRTC live-audio bridge (intentionally — it’s a real-time audio stream that has no place in a CLI).

Backed by /api/v1/app/calling/*. Like broadcasts and email, every send runs a subscription + wallet preflight before submission.

Quick start

splashify calling # overview card (page header) splashify calling analytics # period analytics splashify calling calls --limit 50 # recent calls # Templates splashify calling templates # list splashify calling template create-call-button # tap-to-call (URL/PHONE) splashify calling template create-permission # permission request splashify calling send <template_id> --to +91… # send a template message # Backend-initiated outbound call splashify calling initiate --to +91… --phone-number-id <id> # Recordings splashify calling upload-recording <file> --call-id <id>

Command reference

Overview, settings, analytics, history

splashify calling # page-header overview splashify calling overview # alias splashify calling settings # business hours + icon visibility splashify calling settings update --hours --icon-visible true splashify calling analytics [--period 30d|7d|today] splashify calling calls [--limit N] [--status sent|delivered|failed] splashify calling call <call_id> # detail (alias: splashify call <id>) splashify calling call <call_id> status # latest status from backend
Backed byGET /app/calling/overview
GET/PUT /app/calling/settings
GET /app/calling/analytics?period=…
GET /app/calling/calls?limit=&status=
GET /app/calling/calls/:call_id
GET /app/calling/calls/:call_id/status

Templates — call buttons & permissions

WhatsApp Calling has two template variants:

TypePurposeBackend
Call buttonAdds a tap-to-call CTA on outbound messagesPOST /app/calling/templates/call-button
PermissionAsks the recipient to grant calling permission firstPOST /app/calling/templates/permission
splashify calling templates # list all splashify calling template <template_id> # show one splashify calling template create-call-button \ --name "support_cb" --label "Call support" --phone-number +919876543210 splashify calling template create-permission \ --name "ask_perm" --body "Tap to allow us to call you" splashify calling template set-default <template_id> # default for sends splashify calling template delete <template_id>
Backed byGET/DELETE /app/calling/templates[/:id]
POST /app/calling/templates/call-button
POST /app/calling/templates/permission
POST /app/calling/templates/:id/set-default

Send a calling template message

splashify calling send <template_id> --to +919876543210 splashify calling send <template_id> --to +919876543210 --vars '["John","ORD-1024"]'
Backed byPOST /app/calling/send

Same preflight as broadcasts/email — refuses on subscription_expired or insufficient_balance before round-trip. Calling has its own per-call rate (separate from text + media).

Initiate an outbound call (backend dial)

splashify calling initiate --to +919876543210 --phone-number-id <waba_phone_id>
Backed byPOST /app/calling/initiate

Triggers a backend-initiated call (the WABA dials the recipient). Same preflight applies. Returns the new call_id you can poll with splashify calling call <id> status.

No browser bridge. The page also has a WebRTC live-audio bridge for answering the call in your browser. The CLI cannot do that — initiate from the CLI and answer in the browser (or via your phone’s WABA app).

Permission lookup

splashify calling permission-status --to +919876543210 # has this user granted calling perm? splashify calling permissions # all granted permissions
Backed byGET /app/calling/permission-status?phone=…
GET /app/calling/permissions

Upload a recording

splashify calling upload-recording ./call.mp3 --call-id <call_id>
Backed byPOST /app/calling/calls/:call_id/recording (multipart)

Uploads a recording to attach to a call row — useful when the audio came from a third-party PBX and you want it logged in /calling/<id>.

Common workflows

Daily call volume report

splashify calling analytics --period 7d | \ jq '.analytics.daily_series[] | {date, total: .count, failed: .failed_count}'

Re-send the default call-button template to every contact tagged “leads”

TPL=$(splashify calling templates | jq -r '.templates[] | select(.is_default) | .template_id') splashify contacts --tag leads | jq -r '.contacts[].phone_number' | \ xargs -I{} splashify calling send "$TPL" --to {}

Watch a call ring through

RESP=$(splashify calling initiate --to +919876543210 --phone-number-id <id>) CID=$(echo "$RESP" | jq -r '.call_id') while : ; do STATUS=$(splashify calling call "$CID" status | jq -r '.status') echo "$(date -u +%H:%M:%S) $STATUS" [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ] && break sleep 2 done

Pause calling outside business hours

splashify calling settings update \ --hours '{"mon":["09:00","18:00"],"tue":["09:00","18:00"], … }' \ --icon-visible true

Troubleshooting

permission_required on send — the recipient hasn’t accepted the permission template. Send a --type permission template first (or check with splashify calling permission-status).

subscription_expired / insufficient_balance — same preflight errors as broadcasts/email. See Subscription and Wallet.

initiate 502s — Meta’s outbound dial gateway is occasionally flaky. Retry after ~30s; persistent failures usually mean the recipient’s IG account is mid-suspension. Check splashify calling call <id> status for the latest reason.

Upload-recording rejects the file — Meta accepts MP3/WAV up to ~25MB. Larger files / other formats are refused with a 400 listing the limits.

No WebRTC bridge in the CLI — by design. Initiate + monitor from the CLI, answer in the browser (or your WABA app).

See also