Как агентство из двух человек мониторит DM и упоминания в X для четырёх клиентов — без оплаты за каждое чтение API — UnifyPort
В январе 2026 года небольшое SMM-агентство из двух человек в Лиссабоне вело аккаунты X (Twitter) четырёх клиентов — два e-commerce бренда, SaaS-стартап и сеть местных ресторанов. Задача была простой: отслеживать входящие DM и упоминания на каждом аккаунте, отвечать в течение нескольких часов, эскалировать то, что требует участия клиента. Техническая реализация тоже была несложной: сервис на Node.js опрашивал API X каждые 30 секунд по каждому аккаунту, проверяя новые сообщения, и перенаправлял их в общий Slack-канал для сортировки.
При старой тарификации X — фиксированные месячные планы, действовавшие с 2023 года — эта конфигурация обходилась в $100/мес на тарифе Basic. Предсказуемо, удобно для бюджета, полностью покрывалось ретейнером клиентов без необходимости объяснять отдельную строку расходов.
А потом наступил февраль.
Счётчик включился
3 февраля 2026 года X заменил фиксированные тарифы на оплату за каждый вызов. Каждое обращение к API — чтение и запись — получило свою цену за запрос. Месячного потолка больше не было. Архитектура опроса, рассчитанная на мир с безлимитными вызовами внутри тарифа, в одночасье начала крутить счётчик.
Арифметика нехитрая. Четыре клиентских аккаунта, каждый опрашивается раз в 30 секунд на предмет DM и упоминаний. Это 8 чтений в минуту (2 эндпоинта на аккаунт × 4 аккаунта), 11 520 чтений в сутки, примерно 345 600 чтений в месяц — и это только мониторинг, ни одного полученного сообщения.
20 апреля X пересмотрел тарифы: чтение собственных ресурсов снизилось до $0,001 за вызов — месячные расходы на мониторинг упали примерно до $346. Но тот же пересмотр поднял стоимость записи (ответы) с $0,010 до $0,015. Агентство отправляло 400–600 ответов в месяц по всем четырём аккаунтам; по $0,015 — дополнительные $6–$9. Само по себе немного, но тренд настораживал: каждый новый клиентский аккаунт — ещё один цикл опроса, каждый дополнительный ответ — давление на счёт с обеих сторон.
Дорого стоит не тариф, а архитектура
Основатель агентства прикинул расходы на гипотетический Q3: при подключении ещё двух клиентов (вполне реальный сценарий по текущей воронке) чтения только от опроса примерно удвоились бы. Цена за отдельный вызов действительно низкая, но объём — структурный: он определяется частотой проверки, а не количеством реально поступивших сообщений. В тихое воскресенье без единого DM цикл опроса работает ровно с той же скоростью и стоит ровно столько же, сколько в день запуска продукта.
Именно эту деталь модели X «оплата за вызов» не показывают обзоры тарифов: стоимость ожидания сообщений не равна нулю, и она масштабируется вместе с архитектурой мониторинга, а не с реальным объёмом входящих. Четыре аккаунта с опросом каждые 30 секунд — это 345 600 чтений в месяц, независимо от того, пришло 10 сообщений или 10 000.
Замедление интервала опроса — очевидное решение. Агентство попробовало 2-минутный интервал в течение недели. Время отклика заметно ухудшилось: DM мог оставаться непрочитанным до 4 минут в худшем случае, а два клиента прописали в контракте SLA «ответ в течение 2 часов». Формально SLA не нарушался, но ощущение от сервиса сменилось с «почти в реальном времени» на «когда-нибудь увидим». Через три дня вернулись к прежнему интервалу.
С pull на push
Правильное решение было не в оптимизации опроса, а в его устранении. Агентство подключило все четыре клиентских аккаунта X к UnifyPort — DM и упоминания стали приходить в webhook в момент поступления. Никакого цикла опроса, никакой оплаты за чтение, никаких расходов, растущих с частотой проверки.
Изменение архитектуры выглядело так:
До (опрос):
Сервис ──► X API (чтение DM) ×4 аккаунта ×2/мин = 345 600 чтений/мес
Сервис ──► X API (чтение упоминаний) ×4 аккаунта ×2/мин = 345 600 чтений/мес
Итого: ~691 200 тарифицируемых API-чтений/мес
После (webhook push):
X аккаунт ──► UnifyPort ──► POST /webhook ──► Slack (клиент A)
X аккаунт ──► UnifyPort ──► POST /webhook ──► Slack (клиент B)
X аккаунт ──► UnifyPort ──► POST /webhook ──► Slack (клиент C)
X аккаунт ──► UnifyPort ──► POST /webhook ──► Slack (клиент D)
Итого: 0 чтений X API
Входящие сообщения каждого аккаунта доставляются как событие message.received — в том же нормализованном формате, который агентство получит, если позже подключит для тех же клиентов WhatsApp или Telegram:
{
"event": "message.received",
"account_id": "acct_client_a",
"provider": "twitter",
"from": "user_7d2e1f",
"text": "Hey, is the summer sale still on? Saw a post but the link was broken",
"timestamp": 1750320000,
"message_id": "x_msg_8a3b2c"
}
Обработчик webhook верифицирует каждую доставку с помощью HMAC-SHA256, затем маршрутизирует по account_id в нужный Slack-канал клиента:
app.post("/webhook", (req, res) => {
if (!verifySignature(req)) return res.sendStatus(401);
const evt = req.body;
if (evt.event === "message.received") {
const channel = clientChannelMap[evt.account_id];
slack.postMessage(channel, {
text: `[${evt.provider}] ${evt.from}: ${evt.text}`,
metadata: { messageId: evt.message_id },
});
}
res.sendStatus(200);
});
Четыре аккаунта, один эндпоинт, один ключ подписи. Сервис опроса выключен полностью.
Что изменилось
Расходы агентства на X API снизились с ~$350/мес (с тенденцией к росту при каждом новом клиенте) до нуля тарифицируемых чтений. Задержка ответа даже улучшилась — события приходят в течение секунд после отправки сообщения, а не в ожидании следующего цикла опроса. Подключение нового клиентского аккаунта — это теперь не добавление цикла опроса в счёт, а одна новая строка в clientChannelMap.
Команда из двух человек по-прежнему отвечает на DM и упоминания в X тем же способом — из Slack, через эндпоинт ответов UnifyPort. Изменилось то, что «мониторинг четырёх аккаунтов X» больше не является статьёй расходов на API, которую нужно моделировать, объяснять клиентам и переживать о масштабировании. Если в Q3 воронка принесёт ещё два аккаунта, webhook будет получать шесть вместо четырёх. Счёт разницы не увидит.
Для агентств и команд, управляющих несколькими аккаунтами X — особенно тех, у кого расходы на X API масштабируются с частотой опроса, а не с объёмом сообщений — архитектурный вопрос не в том, «какой интервал опроса самый дешёвый». А в том, нужна ли модель pull вообще, когда push-webhook может доставить те же сообщения, не крутя счётчик.