跳转到内容
交付 API
在围绕某项功能进行规划之前,请先查看功能状态。

参考

Webhook

内容发布时 Atlas 发送给您网站的带签名通知,使您能够精确刷新受影响的页面。

本页面由英文翻译而来。如有任何差异,以英文版本为准。 阅读英文版

在 Studio 的 Integrations → Webhooks 下创建 Webhook。每个 Webhook 都有一个 HTTPS URL、它所接收的事件,以及以 whsec_ 开头的签名密钥(只显示一次)。

Atlas 只向公共 HTTPS 地址投递。私有网络地址会被拒绝;只有在开发期间向 localhost 才允许使用普通 HTTP。

POST https://your-site.example/api/atlas/webhook
Content-Type: application/json
X-Atlas-Event: content.page.published
X-Atlas-Delivery: <unique delivery id>
X-Atlas-Signature: t=1761210000,v1=5f2b…
app/api/atlas/webhook/route.ts
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 });
}

检查步骤依次为:

  1. 使用原始请求体。
  2. 拒绝时间戳早于 5 分钟的请求。
  3. 使用您的签名密钥计算 HMAC-SHA256("<t>.<raw body>"),并以恒定时间进行比较。
  4. 忽略重复的 X-Atlas-Delivery id。

请记录事件类型和投递 id,切勿记录请求体或密钥。

请求体就是事件的载荷。对于 content.page.published,它是 { "pageId", "route", "revision" }。事件类型位于 X-Atlas-Event 标头中。

Webhook 只需在开发环境中设置一次,也会接收来自线上网站的事件。每个载荷都带有 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 收到新线索(仅含 id,不含个人数据)
lead.merged 线索被合并到另一条线索(仅含 id)
bot.published 聊天机器人被发布

Atlas 最多等待您的响应 10 秒,并且不会跟随重定向。请使用 Studio 的投递历史查看载荷和失败情况。