
# API de plantillas de WhatsApp

Las plantillas de mensajes de WhatsApp son mensajes preescritos que han sido aprobados para enviarse fuera de la ventana de conversación normal de 24 horas; por ejemplo, un mensaje de bienvenida, un recordatorio de cita o un aviso de reinteracción. Esta API le permite listar, crear, editar, enviar, verificar, eliminar y enviar plantillas mediante programación.

Todas las rutas a continuación son relativas a la URL base de la API:

```
https://api.youraiconnector.com/v1
```

Cada solicitud debe estar autenticada. Consulte [Autenticación](authentication.md) para conocer los cuatro métodos aceptados. Los ejemplos en esta página utilizan el encabezado `X-API-Key` (y una forma de parámetro de consulta para cURL).

::: note
**Nota:** Las plantillas funcionan a través del canal de la API de WhatsApp Business, por lo que esta parte de la API requiere tanto acceso a la API como un plan que incluya canales de WhatsApp. Sin ellos, las solicitudes serán rechazadas con un `403`.
:::


---

## Trabajar con subcuentas (agencias)


---

## Estados de aprobación

Debido a que los mensajes enviados fuera de una conversación abierta deben ser revisados primero por WhatsApp, cada plantilla conlleva un `status` de aprobación:

| Estado | Significado |
|---|---|
| `draft` | Creada o guardada pero aún no enviada para revisión. Todavía puede editarla. |
| `received` | Enviada y aceptada en la cola de revisión. |
| `pending` | En revisión. |
| `approved` | Autorizada para el envío. |
| `rejected` | Rechazada. El campo `rejection_reason` explica el motivo; corríjalo y envíelo de nuevo. |

Solo las plantillas `draft` y `rejected` pueden editarse o (re)enviarse. Una vez que una plantilla está `approved`, queda bloqueada; cree una nueva si necesita realizar cambios.

> **Aprobación automática:** Algunos canales no requieren un paso de revisión externa. Las plantillas creadas o enviadas para una campaña en dicho canal se almacenan como `approved` inmediatamente, sin un ID de contenido (`sid`).

---

## Plantillas en cuentas conectadas a Meta

Estos endpoints funcionan de la misma manera independientemente de la conexión de WhatsApp que utilice su cuenta, pero lo que sucede detrás de ellos es diferente:

- En una **conexión de WhatsApp gestionada**, las plantillas se registran con el proveedor de mensajería y `sid` es el ID de contenido del proveedor (`HXXXXXXXX…`).
- En una cuenta cuyo número se ejecuta en **su propia cuenta de WhatsApp Business** (cualquiera de las opciones de conexión de Meta), las plantillas se crean y revisan **en esa cuenta de WhatsApp Business** y `sid` es el ID de plantilla propio de Meta: una cadena numérica como `"3394843740694756"`. `status` sigue utilizando los valores de la tabla anterior y `rejection_reason` sigue conteniendo la explicación de Meta.

Existen dos endpoints adicionales para esto: uno para consultar qué conexión está utilizando y otro para reconciliar su lista de plantillas con su cuenta de WhatsApp Business. Las plantillas que ya existen en la cuenta de WhatsApp Business se importan a su biblioteca mediante la sincronización, por lo que un `GET /whatsapp-templates` posterior las enumera como cualquier otra plantilla.

### Comprobar en qué conexión se ejecutan las plantillas

`GET /whatsapp-templates/provider`

| Campo | Descripción |
|---|---|
| `provider` | `twilio` cuando las plantillas se registran con el proveedor de mensajería gestionado, `meta` cuando residen en su propia cuenta de WhatsApp Business. |
| `lane` | Qué conexión de Meta se está utilizando: `meta_cloud_api` (su propia aplicación de Meta) o `meta_embedded` (conectada a través de nuestra aplicación de Meta). `null` en una conexión gestionada. |
| `waba_id` | La cuenta de WhatsApp Business en la que se crean las plantillas, o `null`. |
| `templates_enabled` | `false` cuando la conexión con Meta aún no se ha completado (no hay una cuenta de WhatsApp Business o un token de acceso almacenado). La creación o el envío de plantillas fallará con un `400` hasta que se complete. |

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/whatsapp-templates/provider?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/whatsapp-templates/provider", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/whatsapp-templates/provider",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "provider": "meta",
  "lane": "meta_cloud_api",
  "waba_id": "2357661648036355",
  "templates_enabled": true
}
```

### Sincronizar plantillas desde Meta

Actualiza el estado de aprobación de cada plantilla que reside en su cuenta de WhatsApp Business e importa cualquier plantilla que exista allí pero que aún no esté en su biblioteca. Es seguro llamarlo tantas veces como desee. En una conexión gestionada no hay nada que sincronizar, por lo que la llamada no hace nada y simplemente informa cuántas plantillas tiene.

`POST /whatsapp-templates/meta-sync`

| Campo | Descripción |
|---|---|
| `imported` | Plantillas encontradas en la cuenta de WhatsApp Business que se agregaron a su biblioteca mediante esta llamada. |
| `updated` | Plantillas existentes cuyo estado o detalles cambiaron. |
| `total` | Plantillas en su biblioteca después de la sincronización. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/whatsapp-templates/meta-sync?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/whatsapp-templates/meta-sync", {
  method: "POST",
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/whatsapp-templates/meta-sync",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "provider": "meta",
  "imported": 2,
  "updated": 5,
  "total": 12
}
```

### Comunicación directa con Meta (avanzado)

Si necesita algo que los endpoints anteriores no exponen (encabezados de plantilla, pies de página, botones o una plantilla completamente creada a mano), `/v1/meta-templates` envía su solicitud directamente a la API de plantillas de Meta, sin almacenar nada en su biblioteca de plantillas. Solo funciona en cuentas cuyo número se ejecuta en su propia cuenta de WhatsApp Business; en una conexión gestionada, cada llamada devuelve `400` solicitándole que conecte una aplicación de Meta primero.

| Endpoint | Qué hace |
|---|---|
| `GET /meta-templates` | Enumera las plantillas en su cuenta de WhatsApp Business con su estado más reciente. Agregue `?name=` para filtrar por un nombre de plantilla exacto. Devuelve `{ "success": true, "templates": [...] }`. |
| `POST /meta-templates` | Crea una plantilla y la envía para revisión de Meta en un solo paso. Requiere `name`, `language` y `body` (o una matriz `components` completa en lugar de `body`). Opcional: `variables` (matriz de cadenas), `category` (`MARKETING`, `UTILITY` o `AUTHENTICATION`), `header`, `footer`, `buttons`. Devuelve `201` con `{ "success": true, "template": {...} }`. |
| `DELETE /meta-templates/{name}` | Elimina la plantilla por su nombre de Meta: **todos sus idiomas**. Agregue `?hsm_id=` con el ID de plantilla de Meta para eliminar un solo idioma. Devuelve `{ "success": true, "name": "..." }`. |

Una plantilla que Meta rechaza devuelve `400` con la explicación propia de Meta en `error`.

---

## Listar plantillas

Devuelve todas las plantillas de su cuenta, con un resumen ligero de cada una.

`GET /whatsapp-templates`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/whatsapp-templates?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/whatsapp-templates", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/whatsapp-templates",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "data": [
    {
      "id": "template_abc123",
      "name": "welcome_message",
      "status": "approved",
      "language": "en",
      "body": "Hi {{first_name}}, thanks for reaching out!"
    },
    {
      "id": "template_def456",
      "name": "appointment_reminder",
      "status": "pending",
      "language": "en",
      "body": "Hi {{first_name}}, this is a reminder about your appointment."
    }
  ]
}
```

---

## Obtener una plantilla

Devuelve el detalle completo de una plantilla individual, incluyendo sus variables, estado y marcas de tiempo.

`GET /whatsapp-templates/{templateId}`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123",
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "template": {
    "id": "template_abc123",
    "name": "welcome_message",
    "body": "Hi {{first_name}}, thanks for reaching out!",
    "language": "en",
    "variables": ["first_name"],
    "status": "approved",
    "sid": "HXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "type": "general",
    "category": "marketing",
    "rejection_reason": null,
    "campaign_id": "campaign123",
    "date_created": "2026-06-01T10:00:00.000Z",
    "date_updated": "2026-06-02T08:30:00.000Z",
    "submitted_at": "2026-06-01T10:05:00.000Z",
    "approved_at": "2026-06-02T08:30:00.000Z"
  }
}
```

Una plantilla que no existe en su cuenta devuelve `404` con `{ "success": false, "error": "Template not found" }`.

---

## Crear una plantilla

Crea una plantilla para el mensaje de apertura de una campaña y la envía para su aprobación en un solo paso.

`POST /whatsapp-templates`

| Campo | Obligatorio | Descripción |
|---|---|---|
| `campaign_id` | Sí | La campaña a la que pertenece la plantilla. |
| `name` | Sí | Un nombre para la plantilla. |
| `language` | Sí | Código de idioma, por ejemplo `en`, `es`, `de`, `pt_BR`, `zh_CN`. |
| `body` | Sí | El texto del mensaje, hasta 1024 caracteres. |
| `variables` | No | Lista ordenada de nombres de variables utilizados en el cuerpo. |

Los marcadores de posición de variables pueden escribirse como `{{first_name}}`, `{first_name}` o `[first_name]`; todos se normalizan a la forma de doble llave.

El resultado depende de los canales de la campaña:

- **Campaña de WhatsApp Business API:** el contenido se envía para revisión de WhatsApp. La respuesta contiene `campaign_status` (`received` o `pending`) y un `template_sid`.
- **Un canal sin paso de revisión externa:** la plantilla se almacena y se aprueba automáticamente (`campaign_status: "approved"`, `template_sid: null`).
- **Sin canal de WhatsApp en la campaña:** no se crea nada y `campaign_status` es `not_applicable`.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/whatsapp-templates?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "campaign_id": "campaign123",
    "name": "welcome_message",
    "language": "en",
    "body": "Hi {{first_name}}, thanks for reaching out!",
    "variables": ["first_name"]
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/whatsapp-templates", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    campaign_id: "campaign123",
    name: "welcome_message",
    language: "en",
    body: "Hi {{first_name}}, thanks for reaching out!",
    variables: ["first_name"],
  }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/whatsapp-templates",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "campaign_id": "campaign123",
        "name": "welcome_message",
        "language": "en",
        "body": "Hi {{first_name}}, thanks for reaching out!",
        "variables": ["first_name"],
    },
)
data = res.json()
```

**Respuesta** (enviada para revisión)

```json
{
  "success": true,
  "campaign_status": "pending",
  "template_sid": "HXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
```

---

## Crear una plantilla independiente

Crea una plantilla en su biblioteca de plantillas sin vincularla al mensaje inicial de una campaña. Este es el paso de creación del ciclo de vida que sigue el resto de esta página: créela aquí, edítela, envíela para revisión, consulte su estado y elimínela cuando ya no la necesite.

`POST /whatsapp-templates/docs`

| Campo | Obligatorio | Descripción |
|---|---|---|
| `name` | Sí | Un nombre para la plantilla. |
| `language` | Sí | Código de idioma, por ejemplo `en`, `es`, `de`, `pt_BR`, `zh_CN`. |
| `body` | Sí | El texto del mensaje, hasta 1024 caracteres. |
| `variables` | No | Lista ordenada de nombres de variables utilizados en el cuerpo. |
| `status` | No | `draft` (predeterminado) la almacena sin enviarla; `submitted` la pone en cola para la revisión de WhatsApp de inmediato. |
| `type` | No | `general` (predeterminado) o `smart_followup`. |
| `category` | No | `marketing`, `utility`, `authentication` o `authentication-international`. |
| `campaign_id` | No | Vincula la plantilla a una de sus campañas. |

> **Plantillas de autenticación (código de un solo uso).** WhatsApp no acepta plantillas de autenticación de texto libre: el cuerpo del mensaje está preestablecido por WhatsApp y la plantilla debe incluir un botón de "copiar código". Cuando crea una plantilla con `category: "authentication"`, la enviamos con ese formato fijo por usted. Su `body` se mantiene como la vista previa que se muestra en la aplicación, pero el texto que recibe su contacto es la redacción propia de WhatsApp (el código, un recordatorio de seguridad y una nota de caducidad de 10 minutos). Declare exactamente una variable, por ejemplo `["code"]`, y pase el código cuando realice el envío (consulte el campo `variables` en [Enviar una plantilla a un contacto](#send-a-template-to-a-contact)). El código debe tener menos de 15 caracteres.

> **¿Qué creación debo usar?** Use esta cuando desee una plantilla que usted mismo pueda editar y enviar. Use `POST /whatsapp-templates` (arriba) cuando desee establecer el mensaje inicial de una campaña; esa opción requiere `campaign_id` y escribe directamente en la campaña.

Una plantilla creada como `submitted` se envía para la revisión de WhatsApp en segundo plano, por lo que debe consultar el endpoint de estado para conocer el resultado en lugar de esperar que aparezca en la respuesta.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/whatsapp-templates/docs?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "welcome_message",
    "language": "en",
    "body": "Hi {{first_name}}, thanks for reaching out!",
    "variables": ["first_name"],
    "status": "draft",
    "category": "marketing"
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/whatsapp-templates/docs", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "welcome_message",
    language: "en",
    body: "Hi {{first_name}}, thanks for reaching out!",
    variables: ["first_name"],
    status: "draft",
    category: "marketing",
  }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/whatsapp-templates/docs",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "name": "welcome_message",
        "language": "en",
        "body": "Hi {{first_name}}, thanks for reaching out!",
        "variables": ["first_name"],
        "status": "draft",
        "category": "marketing",
    },
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "template_id": "template_abc123",
  "status": "draft"
}
```

Si falta un `name`, `language` o `body`, si el idioma no es compatible, si un `status` es distinto de `draft` o `submitted`, si un `type` o `category` es desconocido, o si el cuerpo supera los 1024 caracteres, se devolverá un `400` con un `error` explicativo. Un `campaign_id` que no sea una de sus campañas devolverá un `404`.

---

## Actualizar una plantilla

Edita una plantilla que aún no ha sido aprobada. Solo se pueden editar las plantillas con estado `draft` o `rejected`. Proporcione cualquier combinación de `name`, `body`, `language` y `variables`; solo se cambiarán los campos que envíe.

`PUT /whatsapp-templates/{templateId}`

> La edición **no** vuelve a enviar la plantilla para su revisión. Utilice el endpoint de envío después.

**cURL**

```bash
curl -X PUT "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "body": "Hi {{first_name}}, here is an update for you.",
    "variables": ["first_name"]
  }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123",
  {
    method: "PUT",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      body: "Hi {{first_name}}, here is an update for you.",
      variables: ["first_name"],
    }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.put(
    "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "body": "Hi {{first_name}}, here is an update for you.",
        "variables": ["first_name"],
    },
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "template_id": "template_abc123"
}
```

Intentar editar una plantilla que ya está `approved` (o que no es editable por otro motivo), no enviar campos o enviar un valor no válido devuelve `400` con un `error` explicativo.

---

## Enviar una plantilla para su aprobación

Envía una plantilla `draft` o `rejected` para su revisión. Las plantillas en un canal que no requiere revisión externa se aprueban de inmediato; todas las demás se envían a WhatsApp y el `status` devuelto (normalmente `received` o `pending`) se almacena en la plantilla.

`POST /whatsapp-templates/{templateId}/submit`

> Las **plantillas de seguimiento** deben declarar y utilizar sus variables obligatorias antes de poder enviarse: un marcador de posición para el nombre y un marcador de posición de contexto personal para seguimientos inteligentes.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123/submit" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123/submit",
  { method: "POST", headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123/submit",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "template_id": "template_abc123",
  "status": "pending",
  "sid": "HXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
```

---

## Comprobar el estado de aprobación

Un endpoint ligero para consultar el estado actual de una plantilla. El estado se lee del registro almacenado, que se actualiza periódicamente en segundo plano, por lo que una aprobación o rechazo muy reciente puede tardar un poco en aparecer.

`GET /whatsapp-templates/{templateId}/status`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123/status" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123/status",
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123/status",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "template_id": "template_abc123",
  "name": "welcome_message",
  "status": "approved",
  "sid": "HXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "rejection_reason": null,
  "date_updated": "2026-06-02T08:30:00.000Z"
}
```

---

## Eliminar una plantilla

Elimina el registro de la plantilla de su cuenta.

`DELETE /whatsapp-templates/{templateId}`

::: warning
**Importante:** En una conexión gestionada, solo se elimina el registro almacenado; el contenido que WhatsApp ya haya aprobado puede permanecer registrado en el proveedor de mensajería. En una cuenta que funciona con su propia cuenta de WhatsApp Business, la plantilla también se elimina de dicha cuenta. De cualquier modo, si una campaña sigue utilizando esta plantilla, redirija esa campaña a otra plantilla **antes** de eliminarla; de lo contrario, los envíos que dependan de ella fallarán.
:::


**cURL**

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123",
  { method: "DELETE", headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.delete(
    "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "template_id": "template_abc123",
  "note": "The template record was removed from your account. Content already approved by WhatsApp may remain registered with the messaging provider."
}
```

---

## Enviar una plantilla a un contacto

Envía una plantilla aprobada a un contacto, incluso cuando no hay una conversación abierta; esto vuelve a abrir la sesión de chat. Puede dirigirse al contacto mediante `contactId` o mediante `phoneNumber`, y elegir la plantilla mediante `whatsappTemplateId` o mediante `templateName`.

`POST /whatsapp-templates/send`

| Campo | Obligatorio | Descripción |
|---|---|---|
| `contactId` | Uno de estos dos | El ID del contacto. |
| `phoneNumber` | Uno de estos dos | El número de teléfono del contacto (con código de país, sin espacios). Se busca o se crea si es necesario. |
| `whatsappTemplateId` | Uno de estos dos | El ID de la plantilla. |
| `templateName` | Uno de estos dos | El nombre de la plantilla, tal como se muestra en la aplicación. |
| `firstName` | No | Se utiliza para completar un contacto recién creado. |
| `lastName` | No | Se utiliza para completar un contacto recién creado. |
| `email` | No | Se utiliza para completar un contacto recién creado. |
| `variables` | No | Valores explícitos para las variables de la plantilla, organizados por nombre de variable, por ejemplo `{ "code": "482913" }`. Un valor proporcionado aquí prevalece sobre los campos del contacto para esa variable; las variables que omita se seguirán completando a partir del contacto como se describe a continuación. Así es como se pasa un código de un solo uso a una plantilla de autenticación. |

El cuerpo de la plantilla admite la sustitución avanzada de variables:

- **Variables básicas:** `{{first_name}}`, `{{email}}`, `{{company}}`
- **Valores predeterminados:** `{{first_name|there}}` muestra `there` si el campo está vacío
- **Transformaciones:** `{{company|uppercase}}`, `{{name|lowercase}}`, `{{name|capitalize}}`
- **Combinado:** `{{company|Your Company|uppercase}}`

> **Créditos:** El envío de una plantilla consume créditos. El costo exacto depende del país del destinatario y de la categoría de la plantilla.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/whatsapp-templates/send?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contactId": "contact123",
    "whatsappTemplateId": "template_abc123"
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/whatsapp-templates/send", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    contactId: "contact123",
    whatsappTemplateId: "template_abc123",
  }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/whatsapp-templates/send",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "contactId": "contact123",
        "whatsappTemplateId": "template_abc123",
    },
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "data": "WhatsApp template message sent successfully"
}
```

Una solicitud a la que le falten tanto un identificador de contacto como ambos identificadores de plantilla devuelve `400`. Si a su cuenta le faltan las credenciales de mensajería necesarias para enviar, la respuesta es `403`.

---

## Crear o actualizar la plantilla activa de una campaña

Un segundo par de endpoints para la plantilla de apertura de una campaña, definidos por ruta en lugar de por un `campaign_id` en el cuerpo. Estos son los que se deben usar para una campaña que ya está activa: a diferencia de [Crear una plantilla](#create-a-template) arriba, la actualización aquí también vuelve a enviar los borradores de seguimiento de la campaña para su revisión, de modo que la plantilla de apertura y sus seguimientos permanezcan sincronizados.

`POST /whatsapp-templates/campaign/{campaignId}` crea la plantilla de apertura de la campaña. `PUT /whatsapp-templates/campaign/{campaignId}` la edita; la campaña debe tener ya una plantilla, o esto devolverá `400`.

| Campo | Obligatorio | Descripción |
|---|---|---|
| `name` | Sí | Un nombre para la plantilla. |
| `language` | Sí | Código de idioma, por ejemplo `en`, `es`, `de`, `pt_BR`, `zh_CN`. |
| `body` | Sí | El texto del mensaje, hasta 1024 caracteres. |
| `variables` | Sí | Lista ordenada de nombres de variables utilizados en el cuerpo. Pase una matriz vacía si la plantilla no utiliza ninguno. |

**cURL** (crear)

```bash
curl -X POST "https://api.youraiconnector.com/v1/whatsapp-templates/campaign/campaign123?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "welcome_message",
    "language": "en",
    "body": "Hi {{first_name}}, thanks for reaching out!",
    "variables": ["first_name"]
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/whatsapp-templates/campaign/campaign123", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "welcome_message",
    language: "en",
    body: "Hi {{first_name}}, thanks for reaching out!",
    variables: ["first_name"],
  }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/whatsapp-templates/campaign/campaign123",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "name": "welcome_message",
        "language": "en",
        "body": "Hi {{first_name}}, thanks for reaching out!",
        "variables": ["first_name"],
    },
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "campaign_status": "pending",
  "template_sid": "HXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "message": "WhatsApp template created and campaign updated successfully."
}
```

Para editar, cambie el método a `PUT` y utilice los mismos campos; esto vuelve a enviar la plantilla de apertura (y los borradores de seguimiento de la campaña, en una campaña de la API de WhatsApp) para su revisión.

Una campaña que no pertenece a su cuenta devuelve `404`; una campaña que pertenece a otra cuenta para la que no está autorizado devuelve `403`. Editar una campaña sin una plantilla existente devuelve `400`.

---

## Enviar una plantilla a un contacto existente

Una alternativa más sencilla, definida por ruta, a [Enviar una plantilla a un contacto](#send-a-template-to-a-contact) arriba: tanto la plantilla como el contacto deben existir ya; no se busca nada por nombre ni se crea sobre la marcha.

`POST /whatsapp-templates/{templateId}/send-to-contact`

| Campo | Obligatorio | Descripción |
|---|---|---|
| `contactId` | Sí | El ID del contacto. Debe pertenecer a su cuenta. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123/send-to-contact?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "contactId": "contact123" }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123/send-to-contact",
  {
    method: "POST",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ contactId: "contact123" }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123/send-to-contact",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"contactId": "contact123"},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "data": "WhatsApp template message sent successfully"
}
```

> **Créditos:** El envío consume créditos, con el mismo precio que el endpoint anterior. Un `contactId` que falte o no esté en su cuenta devuelve `403`; un `templateId` que no exista devuelve `404`.

---

## Envío masivo de una plantilla

Envíe una plantilla a muchos contactos en una sola llamada, con una vista previa del costo que puede mostrar antes de confirmar.

### Estimar el costo primero

Devuelve el coste del envío, desglosado por país de destino, sin enviar nada ni descontar créditos. El precio de la plantilla es por país de destino, por lo que debe calcularse en el servidor con los contactos reales en lugar de estimarse en el cliente.

`POST /whatsapp-templates/{templateId}/estimate-bulk-cost`

| Campo | Obligatorio | Descripción |
|---|---|---|
| `contactIds` | Sí | Contactos a presupuestar, hasta 500 por llamada. Los duplicados se cuentan una sola vez. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123/estimate-bulk-cost?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "contactIds": ["contact123", "contact456"] }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123/estimate-bulk-cost",
  {
    method: "POST",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ contactIds: ["contact123", "contact456"] }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123/estimate-bulk-cost",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"contactIds": ["contact123", "contact456"]},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "data": {
    "countries": [
      {
        "countryCode": "1",
        "name": "United States",
        "iso": "US",
        "flag": "🇺🇸",
        "contactCount": 120,
        "costPerContact": 0.5,
        "subtotal": 60.0
      }
    ],
    "totalContacts": 120,
    "totalTemplateCost": 60.0,
    "templateCategory": "marketing",
    "skippedContacts": 2
  }
}
```

`skippedContacts` cuenta los identificadores que faltaban, que no eran suyos o que no tenían número de teléfono; la estimación solo cubre el resto, por lo que un valor distinto de cero significa que el envío real llegará a menos contactos de los que seleccionó.

### Enviar el lote

Envía la plantilla a todos los contactos de la lista, resolviendo cualquier variable inteligente por contacto y descontando créditos por envío.

`POST /whatsapp-templates/{templateId}/bulk-send`

| Campo | Obligatorio | Descripción |
|---|---|---|
| `contactIds` | Sí | Contactos a los que enviar, hasta 5000 por llamada. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123/bulk-send?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "contactIds": ["contact123", "contact456"] }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123/bulk-send",
  {
    method: "POST",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ contactIds: ["contact123", "contact456"] }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/whatsapp-templates/template_abc123/bulk-send",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"contactIds": ["contact123", "contact456"]},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "data": { "sent": 118, "failed": 2, "total": 120 }
}
```

Un contacto que falla (no encontrado, no está en su cuenta o un error de envío) se omite y se cuenta en `failed` en lugar de detener el lote. Un `contactIds` vacío, más de 5000 identificadores en un envío (500 en una estimación) o un `templateId` faltante devuelve `400`.

---

## Reintentar un mensaje fallido

Dos endpoints para reenviar un mensaje que falló, sin crear un nuevo registro de mensaje ni gastar créditos nuevamente.

`POST /whatsapp-templates/messages/{contactId}/{messageId}/retry-template` reintenta específicamente un mensaje de plantilla fallido; vuelve a resolver el contenido de la plantilla desde la campaña si el mensaje fallido aún no lo contiene. Solo los mensajes con estado `failed` y tipo `template` pueden reintentarse de esta manera.

`POST /whatsapp-templates/messages/{contactId}/{messageId}/retry` es independiente del canal y funciona para cualquier mensaje fallido que no sea de plantilla (por ejemplo, WhatsApp Web), enviándolo a la ruta de envío correcta según el canal del mensaje. Acepta el estado `failed`, `failed_connection`, `limit_exceeded` o `queued_retry`.

Ninguno de los endpoints requiere un cuerpo de solicitud.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/whatsapp-templates/messages/contact123/msg_abc789/retry-template?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/whatsapp-templates/messages/contact123/msg_abc789/retry-template",
  { method: "POST", headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/whatsapp-templates/messages/contact123/msg_abc789/retry-template",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "data": "Message retry initiated successfully"
}
```

Para la versión independiente del canal, cambie la ruta a `.../msg_abc789/retry`. Un mensaje cuyo estado no sea elegible para reintento, o (en el endpoint de plantilla) que no sea un mensaje de plantilla, devuelve `400`. Un contacto o mensaje faltante devuelve `404`.

---

## Perfil de WhatsApp Business

Administre el perfil de WhatsApp Business (información, dirección, descripción, correo electrónico, sitios web, categoría de negocio y logotipo) que se muestra a los contactos en WhatsApp. Funciona tanto en una conexión administrada como en una cuenta que ejecuta su propia cuenta de WhatsApp Business.

### Guardar el perfil

`PUT /whatsapp-templates/profile`

| Campo | Obligatorio | Descripción |
|---|---|---|
| `phoneNumber` | Sí | El número de WhatsApp al que pertenece este perfil. Debe estar conectado a su cuenta. |
| `about` | No | Texto breve de "Información" que se muestra en el perfil. |
| `address` | No | Dirección del negocio. |
| `description` | No | Descripción más larga del negocio. |
| `email` | No | Correo electrónico de contacto que se muestra en el perfil. |
| `websites` | No | Matriz de URLs de sitios web. Cada una debe ser una URL válida. |
| `vertical` | No | Categoría del negocio, por ejemplo `Retail` o `Professional Services`. |
| `profilePictureHandle` | No | El identificador devuelto por el endpoint de carga de imágenes a continuación, para establecer la foto de perfil. |

**cURL**

```bash
curl -X PUT "https://api.youraiconnector.com/v1/whatsapp-templates/profile?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "+31612345678",
    "about": "We reply within a few hours",
    "email": "support@example.com",
    "websites": ["https://example.com"]
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/whatsapp-templates/profile", {
  method: "PUT",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    phoneNumber: "+31612345678",
    about: "We reply within a few hours",
    email: "support@example.com",
    websites: ["https://example.com"],
  }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.put(
    "https://api.youraiconnector.com/v1/whatsapp-templates/profile",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "phoneNumber": "+31612345678",
        "about": "We reply within a few hours",
        "email": "support@example.com",
        "websites": ["https://example.com"],
    },
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "data": "WhatsApp Business profile updated successfully"
}
```

Si falta un `phoneNumber`, una URL de sitio web no es válida o un `phoneNumber` no está conectado a su cuenta, se devolverá `400` o `404`.

### Cargar una foto de perfil

Descarga una imagen desde una URL que usted proporcione y la carga en WhatsApp, devolviendo un identificador. Pase ese identificador como `profilePictureHandle` en la llamada de guardar perfil anterior para establecerla como foto; este endpoint solo carga la imagen, no la establece por sí mismo.

`POST /whatsapp-templates/profile/picture`

| Campo | Obligatorio | Descripción |
|---|---|---|
| `phoneNumber` | Sí | El número de WhatsApp al que pertenece este perfil. |
| `fileUrl` | Sí | Una URL accesible públicamente de la imagen que se va a cargar. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/whatsapp-templates/profile/picture?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "+31612345678",
    "fileUrl": "https://example.com/logo.png"
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/whatsapp-templates/profile/picture", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    phoneNumber: "+31612345678",
    fileUrl: "https://example.com/logo.png",
  }),
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/whatsapp-templates/profile/picture",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "phoneNumber": "+31612345678",
        "fileUrl": "https://example.com/logo.png",
    },
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "data": "1234567890123456"
}
```

`data` es el identificador de la imagen cargada. Si falta un `phoneNumber` o `fileUrl`, o un `phoneNumber` sin token de acceso de WhatsApp en el archivo, se devolverá `400`; una `fileUrl` inaccesible o no válida devolverá un error que describe por qué falló la descarga.

---

## Comprobar el estado de un remitente

Consulta (y actualiza) el estado de envío en tiempo real de un número de WhatsApp conectado con el proveedor de mensajería. Es útil para confirmar que un número realmente puede enviar mensajes antes de depender de él.

`GET /whatsapp-templates/sender-status/{phoneNumber}`

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/whatsapp-templates/sender-status/+31612345678" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/whatsapp-templates/sender-status/+31612345678",
  { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/whatsapp-templates/sender-status/+31612345678",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

**Respuesta**

```json
{
  "success": true,
  "data": "ONLINE"
}
```

`data` es uno de `ONLINE` (enviando normalmente), `PENDING` (aún en proceso de verificación) o `DELETED` (el proveedor ya no reconoce a este remitente; vuelva a conectar el número). Un `phoneNumber` sin información de negocio de WhatsApp en el archivo devolverá `404`.

---

## Generar plantillas de seguimiento con IA

La plataforma puede redactar por usted las plantillas de seguimiento de WhatsApp de una campaña (los recordatorios que se envían cuando una conversación se queda en silencio) a partir de las propias instrucciones y objetivos de la campaña. Existe un endpoint de trabajo que se ejecuta en segundo plano, además de tres endpoints antiguos que se mantienen para integraciones existentes. Todos ellos consumen créditos de IA.

### Iniciar un trabajo de generación

`POST /campaigns/{campaignId}/template-generation`

| Campo | Obligatorio | Descripción |
|---|---|---|
| `type` | No | `all` (el valor predeterminado) redacta todo el conjunto de seguimiento. `cold_only` redacta solo los mensajes para los contactos que nunca respondieron. |

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/campaigns/campaign_abc123/template-generation?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "type": "all" }'
```

**JavaScript**

```javascript
const res = await fetch(
  "https://api.youraiconnector.com/v1/campaigns/campaign_abc123/template-generation",
  {
    method: "POST",
    headers: {
      "X-API-Key": "YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ type: "all" }),
  }
);
const data = await res.json();
```

**Python**

```python
import requests

res = requests.post(
    "https://api.youraiconnector.com/v1/campaigns/campaign_abc123/template-generation",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"type": "all"},
)
data = res.json()
```

**Respuesta** (`202`)

```json
{ "success": true, "campaign_id": "campaign_abc123", "type": "all" }
```

La llamada devuelve una respuesta tan pronto como el trabajo se pone en cola. Lea la campaña (`GET /campaigns/{campaignId}`, consulte la [API de campañas](campaigns.md)) y observe su objeto `template_generation_status` hasta que finalice:

| Campo | Descripción |
|---|---|
| `status` | `processing` mientras se ejecuta el trabajo, luego `completed` o `failed`. |
| `progress` | De 0 a 100. |
| `current_template`, `total_templates` | Cuántas plantillas se han redactado hasta el momento, del total que redactará el trabajo: 11 para una campaña saliente o combinada, 9 en caso contrario. |
| `error` | Por qué se detuvo un trabajo `failed`, por ejemplo, por falta de créditos. |
| `started_at`, `completed_at` | Cuándo comenzó y terminó el trabajo. |

Las plantillas generadas se guardan en la campaña como cualquier otra, por lo que aparecen en [Listar plantillas](#list-templates) y deben pasar por la aprobación de WhatsApp antes de poder enviarse. Un `400` significa que `type` era algo distinto a `all` o `cold_only`; un `404` significa que la campaña no existe o pertenece a otra cuenta.

Los agentes tienen una versión gemela de esta llamada, `POST /agents/{agentId}/template-generation`, que redacta los seguimientos para un agente y finaliza durante la llamada en el caso habitual; consulte [Generar mensajes de seguimiento](agents.md#generate-follow-up-messages) en la API de agentes de IA.

### Los endpoints de generación antiguos

Tres endpoints anteriores realizan el mismo trabajo y se mantienen para que las integraciones existentes sigan funcionando. El código nuevo debe utilizar el endpoint de trabajo anterior.

| Endpoint | Qué hace |
|---|---|
| `POST /whatsapp-templates/campaign/{campaignId}/generate-async` | Inicia la generación de seguimiento para la campaña en segundo plano y devuelve `202` con `{ "success": true, "data": { "result": "success", "message": "..." } }`. Los créditos se cobran por adelantado (se omite en una cuenta que aporta su propia clave de IA) y el `template_generation_status` de la campaña informa del progreso exactamente como se indicó anteriormente. |
| `POST /whatsapp-templates/campaign/{campaignId}/generate-followups` | Genera las nueve plantillas de seguimiento durante la llamada (para una campaña creada antes de que existieran los seguimientos automáticos, o una que necesite que se redacten de nuevo) y devuelve `200` con `templatesGenerated` dentro de `data`. |
| `POST /whatsapp-templates/agent/{agentId}/generate-followups` | La misma generación síncrona dirigida por el agente. La respuesta añade `agent_id`, `campaign_id` y `target`: `"campaign"` cuando las plantillas se redactaron en la campaña del agente, `"agent"` (con `campaign_id: null`) cuando el agente no tiene campaña y se almacenaron en el propio agente. Un agente inexistente o ajeno es un `404`. |

Los tres requieren seguimientos automáticos en la cuenta y suficientes créditos (un `400` indica cuál falta), y el par dirigido a la campaña devuelve `403` cuando la campaña pertenece a otra cuenta.

---

## Errores de la API de plantillas

Los endpoints de plantillas devuelven el sobre de error estándar:

```json
{
  "success": false,
  "error": "Template not found"
}
```

Un `404` en estos endpoints generalmente significa que el recurso no se encontró; ya sea porque no existe o porque pertenece a otra cuenta. Algunos endpoints (los de creación/actualización con ámbito de campaña y los envíos a un contacto existente) devuelven `403` en su lugar cuando la campaña o el contacto pertenecen a otra persona en lugar de no existir en absoluto. Algunos endpoints también incluyen un campo `error_code` que refleja el estado HTTP. Los códigos compartidos que puede devolver cualquier endpoint — `400`, `401`, `403` (su plan no incluye acceso a la API), `429` (límite de tasa) y `500` — se enumeran con orientación sobre reintentos en [Errores y paginación](errors-and-pagination.md).

---

## Próximos pasos

- [Autenticación](authentication.md) — las cuatro formas de autenticar una solicitud.
- [Errores y límites de tasa](errors-and-pagination.md) — códigos de estado y el límite de 300 solicitudes/min.
- [API de campañas](campaigns.md) — gestione las campañas a las que están adjuntas las plantillas.
