Enviar plantilla de mensaje
Envía una plantilla de WhatsApp aprobada para iniciar una conversación con un cliente. Si ya existe una conversación abierta, el mensaje se añade a ella; si no, se crea una nueva.
Actualmente, este endpoint solo es compatible con el canal de WhatsApp.
POST https://api.platica.mx/v1/messages/template Cuerpo de la solicitud
{
"channelId": "521234567890",
"conversationId": "521234567890",
"campaignId": "pV6PvG2lc8ChQb2VmETr",
"template": {
"name": "bienvenida_cliente",
"params": ["Juan", "Premium"],
"type": "image",
"file": "https://cdn.assets.com/welcome_image.jpg",
"buttons": [
{
"index": 0,
"parameters": [{ "type": "text", "text": "promo/enero" }]
}
]
},
"client": {
"name": "José",
"customFields": {
"placas": "ABC123",
"id_recepcion": "REC001"
}
}
} Parámetros del cuerpo
| Campo | Tipo | Descripción | Requerido |
|---|---|---|---|
channelId | string | ID interno del canal O número de teléfono del agente (formato E.164 sin +) | ✓ |
conversationId | string | Número de teléfono del cliente en formato E.164 sin + | ✓ |
campaignId | string | ID de la campaña a la que se atribuye el mensaje. Si se omite, el mensaje se registra bajo la campaña api | — |
template.name | string | Nombre de la plantilla a utilizar | ✓ |
template.params | array | Variables para el cuerpo de la plantilla. La cantidad debe coincidir exactamente con el número de variables definidas en la plantilla | — |
template.type | enum | Tipo de encabezado: image, document, video. Obligatorio si la plantilla tiene encabezado multimedia | — |
template.file | string | URL pública https:// del archivo para el encabezado. Obligatoria si template.type está presente | — |
template.buttons | array | Variables dinámicas de los botones de la plantilla. Máximo 3 elementos | — |
delay | number | Retraso en milisegundos (3,000 – 86,400,000) | — |
scheduleTime | string | Fecha/hora de envío programado (ISO 8601). Máximo 1 año en el futuro | — |
client | object | Información del cliente a actualizar (Upsert) | — |
Si se envía el objeto client, se actualizará la información del perfil del cliente (o se creará si no existe), permitiendo al agente de IA tener acceso inmediato a los nuevos datos.
Cada elemento del array representa un botón dinámico de la plantilla. Los botones estáticos (sin variables) no necesitan incluirse.
| Campo | Tipo | Descripción | Requerido |
|---|---|---|---|
index | integer | Índice base-0 del botón en la plantilla. Debe corresponder a un botón existente | ✓ |
sub_type | enum | url, phone_number, quick_reply, otp. Se infiere automáticamente del tipo definido en la plantilla si se omite | — |
parameters | array | Exactamente un elemento con { "type": "text", "text": "<valor>" } | ✓ |
Reglas importantes:
- Los índices no pueden repetirse dentro del mismo array
- Para botones de tipo URL,
textdebe ser un segmento de ruta (ej:"promo/enero"), no una URL completa. Enviar"https://..."devuelve error 400 - Si
sub_typese omite, se infiere del tipo del botón definido en la plantilla (URL→url,OTP→otp,PHONE_NUMBER→phone_number)
"buttons": [
{
"index": 0,
"parameters": [{ "type": "text", "text": "promo/enero" }]
},
{
"index": 1,
"sub_type": "otp",
"parameters": [{ "type": "text", "text": "482910" }]
}
] Envío con retraso (delay):
- Mínimo:
3000ms (3 segundos) - Máximo:
86400000ms (24 horas) - Ejemplo:
"delay": 5000envía el mensaje en 5 segundos
Envío programado (scheduleTime):
- Formato ISO 8601
- Debe ser una fecha futura
- No puede ser más de 1 año en el futuro
- Ejemplos:
"2025-07-01T18:40:00"— Hora de México (UTC-6)"2025-07-01T18:40:00Z"— Hora UTC"2025-07-01T18:40:00-06:00"— Con zona horaria específica
No puedes usar delay y scheduleTime en la misma solicitud.
| Campo | Tipo | Descripción |
|---|---|---|
client.name | string | Nombre completo del cliente |
client.firstname | string | Primer nombre |
client.lastname | string | Apellido |
client.email | string | Correo electrónico |
client.birthdate | string | Fecha de nacimiento (dd/mm/yyyy) |
client.gender | enum | Género: male o female |
client.company | string | Nombre de la compañía |
client.country | enum | Código ISO 3166-1 alpha-2 (ej: MX, US) |
client.state | string | Estado de residencia |
client.city | string | Ciudad de residencia |
client.address | string | Dirección completa |
client.postalCode | string | Código postal |
client.customFields | map | Objeto con pares clave-valor de los campos personalizados definidos en el workspace. Consulta Campos Personalizados para ver los disponibles. |
client.owners | array | Correos de usuarios responsables |
Validación contra la plantilla
Al recibir la solicitud, el API verifica que el payload sea compatible con la definición de la plantilla registrada en WhatsApp. Si hay incompatibilidades, se devuelve un error 400 con el detalle de cada problema.
Las reglas que se validan automáticamente son:
- Cantidad de params: debe coincidir exactamente con el número de variables
{{1}},{{2}}... en el cuerpo de la plantilla - Encabezado multimedia: si la plantilla tiene encabezado de imagen, video o documento,
template.typeytemplate.fileson obligatorios ytypedebe coincidir con el formato definido - Índices de botones: cada
indexentemplate.buttonsdebe corresponder a un botón existente en la plantilla - Variables de botones URL: el valor de
textdebe ser un segmento de ruta, no una URL completa
{
"message": "Template payload is incompatible with template configuration",
"template": "bienvenida_cliente",
"errors": [
{
"field": "template.params",
"message": "The number of params does not match the template definition",
"expected": 2,
"received": 1
},
{
"field": "template.type",
"message": "This template requires media header type",
"expected": "image",
"received": null,
"example": {
"type": "image",
"file": "https://example.com/your-media-file"
}
}
]
} Respuesta
La respuesta varía según si el mensaje se envía de forma inmediata, diferida o programada.
Envío inmediato:
{
"messageId": "msg_123xyz",
"status": "sent",
"timestamp": "2025-02-14T12:00:00Z"
} Con delay:
{
"messageId": "msg_123xyz",
"status": "delayed",
"timestamp": "2025-02-14T12:00:00Z",
"executeAt": "2025-02-14T12:00:05.000Z",
"delayMs": 5000
} Con scheduleTime:
{
"messageId": "msg_123xyz",
"status": "scheduled",
"timestamp": "2025-02-14T12:00:00Z",
"executeAt": "2025-07-01T00:40:00.000Z",
"scheduledTime": "2025-07-01T18:40:00"
} | Campo | Tipo | Descripción |
|---|---|---|
messageId | string | ID del mensaje creado. Úsalo para rastrear el estado en la campaña |
status | enum | sent, delayed o scheduled |
timestamp | string | Fecha/hora en que se procesó la solicitud (ISO 8601 UTC) |
executeAt | string | Fecha/hora en que se enviará el mensaje (ISO 8601 UTC). Solo presente en envíos diferidos o programados |
delayMs | number | Retraso configurado en milisegundos. Solo presente cuando se usó delay |
scheduledTime | string | Valor original de scheduleTime enviado en la solicitud. Solo presente cuando se usó scheduleTime |
Reglas de WhatsApp
Plantillas obligatorias
Para iniciar una conversación debes usar una plantilla pre-aprobada. No puedes enviar mensajes de texto libre hasta que el cliente responda.
Ventana de 24 horas
Las conversaciones permanecen activas durante 24 horas desde el último mensaje del cliente.
Si el cliente NO responde:
- Envías la plantilla
- El cliente no responde
- No puedes enviar más mensajes hasta que responda
Si el cliente SÍ responde:
- Envías la plantilla
- El cliente responde
- Puedes enviar mensajes libremente durante 24 horas
- La ventana se reinicia con cada mensaje del cliente
Limitaciones de entrega
WhatsApp puede bloquear mensajes por:
- Restricciones del país del cliente
- Números en experimentos de WhatsApp
- Clientes que desactivaron notificaciones de marketing
Consultar estado
Verifica si tu mensaje fue entregado:
- Desde la bandeja de entrada de la plataforma
- Usando el endpoint Obtener Conversación