waiaconnect

Documentação / Essencial

Enviar mídia (imagem · documento · áudio · vídeo)

POST /v1/messages

Markdown

O Connect não armazena arquivos. Para mandar um arquivo seu, hospede-o e mande o link dele (link) — quem baixa é a Meta, não nós. Esse é o caminho principal, não a alternativa.

Os identificadores (id) são os de arquivos que você RECEBEU: chegam dentro do evento de uma mensagem recebida (data.message.image.id, .document.id, …). Não há endpoint de upload — GET /v1/media/:mediaId é só de download —, então não existe forma de obter um id para um arquivo seu.

⚠ E a parte incômoda, dita como é: a Meta costuma permitir reutilizar um identificador recebido para responder do mesmo número, mas não garante e nós ainda não verificamos contra a Meta real. Não afirmamos nem negamos. Se importa para você que saia sempre, use o link.

Quer mandar SEMPRE o mesmo arquivo — uma lista de preços, um manual, um catálogo? Hospede-o e mande o link. É a resposta completa: não há um id próprio para guardar e reutilizar. E não é uma limitação disfarçada — não guardamos arquivos porque não guardamos conteúdo (nem o texto das suas mensagens, salvo o histórico de Coexistence que você escolhe receber: criptografado e por 7 dias no máximo). É exatamente o que a nossa política de privacidade promete, aplicado aqui.

Como se manda. POST /v1/messages com type image/document/audio/video e, dentro do objeto desse tipo, link ou id — exatamente um dos dois. caption para image/document/video; audio não aceita caption; document pode levar filename (o nome que quem recebe vê).

O que o link precisa para a Meta aceitá-lo: ser https e apontar direto para o arquivo (que a resposta sejam os bytes, sem login nem página intermediária); trazer o Content-Type correto — se não coincidir com o arquivo, a Meta recusa; e respeitar os limites da Meta: imagem JPEG/PNG 5 MB, áudio (aac · amr · mp3 · m4a · ogg só OPUS) 16 MB, vídeo mp4/3gpp 16 MB, documento (pdf · doc/docx · xls/xlsx · ppt/pptx · txt) 100 MB.

⚠ A armadilha mais comum: Google Drive, Dropbox e similares NÃO servem. Um link de "compartilhar" devolve uma página HTML intermediária, não os bytes do arquivo: a Meta baixa essa página e recusa o envio. Sirva-o a partir de uma URL que responda com o arquivo direto.

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":"image","image":{"link":"https://example.com/product.jpg","caption":"New product 📦"}}'
# document: {"type":"document","document":{"link":"https://…/invoice.pdf","filename":"invoice.pdf","caption":"Your invoice"}}
# audio (no caption): {"type":"audio","audio":{"link":"https://…/note.ogg"}}
# video: {"type":"video","video":{"link":"https://…/demo.mp4","caption":"Demo"}}
# by media id instead of a link: {"image":{"id":"1234567890"}}
# ...but the only ids that exist are the ones you RECEIVED (from a message.received
# event); there is no upload endpoint. To send a file of your own, host it and link it.
// Media is sent by { link } (Meta fetches the URL) or { id }. The only media ids that
// exist are the ones you RECEIVED: there is no upload endpoint. Host your own files.
const res = await fetch("https://api.waiaconnect.com/v1/messages", {
  method: "POST",
  headers: {
    "Authorization": "Bearer wc_live_YOUR_API_KEY",
    "Idempotency-Key": crypto.randomUUID(),
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
  "connectionId": "conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "to": "5493511234567",
  "type": "image",
  "image": {
    "link": "https://example.com/product.jpg",
    "caption": "New product 📦"
  }
})
});
console.log(await res.json()); // { id: "msg_…", status: "queued" }
<?php
// Media is sent by ["link" => …] (Meta fetches it) or ["id" => …]. The only media ids
// that exist are the ones you RECEIVED: there is no upload endpoint. Host your own files.
$ch = curl_init("https://api.waiaconnect.com/v1/messages");
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    "Authorization: Bearer wc_live_YOUR_API_KEY",
    "Idempotency-Key: " . bin2hex(random_bytes(16)),
    "Content-Type: application/json",
  ],
  CURLOPT_POSTFIELDS => json_encode(["connectionId" => "conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","to" => "5493511234567","type" => "image","image" => ["link" => "https://example.com/product.jpg","caption" => "New product 📦"]]),
]);
echo curl_exec($ch);
import requests, uuid
# Media is sent by {"link": …} (Meta fetches it) or {"id": …}. The only media ids that
# exist are the ones you RECEIVED: there is no upload endpoint. Host your own files.
res = requests.post("https://api.waiaconnect.com/v1/messages",
  headers={
    "Authorization": "Bearer wc_live_YOUR_API_KEY",
    "Idempotency-Key": str(uuid.uuid4()),
  },
  json={"connectionId":"conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","to":"5493511234567","type":"image","image":{"link":"https://example.com/product.jpg","caption":"New product 📦"}})
print(res.json())  # {"id": "msg_…", "status": "queued"}

⚠ Um identificador que chega num webhook vence na Meta em poucos dias (o prazo é definido pela Meta). Vencido, não serve nem para baixá-lo nem para reenviá-lo.

A Meta guarda o seu link em cache por 10 minutos. Se você trocar o arquivo por trás da MESMA URL, acrescente uma query string aleatória (?v=…) ou vai mandar o antigo.

Se o link não servir, você fica sabendo em dois momentos. (1) Ao aceitar, com um 400 e o seu code: MEDIA_LINK_OR_ID_REQUIRED (não mandou nenhum), MEDIA_LINK_AND_ID (mandou os dois), MEDIA_LINK_INVALID (não é uma URL https bem formada), AUDIO_CAPTION_NOT_ALLOWED.

(2) Se passou pela validação mas a Meta não conseguiu baixá-lo, a recusa chega DEPOIS do 202: consulte GET /v1/messages/:id → lastErrorCode = MEDIA_DOWNLOAD_FAILED (link inacessível ou página intermediária), MEDIA_FILE_REJECTED (formato ou tamanho) ou MEDIA_TYPE_UNSUPPORTED. O que fazer: servir o arquivo direto, com o seu Content-Type, dentro dos limites acima.

Para baixar um arquivo que mandaram para você, veja «Baixar mídia recebida».