Клиент WAIX для Python 3.10 и новее. Работает на стандартной библиотеке, содержит аннотации типов. Запросы синхронные: в асинхронном веб-приложении вызывайте SDK через рабочий поток.
python -m pip install waix-pythonПодключите номер в WAIX, получите Connection ID и серверный ключ с правом messages:write. Пример использует одобренный шаблон order_ready на русском языке с одной переменной в теле.
import os
import uuid
from waix import Waix, WaixError
waix = Waix(os.environ['WAIX_API_KEY'])
# Создайте и сохраните UUID вместе с событием заказа до отправки.
event_id = str(uuid.uuid4())
result = waix.messages.send({
'connection_id': os.environ['WAIX_CONNECTION_ID'],
'to': '+77071234567', 'type': 'template',
'template': {
'name': 'order_ready', 'language': {'code': 'ru'},
'components': [{'type': 'body', 'parameters': [{'type': 'text', 'text': '42'}]}],
},
}, event_id)
print(result['data']['id'], result['data']['status'])otp = Waix(os.environ['WAIX_OTP_PROJECT_KEY'])
sent = otp.otp.send({'to': '+77071234567', 'ttl': 300}, event_id)
# Сохраните sent['data']['id'] в серверной сессии пользователя.
status = otp.otp.status(sent['data']['id'])
# supplied_code — код, введённый пользователем в той же сессии.
verified = otp.otp.verify(sent['data']['id'], supplied_code)Перехватывайте WaixError. Поля: status (0 при сетевой ошибке), code, request_id, retry_after, body. Таймаут задаётся в секундах:
waix = Waix(os.environ['WAIX_API_KEY'], timeout=30, base_url='https://waix.kz/api/v1')Проверка TLS-сертификатов включена. Если локальный Python не находит доверенный сертификат, настройте хранилище CA операционной системы или Python; не отключайте проверку TLS.
Загрузка файла: waix.media.upload(connection_id, 'invoice.pdf', content_type='application/pdf', type='document'). Файл читается в память; предел SDK — 100 МБ, дополнительно действуют ограничения API для типа файла.
Пагинация: waix.messages.list(limit=50, before=cursor, before_id=cursor_id).
Проверка вебхука: verify_webhook(raw_body, timestamp_header, signature_header, secret); функция импортируется из waix.
PYTHONPATH=src python -m unittest discover -s tests
python -m pip install build
python -m buildТесты используют локальный HTTP-сервер и не отправляют сообщения клиентам.
| Раздел | Возможности |
|---|---|
| Сообщения | Отправка, список с пагинацией, просмотр, явный повтор |
| Подключения | Список номеров, чтение и изменение профиля компании |
| Шаблоны | Список, просмотр, создание, изменение, удаление, предварительный просмотр |
| Медиа | Загрузка файла, список, получение URL, удаление |
| Вебхуки | Чтение и изменение настроек, тест, удаление, смена секрета |
| OTP | Отправка кода, проверка, статус запроса |
Все запросы идут на https://waix.kz/api/v1. SDK возвращает полный JSON-ответ: data, а также pagination, если она есть. Для остальных операций API v1 можно использовать метод request с относительным путём. Не передавайте в него адрес, полученный от непроверенного пользователя.
Некоторым операциям нужны права управления и ключ компании. Ключ отдельного OTP-проекта не даёт доступа к настройкам вебхука компании. Список прав и полей: спецификация API.
Создайте UUID один раз при записи события в своей базе. Передайте его как ключ идемпотентности. При потере ответа повторяйте запрос с тем же UUID и теми же параметрами: новый ключ означает новое сообщение.
HTTP 202 означает, что сообщение поставлено в очередь. Доставку проверяйте по вебхуку, журналу WAIX или методу просмотра сообщения. У SDK нет автоматических повторов и переходов по HTTP redirect. Для 429 учитывайте Retry-After; ошибки 400, 401, 403 требуют исправления параметров или доступа. Сообщение со статусом outcome_unknown нельзя повторять вслепую.
Передавайте в функцию проверки исходные байты тела HTTP-запроса до разбора JSON, заголовки X-Waix-Timestamp, X-Waix-Signature и секрет вебхука. Подпись: HMAC-SHA256 от timestamp + "." + rawBody, с префиксом v1=. Сравнение выполняется за постоянное время; допустимое отклонение времени по умолчанию — 300 секунд.
Отклоняйте неверную подпись. Повторные события определяйте по X-Waix-Delivery: верная подпись сама по себе не защищает от повторной доставки в пределах допустимого времени. Сначала надёжно сохраните событие, затем ответьте кодом 2xx.
- Храните ключи на сервере. Не включайте их в код сайта, мобильного приложения или общий файл сценария. Выдавайте только нужные права.
- Для первого сообщения клиенту обычно нужен одобренный шаблон. Произвольный текст разрешён в рамках действующего окна обслуживания Meta. Проверяйте согласие клиента и учитывайте отказ от сообщений.
- OTP использует отдельный ключ проекта. Начните с sandbox: он возвращает
test_codeи не отправляет сообщение WhatsApp. Тестовый код нельзя показывать человеку, чью личность вы проверяете. - Сохраните ID OTP-запроса в серверной сессии пользователя. Проверять код должна именно эта сессия. Выдавайте доступ только после успешной проверки; ограничивайте попытки по аккаунту и IP.
- Для рабочих OTP нужны доступный тариф и одобренный отправитель. Проверьте их состояние в кабинете WAIX до включения реальной отправки.
- SDK не записывает ключи, сообщения и коды в лог. Если добавляете свои логи, скрывайте эти данные и сохраняйте
request_idдля диагностики.
Документация WAIX · Поддержка · Тарифы.
SDK работает с API v1 WAIX. Это не клиент Meta Graph API. Версии SDK следуют SemVer. Лицензия — MIT.
SDK не повторяет запрос за вас. HTTP-ошибка от прокси остаётся HTTP-ошибкой, даже если вместо JSON пришёл HTML: сохраняются статус, request ID и Retry-After. Перенаправления запрещены. Некорректный успешный ответ вызывает INVALID_RESPONSE; ответ больше установленного лимита — RESPONSE_TOO_LARGE. Лимит по умолчанию — 2 МиБ, его можно увеличить до 16 МиБ.
| Ситуация | Что делать |
|---|---|
400 / 422 |
Исправить поля, формат телефона, шаблон или код OTP. |
401 / 403 |
Проверить ключ, права и принадлежность подключения/OTP-проекта. |
409 |
Проверить конфликт ключа идемпотентности: под одним ключом нельзя менять тело. |
429 |
Отложить запрос на срок из Retry-After, сохранив прежний ключ и тело. |
5xx, TIMEOUT, TRANSPORT_ERROR |
Результат отправки может быть неизвестен. Сначала проверить сохранённый ID; если ID не получен, повторять прежний запрос с прежним ключом через ограниченную очередь повторов. |
INVALID_RESPONSE / RESPONSE_TOO_LARGE |
Проверить прокси, адрес API и размер страницы. Не создавать новую отправку. |
OTP_INVALID |
Код неверен, истёк или уже использован. Не выдавать сессию приложения. |
body исключения доступен для диагностики, но может содержать данные клиента. В журнал записывайте только безопасные метаданные из примера ниже. Не сериализуйте целиком ответ sandbox OTP.
Имена существующих методов сохранены. У otp.verify код должен быть строкой из шести цифр: '012345', а не число. Значения query — только строки, конечные числа и boolean; сложные объекты нужно разобрать на параметры. Ошибки HTML от прокси теперь имеют API_ERROR, а перенаправления — REDIRECT_DISALLOWED. При обработке ошибок ориентируйтесь также на HTTP-статус.
waix = Waix(os.environ['WAIX_API_KEY'], timeout=30, max_response_bytes=2097152)
for message in waix.messages.iterate(connection_id=connection_id, limit=100, max_pages=100):
save_status(message['id'], message['status'])Генератор запрашивает страницы по мере чтения, сохраняет фильтры и передаёт оба курсора. Повторный курсор вызывает INVALID_PAGINATION; достижение max_pages — PAGINATION_LIMIT. По умолчанию предел — 1000 страниц. break останавливает загрузку следующих страниц.
try:
result = waix.messages.get(saved_message_id)
except WaixError as error:
logger.warning('WAIX request failed', extra=error.to_dict())
delay_seconds = error.retry_delay() # секунды или None
# Решение о повторе принимает ваша очередь.Python-клиент синхронный. timeout задаёт таймаут сетевых операций urllib, а не общий дедлайн задания. В асинхронном сервере запускайте клиент в отдельном потоке или очереди; не блокируйте event loop. Файл multipart загружается в память; для больших файлов выделите отдельный worker.