niiko/developers

Miira · leads & WhatsApp v1 current

miira.broadcast_quoted

Quotes sending the SAME WhatsApp message to several clients named by name (up to 50). Sends NOTHING: per client, it says whether the text goes as-is (24-hour window open, free), whether an approved template is needed and what it costs, or why that client cannot be messaged. Returns a signed quote valid for 15 minutes; to send, call miira.broadcast_sent with it. Show the quote to the person first. Optional `purpose`: `notice` (default) is the usual notice; `promotion` NEVER sends free text, even with the window open, and requires an approved MARKETING template (otherwise plantilla_invalida): it only reaches clients with granted marketing consent (no_marketing_consent otherwise) and leaves US numbers out (us_moratorium). In a promotion `message` is never sent: what goes is the template with its `templateValues`. Use `promotion` for offers and campaigns, never for a reply or a notice.

Last updated

POST /api/v1/actions/miira.broadcast_quoted
Key scope
miira.broadcast_quoted@1
Workspace permission
api.miira.broadcast_quoted off by default
Two permissions, not one

Both are needed: a key with that scope, and the workspace owner having switched the permission on. Holding the key is not enough — they are two decisions made by different people.

Request

fieldtyperules
clientsstring[]required
messagestringrequiredmin 1 · max 4096
templatestringoptionalmin 1 · max 512
templateValuesstring[]optional
purpose"notice" | "promotion"optional

Response — output when status is done

fieldtyperules
rowsobject[]required
totalsobjectrequired
quotestring | nullrequired
expiresAtstring | nullrequired

rows[]

fieldtyperules
clientstringrequired
clientIdstring | nullrequired
clientNamestring | nullrequired
outcome"free_text" | "template" | "needs_template" | "no_phone" | "suppressed" | "consent_revoked" | "no_marketing_consent" | "quiet_hours" | "not_found" | "ambiguous" | "too_many" | "us_moratorium"required
costUsdstring | nullrequired
candidatesstring[]optional

totals

fieldtyperules
freeTextintegerrequired
templateintegerrequired
skippedintegerrequired
costUsdstringrequired

Example

# One request, one idempotency key: retrying with the same key never runs twice.
curl -X POST https://niiko.org/api/v1/actions/miira.broadcast_quoted \
  -H "Authorization: Bearer nk_…" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "clients": [
      "…"
    ],
    "message": "…"
  }'
# 200 → done · 202 → pending_approval (a person signs later) · 4xx → refused, with a named reason

Why it may refuse

Each reason names who can fix it and how. With reason stale, detail.message says what to do.

plantilla_invalidatarifas_vencidassin_permiso

In the clients

@vorluno/niiko-sdkniiko.quotedBroadcast()
niiko (Python)niiko.quoted_broadcast()
niiko-cliniiko run miira.broadcast_quoted
n8n-nodes-niikomiiraBroadcastQuoted
niiko-mcp-servermiira_broadcast_quoted

History