Canned Messages
The canned command (aliases: cm, cms, canned-messages) mirrors the
Settings → Canned Messages page in the app. Use it to save commonly-sent
WhatsApp replies — plain text, images, videos, documents, audio, or any
advanced Meta Cloud API payload — and recall them from chat handlers or
scripts later.
Backed by /api/v1/app/canned-messages[/:id]. Every call uses your stored
oc_live_ token and is scoped to your account.
Quick start
# Save a text snippet
splashify canned create \
--name "Welcome message" \
--shortcut "/welcome" \
--description "First-touch greeting" \
--type TEXT \
--text "Hi! Thanks for reaching out — how can we help?"
# Save an image with a caption
splashify canned create \
--name "Receipt template" \
--type IMAGE \
--url https://cdn.example.com/receipt.png \
--caption "Your receipt is attached"
# See what you've got
splashify cannedMessage types
The backend stores any of these message_type values. The CLI provides
convenience flags for the first five (the ones the app dialog exposes
interactively); the rest are reachable via --payload '<json>'.
| Type | Convenience flags | Built payload shape |
|---|---|---|
TEXT | --text | {"text":{"body":"…"}} |
IMAGE | --url --caption | {"image":{"link":"…","caption":"…"}} |
VIDEO | --url --caption | {"video":{"link":"…","caption":"…"}} |
AUDIO | --url | {"audio":{"link":"…"}} |
DOCUMENT | --url --filename --caption | {"document":{"link":"…","filename":"…","caption":"…"}} |
LOCATION | use --payload | Meta location object |
CONTACT | use --payload | Meta contacts array |
INTERACTIVE_BUTTON | use --payload | Meta interactive (buttons) |
INTERACTIVE_LIST | use --payload | Meta interactive (list) |
INTERACTIVE_CTA_URL | use --payload | Meta interactive (cta_url) |
ADDRESS | use --payload | Meta address-request body |
Why these shapes? They match the app dialog’s
buildPayload()exactly, so payloads written from the CLI render identically in the app’s preview pane and on WhatsApp itself.
Command reference
splashify canned — list
splashify canned # default: every canned message
splashify canned list # alias
splashify canned list --search receipt # name/shortcut/description match
splashify canned list --type IMAGE # filter by message_type
splashify canned list --search hi --type TEXT # combined| Backed by | GET /api/v1/app/canned-messages |
|---|
--search and --type are applied client-side (the backend returns the
full list — same as the app does).
Response shape:
{
"success": true,
"messages": [
{
"id": "uuid",
"name": "Welcome message",
"shortcut": "/welcome",
"description": "First-touch greeting",
"message_type": "TEXT",
"message_payload": {"text": {"body": "Hi! Thanks for reaching out…"}},
"is_active": true,
"created_at": "...",
"updated_at": "..."
}
]
}splashify canned <id> — show one
splashify canned <message_id>No dedicated backend endpoint — the CLI fetches the list and filters
client-side, same pattern as splashify attribute <id> and
splashify member <id>.
splashify canned create — save a new message
splashify canned create \
--name <string> \
--type <TEXT|IMAGE|VIDEO|AUDIO|DOCUMENT|…> \
[--shortcut <string>] [--description <string>] \
[convenience flags OR --payload '<json>']| Flag | Required? | Notes |
|---|---|---|
--name | yes | Max 200 chars. Duplicate names (case-insensitive) are refused with HTTP 409 |
--type | yes | Defaults to TEXT if omitted |
--shortcut | no | The short trigger you type in chat to recall this message |
--description | no | Free-text note |
--text | TEXT | Body text |
--url | media types | Public media URL (use splashify media upload to get one) |
--caption | optional | Caption for IMAGE / VIDEO / DOCUMENT |
--filename | optional | Filename hint for DOCUMENT |
--payload | advanced | Full message_payload JSON — wins over the convenience flags |
| Backed by | POST /api/v1/app/canned-messages |
|---|
splashify canned update — change an existing message
splashify canned update <message_id> [--name …] [--shortcut …] \
[--description …] [--type …] \
[--text … | --url … --caption … --filename …] \
[--payload '{…}']| Backed by | PUT /api/v1/app/canned-messages/:id |
|---|
Read-modify-write. The backend’s PUT replaces every column, so the CLI loads the current record first, overlays only the flags you passed, then sends the full body. Fields you don’t mention stay intact.
# Just rename it
splashify canned update <id> --name "New welcome message"
# Switch the body of a TEXT canned message
splashify canned update <id> --text "Hi there 👋 — what can I do for you?"
# Add a caption to an existing IMAGE canned message
splashify canned update <id> --caption "Updated caption"
# Change a TEXT canned message to a VIDEO (must also pass --url)
splashify canned update <id> --type VIDEO --url https://cdn.example.com/intro.mp4
# Replace the whole payload (advanced types)
splashify canned update <id> --type INTERACTIVE_LIST \
--payload '{"interactive":{"type":"list","body":{"text":"Choose one"}, …}}'splashify canned toggle — activate / deactivate
splashify canned toggle <message_id>| Backed by | POST /api/v1/app/canned-messages/:id/toggle |
|---|
Flips is_active. The endpoint always returns the new state — is_active: true means the message is now usable by chat handlers, false hides it.
splashify canned delete — remove
splashify canned delete <message_id>
splashify canned rm <message_id> # alias
splashify canned remove <message_id> # alias| Backed by | DELETE /api/v1/app/canned-messages/:id |
|---|
Permanent. There is no soft-delete and no recovery — back up first if you need to keep a copy.
Advanced — interactive payloads
For the message types the app dialog does not expose (interactive buttons,
lists, CTA URLs, location, contact, address) use --payload:
splashify canned create \
--name "Quick reply buttons" \
--type INTERACTIVE_BUTTON \
--payload '{
"interactive": {
"type": "button",
"body": {"text": "How can we help?"},
"action": {
"buttons": [
{"type": "reply", "reply": {"id": "billing", "title": "Billing"}},
{"type": "reply", "reply": {"id": "support", "title": "Support"}},
{"type": "reply", "reply": {"id": "sales", "title": "Sales"}}
]
}
}
}'
splashify canned create \
--name "Open store CTA" \
--type INTERACTIVE_CTA_URL \
--payload '{
"interactive": {
"type": "cta_url",
"body": {"text": "Open our online store"},
"action": {
"name": "cta_url",
"parameters": {"display_text": "Open store", "url": "https://shop.example.com"}
}
}
}'
splashify canned create \
--name "Office location" \
--type LOCATION \
--payload '{
"location": {
"latitude": 12.9716,
"longitude": 77.5946,
"name": "HQ",
"address": "Bangalore, India"
}
}'The backend forwards message_payload to Meta verbatim — anything the
WhatsApp Cloud API accepts works.
Common workflows
Bulk-create from a JSON file
// canned.json
[
{"name": "Hi", "type": "TEXT", "text": "Hi! How can we help?"},
{"name": "Hours", "type": "TEXT", "text": "We're open 9-6, Mon-Sat."},
{"name": "Brochure", "type": "DOCUMENT", "url": "https://…/brochure.pdf", "filename": "brochure.pdf"}
]jq -c '.[]' canned.json | while read -r row; do
splashify canned create \
--name "$(echo "$row" | jq -r '.name')" \
--type "$(echo "$row" | jq -r '.type')" \
$(echo "$row" | jq -r 'select(.text) | "--text \"\(.text)\""') \
$(echo "$row" | jq -r 'select(.url) | "--url \(.url)"') \
$(echo "$row" | jq -r 'select(.filename) | "--filename \(.filename)"')
doneDeactivate every TEXT canned message you used last quarter
splashify canned list --type TEXT | \
jq -r '.messages[] | select(.updated_at < "2026-04-01") | .id' | \
xargs -I{} splashify canned toggle {}Find the message backing a /welcome shortcut
splashify canned list --search /welcome | \
jq '.messages[] | select(.shortcut == "/welcome") | {id, name, message_type}'Round-trip an existing payload — copy with a new name
SRC_ID="<existing message_id>"
PAYLOAD=$(splashify canned $SRC_ID | jq -c '.message_payload')
TYPE=$(splashify canned $SRC_ID | jq -r '.message_type')
splashify canned create --name "Welcome — variant B" --type "$TYPE" --payload "$PAYLOAD"Re-upload media + swap the link on an existing canned message
NEW_URL=$(splashify media upload ./receipt-v2.png | jq -r '.file_url')
splashify canned update <id> --url "$NEW_URL" --caption "Updated receipt"Troubleshooting
“A canned message with this name already exists” — names are unique
case-insensitively across your account. Use splashify canned list --search <name> to find the duplicate, then either rename or delete the old row.
“Name must be 200 characters or less” — trim the --name argument.
“Invalid message payload” — your --payload JSON didn’t parse on the
backend. Validate locally with jq first: echo "$PAYLOAD" | jq .
Update didn’t change the type — make sure you passed --type and the
matching media flag. Switching from TEXT → IMAGE without --url would fail
validation; the CLI catches this before the round-trip and prints a usage
error.
--text ignored on an IMAGE — --text only builds the payload for
--type TEXT. For IMAGE/VIDEO/DOCUMENT captions, use --caption instead.
See also
splashify media— upload files first to get the CDN URLs you pass to--url.splashify templates— approved WhatsApp templates, which are different from canned messages (templates need Meta approval, canned messages don’t).splashify message— the send-side commands that can include the payloads you stored here.