waiaconnect

Documentazione / Essenziale

Inviare media (immagine · documento · audio · video)

POST /v1/messages

Markdown

Connect non archivia file. Per mandare un tuo file, ospitalo da qualche parte e manda il suo link (link) — lo scarica Meta, non noi. Questa è la strada principale, non l'alternativa.

Gli identificativi (id) sono quelli dei file che hai RICEVUTO: arrivano dentro l'evento di un messaggio in arrivo (data.message.image.id, .document.id, …). Non c'è un endpoint di caricamento — GET /v1/media/:mediaId serve solo per scaricare —, quindi non c'è modo di ottenere un id per un tuo file.

⚠ E la parte scomoda, detta così com'è: Meta di solito permette di riusare un identificativo ricevuto per rispondere dallo stesso numero, ma non lo garantisce e noi non l'abbiamo ancora verificato con Meta reale. Non lo affermiamo né lo neghiamo. Se ti importa che parta sempre, usa il link.

Vuoi mandare SEMPRE lo stesso file — un listino prezzi, delle istruzioni, un catalogo? Ospitalo e manda il link. È la risposta completa: non esiste un id tuo da salvare e riusare. E non è una limitazione mascherata — non conserviamo file perché non conserviamo contenuti (nemmeno il testo dei tuoi messaggi, salvo la cronologia di Coexistence che scegli di ricevere: cifrata e per 7 giorni al massimo). È esattamente quello che promette la nostra informativa sulla privacy, applicato qui.

Come si manda. POST /v1/messages con type image/document/audio/video e, dentro l'oggetto di quel tipo, link o id — esattamente uno dei due. caption per image/document/video; audio non accetta caption; document può avere filename (il nome che vede chi lo riceve).

Cosa serve al link perché Meta lo accetti: essere https e puntare direttamente al file (la risposta devono essere i byte, senza login né pagine intermedie); avere il Content-Type corretto — se non corrisponde al file, Meta lo rifiuta; e rispettare i limiti di Meta: immagine JPEG/PNG 5 MB, audio (aac · amr · mp3 · m4a · ogg solo OPUS) 16 MB, video mp4/3gpp 16 MB, documento (pdf · doc/docx · xls/xlsx · ppt/pptx · txt) 100 MB.

⚠ La trappola più comune: Google Drive, Dropbox e simili NON vanno bene. Un link di "condivisione" restituisce una pagina HTML intermedia, non i byte del file: Meta scarica quella pagina e rifiuta l'invio. Servilo da un URL che risponda direttamente con il file.

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"}

⚠ Un identificativo che arriva in un webhook scade in Meta dopo pochi giorni (la scadenza la fissa Meta). Scaduto, non serve né per scaricarlo né per rimandarlo.

Meta tiene in cache il tuo link per 10 minuti. Se cambi il file dietro lo STESSO URL, aggiungi una query string casuale (?v=…) o manderai quello vecchio.

Se il link non va bene, lo scopri in due momenti. (1) All'accettazione, con un 400 e il suo code: MEDIA_LINK_OR_ID_REQUIRED (non ne hai mandato nessuno), MEDIA_LINK_AND_ID (li hai mandati entrambi), MEDIA_LINK_INVALID (non è un URL https ben formato), AUDIO_CAPTION_NOT_ALLOWED.

(2) Se ha superato la validazione ma Meta non è riuscita a scaricarlo, il rifiuto arriva DOPO il 202: consulta GET /v1/messages/:id → lastErrorCode = MEDIA_DOWNLOAD_FAILED (link inaccessibile o pagina intermedia), MEDIA_FILE_REJECTED (formato o dimensione) o MEDIA_TYPE_UNSUPPORTED. Cosa fare: servire il file direttamente, con il suo Content-Type, entro i limiti indicati sopra.

Per scaricare un file che ti hanno mandato, vedi «Scaricare i media in arrivo».