Recordatorio de respuesta pendiente (WhatsApp API)
El escenario envía al cliente una plantilla de WhatsApp personalizada cuando soporte está bloqueado esperando su respuesta.
Descripción del caso de uso
El escenario envía al cliente una plantilla de WhatsApp personalizada cuando soporte está bloqueado esperando su respuesta. El mensaje incluye el nombre del cliente, número de ticket y qué respuesta o acción aún se necesita. Un botón URL estático abre la página del ticket o portal de ayuda para responder.
Ejemplo de plantilla
Hola, {{1}}! Esperamos tu respuesta sobre la solicitud #{{2}}. {{3}} Por favor responde para que podamos continuar.
- {{1}}nombre del cliente
- {{2}}número de ticket o caso
- {{3}}detalle de la solicitud o texto del recordatorio (p. ej. confirma la dirección de entrega, responde antes del viernes)
- “Responder”botón — fijo en la plantilla de Meta

Cuándo usarlo
Recurre a este escenario cuando un ticket está estancado esperando la respuesta del cliente y soporte no puede avanzar sin ella. Encaja en helpdesks que persiguen aclaraciones en casos detenidos, equipos de reclamos y KYC cerca del SLA de respuesta del cliente, y agencias que automatizan seguimiento cuando el estado del ticket es waiting-on-customer.
Flujo de trabajo
- Disparador
El helpdesk marca el ticket como esperando respuesta del cliente o se dispara un temporizador.
evento·disparado - Capturar evento
El sistema obtiene el teléfono del destinatario y los campos del recordatorio.
phone:"+…" - Construir y enviar
Se construye un mensaje de plantilla personalizado con tres variables en el cuerpo y un botón URL estático.
POST/sendTemplate - Entregado
El cliente recibe el recordatorio en WhatsApp con el contexto del ticket y la acción requerida.
entregado - Estado registrado
Se registra el resultado de entrega; la respuesta del cliente puede continuar en sesión tras responder.
status:"read"

Implementación técnica
Requisitos previos
- Clave API de 1MSG · Cómo obtener la clave API
- Cuenta de WhatsApp Business · Cómo conectar WABA
- Plantilla de WhatsApp · Cómo aprobar una plantilla WABA
- Opt-in del cliente · Cómo gestionar el consentimiento
Ejemplos de código
#!/usr/bin/env bash
set -euo pipefail
# === Configuration (replace "___" placeholders) ===
API_BASE_URL="https://api.1msg.io" # production 1MSG API base URL
CHANNEL_ID="___" # channel ID from 1MSG dashboard
API_TOKEN="___" # channel JWT token (Bearer)
TEMPLATE_NAME="___" # approved template name
TEMPLATE_NAMESPACE="___" # template namespace (required — send fails without it)
TEMPLATE_LANGUAGE="___" # template language code, e.g. "en"
# === Test data ===
TEST_PHONE="___" # client phone in international format
TEST_CUSTOMERNAME="___" # {{1}} customer name
TEST_TICKETNUMBER="___" # {{2}} ticket number
TEST_REQUESTDETAIL="___" # {{3}} request detail
PHONE_NORM="$(printf '%s' "$TEST_PHONE" | tr -cd '0-9')"
for pair in "CHANNEL_ID=$CHANNEL_ID" "API_TOKEN=$API_TOKEN" \
"TEMPLATE_NAME=$TEMPLATE_NAME" "TEMPLATE_NAMESPACE=$TEMPLATE_NAMESPACE" \
"TEMPLATE_LANGUAGE=$TEMPLATE_LANGUAGE" "TEST_PHONE=$TEST_PHONE" \
"TEST_CUSTOMERNAME=$TEST_CUSTOMERNAME" \
"TEST_TICKETNUMBER=$TEST_TICKETNUMBER" \
"TEST_REQUESTDETAIL=$TEST_REQUESTDETAIL"; do
val="${pair#*=}"
if [ -z "$val" ] || [ "$val" = "___" ]; then
echo "Missing configuration value: ${pair%%=*}" >&2
exit 1
fi
done
if [ -z "$PHONE_NORM" ]; then
echo "Error: phone number has no digits after normalization" >&2
exit 1
fi
URL="${API_BASE_URL%/}/${CHANNEL_ID}/sendTemplate"
# params carries body ONLY. Button text is fixed in the Meta template — no button param.
# {{1}} customer name → ${TEST_CUSTOMERNAME}
# {{2}} ticket number → ${TEST_TICKETNUMBER}
# {{3}} request detail → ${TEST_REQUESTDETAIL}
read -r -d '' PAYLOAD <<JSON || true
{
"phone": "${PHONE_NORM}",
"template": "${TEMPLATE_NAME}",
"namespace": "${TEMPLATE_NAMESPACE}",
"language": { "policy": "deterministic", "code": "${TEMPLATE_LANGUAGE}" },
"params": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "${TEST_CUSTOMERNAME}" },
{ "type": "text", "text": "${TEST_TICKETNUMBER}" },
{ "type": "text", "text": "${TEST_REQUESTDETAIL}" }
]
}
]
}
JSON
RESPONSE="$(curl -s -w '\n%{http_code}' -X POST "$URL" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${API_TOKEN}" \
-d "$PAYLOAD")"
HTTP_CODE="$(printf '%s' "$RESPONSE" | tail -n1)"
BODY="$(printf '%s' "$RESPONSE" | sed '$d')"
case "$BODY" in
*'"sent":true'*) ok=1 ;;
*) ok=0 ;;
esac
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ] && [ "$ok" -eq 1 ]; then
echo "Message sent to client."
echo "API response: $BODY"
else
echo "Send failed. HTTP status: $HTTP_CODE" >&2
echo "$BODY" >&2
exit 1
fi
Respuesta y estado de entrega
HTTP 2xx y JSON "sent": true significan que 1MSG aceptó el mensaje para envío — no que ya llegó al teléfono del cliente. Guarda el campo id (tipo wamid.…) para correlacionar los callbacks de entrega.
{
"sent": true,
"message": "Sent to [email protected]",
"description": "Message has been sent to the provider",
"id": "wamid.HBgLMzgwNjM5..."
}sentAceptado para envío — aún no en el teléfono del cliente
idGuárdalo; los callbacks de entrega y
hookInfose basan en él
Errores frecuentes
| Estado | Respuesta de la API | Causa | Solución |
|---|---|---|---|
| 200 | Message was not sent: template is not defined | Falta namespace, template o language en el cuerpo de la petición. | Envía los tres. Toma namespace y el nombre exacto de la plantilla de GET /templates; language es un objeto: {"policy": "deterministic", "code": "es_MX"}. |
| 200 | template name (…) does not exist in <language> | La plantilla está aprobada en otro idioma que el solicitado. | Usa el código de idioma exacto con el que se aprobó la plantilla (por ejemplo, es_MX no es lo mismo que es). Revísalo en GET /templates. |
| 200 | Message was not sent: provide chatId, phone, bsuid, or username | Ningún destinatario que el canal pudiera resolver. | Envía un solo destinatario: phone (código de país y número, solo dígitos), chatId (por ejemplo [email protected]) o bsuid. |
