WhatsApp Business API para respuesta en sesión — consulta de precio
Este escenario envía un mensaje de texto libre de WhatsApp con sendMessage dentro de la ventana de atención al cliente de 24 horas después de que el cliente pregunte cuánto cuesta un producto o servic
Descripción del caso de uso
Este escenario envía un mensaje de texto libre de WhatsApp con sendMessage dentro de la ventana de atención al cliente de 24 horas después de que el cliente pregunte cuánto cuesta un producto o servicio.
Ejemplo de plantilla
Hola, {{1}}! El precio de «{{2}}» es {{3}}. Si necesitas una cotización personalizada o descuento por volumen, responde aquí y nuestro gerente te ayudará.
- {{1}}nombre del cliente
- {{2}}nombre del producto o servicio
- {{3}}precio formateado con moneda

Cuándo usarlo
Usa este escenario cuando un prospecto pregunta cuánto cuesta un producto o servicio dentro de una conversación abierta de WhatsApp y necesitas devolver la cotización antes de que se vaya. Encaja en equipos de ventas que obtienen precios en vivo desde CRM o una API de catálogo, pequeños negocios que atienden consultas de precio en el chat, y agencias que conectan tiendas de clientes a respuestas en sesión en lugar de plantillas cold-start.
Flujo de trabajo
- Estado registrado
Llega un mensaje entrante del cliente con una pregunta de precio vía webhook.
status:"read" - Capturar evento
Tu backend obtiene el SKU del producto y el precio de lista actual.
phone:"+…" - Construir y enviar
Un mensaje de texto en sesión envía la cotización con nombre del producto y monto formateado.
POST/sendMessage - Entregado
El cliente continúa el diálogo para descuentos o checkout en la misma sesión.
entregado

Implementación técnica
Requisitos previos
- Clave API de 1MSG · Cómo obtener la clave API
- Cuenta de WhatsApp Business · Cómo conectar WABA
- Ventana de sesión de 24 horas abierta · Cómo funciona la ventana de 24 horas
- Opt-in del cliente · Cómo gestionar el consentimiento
- Endpoint de webhook · Cómo configurar webhooks
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)
# === Test data ===
TEST_PHONE="___" # client phone in international format · requires open 24-hour session window
TEST_CUSTOMERNAME="___" # {{1}} customer name
TEST_PRODUCTORSERVICENAME="___" # {{2}} product or service name
TEST_PAYMENTAMOUNT="___" # {{3}} payment amount
PHONE_NORM="$(printf '%s' "$TEST_PHONE" | tr -cd '0-9')"
for pair in "CHANNEL_ID=$CHANNEL_ID" "API_TOKEN=$API_TOKEN" "TEST_PHONE=$TEST_PHONE" \
"TEST_CUSTOMERNAME=$TEST_CUSTOMERNAME" \
"TEST_PRODUCTORSERVICENAME=$TEST_PRODUCTORSERVICENAME" \
"TEST_PAYMENTAMOUNT=$TEST_PAYMENTAMOUNT"; 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}/sendMessage"
read -r -d '' PAYLOAD <<JSON || true
{
"phone": "${PHONE_NORM}",
"body": "Hello, Alexey! The price for «Premium Plan (annual)» is 49 900 RUB. If you need a custom quote or volume discount, reply here and our manager will help."
}
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,
"id": "wamid.HBgLMzgwNjM5...",
"message": "Message accepted for delivery"
}sentAceptado para envío — aún no en el teléfono del cliente
idGuárdalo; los callbacks de entrega y
hookInfose basan en él
La entrega llega después, como un callback aparte. Registra un webhook (POST …/webhook) y 1MSG enviará las actualizaciones de estado a tu endpoint HTTPS en un payload hooks[] de nivel superior.
{
"hooks": [
{
"id": "gBGGeSaGViBfAgnlzOSHEwK9O6F",
"type": "message",
"status": "sent",
"timestamp": "1654864094",
"recipient_id": "556123122026"
}
]
}statussent,delivered,read— o un estado de fallo cuando apliqueidCorrelaciona el callback con el
iddevuelto por el envíotimestampSegundos Unix, como cadena
Si prefieres no recibir callbacks, consulta GET {base}/{channel}/hookInfo?messageId=<id> en su lugar. En la práctica la entrega suele completarse en segundos — pero el contrato de la API no lo garantiza, así que nunca bloquees un flujo esperándola.
Errores frecuentes
| Estado | Respuesta | Causa |
|---|---|---|
| 200 | Message was not sent: empty body | Falta body en la petición. |
| 200 | Message was not sent: provide chatId, phone, bsuid, or username | Ningún destinatario que el canal pudiera resolver. |
| 200 | wrong file | El archivo no se pudo descargar ni subir — URL inalcanzable o base64 inválido. |
| 403 | access denied | El token es incorrecto, o pertenece a otro canal que el de la URL. |
| 200 | Message was not sent: filename | sendFile sin filename: el archivo no tiene extensión que enviar. |

