WhatsApp Business API для запроса отзыва после обслуживания
Сценарий отправляет клиенту персонализированный шаблон WhatsApp после завершения услуги, прося оценить ее качество.
Обзор сценария
Сценарий отправляет клиенту персонализированный шаблон WhatsApp после завершения услуги, предлагая оценить качество работы. Сообщение включает имя клиента, название услуги и короткий запрос на оценку. Статическая кнопка URL открывает форму обратной связи или страницу отзыва.
Пример шаблона
Здравствуйте, {{1}}! Услуга «{{2}}» завершена. {{3}}Пожалуйста, оцените качество обслуживания — это займет примерно минуту.
- {{1}}имя клиента
- {{2}}завершенная услуга (например, ремонт ноутбука, чистка зубов, доставка на дом)
- {{3}}оценка запроса или инструкции (например, оцените свой опыт от 1 до 5, это займет 1 минуту)
- “Оценка сервиса”кнопка — исправлено в шаблоне Meta

Когда использовать это
Используйте этот сценарий, когда встреча по оказанию услуги, доставка или выездное посещение завершены, и команде нужен структурированный рейтинг качества в WhatsApp вместо ручного сообщения или опроса только по электронной почте. Это подходит для сервисных и ремонтных компаний, которые собирают отзывы в виде 1–5 звезд после выполнения работы, а также агентств, подключающих триггеры завершенной услуги из CRM, системы бронирования или пользовательских процессов как это работает.
Как это работает
- Триггер
Система управления запускает событие service-completed, когда задача или визит отмечены как выполненные.
event·triggered - Отслеживать событие
Система определяет номер телефона получателя и рейтинг.
phone:"+…" - Собрать и отправить
Персонализированное сообщение по шаблону создается с тремя переменными в теле и статической кнопкой URL.
POST/sendTemplate - Доставлено
Клиент получает в WhatsApp запрос на оценку с контекстом услуги.
delivered - Статус отслеживается
Результат доставки фиксируется, завершение опроса отслеживается за пределами WhatsApp.
status:"read"

Техническая реализация
Предварительные условия
- Ключ API для 1MSG · Как получить ключ API
- Аккаунт WhatsApp Business · Как подключить WABA
- Шаблон WhatsApp · Как утвердить шаблон WABA
- Подключение клиента · Как управлять согласием клиентов
Примеры кода
#!/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_SERVICE="___" # {{2}} service name
TEST_INFO="___" # {{3}} additional info
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_SERVICE=$TEST_SERVICE" \
"TEST_INFO=$TEST_INFO"; 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}} service name → ${TEST_SERVICE}
# {{3}} additional info → ${TEST_INFO}
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_SERVICE}" },
{ "type": "text", "text": "${TEST_INFO}" }
]
}
]
}
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
Статус отклика и доставки
Коды HTTP 2xx и JSON "sent": true означают, что 1MSG принял сообщение для отправки, но не то, что оно уже доставлено на телефон клиента. Сохраните поле id (выглядит как wamid.…), чтобы сопоставить с уведомлениями о доставке.
{
"sent": true,
"id": "wamid.HBgLMzgwNjM5...",
"message": "Message accepted for delivery"
}sentПринято для отправки — еще не на телефоне клиента
idСохраните это — обратные вызовы доставки и
hookInfoпривязаны к этому
Само уведомление о доставке приходит позже, как отдельный обратный вызов. Зарегистрируйте вебхук (POST …/webhook), и 1MSG будет отправлять обновления статусов на ваш HTTPS-эндпоинт в виде верхнеуровневых hooks[]данных.
{
"hooks": [
{
"id": "gBGGeSaGViBfAgnlzOSHEwK9O6F",
"type": "message",
"status": "sent",
"timestamp": "1654864094",
"recipient_id": "556123122026"
}
]
}statussent,delivered,read— или статус ошибки, если это возможноidСопоставляет callback с
id, возвращенным вызовом sendtimestampСтрока с Unix-временем в секундах
Если вы не хотите получать обратные вызовы, GET {base}/{channel}/hookInfo?messageId=<id>вместо этого опрашивайте. На практике доставка часто завершается в течение нескольких секунд — но API не дает гарантий, поэтому никогда не блокируйте процесс в ожидании
Частые ошибки
| Статус | Ответить | Причина |
|---|---|---|
| 200 | Message was not sent: template is not defined | namespace, template or language missing from the request body. |
| 200 | template name (…) does not exist in <language> | The template is approved in a different language than the one requested. |
| 200 | Message was not sent: provide chatId, phone, bsuid, or username | No recipient the channel could resolve. |
| 403 | access denied | The token is wrong, or belongs to a different channel than the URL. |
| 429 | too many requests. please try later | The channel is over its send rate. |

