# Creare modelli con immagine, documento e pulsanti

`POST /v1/templates/media`

**Prepara il modello dal tuo sistema, mostra l'anteprima al tuo cliente e invialo in revisione.** Quattro chiamate, e nessuna invia un messaggio:

1. **`POST /v1/templates/media`** — il file di **esempio** che Meta revisiona (PDF, JPG/PNG o MP4; multipart con `file`, o JSON con `file` in base64). Restituisce `{ handle, type, format, mimeType, bytes }`. Non è il file che si invia: quello va in ogni invio, con `link` o `mediaId`. Non conserviamo il file.
2. **`POST /v1/templates/validate`** — lo stesso controllo della creazione, **senza inviare nulla a Meta**: `ok`, e in `errors[]` tutti i problemi insieme, ognuno con il suo `field` (`header.handle`, `buttons[1].url`…) e il messaggio nella tua lingua.
3. **`POST /v1/templates`** — `header: { "format": "IMAGE", "handle": "…" }` (anche `VIDEO`, `DOCUMENT` e `LOCATION`) e `buttons`: `QUICK_REPLY` (`text`), `URL` (`text`, `url` e, se finisce con `{{1}}`, `example` con la parte finale di esempio), `PHONE_NUMBER` (`text`, `phoneNumber` con prefisso internazionale) e `COPY_CODE` (`example`). Nasce `PENDING`; ti avvisa **`template.status_changed`** (con `previousStatus`).
4. **`POST /v1/templates/preview?format=html`** — una pagina autonoma con la nuvoletta di WhatsApp (senza script né risorse esterne) da mostrare al tuo cliente in un `<iframe sandbox>`. Senza `format`, la stessa vista in JSON.

**I limiti di Meta, controllati prima di Meta:** fino a 10 pulsanti, 2 URL, 1 telefono, 1 copia codice; il testo di un pulsante fino a 25 caratteri; le risposte rapide insieme (all'inizio o alla fine). Se l'account Meta ha `141006` (metodo di pagamento) o `141010` (verifica dell'azienda), il modello viene creato lo stesso e la risposta porta un `warning`: Meta può approvarlo, ma non potrai inviarlo finché non lo risolvi.

## Esempi

### cURL

```bash
# 1) The sample file Meta reviews (PDF, JPG/PNG or MP4) → its handle
HANDLE=$(curl -s -X POST https://api.waiaconnect.com/v1/templates/media   -H "Authorization: Bearer wc_live_YOUR_API_KEY"   -F file=@foto.png | jq -r .handle)

# 2) Validate: every error at once, nothing sent to Meta
BODY='{"connectionId":"conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","name":"envio_factura","language":"es","category":"UTILITY","header":{"format":"IMAGE","handle":"HANDLE"},"body":{"text":"Hola {{1}}, tu factura *{{2}}* está lista.","examples":["María","A-1042"]},"footer":{"text":"Tu negocio"},"buttons":[{"type":"QUICK_REPLY","text":"Recibido"},{"type":"URL","text":"Ver factura","url":"https://your-site.example/f/{{1}}","example":"A-1042"},{"type":"PHONE_NUMBER","text":"Llamar","phoneNumber":"+5493511234567"}]}'
BODY=${BODY/HANDLE/$HANDLE}
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"
# → { "ok": true, "errors": [], "warnings": [], "components": [...] }

# 3) Create it (born PENDING; template.status_changed tells you when Meta decides)
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"

# 4) The WhatsApp-style preview for your customer (self-contained HTML)
curl -s -X POST "https://api.waiaconnect.com/v1/templates/preview?format=html" -H "Authorization: Bearer wc_live_YOUR_API_KEY"   -H "Content-Type: application/json" -d "$BODY" > preview.html
```

### Node.js

```javascript
import { readFile } from "node:fs/promises";
const H = { Authorization: "Bearer wc_live_YOUR_API_KEY" };
const J = { ...H, "Content-Type": "application/json" };

// 1) The sample file Meta reviews (PDF, JPG/PNG or MP4) → its handle
const form = new FormData();
form.append("file", new Blob([await readFile("foto.png")]), "foto.png");
const { handle } = await (await fetch("https://api.waiaconnect.com/v1/templates/media", { method: "POST", headers: H, body: form })).json();

const def = {
  "connectionId": "conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "name": "envio_factura",
  "language": "es",
  "category": "UTILITY",
  "header": {
    "format": "IMAGE",
    "handle": handle
  },
  "body": {
    "text": "Hola {{1}}, tu factura *{{2}}* está lista.",
    "examples": [
      "María",
      "A-1042"
    ]
  },
  "footer": {
    "text": "Tu negocio"
  },
  "buttons": [
    {
      "type": "QUICK_REPLY",
      "text": "Recibido"
    },
    {
      "type": "URL",
      "text": "Ver factura",
      "url": "https://your-site.example/f/{{1}}",
      "example": "A-1042"
    },
    {
      "type": "PHONE_NUMBER",
      "text": "Llamar",
      "phoneNumber": "+5493511234567"
    }
  ]
};

// 2) Validate: every error at once, nothing sent to Meta
const v = await (await fetch("https://api.waiaconnect.com/v1/templates/validate", { method: "POST", headers: J, body: JSON.stringify(def) })).json();
if (!v.ok) throw new Error(v.errors.map(e => `${e.field}: ${e.message}`).join("\n"));

// 3) Create it (PENDING until Meta decides → template.status_changed)
const created = await (await fetch("https://api.waiaconnect.com/v1/templates", { method: "POST", headers: J, body: JSON.stringify(def) })).json();

// 4) The WhatsApp-style preview (self-contained HTML, show it in an <iframe sandbox>)
const html = await (await fetch("https://api.waiaconnect.com/v1/templates/preview?format=html", { method: "POST", headers: J, body: JSON.stringify(def) })).text();
console.log(created.template.status, created.warning?.message ?? "");
```

### PHP

```php
<?php
$key = "wc_live_YOUR_API_KEY";
function call($method, $url, $key, $body, $json = true) {
  $ch = curl_init($url);
  curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => $method,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => array_merge(["Authorization: Bearer $key"], $json ? ["Content-Type: application/json"] : []),
    CURLOPT_POSTFIELDS => $json ? json_encode($body) : $body,
  ]);
  return curl_exec($ch);
}
// 1) The sample file Meta reviews (PDF, JPG/PNG or MP4) → its handle
$handle = json_decode(call("POST", "https://api.waiaconnect.com/v1/templates/media", $key, ["file" => new CURLFile("foto.png")], false), true)["handle"];

$def = ["connectionId" => "conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","name" => "envio_factura","language" => "es","category" => "UTILITY","header" => ["format" => "IMAGE","handle" => $handle],"body" => ["text" => "Hola {{1}}, tu factura *{{2}}* está lista.","examples" => ["María","A-1042"]],"footer" => ["text" => "Tu negocio"],"buttons" => [["type" => "QUICK_REPLY","text" => "Recibido"],["type" => "URL","text" => "Ver factura","url" => "https://your-site.example/f/{{1}}","example" => "A-1042"],["type" => "PHONE_NUMBER","text" => "Llamar","phoneNumber" => "+5493511234567"]]];

// 2) Validate (nothing sent to Meta) · 3) create · 4) the HTML preview
$v = json_decode(call("POST", "https://api.waiaconnect.com/v1/templates/validate", $key, $def), true);
if (!$v["ok"]) { print_r($v["errors"]); exit; }
echo call("POST", "https://api.waiaconnect.com/v1/templates", $key, $def);
file_put_contents("preview.html", call("POST", "https://api.waiaconnect.com/v1/templates/preview?format=html", $key, $def));
```

### Python

```python
import requests
H = {"Authorization": "Bearer wc_live_YOUR_API_KEY"}

# 1) The sample file Meta reviews (PDF, JPG/PNG or MP4) -> its handle
handle = requests.post("https://api.waiaconnect.com/v1/templates/media", headers=H, files={"file": open("foto.png", "rb")}).json()["handle"]

definition = {"connectionId":"conn_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX","name":"envio_factura","language":"es","category":"UTILITY","header":{"format":"IMAGE","handle":handle},"body":{"text":"Hola {{1}}, tu factura *{{2}}* está lista.","examples":["María","A-1042"]},"footer":{"text":"Tu negocio"},"buttons":[{"type":"QUICK_REPLY","text":"Recibido"},{"type":"URL","text":"Ver factura","url":"https://your-site.example/f/{{1}}","example":"A-1042"},{"type":"PHONE_NUMBER","text":"Llamar","phoneNumber":"+5493511234567"}]}

# 2) Validate: every error at once, nothing sent to Meta
v = requests.post("https://api.waiaconnect.com/v1/templates/validate", headers=H, json=definition).json()
if not v["ok"]:
    raise SystemExit("\n".join(f"{e['field']}: {e['message']}" for e in v["errors"]))

# 3) Create it (PENDING until Meta decides -> template.status_changed)
created = requests.post("https://api.waiaconnect.com/v1/templates", headers=H, json=definition).json()

# 4) The WhatsApp-style preview (self-contained HTML)
open("preview.html", "w").write(requests.post("https://api.waiaconnect.com/v1/templates/preview", params={"format": "html"}, headers=H, json=definition).text)
```

## Note

- Per cambiarlo dopo: `PATCH /v1/templates/:id` (approvato, rifiutato o in pausa; quello approvato 1 volta ogni 24 h e con la stessa categoria).
- Con 4 pulsanti o più, WhatsApp ne mostra 2 e «Vedi tutte le opzioni»: l'anteprima lo disegna allo stesso modo.
