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

Когда использовать
Используйте этот сценарий, когда клиент должен загрузить обязательный документ для продолжения онбординга, но ещё не отправил его, и нет открытого разговора в WhatsApp, чтобы связаться с ним. Он подходит для продуктовых команд, которые ограничивают активацию аккаунта из-за отсутствия KYC-файлов, для служб поддержки, ожидающих вложений или подписанных форм, а также для агентств, которые интегрируют загрузку документов из CRM или BPM в оповещения через WhatsApp.
Как это работает
- Триггер
Правило или как это работает требует, чтобы клиент загрузил конкретный документ.
event·triggered - Фиксировать событие
Система обнаруживает событие, требующее загрузить документ, и определяет номер телефона получателя.
phone:"+…" - Собрать и отправить
Персонализированное сообщение по шаблону создаётся с тремя переменными в теле и кнопкой со статичным URL.
POST/sendTemplate - Доставлено
Клиент получает запрос на загрузку документа WhatsApp с контекстом и инструкциями.
delivered - Статус отслеживается
Результат доставки записывается в журнал; клиент может загрузить данные через ссылку на портале.
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_AWAITEDITEM="___" # {{2}} awaited item
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_AWAITEDITEM=$TEST_AWAITEDITEM" \
"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}} awaited item → ${TEST_AWAITEDITEM}
# {{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_AWAITEDITEM}" },
{ "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
Статус ответа и доставки
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[] payload.
{
"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. |

