Webhook
コンテンツの公開時に Atlas がウェブサイトへ送る署名付き通知で、影響を受けたページだけを正確に更新できます。
このページは英語から翻訳されたものです。内容に相違がある場合は、英語版が優先されます。 英語版を読む
Webhook は Studio の Integrations → Webhooks で作成します。それぞれに、HTTPS の URL、受信するイベント、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…すべてのリクエストを検証する
Section titled “すべてのリクエストを検証する”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の ID は無視する。
ログに残すのはイベントタイプと配信 ID だけにし、ボディやシークレットは決して記録しないでください。
リクエストボディは、イベントのペイロードです。content.page.published の場合は { "pageId", "route", "revision" } です。イベントタイプは X-Atlas-Event ヘッダーに入っています。
Webhook は開発環境で 1 回設定するだけで、ライブウェブサイトのイベントも受信します。各ペイロードには 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 の配信履歴を使ってください。