Перейти к содержимому
Документация

Исходящие вебхуки: структура запроса и подпись

Получайте оповещения и отчёты AutoPSEO в виде подписанного JSON на любой HTTPS-эндпоинт: заголовки запроса, поля тела, типы событий и проверка подписи.

Аккаунт → Slack, Teams и вебхуки → Исходящие вебхукиНужна подписка или пробный период5 мин чтения

Исходящий вебхук отправляет оповещения AutoPSEO, отчёты по расписанию, тестовые сообщения и сводки отчётов на ваш эндпоинт: каждое сообщение приходит отдельным JSON-запросом POST, подписанным по алгоритму HMAC-SHA256. Используйте его, чтобы передавать данные в Zapier, Make, n8n, систему управления инцидентами или собственный код; аккаунт Slack или Teams при этом не нужен. Ищете вебхук, который доставляет статьи на ваш сайт? Он относится к контент-движку: см. доставку контента.

Как добавить вебхук

  1. В разделе Outbound webhooks нажмите New webhook.
  2. Укажите Name и вставьте URL эндпоинта. Адрес должен быть публичным и использовать HTTPS: обычный http, localhost, имена с окончанием .local или .internal, хосты без точки, а также частные и link-local IP-адреса отклоняются.
  3. Скопируйте signing secret, который появится после сохранения. Он показывается только один раз.
  4. Нажмите Send test, чтобы отправить событие test, а затем подключите к вебхуку отчёты по расписанию или оповещения.

Как выглядит запрос вебхука

Каждое сообщение — это POST со следующими заголовками:

ЗаголовокЗначение
Content-Typeapplication/json
User-AgentAutoPSEO-Webhook/1.0
X-AutoPSEO-EventТип события, например traffic_drop
X-AutoPSEO-Signaturesha256= и 64 строчных шестнадцатеричных символа

Ниже показано оповещение о падении трафика для доменного ресурса по запуску в 06:00 UTC 12 октября 2026 года. Оно отформатировано для удобства чтения (в реальном запросе JSON передаётся в компактном виде, а значения id и site_id придуманы):

{
  "id": "9b2e61f04c3a4d7e8f15a0b6c2d39e47",
  "event_type": "traffic_drop",
  "severity": "high",
  "site_id": "4f0c1e9a2b7d4c58",
  "site_url": "sc-domain:example.com",
  "occurred_at": "2026-10-12T06:00:04.183Z",
  "title": "Traffic drop: example.com",
  "text": "Clicks 1,500 vs 2,000 in the previous window (-25.0%).",
  "url": "https://app.autopseo.com/property/sc-domain%3Aexample.com",
  "payload": {
    "fields": [
      { "label": "Metric", "value": "clicks" },
      { "label": "Current", "value": "1,500" },
      { "label": "Baseline", "value": "2,000" },
      { "label": "Window", "value": "7 days (2026-10-05 → 2026-10-11 vs 2026-09-28 → 2026-10-04)" },
      { "label": "Change", "value": "-25.0%" }
    ],
    "table": null,
    "detector": "traffic_drop",
    "window": 7,
    "range": { "start": "2026-10-05", "end": "2026-10-11", "compStart": "2026-09-28", "compEnd": "2026-10-04" },
    "result": {
      "fired": true,
      "metric": "clicks",
      "value": 1500,
      "baseline": 2000,
      "change": -0.25,
      "severity": "high",
      "summary": "Clicks 1,500 vs 2,000 in the previous window (-25.0%)."
    }
  },
  "source": "autopseo"
}

Поля верхнего уровня одинаковы для всех событий:

ПолеЧто содержит
idСлучайная строка из 32 шестнадцатеричных символов, новая для каждого запроса
event_typeЧто произошло (см. следующий раздел)
severitycritical, high, medium или low для оповещений; info для отчётов, сводок и тестов
site_idИдентификатор ресурса в AutoPSEO или null для тестов и демонстрационного ресурса
site_urlРесурс Search Console, например sc-domain:example.com или https://www.example.com/, либо null для тестов
occurred_atВремя формирования сообщения в формате ISO 8601 (UTC)
title, textЗаголовок и краткое описание, которые показывают Slack и Teams
urlСсылка на отчёт в AutoPSEO или null для тестов
payload.fieldsИменованные значения: Slack показывает их как поля, а Teams — как факты
payload.tablecolumns и rows для отчётов и сводок, в остальных случаях null
sourceВсегда autopseo

Относительные величины передаются долями: change, равный -0.25, означает падение на 25%, а ctr, равный 0.034, — 3,4%.

Типы событий

event_typeКогда отправляетсяДополнительные ключи в payload
traffic_drop, traffic_spike, position_drop, ctr_drop, new_lost_rankings, anomaly, index_flip, rank_drop, audit_regressionСрабатывает правило оповещения — по расписанию или через Test ruledetector, window, range (даты или null для index_flip, rank_drop и audit_regression), result
scheduled_reportОтправляется отчёт по расписанию — по расписанию или через Send nowreportType (summary, queries, pages или rankings), range (даты и label), totals, previous
report_summaryКто-то нажимает Send to Slack на странице отчётаНет: показатели находятся в fields и table
testКто-то нажимает Send test у вебхукаsample, всегда true

В result повторяется то, что измерил детектор: fired, metric, value, baseline, change (null, если сравнивать не с чем), severity и summary, а для anomaly ещё и z — модифицированная z-оценка. В totals и previous находятся clicks, impressions, ctr и position для двух периодов отчёта. Что именно измеряет каждый детектор, описано в разделе Оповещения.

Как проверить подпись

Подпись — это HMAC-SHA256 от точных байтов, отправленных AutoPSEO, с использованием signing secret вебхука в качестве ключа; она записывается как sha256= и строчный hex. Для проверки:

  1. Прочитайте необработанное тело запроса до любого разбора JSON. Повторный разбор и сериализация могут изменить байты.
  2. Вычислите HMAC-SHA256 от этих байтов, используя секрет как текст: 64-символьную строку ровно в том виде, в каком она показана, без декодирования из hex.
  3. Добавьте префикс sha256= и сравните результат с заголовком X-AutoPSEO-Signature за постоянное время.
  4. Если значения не совпадают, отклоните запрос. Иначе сразу ответьте статусом 2xx, а долгую обработку выполните позже.

Приёмник для Node.js без зависимостей:

import { createServer } from 'node:http';
import { createHmac, timingSafeEqual } from 'node:crypto';

const secret = process.env.AUTOPSEO_WEBHOOK_SECRET;

createServer((req, res) => {
  const chunks = [];
  req.on('data', (chunk) => chunks.push(chunk));
  req.on('end', () => {
    const raw = Buffer.concat(chunks);
    const expected = Buffer.from('sha256=' + createHmac('sha256', secret).update(raw).digest('hex'));
    const received = Buffer.from(String(req.headers['x-autopseo-signature'] || ''));
    if (received.length !== expected.length || !timingSafeEqual(received, expected)) {
      res.writeHead(401).end();
      return;
    }
    res.writeHead(204).end();
    const event = JSON.parse(raw.toString('utf8'));
    console.log(event.event_type, event.severity, event.site_url);
  });
}).listen(8080);

Проверка длины идёт первой, потому что timingSafeEqual в Node выбрасывает исключение, если длины буферов различаются.

Правила доставки

  • На каждое сообщение делается одна попытка с таймаутом 10 секунд. Любой ответ, кроме 2xx, считается неудачей и сохраняется в Delivery history вместе с кодом статуса и началом тела вашего ответа.
  • Перенаправления не выполняются. Ответ 3xx считается неудачей, и в примечании предлагается использовать конечный URL.
  • По таймеру ничего не повторяется. Неудачное оповещение не помечается как отправленное, поэтому при следующей проверке оно будет оценено снова и отправлено, если условие всё ещё выполняется: на следующее утро для большинства детекторов и через час для index flip. Неудачный отчёт по расписанию в том же периоде повторно не отправляется, поэтому после исправления эндпоинта воспользуйтесь Send now.
  • id создаётся для каждого запроса, поэтому он идентифицирует доставку, а не событие. Чтобы убрать дубликаты оповещений, объедините event_type, site_url и дату из occurred_at: правило отправляет оповещение не чаще одного раза в сутки (UTC) на ресурс, если только кто-то не запустил Test rule.

Signing secret

AutoPSEO показывает signing secret один раз, при сохранении вебхука, а в списке он больше не отображается. Сразу сохраните его в конфигурации вашего приёмника рядом с эндпоинтом, который он защищает.

Сам URL хранится в зашифрованном виде, а в списке отображаются только его хост и последние символы. Удаление вебхука также удаляет все правила, которые отправляют сообщения на него. Если вместо JSON нужна читаемая карточка в канале Teams, воспользуйтесь Microsoft Teams.

Переведите SEO-контент на автопилот

Подключите Search Console и свой сайт. AutoPSEO просканирует его и сразу спланирует первые темы. Банковская карта не нужна.