Programmi con l'IA? Collegala al tuo account via MCP: controlla la tua configurazione, crea webhook e modelli con la tua conferma e scrive il codice. Scopri come →
Un messaggio con da 2 a 10 schede che scorrono, ognuna con la sua foto o il suo video, il suo testo e i suoi pulsanti. Lo prepari dal tuo sistema e lo invii in revisione, come qualsiasi modello:
1. Un campione per scheda:POST /v1/templates/media con l'immagine (JPG/PNG) o il video (MP4) → handle. È quello che Meta revisiona; in ogni invio va la foto vera. 2. Creare:POST /v1/templates con category: "MARKETING", il body principale e carousel.cards[]. Ogni scheda: header { format: IMAGE|VIDEO, handle }, body facoltativo e fino a 2 pulsanti (QUICK_REPLY, URL, PHONE_NUMBER). Prima di Meta controlliamo le sue regole: lo stesso numero di schede all'invio, lo stesso formato in tutte, gli stessi pulsanti nello stesso ordine, il testo della scheda fino a 160 caratteri (in tutte o in nessuna) ed esempi per ogni {{n}}. POST /v1/templates/validate lo prova senza creare nulla; /preview?format=html disegna la striscia scorrevole. 3. Attenderetemplate.status_changed con APPROVED. 4. Inviare:POST /v1/messages con template.carousel.cards[], una per scheda e in ordine: l'header (image/video con mediaId o link), i valori del body e dei pulsanti (quick_reply → il tuo payload, url → la fine del link). 5. Il tocco: arriva message.received con button.payload intatto e tap { cardIndex, buttonIndex }. Meta non invia questi indici: li ricaviamo noi dal tuo payload.
Cosa stabilisce Meta: il carosello esiste solo come MARKETING e ogni invio è addebitato come marketing; Meta lo approva o lo rifiuta come qualsiasi modello; dal 1/4/2025 non consegna marketing ai numeri degli USA (131049), e applica i suoi limiti per persona a tutto il marketing.
# 1) One sample image per card (Meta reviews them) → handles
H1=$(curl -s -X POST https://api.waiaconnect.com/v1/templates/media -H "Authorization: Bearer wc_live_YOUR_API_KEY" -F file=@remera.jpg | jq -r .handle)
H2=$(curl -s -X POST https://api.waiaconnect.com/v1/templates/media -H "Authorization: Bearer wc_live_YOUR_API_KEY" -F file=@buzo.jpg | jq -r .handle)
# 2) Create the carousel (MARKETING, 2–10 cards, same buttons in every card)
BODY='{"connectionId":"conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","name":"novedades_semana","language":"es","category":"MARKETING","body":{"text":"Hola {{1}}, mirá lo nuevo de esta semana.","examples":["Martín"]},"carousel":{"cards":[{"header":{"format":"IMAGE","handle":"H1"},"body":{"text":"Remera {{1}} de algodón.","examples":["azul"]},"buttons":[{"type":"QUICK_REPLY","text":"Me interesa"},{"type":"URL","text":"Ver","url":"https://your-shop.example/p/{{1}}","example":"remera-azul"}]},{"header":{"format":"IMAGE","handle":"H2"},"body":{"text":"Buzo {{1}} de algodón.","examples":["gris"]},"buttons":[{"type":"QUICK_REPLY","text":"Me interesa"},{"type":"URL","text":"Ver","url":"https://your-shop.example/p/{{1}}","example":"buzo-gris"}]}]}}'
BODY=${BODY/H1/$H1}; BODY=${BODY/H2/$H2}
curl -s -X POST https://api.waiaconnect.com/v1/templates/validate -H "Authorization: Bearer wc_live_YOUR_API_KEY" -H "Content-Type: application/json" -d "$BODY"
curl -s -X POST https://api.waiaconnect.com/v1/templates -H "Authorization: Bearer wc_live_YOUR_API_KEY" -H "Content-Type: application/json" -d "$BODY"
# 3) Wait for the template.status_changed webhook with status APPROVED
# 4) Send it: one card per card of the template, in order
curl -s -X POST https://api.waiaconnect.com/v1/messages -H "Authorization: Bearer wc_live_YOUR_API_KEY" \
-H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
-d '{"connectionId":"conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","to":"5493511234567","type":"template","template":{"name":"novedades_semana","language":"es","body":["Sofía"],"carousel":{"cards":[{"header":{"type":"image","link":"https://your-shop.example/img/remera-azul.jpg"},"body":["azul"],"buttons":[{"type":"quick_reply","payload":"remera-azul:me-interesa"},{"type":"url","text":"remera-azul"}]},{"header":{"type":"image","link":"https://your-shop.example/img/buzo-gris.jpg"},"body":["gris"],"buttons":[{"type":"quick_reply","payload":"buzo-gris:me-interesa"},{"type":"url","text":"buzo-gris"}]}]}}}'
# 5) The tap arrives as message.received:
# data.message.button.payload = "buzo-gris:me-interesa" (yours, intact)
# data.tap = { "cardIndex": 1, "buttonIndex": 0 }
import uuid, requests
H = {"Authorization": "Bearer wc_live_YOUR_API_KEY"}
# 1) One sample image per card (Meta reviews them) -> handles
h1 = requests.post("https://api.waiaconnect.com/v1/templates/media", headers=H, files={"file": open("remera.jpg", "rb")}).json()["handle"]
h2 = requests.post("https://api.waiaconnect.com/v1/templates/media", headers=H, files={"file": open("buzo.jpg", "rb")}).json()["handle"]
# 2) Create the carousel (MARKETING, 2-10 cards, same buttons in every card)
definition = {"connectionId":"conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","name":"novedades_semana","language":"es","category":"MARKETING","body":{"text":"Hola {{1}}, mirá lo nuevo de esta semana.","examples":["Martín"]},"carousel":{"cards":[{"header":{"format":"IMAGE","handle":h1},"body":{"text":"Remera {{1}} de algodón.","examples":["azul"]},"buttons":[{"type":"QUICK_REPLY","text":"Me interesa"},{"type":"URL","text":"Ver","url":"https://your-shop.example/p/{{1}}","example":"remera-azul"}]},{"header":{"format":"IMAGE","handle":h2},"body":{"text":"Buzo {{1}} de algodón.","examples":["gris"]},"buttons":[{"type":"QUICK_REPLY","text":"Me interesa"},{"type":"URL","text":"Ver","url":"https://your-shop.example/p/{{1}}","example":"buzo-gris"}]}]}}
requests.post("https://api.waiaconnect.com/v1/templates", headers=H, json=definition).raise_for_status()
# 3) Wait for template.status_changed (APPROVED) on your webhook, then
# 4) send it: one card per card of the template, in order
requests.post("https://api.waiaconnect.com/v1/messages", headers={**H, "Idempotency-Key": str(uuid.uuid4())}, json={"connectionId":"conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","to":"5493511234567","type":"template","template":{"name":"novedades_semana","language":"es","body":["Sofía"],"carousel":{"cards":[{"header":{"type":"image","link":"https://your-shop.example/img/remera-azul.jpg"},"body":["azul"],"buttons":[{"type":"quick_reply","payload":"remera-azul:me-interesa"},{"type":"url","text":"remera-azul"}]},{"header":{"type":"image","link":"https://your-shop.example/img/buzo-gris.jpg"},"body":["gris"],"buttons":[{"type":"quick_reply","payload":"buzo-gris:me-interesa"},{"type":"url","text":"buzo-gris"}]}]}}})
# 5) In your webhook handler: which card and which button
def on_event(evt):
if evt["type"] == "message.received" and evt["data"]["message"]["type"] == "button":
payload = evt["data"]["message"]["button"]["payload"] # yours, intact
tap = evt["data"].get("tap") # {"cardIndex": 1, "buttonIndex": 0}
print(payload, tap)
Dai a ogni risposta rapida il suo payload (per esempio felpa-grigia:mi-interessa): con due uguali nello stesso messaggio non si può sapere quale è stata toccata, e tap non arriva. Una risposta rapida «Disiscrivimi» arriva allo stesso modo: la disiscrizione la registra il tuo sistema.
I pulsanti di link e di chiamata non generano avvisi: Meta apre il browser o il telefono.
Un carosello creato in WhatsApp Manager si sincronizza con le sue schede (GET /v1/templates, carousel.cards) e si invia allo stesso modo.
Il carosello di prodotti del catalogo (pulsante «Vedi», acquisto dentro WhatsApp) non ancora.