11 февраля 2026 года я настроил автопубликацию из WordPress в MAX: новая запись на сайте попадает в очередь, а фоновая задача отправляет в канал заголовок, анонс, ссылку и обложку. Ниже разберу эту схему с учётом документации API MAX. Сам сайт остаётся основной площадкой, а канал помогает читателям узнавать о новых статьях без ручного копирования.
Мне было важно, чтобы ожидание ответа внешнего API не задерживало сохранение записи в редакторе. Поэтому подготовка публикации и отправка в MAX выполняются отдельно. Это тот же принцип разделения задач, который полезен и в оптимизации WordPress: сторонний сервис не должен без необходимости замедлять основной запрос.
Бот, канал и права на публикацию
В моей исходной настройке всё начиналось с партнёрской панели MAX. Я завёл отдельного бота для публикаций, получил токен и указал идентификатор канала. Это два разных значения: токен подтверждает полномочия бота, а Chat ID определяет получателя. Бота нужно добавить в канал с правами, необходимыми для публикации.
Сначала стоит проверить доступ на отдельном тестовом канале. Если отправка не проходит, разбирать нужно HTTP-ответ и описание ошибки: неверный токен, неподходящий Chat ID и отсутствие прав не исправляются повторной отправкой одного и того же запроса. Рабочий канал не стоит использовать для отладки массовых повторов.
Настройки плагина и защита токена
В плагине я сделал отдельную страницу с токеном, Chat ID, переключателями картинки и кнопки, а также тестовой отправкой. Доступ к настройкам ограничен администратором, сохранение защищено проверкой полномочий и nonce. Проверка nonce защищает запрос от подделки, но не заменяет проверку прав пользователя.
Хранить токен нужно только на стороне сервера, не в JavaScript страницы. Нельзя записывать его в публичный журнал или оставлять в URL: документация MAX требует заголовок Authorization. Доступ к резервным копиям настроек тоже важен, поскольку они могут содержать этот секрет. Общие меры защиты разобраны в статье о безопасности сайта.
Очередь отделяет публикацию от отправки
При выпуске статьи плагин сохраняет задание, а отдельный обработчик готовит сообщение и обращается к API. Для задания полезно хранить ID записи, канал, состояние, количество попыток, время следующей попытки и идентификатор отправленного сообщения. В журнале достаточно HTTP-кода и безопасного текста ошибки, без секретов и полного содержимого запроса.
Для запуска можно использовать WP-Cron или системный планировщик. WP-Cron проверяет задачи при посещениях сайта, поэтому на малопосещаемом сайте отправка может задержаться. Если нужна более предсказуемая периодичность, задачи запускают системным cron, согласовав его с настройками WordPress. Это всё равно не гарантирует доставку в точную секунду: остаются сеть, очередь и доступность API.
Особенно важна защита от повторов. Хук transition_post_status может вызываться и при обновлении уже опубликованной записи. Недостаточно проверить только новый статус publish: нужно отличать новый выпуск от обычного редактирования и учитывать уже выполненные задания. Для ручного повторного отправления лучше предусмотреть отдельную явную команду.
Как отправить текст, кнопку и картинку
В действующей документации описан метод POST /messages. Для канала chat_id передаётся параметром запроса, токен в заголовке Authorization, а текст и вложения в JSON. HTML-разметку следует объявить полем format со значением html. Не нужно автоматически добавлять префикс Bearer: образцы MAX показывают сам токен в заголовке.
$endpoint = add_query_arg(
'chat_id', (string) $chat_id,
'https://platform-api2.max.ru/messages'
);
$payload = [
'text' => '<b>' . esc_html($title) . "</b>\n\n" . esc_html($excerpt),
'format' => 'html',
'attachments' => [[
'type' => 'inline_keyboard',
'payload' => ['buttons' => [[[
'type' => 'link', 'text' => 'Читать', 'url' => $post_url,
]]]],
]],
];
$response = wp_remote_post($endpoint, [
'timeout' => 15,
'headers' => [
'Authorization' => $token,
'Content-Type' => 'application/json; charset=utf-8',
],
'body' => wp_json_encode($payload, JSON_UNESCAPED_UNICODE),
]);
Это фрагмент формирования запроса, а не готовый плагин: вокруг него нужны проверка настроек, обработка ответа и очередь. MAX ограничивает длину текста 4000 символами. Для одного чата или канала документация указывает не больше двух сообщений в секунду, поэтому массовую выгрузку архива нужно ограничивать по скорости.
Для загрузки файла сначала выполняют POST /uploads?type=image, затем передают файл по полученному URL. После загрузки используется информация о вложении для сообщения. У больших файлов обработка может занять время: ошибка attachment.not.ready означает, что с отправкой нужно подождать. В документации также предусмотрено прикрепление изображения по внешнему URL, поэтому загрузка файлом является выбором реализации, а не единственным способом.
Повторы после ошибки не должны создавать дубли
Проверять один HTTP-код недостаточно: после успешной отправки нужно разобрать ответ и сохранить идентификатор сообщения. Если запрос оборвался по тайм-ауту, сообщение могло уже появиться в канале. Слепая повторная отправка в такой ситуации способна создать дубль. Для очереди нужны блокировка параллельных обработчиков, ограничение попыток и отдельное состояние для неоднозначного результата.
Отправка картинки и текста двумя сообщениями тоже не атомарна: первое может пройти, а второе завершиться ошибкой. Если выбран такой режим, храните состояние каждого шага. При временных сбоях интервалы повторов стоит увеличивать, а ошибки прав или авторизации выносить на исправление администратору.
В результате редактор работает с WordPress, а очередь занимается доставкой в MAX. Самое важное здесь не кнопка «Отправить», а предсказуемое поведение при повторном сохранении статьи, задержке обработки картинки и сбое сети. Именно эти случаи нужно проверить до массовой публикации архива.