Webhooks
سجّل webhook
يسجّل رابط https تستدعيه Sofia بحدث JSON موقّع، مع إعادة المحاولة حتى خمس مرات عند الفشل. يظهر السر مرة واحدة؛ 10 webhooks كحد أقصى.
تسجيل webhook
سجّل عنوان https عامًا والأحداث المطلوبة. لا يظهر سرّ التوقيع (whsec_…) إلا في هذا الرد. يمكن للتطبيق أن يملك حتى 10 webhooks.
curl -X POST https://api.sofia-post.com/api/v1/webhooks \
-H "Authorization: Bearer $SOFIA_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"url":"https://app.example.com/hooks/sofia","events":["post.published","post.failed"]}'الأحداث
| الحدث | data |
|---|---|
post.published | postId وestablishmentId وplatform وpublishedAt وpermalink |
post.failed | postId وestablishmentId وplatform وerror |
webhook.test | webhookId |
ترسل Sofia كل حدث بـ POST بصيغة JSON { id, type, createdAt, data }، مع الترويسات Sofia-Event-Id وSofia-Event-Type وSofia-Signature. لا تُعلَن سوى المنشورات التي أنشأها تطبيقك.
التحقق من التوقيع
قيمة Sofia-Signature هي t=<unix time>,v1=<hex>، حيث v1 هو HMAC-SHA256 للقيمة <t>.<raw body> بسرّك. تحقق منه على الجسم الخام، وارفض ختمًا زمنيًا قديمًا:
import { createHmac, timingSafeEqual } from 'node:crypto';
const isSignedBySofia = (header, rawBody, secret) => {
const parts = Object.fromEntries(
(header ?? '').split(',').map((part) => part.trim().split('=', 2)),
);
const timestamp = Number(parts.t);
if (!Number.isInteger(timestamp) || typeof parts.v1 !== 'string') return false;
if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
const expected = createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest();
const received = Buffer.from(parts.v1, 'hex');
return received.length === expected.length && timingSafeEqual(received, expected);
};التسليم وإعادة المحاولة
- رد
2xxيسلّم الحدث. وأي رد آخر، أو تحويل (لا يُتَّبع أبدًا)، أو 10 ثوانٍ دون رد، يطلق محاولة جديدة بعد دقيقة، ثم 5 دقائق، ثم 30 دقيقة، ثم ساعتين، حتى 5 محاولات. - قد يصل الحدث نفسه مرتين: أزل التكرار بحسب
Sofia-Event-Id. - أجب بسرعة وعالج الحدث بعد ذلك.
التفويضات
Authorizationstringheaderمطلوبمفتاحك الشخصي أو رمز وصول OAuth، يُرسل كـ
Bearer <token>.
الجسم
urlstringمطلوبعنوان https الذي تستدعيه Sofia. يُرفض المضيف الذي يُحلّ إلى عنوان خاص أو loopback أو link-local
eventsstring[]مطلوبالأحداث المراد استلامها
الاستجابة
الـ webhook وسرّ توقيعه، يظهر مرة واحدة فقط.
idstringمطلوبمعرّف الـ webhook
urlstringمطلوبالعنوان الذي تستدعيه Sofia
eventsstring[]مطلوبالأحداث المشترك فيها
createdAtstring<date-time>مطلوبوقت تسجيل الـ webhook
secretstringمطلوبمفتاح HMAC-SHA256 الذي يوقّع كل عملية تسليم (
Sofia-Signature). يظهر هذه المرة فقط