# 04 · Plantillas

Una plantilla es el único mensaje con el que se puede **iniciar** una conversación. Cada tenant tiene las suyas (las aprueba Meta por cada cuenta de WhatsApp). Alcances `templates:read` / `templates:write`; función de licencia `templates`. Crear y editar exige rol `admin` en las pantallas embebidas.

## Crear

```http
POST /v1/templates
```

```json
{
  "name": "recordatorio_cita",
  "language": "es",
  "category": "utility",
  "header": { "type": "text", "text": "Recordatorio de cita" },
  "body": { "text": "Hola {{1}}, te esperamos el {{2}}.", "examples": ["Ana", "15 de octubre a las 10:30"] },
  "footer": "Responde a este mensaje si necesitas cambiarla",
  "buttons": [{ "type": "quick_reply", "text": "Confirmar" }, { "type": "quick_reply", "text": "Cambiar" }],
  "submit": true
}
```

| Campo | Reglas |
| --- | --- |
| `name` | Minúsculas, números y `_`. Único por idioma y cuenta |
| `language` | Código de Meta: `es`, `es_ES`, `en`, `en_US`, `ca`… |
| `category` | `marketing`, `utility` o `authentication`. **Meta decide la categoría final**; si la cambia llega `whatsapp.template.category_changed` (afecta al coste) |
| `body.text` | ≤ 1024 caracteres. **No puede empezar ni terminar con una variable** |
| Variables | Posicionales `{{1}}`, `{{2}}`… **seguidas y sin saltos**, o con nombre (`parameter_format: "named"`: `{{nombre}}`, minúsculas, números y `_`) |
| `body.examples` | Obligatorio **uno por variable** (lista, o objeto en plantillas con nombre). Meta los pide para aprobar |
| `header` | Solo `type: "text"`, ≤ 60 caracteres, **sin variables** |
| `footer` | ≤ 60 caracteres |
| `buttons` | `quick_reply`, `url` (con `url`) o `phone_number` (con `phone_number`); texto ≤ 25 caracteres; hasta 10 |
| `submit` | `true`: se envía a revisión de Meta al crearla. `false` (por defecto): queda en borrador |

Cada regla incumplida devuelve `422 validation_failed` con el campo exacto en `details.fields`.

**Todavía no soportado:** cabeceras de imagen, vídeo o documento; botones de código de un solo uso de las plantillas de autenticación.

## Estados

```
draft ─ enviar ─▶ pending ─▶ approved ─ calidad baja ─▶ paused ─▶ disabled
                      └────▶ rejected ─ editar y reenviar ─▶ pending
approved ─ editar ─▶ pending (revisión nueva)
```

| Estado | ¿Se puede enviar? | Qué hacer |
| --- | --- | --- |
| `draft` | no | Editar o enviar a revisión (`POST /v1/templates/{id}/submit`) |
| `pending` | no | Esperar (Meta suele tardar de minutos a un día). **No se puede editar** mientras tanto |
| `approved` | **sí** | — |
| `rejected` | no | `rejected_reason` explica el motivo; corregir y reenviar |
| `paused` | no | Meta la pausó por mala calidad; editarla o esperar |
| `disabled` | no | Permanente: crear otra con otro contenido |
| `deleted` | no | Borrada (también en Meta). Se puede volver a crear con el mismo nombre |

Los cambios llegan por [evento](05-recibir-eventos.md) `whatsapp.template.status_changed` (con `previous.status`), `…quality_changed` y `…category_changed`. No hace falta consultar en bucle.

## Editar y borrar

- `PATCH /v1/templates/{id}`: en un borrador edita en sitio; en una `approved`/`rejected`/`paused` crea una **revisión nueva** (`revision + 1`) y la devuelve a `pending`. Si estaba en `pending`: `409 invalid_state`. La categoría solo se cambia en borradores y rechazadas.
- `DELETE /v1/templates/{id}`: la borra también en Meta. Los mensajes ya enviados con ella conservan su historial.

## Vista previa

`POST /v1/templates/{id}/preview` con `{ "variables": [...] }` devuelve el texto ya renderizado, sin enviar nada. Úsalo antes de enviar para enseñárselo a un usuario.

## Sincronizar con Meta

`POST /v1/templates/sync` importa las plantillas que el cliente creó directamente en WhatsApp Manager (`origin: "meta"`) y marca como `deleted` las que ya no existen allí. Se ejecuta además cada noche.

## Biblioteca compartida

Plantillas base que mantiene el equipo de plataforma:

```bash
curl $BASE_URL/v1/template-library?language=es -H "Authorization: Bearer $API_KEY"
curl -X POST $BASE_URL/v1/template-library/confirmacion_cita/activate -H "Authorization: Bearer $API_KEY"
```

Activarla **crea la plantilla en la cuenta del tenant y la envía a revisión**: cada tenant tiene su propia aprobación (Meta puede aprobar una y rechazar otra con el mismo texto).

## Límites

- `max_templates` de la licencia: `403 license_limit_reached` (se respeta con altas simultáneas).
- Meta limita además el número de plantillas por cuenta y el ritmo de creación; si los supera, la creación falla con `502 meta_error` y la plantilla queda en `draft` con el motivo en `rejected_reason`.
