BROADCAST
REST API · ВЕРСИЯ 0.3

От первого запроса
до готовой рассылки.

Отправляйте текст и изображения в WhatsApp. Сервис ставит сообщения в очередь, отправляет их по одному и сохраняет результат для каждого получателя.

Базовый адресhttp://185.113.132.60
01

Подключите WhatsApp

Отсканируйте QR-код в панели.

02

Создайте рассылку

Передайте текст или изображение и номера.

03

Следите за отправкой

Получайте прогресс через API или в панели.

01 · ПОДГОТОВКА

Начало работы

Откройте страницу подключения WhatsApp, войдите с API-токеном и отсканируйте QR-код. Затем укажите токен в заголовке X-Api-Key каждого запроса с данными.

Замените YOUR_API_TOKEN своим токеном. Номера в примерах также замените на номера получателей. Переменные ниже используются во всех примерах cURL.

Bash · адрес и токен
export MAILING_API_URL='http://185.113.132.60'
export MAILING_API_KEY='YOUR_API_TOKEN'

curl --fail-with-body "$MAILING_API_URL/status" \
  -H "X-Api-Key: $MAILING_API_KEY"

В ответе session.status: WORKING означает, что WhatsApp подключён. ready: true означает, что сервис готов отправлять сообщения. Если аккаунт ещё не подключён или очередь на паузе, созданные рассылки сохраняются и ждут.

Примеры используют адрес открытой страницы. После перехода на https://broadcast.1game.kz изменится только базовый URL; токен и методы останутся прежними.

Создать рассылку без API

В панели нажмите «Создать рассылку». Вставьте номера с новой строки, через запятую или точку с запятой, добавьте текст и при необходимости картинку. Переключатель «Сначала поздороваться и дождаться ответа» включает приветствие. Нажмите «Запустить рассылку» — откроются прогресс и получатели.

Если очередь на паузе или WhatsApp не подключён, задание сохранится и будет ждать. При обрыве связи повторите запрос кнопкой в форме: повтор не создаст дубликат рассылки.

02 · СООБЩЕНИЯ

Отправить текст

POST /broadcasts принимает список recipients и текст. Один номер в списке — отправка одному человеку; несколько — рассылка.

cURL · текстовая рассылка
curl --fail-with-body "$MAILING_API_URL/broadcasts" \
  -H "X-Api-Key: $MAILING_API_KEY" \
  -H 'Idempotency-Key: promo-text-2026-001' \
  -H 'Content-Type: application/json' \
  -d '{
    "recipients": ["+77001234567", "+77001234568"],
    "text": "Приглашаем на турнир в 1GAME!"
  }'
Ответ · 202 Accepted
{
  "id": "YOUR_BROADCAST_ID",
  "created": true,
  "status_url": "/broadcasts/YOUR_BROADCAST_ID"
}

202 означает, что задание принято в очередь. Сохраните id или status_url, чтобы узнать результат. Получатели обрабатываются по порядку, с паузами.

Подключить другой номер

В панели откройте «Подключение» и нажмите «Отключить WhatsApp». Очередь станет на паузу. Нажмите «Получить QR-код», отсканируйте его другим телефоном и затем нажмите «Продолжить очередь».

Через API используйте POST /session/disconnect, затем POST /session/start и GET /session/qr. После подключения нового номера отправку включает POST /queue/resume. При ответе 409 на отключение очередь уже на паузе: дождитесь текущей отправки и повторите запрос. При ошибке отключения повторите его до успешного завершения.

История сохраняется. Ожидания ответов и ещё не отправленные основные сообщения после приветствий старого аккаунта отменяются: эти разговоры не переносятся на новый номер. Остальные задания остаются в очереди.

Защита от повторной отправки

Заголовок Idempotency-Key обязателен при создании рассылки. Придумайте уникальный ключ для каждого нового задания, например promo-text-2026-001. При сетевом сбое повторите тот же запрос с тем же ключом: сервис вернёт прежнюю рассылку с кодом 200 и created: false.

Если поменять текст, приветствие, изображение или список получателей, сохранив ключ, сервис вернёт 409. Новый ключ создаёт отдельную рассылку, даже если содержимое совпадает. Допустимы 1–128 символов: латинские буквы, цифры, - _ . :.

ОПЦИОНАЛЬНЫЙ РЕЖИМ

Приветствие → ответ → основное сообщение

Добавьте поле greeting в POST /broadcasts. Сначала получателю отправится только приветствие. Основной text или картинка с подписью отправятся после нового входящего сообщения от этого человека.

cURL · отправка после ответа
curl --fail-with-body "$MAILING_API_URL/broadcasts" \
  -H "X-Api-Key: $MAILING_API_KEY" \
  -H 'Idempotency-Key: greeting-2026-001' \
  -H 'Content-Type: application/json' \
  -d '{
    "recipients": ["+77001234567"],
    "greeting": "Здравствуйте! Можно рассказать о нашем турнире?",
    "text": "Турнир состоится в субботу. Вот подробности…"
  }'

Для картинки добавьте image_id из загрузки файла; она отправится только на втором этапе. Приветствие — непустая строка до 4096 символов. Чтобы отправлять сразу, не передавайте greeting или укажите null.

  • После приветствия статус получателя — waiting_reply. Ожидание не блокирует других получателей и сохраняется после перезапуска.
  • Ответом считается новое входящее сообщение, включая текст или медиа. Старые сообщения, прочтение и реакции не запускают отправку. Содержание ответа не анализируется: любой новый ответ запускает основной текст.
  • Проверка ответов обычно выполняется раз в 15 секунд; при большой очереди или недоступности WhatsApp — дольше. Затем основной текст ждёт свободного отправителя и общей паузы между сообщениями.
  • Ожидание продолжается до ответа или отмены рассылки. На общей паузе ответ сохраняется, но отправка ждёт возобновления очереди.
  • Для одного номера одновременно обрабатывается одна рассылка с приветствием; следующие ждут её завершения или отмены.

В messages[] поле phase показывает этап: greeting или main. Доступны greeting_sent_at, greeting_remote_id, reply_received_at и reply_remote_id. Счётчик sent увеличивается после основного сообщения; ожидающие ответа ещё не включены в обработанный прогресс.

Если результат приветствия оказался unknown, сначала проверьте чат. Подтверждение sent через /messages/{id}/resolve переведёт получателя в ожидание ответа.

03 · МЕДИА

Отправить изображение

Сначала загрузите файл, затем передайте его id в рассылку. Изображение хранится на сервере и может использоваться в нескольких заданиях.

JPG / PNGДо 5 МиБДо 16 мегапикселейОдна картинка на сообщение

Шаг 1. Загрузите файл

POST /images принимает файл в теле запроса. Для JPG укажите image/jpeg, для PNG — image/png. Используйте --data-binary; здесь не нужны JSON, multipart или Base64. Команда ниже сохраняет идентификатор в IMAGE_ID и использует Python 3 для чтения ответа.

cURL · загрузка файла
IMAGE_ID=$(curl --fail-with-body "$MAILING_API_URL/images" \
  -H "X-Api-Key: $MAILING_API_KEY" \
  -H 'Content-Type: image/jpeg' \
  --data-binary @poster.jpg \
  | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')

echo "$IMAGE_ID"

Первая загрузка возвращает 201, повторная загрузка того же файла — 200 и тот же id. В ответе также есть mimetype, size в байтах, width, height и url. Просмотр файла по url тоже требует токен.

Шаг 2. Создайте рассылку с картинкой

cURL · изображение с подписью
curl --fail-with-body "$MAILING_API_URL/broadcasts" \
  -H "X-Api-Key: $MAILING_API_KEY" \
  -H 'Idempotency-Key: promo-image-2026-001' \
  -H 'Content-Type: application/json' \
  -d "{
    \"recipients\": [\"+77001234567\", \"+77001234568\"],
    \"text\": \"Афиша ближайшего турнира\",
    \"image_id\": \"$IMAGE_ID\"
  }"

text становится подписью к картинке, до 1024 символов. Чтобы отправить только изображение, уберите поле text или передайте пустую строку. Каждый получатель получает одно сообщение с картинкой и подписью.

В очереди рассылок такие задания отмечены как «Изображение». Откройте детали, чтобы увидеть картинку, подпись и статусы получателей.

04 · КОНТРОЛЬ

Прогресс и управление очередью

Запрашивайте состояние примерно раз в 4 секунды или следите за ним в панели. Подставьте id, полученный при создании задания.

cURL · состояние рассылки
BROADCAST_ID='YOUR_BROADCAST_ID'

curl --fail-with-body "$MAILING_API_URL/broadcasts/$BROADCAST_ID" \
  -H "X-Api-Key: $MAILING_API_KEY"

# Все активные рассылки: до 20 за один запрос
curl --fail-with-body "$MAILING_API_URL/broadcasts?view=active&limit=20&offset=0" \
  -H "X-Api-Key: $MAILING_API_KEY"

В деталях доступны counts, total, processed, progress и массив messages. progress — процент обработанных получателей: ошибки и отмены тоже учитываются. Для числа отправленных сообщений смотрите counts.sent.

Статус получателяЧто означает
pendingПолучатель ожидает своей очереди.
preparing / sendingПодготовка или отправка. Следующий получатель ещё не обрабатывается.
waiting_replyПриветствие отправлено; основное сообщение ждёт ответа.
sentWhatsApp подтвердил отправку. Это не подтверждение прочтения.
failedОшибка подготовки либо вручную подтверждённая неудачная отправка.
unknownРезультат неизвестен. Вся очередь ждёт проверки соответствующего чата.
cancelledОтправка этому получателю отменена.

Пауза, продолжение, отмена

cURL · управление очередью
# Пауза для всей очереди
curl --fail-with-body -X POST "$MAILING_API_URL/queue/pause" \
  -H "X-Api-Key: $MAILING_API_KEY"

# Продолжить отправку
curl --fail-with-body -X POST "$MAILING_API_URL/queue/resume" \
  -H "X-Api-Key: $MAILING_API_KEY"

# Отменить ещё не отправленные сообщения одной рассылки
curl --fail-with-body -X POST "$MAILING_API_URL/broadcasts/$BROADCAST_ID/cancel" \
  -H "X-Api-Key: $MAILING_API_KEY"

На паузе новые задания продолжают добавляться. Уже начатая отправка может завершиться после паузы или отмены. Отмена не удаляет историю и не отзывает отправленные сообщения.

Если результат неизвестен

При таймауте отправки сообщение может уже находиться в WhatsApp. Поэтому статус unknown блокирует всю очередь, а повторная отправка автоматически не выполняется. Откройте нужный чат, проверьте результат и подтвердите его для messages[].id.

cURL · после проверки чата в WhatsApp
MESSAGE_ID='YOUR_MESSAGE_ID'

# Если сообщение действительно отправлено
curl --fail-with-body -X POST "$MAILING_API_URL/messages/$MESSAGE_ID/resolve" \
  -H "X-Api-Key: $MAILING_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"outcome":"sent"}'

# Если не отправлено — используйте {"outcome":"failed"}.
# Это фиксирует результат и не отправляет сообщение повторно.

После разбора всех таких сообщений очередь продолжится с небольшой паузой. Если включена общая пауза, дополнительно вызовите /queue/resume.

05 · ИНТЕГРАЦИЯ

Примеры на Python и JavaScript

Полные примеры загрузки изображения, создания рассылки и чтения её состояния. Задайте MAILING_API_KEY и, при необходимости, MAILING_API_URL в окружении. Сохраните картинку как poster.jpg рядом со скриптом.

Python 3
Python 3 · стандартная библиотека
import json
import os
from pathlib import Path
from urllib.request import Request, urlopen

base = os.getenv("MAILING_API_URL", "http://185.113.132.60").rstrip("/")
key = os.environ["MAILING_API_KEY"]


def api(method, path, body=None, *, mime="application/json", idem=None):
    headers = {"X-Api-Key": key, "Content-Type": mime}
    if idem:
        headers["Idempotency-Key"] = idem
    data = body if isinstance(body, bytes) else (
        json.dumps(body).encode() if body is not None else None
    )
    request = Request(base + path, data=data, headers=headers, method=method)
    with urlopen(request, timeout=90) as response:
        return json.load(response)


image = api("POST", "/images", Path("poster.jpg").read_bytes(), mime="image/jpeg")
job = api("POST", "/broadcasts", {
    "recipients": ["+77001234567"],  # замените номер
    "text": "Афиша турнира 1GAME",
    "image_id": image["id"],
}, idem="python-image-2026-001")
print("Рассылка:", job["id"])
print(api("GET", job["status_url"]))
# Для обычного текста уберите image_id; загрузка файла тогда не нужна.
JavaScript · Node.js
JavaScript · Node.js 18+ · файл send.mjs
import { readFile } from "node:fs/promises";

const base = (process.env.MAILING_API_URL || "http://185.113.132.60").replace(/\/$/, "");
const key = process.env.MAILING_API_KEY;
if (!key) throw new Error("Задайте MAILING_API_KEY");

async function api(path, options = {}) {
  const response = await fetch(base + path, {
    ...options,
    headers: { "X-Api-Key": key, ...options.headers },
    signal: AbortSignal.timeout(90000),
  });
  if (!response.ok) throw new Error(await response.text());
  return response.json();
}

const image = await api("/images", {
  method: "POST",
  headers: { "Content-Type": "image/jpeg" },
  body: await readFile("poster.jpg"),
});
const job = await api("/broadcasts", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "node-image-2026-001",
  },
  body: JSON.stringify({
    recipients: ["+77001234567"], // замените номер
    text: "Афиша турнира 1GAME",
    image_id: image.id,
  }),
});
console.log("Рассылка:", job.id);
console.log(await api(job.status_url));
// Запуск: node send.mjs

Для нового задания используйте новый Idempotency-Key. Для повторения прервавшегося запроса сохраняйте прежний ключ и содержимое.

06 · СПРАВОЧНИК

Методы, ограничения и ошибки

Все методы с данными требуют X-Api-Key. Полная схема параметров и интерактивные запросы — в Swagger.

МетодПутьНазначение
GET/statusПодключение WhatsApp, готовность и счётчики очереди
POST/session/disconnectОтключить текущий WhatsApp и поставить очередь на паузу для смены номера
POST/session/startПодготовить QR-код для привязки аккаунта
GET/session/qrPNG с QR-кодом; проще отсканировать его в панели
POST/session/qr/refreshСгенерировать новый QR для незавершённой привязки
POST/imagesЗагрузить JPG/PNG, получить id
GET/images/{id}Скачать ранее загруженное изображение
POST/broadcastsСоздать текстовую рассылку или рассылку с изображением
GET/broadcastsСписок: limit 1–100, offset, view=all/active/attention
GET/broadcasts/{id}Счётчики, прогресс и результат по каждому номеру
POST/broadcasts/{id}/cancelОтменить ещё не отправленные сообщения
POST/queue/pauseПриостановить всю очередь
POST/queue/resumeПродолжить очередь
POST/messages/{id}/resolveПодтвердить результат unknown: sent или failed
GET/healthzПроверка сервиса без токена; не проверяет подключение WhatsApp

Ограничения одного задания

  • От 1 до 1000 номеров в международном формате: 7–15 цифр, например +77001234567. Допускаются пробелы, скобки и дефисы. Повторы внутри списка объединяются.
  • Текст — до 4096 символов; подпись к изображению — до 1024.
  • Изображение — JPG или PNG, до 5 МиБ (5 242 880 байт) и 16 000 000 пикселей. Анимация не поддерживается.
  • JSON-запрос — до 128 КБ. До 10 000 ожидающих отправки, ответа и активных сообщений во всей очереди.

Коды ошибок

HTTPЧто делать
401Неверный токен или отсутствует X-Api-Key.
404Рассылка или изображение не найдены. Сначала загрузите файл.
409Ключ идемпотентности уже использован с другим содержимым; либо сообщение не в статусе unknown.
413Файл больше 5 МиБ или JSON-запрос больше 128 КБ.
415Для файла нужен Content-Type: image/jpeg или image/png.
422Проверьте номера, обязательные поля, размер подписи и целостность картинки.
429Очередь заполнена: до 10 000 ожидающих и активных сообщений. Повторите запрос позже с тем же ключом.
503WhatsApp или QR-код пока недоступен. Проверьте подключение в панели.

Описание ошибки находится в поле detail. Для ошибок полей оно может содержать список с указанием loc и msg. Ошибки размера запроса от прокси могут приходить обычным текстом.