É o caso de uso mais comum de um template de utilidade: mandar a fatura. Um template da Meta pode levar um cabeçalho com um documento, uma imagem ou um vídeo, e esse arquivo é escolhido a cada envio — o template aprovado define o TIPO, você põe o arquivo.
Como se manda. Igual a qualquer template (POST /v1/messages com type: "template"), mas o array components leva primeiro um componente header com o arquivo:
{ "type": "header", "parameters": [ { "type": "document", "document": { "link": "https://…/A-1042.pdf", "filename": "Fatura A-1042.pdf" } } ] }
De onde sai o arquivo: de um link seu. A Meta aceita link (uma URL https pública que ela baixa) ou id (um identificador de mídia). O Connect não armazena arquivos e não tem endpoint de upload, então os únicos id que existem são os de arquivos que você RECEBEU — para mandar uma fatura sua, hospede-a e mande o link. É o mesmo critério de «Enviar mídia», e pelo mesmo motivo: não guardamos conteúdo.
⚠ O tipo do parâmetro é definido pelo TEMPLATE, não pelo arquivo. Se a Meta aprovou o cabeçalho como DOCUMENT, o parâmetro vai como document mesmo que o arquivo seja um JPG. Mandar image sobre um template DOCUMENT a Meta recusa.
⚠ filename é só para documentos (é o nome que quem recebe vê). Em imagem e vídeo, a Meta recusa.
🔴 O que NÃO dá para fazer: CRIAR um template com cabeçalho de arquivo pelo Connect. Só se criam cabeçalhos de texto. Se você mandar um header.format de imagem/documento/vídeo para POST /v1/templates, respondemos 400 TEMPLATE_PRECHECK_FAILED com o código TPL_HEADER_FORMAT_UNSUPPORTED — não o criamos pela metade nem dizemos que sim. O caminho é: crie-o no Gerenciador de Negócios da Meta (ali sim aceita cabeçalhos de arquivo) e depois POST /v1/templates/sync — o Connect o lê corretamente, lista, avisa quando muda de estado e o envia como dito acima.
curl -X POST https://api.waiaconnect.com/v1/messages \
-H "Authorization: Bearer wc_live_YOUR_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"connectionId":"conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","to":"5493511234567","type":"template","template":{"name":"envio_factura","language":"es","components":[{"type":"header","parameters":[{"type":"document","document":{"link":"https://your-server.example/invoices/A-1042.pdf","filename":"Factura A-1042.pdf"}}]},{"type":"body","parameters":[{"type":"text","text":"María"}]}]}}'
# The header component goes FIRST and its type is the one the APPROVED TEMPLATE
# declares (document | image | video) — NOT the file's mime type.
# image: {"type":"image","image":{"link":"https://…/photo.jpg"}} (no filename)
# by media id instead of a link: {"document":{"id":"1234567890"}}
# ⚠ You cannot CREATE a media-header template from Connect (only TEXT headers).
# Create it in Meta Business Manager, then POST /v1/templates/sync.Como saber se um template leva arquivo: GET /v1/templates devolve header: { format: "DOCUMENT" } (ou IMAGE/VIDEO). No painel estão marcados com 📎.
Se você esquecer o arquivo, avisamos ANTES da Meta: 422 TEMPLATE_HEADER_MEDIA_REQUIRED, com details.example = o componente exato que falta. A Meta, por outro lado, responde um 132000 opaco.
E se chegar mesmo assim (um template que ainda não sincronizamos), a mensagem falha na primeira tentativa com lastErrorCode = TEMPLATE_PARAM_MISMATCH — não se tenta cinco vezes um payload que não pode funcionar.
O que o link precisa: ser https, apontar direto para o arquivo (sem login nem página intermediária) e trazer o Content-Type correto. ⚠ Um link de "compartilhar" do Google Drive ou do Dropbox devolve uma página HTML: a Meta a baixa e recusa o envio. Limites da Meta: documento 100 MB, imagem 5 MB, vídeo 16 MB.
A Meta guarda o seu link em cache por 10 minutos: se você trocar o arquivo por trás da mesma URL, acrescente um ?v=… diferente.