Webhooks
إشعارات موقّعة يرسلها Atlas إلى موقعك عند نشر المحتوى، لتحدّث الصفحات المتأثرة بالضبط.
تُرجمت هذه الصفحة من الإنجليزية. وفي حال وجود أي اختلاف، تسري النسخة الإنجليزية. اقرأ بالإنجليزية
أنشئ webhooks في Studio ضمن Integrations → Webhooks. لكل منها عنوان URL بصيغة 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…تحقق من كل طلب
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المتكررة.
سجّل نوع الحدث ومعرّف التسليم، ولا تسجّل المتن أو السرّ أبدًا.
الأحداث
Section titled “الأحداث”متن الطلب هو حمولة الحدث. وللحدث content.page.published هو { "pageId", "route", "revision" }. ونوع الحدث في ترويسة X-Atlas-Event.
تُعدّ webhooks مرة واحدة، في التطوير، وتستقبل أيضًا أحداثًا من الموقع الحي. لكل حمولة الحقل 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 لفحص الحمولات والإخفاقات.