Уведомления о заказах Kaspi в WhatsApp: как настроить через API
Покупатель оформил заказ на Kaspi и ждёт: приняли ли, где забирать, когда приедет курьер. Короткое сообщение от магазина в WhatsApp снимает эти вопросы и звонки «а где мой заказ». Ниже — как связать Kaspi Магазин API и wapi.kz: скрипт сам замечает новое состояние заказа и пишет покупателю с вашего номера.
Понадобятся токен Kaspi Магазин API, номер WhatsApp, подключённый к wapi.kz, и сервер, где скрипт запускается по расписанию.
Как это устроено
У Kaspi нет вебхуков для продавцов: магазин не узнает о новом заказе, пока сам не спросит. Поэтому схема — опрос по таймеру:
- Раз в 5–10 минут скрипт запрашивает заказы у Kaspi Магазин API (
GET /orders) с фильтром по состоянию и дате создания. - Для каждого заказа проверяет свою базу: уведомляли ли уже покупателя об этом состоянии.
- Если нет — отправляет сообщение через POST /messages/send и записывает отметку «уведомлён».
- Ответы покупателей приходят на телефон и вебхуком — их видит менеджер.
Пункт 2 — главный. Каждый опрос возвращает одни и те же заказы снова и снова, и без отметки покупатель получит десяток одинаковых сообщений. Храните пару «id заказа + состояние»: сообщение уходит один раз на каждый переход.
Запросы к Kaspi идут с заголовком X-Auth-Token — токен выдаётся в кабинете продавца Kaspi. Kaspi режет «небраузерные» запросы, поэтому нужен обычный браузерный User-Agent, иначе соединение просто оборвётся.
Что писать покупателю
Статус заказа покупатель и так видит в приложении Kaspi, поэтому дублировать его смысла мало. Пишите то, чего Kaspi не скажет: адрес и часы самовывоза, как найти вход, когда позвонит курьер, кому задать вопрос.
| Состояние в Kaspi | Когда | Что сказать |
|---|---|---|
NEW | Пришёл новый заказ | Получили, проверяем наличие |
PICKUP | Заказ на самовывоз | Адрес, часы работы, что назвать на выдаче |
DELIVERY | Доставляете вы | Передан курьеру, он позвонит перед приездом |
KASPI_DELIVERY | Доставляет Kaspi | Обычно писать не нужно |
Точный смысл каждого состояния и момент перехода сверьте с документацией Kaspi и проверьте на нескольких своих заказах. Если «собран и готов к выдаче» у вас отдельный шаг, этот момент удобнее брать из своей учётной системы — например, из 1С.
Здравствуйте! Это магазин «{магазин}» на Kaspi. Заказ №{номер} принят.
Самовывоз: Алматы, ул. Абая, 10, ежедневно с 10:00 до 20:00.
Вопросы по заказу — ответьте на это сообщение.Представьтесь в первой строке: покупатель не знает ваш номер. Одно сообщение — один повод, номер заказа обязателен. Ночью не пишите — заказ подождёт до утра.
Правила: только по заказу
Пишите покупателю только по его заказу. Без рекламы, акций, «подпишитесь на наши соцсети» и предложений «в следующий раз купите напрямую, будет дешевле». Увод покупателя с площадки маркетплейсы, как правило, запрещают. Перед запуском перечитайте актуальные правила Kaspi для продавцов.
То же правило бережёт ваш номер: сообщение, которого человек ждёт, — нормальная переписка, а холодная реклама незнакомым — главный повод для жалоб и блокировок. Подробнее — в гайде как снизить риск блокировки.
Настройка по шагам
Шаг 1. Получите токен Kaspi Магазин API
Токен выпускается в кабинете продавца Kaspi. Храните его в переменной окружения, а не в коде: он даёт доступ к заказам магазина.
Шаг 2. Подключите номер к wapi.kz
Зарегистрируйтесь, пополните баланс, добавьте номер и привяжите его по QR-коду или коду по номеру — это около 5 минут. В разделе «API и MCP» возьмите API-ключ. Подрядчику лучше выдать ключ номера: он работает только с одним номером.
Шаг 3. Первый запуск — с флагом --init
Скрипт запишет текущие заказы как уже уведомлённые и ничего не отправит. Без этого покупатели прошлой недели получат сообщения задним числом.
Шаг 4. Поставьте опрос по расписанию
# раз в 10 минут; KASPI_TOKEN, WAPI_KEY, KASPI_PHONE_FIELD — в файле .env
*/10 * * * * cd /opt/kaspi-notify && set -a && . ./.env && python3 kaspi_notify.py >> notify.log 2>&1Шаг 5. Задайте вебхук для ответов
Адрес задаётся в кабинете на карточке номера — подробности ниже.
Пример скрипта на Python
Скрипт опрашивает Kaspi, проверяет, есть ли у покупателя WhatsApp (/contacts/check), отправляет сообщение и ведёт отметки в SQLite. Поля заказа сверьте с документацией Kaspi: здесь используются только id, номер заказа и телефон покупателя.
# kaspi_notify.py — pip install requests; первый запуск: python3 kaspi_notify.py --init
import os, sqlite3, sys, time
from datetime import datetime
from zoneinfo import ZoneInfo
import requests
KASPI = "https://kaspi.kz/shop/api/v2"
WAPI = "https://wapi.kz/api/v1"
KASPI_HEADERS = {
"X-Auth-Token": os.environ["KASPI_TOKEN"],
"Accept": "application/vnd.api+json",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/124.0 Safari/537.36",
}
WAPI_HEADERS = {"Authorization": "Bearer " + os.environ["WAPI_KEY"]}
FROM = os.environ.get("WAPI_FROM") # id номера из GET /numbers, если номеров несколько
PHONE_FIELD = os.environ["KASPI_PHONE_FIELD"] # поле с телефоном покупателя из заказа (сверьте с документацией Kaspi)
SHOP = "Ваш магазин"
TEXTS = {
"PICKUP": "Здравствуйте! Это магазин «{shop}» на Kaspi. Заказ №{code} принят. Самовывоз: "
"Алматы, ул. Абая, 10, с 10:00 до 20:00. Вопросы по заказу — ответьте на это сообщение.",
"DELIVERY": "Здравствуйте! Заказ №{code} из магазина «{shop}» передан курьеру, "
"он позвонит перед приездом. Вопросы по заказу — пишите сюда.",
}
STOP = {"daily_limit", "new_contacts_limit", "cold_blocked", "spam_detected", "number_paused", "not_connected"}
db = sqlite3.connect("kaspi_notified.db")
db.execute("CREATE TABLE IF NOT EXISTS notified (order_id TEXT, state TEXT, PRIMARY KEY (order_id, state))")
def kaspi_orders(state, days=7):
now = int(time.time() * 1000)
since = now - days * 86_400_000 # дата создания — в миллисекундах
orders, page = [], 0
while True:
url = (f"{KASPI}/orders?page%5Bnumber%5D={page}&page%5Bsize%5D=100"
f"&filter%5Borders%5D%5Bstate%5D={state}"
f"&filter%5Borders%5D%5BcreationDate%5D%5B$ge%5D={since}"
f"&filter%5Borders%5D%5BcreationDate%5D%5B$le%5D={now}")
r = requests.get(url, headers=KASPI_HEADERS, timeout=30)
r.raise_for_status()
body = r.json()
orders += body.get("data", [])
page += 1
if page >= body.get("meta", {}).get("pageCount", 1):
return orders
def to_phone(raw):
d = "".join(ch for ch in str(raw or "") if ch.isdigit())
if len(d) == 10:
d = "7" + d
elif len(d) == 11 and d.startswith("8"):
d = "7" + d[1:]
return d if len(d) == 11 and d.startswith("7") else None
def wapi(path, payload):
if FROM:
payload["from"] = int(FROM)
r = requests.post(WAPI + path, json=payload, headers=WAPI_HEADERS, timeout=15)
return r.status_code, r.json()
def mark(order_id, state):
db.execute("INSERT OR IGNORE INTO notified VALUES (?, ?)", (order_id, state))
db.commit()
def main(init):
if not init and not 9 <= datetime.now(ZoneInfo("Asia/Almaty")).hour < 21:
return # ночью не пишем
for state, template in TEXTS.items():
for order in kaspi_orders(state):
oid, a = order["id"], order.get("attributes", {})
if db.execute("SELECT 1 FROM notified WHERE order_id = ? AND state = ?", (oid, state)).fetchone():
continue
phone = to_phone((a.get("customer") or {}).get(PHONE_FIELD))
if init or not phone:
mark(oid, state)
continue
status, check = wapi("/contacts/check", {"phone": phone})
time.sleep(1) # проверки — не чаще одной в секунду
if status != 200:
continue # проверка не прошла — попробуем в следующий запуск
if not check.get("exists"):
mark(oid, state) # WhatsApp нет — статус покупатель увидит в Kaspi
continue
status, res = wapi("/messages/send", {"to": phone, "text": template.format(shop=SHOP, code=a.get("code"))})
code = res.get("code")
if status == 200 or code in ("invalid_to", "empty_text", "text_too_long"):
mark(oid, state) # отправлено или номер негодный — повтор не поможет
elif code in STOP or status in (400, 401, 403):
print("Стоп:", code, res.get("error")) # лимит, пауза, from_required, неверный ключ
return
time.sleep(5) # первые сообщения новым людям — не чаще раза в 5 секунд
if __name__ == "__main__":
main("--init" in sys.argv)Упёрлись в лимит или номер на паузе — скрипт останавливается и подхватит оставшиеся заказы в следующий запуск. Чтобы узнавать об этом сразу, добавьте оповещение в Telegram.
Ответы покупателей
Покупатели отвечают: «можно забрать завтра?», «курьер не позвонил». Номер остаётся на телефоне, поэтому ответ сразу виден в WhatsApp у менеджера, и ответить можно оттуда же. В журнале сообщение покупателя помечено source: "contact", а ответ менеджера с телефона — source: "phone".
Если менеджеров несколько, задайте вебхук: событие message с текстом и номером покупателя можно переслать в рабочий чат или CRM — см. гайд про вебхуки. Не отвечайте на вопросы шаблоном: человек спросил — ему нужен человек.
Если покупатель пришлёт фото, например повреждённой упаковки, в вебхуке будет отметка hasMedia: true, а сам снимок через несколько секунд появится в истории — ссылка на него в поле media.url сообщения GET /messages/{id}. И, конечно, его видно на телефоне.
Лимиты и первые дни
Почти каждое такое уведомление — первое сообщение новому человеку, а для них свои лимиты:
- первые 2 недели после подключения — прогрев: дни 1–3 — до 20 новых контактов в сутки, дни 4–7 — до 40, дни 8–14 — до 80;
- дальше на уровне «Хороший» — 150 новых контактов и 1 000 сообщений в сутки;
- первые сообщения новым людям — не чаще раза в 5 секунд;
- если один и тот же текст за час ушёл 25+ новым людям или за час появилось 40+ новых контактов, первые сообщения новым людям приостанавливаются на 24 часа. Текст, в котором меняется только номер заказа, для этой защиты — один и тот же.
Если заказов больше лимита, не пишите на каждом шаге — оставьте одно самое полезное сообщение. Если поток заказов постоянно упирается в лимиты, это сигнал смотреть на официальный WhatsApp Business API, а не раскидывать уведомления по нескольким номерам: лимиты и защита от рассылок действуют на каждом номере.
Платы за сообщения нет: номер стоит 9 900 ₸ в месяц, сколько бы уведомлений ни ушло в пределах лимитов. Подробнее — на странице цен.
Частые вопросы
Почему опрос по таймеру, а не вебхук от Kaspi?
Вебхуков для продавцов у Kaspi нет, заказы приходится запрашивать самим. Опроса раз в 5–10 минут хватает: сообщение уходит вскоре после смены состояния.
Можно ли писать покупателям Kaspi про акции и новинки?
Нет, только по оформленному заказу. Реклама и увод с площадки ставят под удар ваш магазин на Kaspi и повышают риск блокировки номера.
Что, если у покупателя нет WhatsApp?
Скрипт проверяет номер через /contacts/check (до 200 проверок в сутки на номер) и пропускает такие заказы. Статус покупатель всё равно видит в приложении Kaspi.
Гарантируете, что номер не заблокируют?
Нет, такой гарантии нет ни у кого: риск есть у любого неофициального подключения. Сообщения по заказу, которых человек ждёт, — самый безопасный сценарий, а лимиты сервиса не дают отправке выглядеть как рассылка.
Можно ли использовать основной номер магазина?
Да. Номер остаётся на телефоне и работает как обычно, а скрипт пишет с него через API. Удобно, что ответы покупателей менеджер видит в привычном WhatsApp.
Подключите WhatsApp к своим системам
9 900 ₸ в месяц за номер, без платы за сообщения. Сервер в Казахстане, оплата Kaspi или счётом на ТОО/ИП. Подключение — около 5 минут.