Вебхуки
Подписанные уведомления, которые Atlas отправляет вашему сайту при публикации контента, чтобы вы могли обновить именно затронутые страницы.
Эта страница переведена с английского. При любых расхождениях действует английская версия. Читать на английском
Создавайте вебхуки в Studio в разделе Integrations → Webhooks. У каждого есть HTTPS-адрес, получаемые события и секрет подписи, начинающийся с whsec_ и показываемый один раз.
Atlas доставляет данные только на публичные HTTPS-адреса. Адреса частных сетей отклоняются; обычный HTTP разрешён только для localhost на время разработки.
POST https://your-site.example/api/atlas/webhookContent-Type: application/jsonX-Atlas-Event: content.page.publishedX-Atlas-Delivery: <unique delivery id>X-Atlas-Signature: t=1761210000,v1=5f2b…Проверяйте каждый запрос
Заголовок раздела «Проверяйте каждый запрос»import { createHmac, timingSafeEqual } from 'node:crypto';import { revalidatePath, revalidateTag } from 'next/cache';
const seen = new Set<string>(); // use a shared store (Redis, KV) when you run several instances
export async function POST(request: Request) { const body = await request.text(); // the raw body, before any JSON parsing const header = request.headers.get('x-atlas-signature') ?? ''; const parts = Object.fromEntries(header.split(',').map((part) => part.split('=', 2))); const timestamp = Number(parts.t);
if (!timestamp || Math.abs(Date.now() / 1000 - timestamp) > 300) return new Response(null, { status: 400 });
const expected = createHmac('sha256', process.env.ATLAS_WEBHOOK_SECRET!) .update(`${timestamp}.${body}`) .digest(); const given = Buffer.from(String(parts.v1 ?? ''), 'hex'); if (given.length !== expected.length || !timingSafeEqual(given, expected)) { return new Response(null, { status: 401 }); }
const delivery = request.headers.get('x-atlas-delivery') ?? ''; if (seen.has(delivery)) return new Response(null, { status: 200 }); // already handled seen.add(delivery);
const payload = JSON.parse(body); // e.g. { pageId, route, revision } for content.page.published if (typeof payload.route === 'string') revalidatePath(payload.route); else revalidateTag('atlas'); // entries, globals, translations: refresh everything tagged 'atlas' return new Response(null, { status: 200 });}Проверки по порядку:
- Используйте необработанное тело запроса.
- Отклоняйте временные метки старше 5 минут.
- Вычислите
HMAC-SHA256("<t>.<raw body>")с вашим секретом подписи и сравните за постоянное время. - Игнорируйте повторяющиеся идентификаторы
X-Atlas-Delivery.
Записывайте в журнал тип события и идентификатор доставки, но никогда — тело или секрет.
События
Заголовок раздела «События»Тело запроса — это полезная нагрузка события. Для content.page.published это { "pageId", "route", "revision" }. Тип события указан в заголовке X-Atlas-Event.
Вебхуки настраиваются один раз, в Development, и также получают события с рабочего сайта. В каждой полезной нагрузке есть environment: "development" или "production", чтобы их можно было различать.
| Событие | Когда |
|---|---|
content.page.published |
Страница опубликована или откатана |
content.page.unpublished |
Страница снята с сайта |
content.page.route.changed |
Страница переехала на новый адрес (добавлен редирект) |
content.entry.published |
Запись коллекции опубликована |
content.entry.unpublished |
Запись коллекции снята с сайта |
content.global.published |
Опубликована шапка, подвал или другой глобальный блок |
content.translation.published |
Перевод опубликован |
contract.activated |
Активирован новый контракт сайта |
seo.redirects.changed |
Редиректы изменились |
media.asset.uploaded |
Медиафайл загружен |
form.published |
Форма опубликована |
form.submission.accepted |
Отправка формы принята |
lead.created |
Поступил новый лид (только идентификаторы, без персональных данных) |
lead.merged |
Лид объединён с другим (только идентификаторы) |
bot.published |
Чат-бот опубликован |
Atlas ждёт вашего ответа до 10 секунд и не следует перенаправлениям. Используйте историю доставок в Studio, чтобы изучать полезные нагрузки и сбои.