# Modelli con immagine, documento e pulsanti

`POST /v1/messages`

**Invia un modello ricco senza costruire i `components` di Meta.** In `POST /v1/messages` con `type: "template"`, al posto di `components` puoi inviare tre campi e Connect costruisce il resto, esatto:

- **`header`** — `{ "type": "document", "link": "https://…/A-1042.pdf", "filename": "Fattura A-1042.pdf" }`. Anche `image` e `video` (con `mediaId` o `link`), `text` (`{ "type": "text", "text": "…" }`) e `location` (`latitude`, `longitude`, `name`, `address`). `filename` vale solo per i documenti: è il nome che vede il contatto.
- **`body`** — una lista per `{{1}}`, `{{2}}`… (`["Maria", "A-1042"]`) oppure, se il modello usa variabili con nome, un oggetto (`{ "nome": "Maria" }`).
- **`buttons`** — i pulsanti che ricevono un valore: `url` → `text` (la fine dell'URL dinamico), `copy_code` → `code`, `quick_reply` → `payload` (torna nel `message.received` quando il contatto lo tocca). La posizione (`index`) la deduciamo dal modello approvato; se non l'abbiamo ancora sincronizzato, inviala tu (da 0).

**Gli errori arrivano tutti insieme e prima di Meta.** Se conosciamo il modello, controlliamo quante variabili ha, i loro nomi, i pulsanti e il tipo di intestazione: `400 TEMPLATE_SEND_INVALID` con `details.errors[]`, ognuno con il suo `field` (il percorso nel tuo JSON) e il messaggio nella tua lingua. Non viene inviato nulla a Meta.

**Il percorso:** crea il modello (con file o pulsanti: `POST /v1/templates`, vedi «Creare modelli con immagine, documento e pulsanti») → `POST /v1/templates/sync` → aspetta il webhook **`template.status_changed`** con `APPROVED` → invialo come sopra → seguilo con `GET /v1/messages/{id}` o i webhook `message.sent` / `delivered` / `read` / `failed`.

## Esempi

### cURL

```bash
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","header":{"type":"document","link":"https://your-server.example/invoices/A-1042.pdf","filename":"Factura A-1042.pdf"},"body":["María","A-1042"],"buttons":[{"type":"url","text":"A-1042"}]}}'
# header: image | video | document (mediaId OR link; filename = documents only) | text | location
# body:   ["v1","v2"] for {{1}},{{2}}  —  or {"name":"v1"} for named {{variables}}
# buttons: url → text (the URL suffix) · copy_code → code · quick_reply → payload
# Every mistake comes back at once: 400 TEMPLATE_SEND_INVALID, details.errors[].field
```

### Node.js

```javascript
// header/body/buttons → Connect builds Meta's components (don't send "components" too).
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": "template",
  "template": {
    "name": "envio_factura",
    "language": "es",
    "header": {
      "type": "document",
      "link": "https://your-server.example/invoices/A-1042.pdf",
      "filename": "Factura A-1042.pdf"
    },
    "body": [
      "María",
      "A-1042"
    ],
    "buttons": [
      {
        "type": "url",
        "text": "A-1042"
      }
    ]
  }
})
});
console.log(await res.json()); // { id: "msg_…", status: "queued" }
```

### PHP

```php
<?php
// header/body/buttons → Connect builds Meta's components (don't send "components" too).
$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" => "template","template" => ["name" => "envio_factura","language" => "es","header" => ["type" => "document","link" => "https://your-server.example/invoices/A-1042.pdf","filename" => "Factura A-1042.pdf"],"body" => ["María","A-1042"],"buttons" => [["type" => "url","text" => "A-1042"]]]]),
]);
echo curl_exec($ch);
```

### Python

```python
import requests, uuid
# header/body/buttons -> Connect builds Meta's components (don't send "components" too).
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":"template","template":{"name":"envio_factura","language":"es","header":{"type":"document","link":"https://your-server.example/invoices/A-1042.pdf","filename":"Factura A-1042.pdf"},"body":["María","A-1042"],"buttons":[{"type":"url","text":"A-1042"}]}})
print(res.json())
```

## Note

- `components` continua a funzionare come prima. Invia l'uno o l'altro, non entrambi.
- **Media singoli** (entro le 24 h): `type` `image`, `document`, `video`, `audio` o **`sticker`** (WEBP, senza didascalia), con `link` o `id` (anche `mediaId`).
- Se Meta mette in pausa o disattiva il modello per la sua qualità, il messaggio fallisce con `TEMPLATE_PAUSED` o `TEMPLATE_DISABLED` e non viene ritentato.
- Il link deve essere **https** e puntare direttamente al file (un link di «condivisione» di Drive non funziona). Limiti di Meta: documento 100 MB, immagine 5 MB, video 16 MB.
