تخطَّ إلى المحتوى

الحسابات والمشاريع ومفاتيح API والنطاقات

تغطّي هذه الصفحة تسجيل الدخول، وجلستك، وكيف تُعِدّ المشاريع و مفاتيح API والنطاقات.

تسجّل الدخول عبر SSO فقط. ونحن لا نخزّن أي كلمة مرور.

  • لوحة التحكّم في TEST: https://test-app.segmnt.cloud
  • واجهة API في TEST: https://test-api.segmnt.cloud
  • المعرّفات: الحسابات تبدأ بـ acc_، والمستخدمون بـ usr_، والمشاريع بـ prj_، ومفاتيح API بـ key_، والنطاقات بـ dom_.

1. تسجيل الدخول (عبر SSO فقط)

Section titled “1. تسجيل الدخول (عبر SSO فقط)”

افتح لوحة التحكّم واختر مزوّداً:

  • Google
  • GitHub

وتأتي الأزرار من واجهة API، لذا تعرض اللوحة المزوّدات التي تعمل في هذه البيئة فقط:

نافذة طرفيّة
curl https://test-api.segmnt.cloud/auth/providers
{"data":[{"id":"google","label":"Google"},{"id":"github","label":"GitHub"}]}

وعندما تختار مزوّداً، ينتقل المتصفح إلى /auth/{provider}/start، ويسجّلك المزوّد دخولاً، ثم يعيد المتصفح إلى /auth/{provider}/callback. وينشئ الـ callback حسابك عند أول تسجيل دخول ويبدأ جلستك.

نافذة طرفيّة
curl -i "https://test-api.segmnt.cloud/auth/google/start?return_to=/videos"

الرد: 302 إلى المزوّد. كما نضع كوكي قصير العمر خاصاً بالتدفّق (segmnt_auth، 10 دقائق) يحمل قيمة state لمنع CSRF، ورمز PKCE، وقيمة OIDC nonce.

ملاحظات:

  • يمكن أن تكون return_to مساراً في لوحة التحكّم (/videos) أو رابطاً كاملاً للوحة. وأي قيمة أخرى تذهب إلى الصفحة الرئيسية للوحة، فلا يمكن استخدام هذا المسار لإرسالك إلى موقع آخر.
  • نربط تسجيل الدخول الجديد بحسابك فقط عندما يقول المزوّد إن بريدك الإلكتروني موثّق. سجّل الدخول بـ Google وGitHub بالبريد الموثّق نفسه فتصل إلى حساب واحد. وأي مزوّد لا يعطي بريداً موثّقاً ينشئ حساباً جديداً.
  • Apple وReddit لاحقاً. فـ Apple ينتظر موافقة المجلس على حساب مطوّر Apple المدفوع، وReddit ينتظر موافقة Reddit على تطبيق OAuth الخاص بنا. وإضافة مزوّد تغيير صغير من جانبنا.

بعد تسجيل الدخول نرسل كوكي segmnt_session:

الخاصية القيمة
المدّة 30 يوماً
العلامات HttpOnly, Secure, SameSite=Lax, Path=/

الجلسات من جهة الخادم، وليست JWT. فالكوكي يحمل معرّفاً عشوائياً، ونخزّن فقط تجزئة SHA-256 لذلك المعرّف. وتسجيل الخروج يحذف صفّ الجلسة. وإذا فقدت الكوكي، فسجّل الدخول من جديد.

كل نداء إلى /v1/projects... يحتاج كوكي الجلسة هذا. وبدون جلسة صالحة تحصل على 401 unauthorized:

نافذة طرفيّة
curl https://test-api.segmnt.cloud/v1/projects
{"type":"https://docs.segmnt.cloud/errors/unauthorized","title":"Missing or expired session.","status":401,"code":"unauthorized","detail":"Missing or expired session."}

يعيد GET /v1/me المستخدم والحساب المسجَّلين. ويستخدم كوكي الجلسة ولا يعيد أي حقل مخفي من الحساب:

{
"user": { "id": "usr_...", "email": "you@example.com", "displayName": "...", "role": "owner" },
"account": { "id": "acc_...", "name": "...", "planId": "free", "planStatus": "active", "createdAt": "..." }
}

تسجيل الخروج:

نافذة طرفيّة
curl -X POST https://test-api.segmnt.cloud/auth/logout

الرد 204. وآمن للنداء مرّتين.

استخدم مشروعاً واحداً لكل عميل أو موقع أو دورة. ويمكن للحساب الواحد أن يضمّ مشاريع كثيرة، فتستطيع الوكالة فصل كل عميل عن غيره.

في لوحة التحكّم يمكنك إنشاء مشروع وإعادة تسميته وحذفه. والحذف يعمل للمشروع الفارغ فقط. فاحذف الفيديوهات أولاً، وإلا تحصل على 409 project_not_empty. وحذف المشروع يوقف أيضاً مفاتيح API والنطاقات الخاصة به.

نقاط REST (كلها تستخدم كوكي الجلسة):

الطريقة المسار جسم الطلب / ملاحظات
GET /v1/projects limit (1-100، الافتراضي 20) وcursor. الأحدث أولاً.
POST /v1/projects {"name": "Client A courses"} (من 1 إلى 100 حرف) ← 201
GET /v1/projects/{projectId} مشروع واحد
PATCH /v1/projects/{projectId} {"name": "New name"} ← 200
DELETE /v1/projects/{projectId} مشروع فارغ ← 204؛ غير فارغ ← 409 project_not_empty

وصفحة القائمة تبدو هكذا. ومرّر nextCursor كـ cursor للحصول على الصفحة التالية:

{
"data": [ { "id": "prj_...", "name": "Client A courses", "createdAt": "2026-10-12T07:00:00.000Z" } ],
"nextCursor": null
}

مفاتيح API لكل مشروع، وهي للخوادم لا للمتصفحات. أنشئها في لوحة التحكّم، ثم انسخ المفتاح مرّة واحدة.

الصيغة: sk_{8 characters}_{64 hex characters}، مثال sk_Abcd1234_<64 hex>. ونعرض المفتاح كاملاً في رد الإنشاء فقط، ونخزّن فقط تجزئة SHA-256 للسرّ. فاحفظه سرّياً. وإذا فقدته، أبطله وأنشئ غيره.

ويرسل خادمك المفتاح في ترويسة Authorization:

Authorization: Bearer sk_...

ويوضّح دليل الرفع المباشر النداءات التي تستخدمه.

النقاط (كلها تستخدم كوكي الجلسة؛ ومفتاح API لا يمكنه إدارة المفاتيح أو المشاريع أو النطاقات):

الطريقة المسار جسم الطلب / ملاحظات
GET /v1/projects/{projectId}/api-keys القائمة؛ ولا يُعاد السرّ أبداً
POST /v1/projects/{projectId}/api-keys {"name": "Course site backend"} ← 201، مع secret مرّة واحدة
DELETE /v1/projects/{projectId}/api-keys/{keyId} إبطال ← 204

ويحتوي كل عنصر في القائمة على id وname وprefix وcreatedAt وlastUsedAt. ولا يظهر السرّ في القائمة. والمفتاح المُبطَل يحصل على 401 فوراً. ويعمل المفتاح لمسارات مشروعه فقط (مثل الرفع).

يخبرنا النطاق بالمواقع التي يجوز لها تشغيل فيديوهات المشروع. ويطابق التشغيل المضيف بالتحديد، فالنطاق الفرعي يحتاج سطراً خاصاً به: أضف courses.example.com، لا example.com.

الخطوات:

  1. أضف المضيف في لوحة التحكّم، أو استدعِ POST /v1/projects/{projectId}/domains مع {"hostname": "courses.example.com"}. ويحمل الرد الحالة pending وكتلة verification:

    { "type": "TXT", "name": "_segmnt-verify.courses.example.com", "value": "segmnt-verify=b41c09e2f7a3d6c1" }
  2. أنشئ سجل TXT هذا عند مزوّد DNS لديك.

  3. استدعِ التحقّق. وعندما يُعثر على السجل تصبح status = verified. وإن لم يُعثر عليه بعد، فتبقى pending ويمكنك المحاولة لاحقاً.

النقاط (كلها تستخدم كوكي الجلسة):

الطريقة المسار جسم الطلب / ملاحظات
GET /v1/projects/{projectId}/domains القائمة
POST /v1/projects/{projectId}/domains {"hostname": "courses.example.com"} ← 201
POST /v1/projects/{projectId}/domains/{domainId}/verify فحص سجل DNS
DELETE /v1/projects/{projectId}/domains/{domainId} إزالة ← 204

حدّ الخطة: الحساب المجاني يمكنه توثيق نطاق واحد. وأكثر من ذلك يعطي 403 plan_limit_reached؛ فأزل القديم أو ترقَّ أولاً. وإذا كان المضيف مستخدَماً بالفعل، تحصل على 409 hostname_taken. وإزالة نطاق ترفض الرموز الجديدة له. أمّا الرموز الصادرة مسبقاً فتبقى تعمل حتى انتهاء صلاحيتها.

مسارات النطاقات مباشرة في TEST الآن. أمّا الأجزاء الظاهرة للعميل - تدفّق لوحة التحكّم وفحص نطاق التشغيل - فتُطلق مع إصدار النطاقات.

الأخطاء تستخدم application/problem+json. استخدم الحقل code في الكود، لا النص. ويشير الحقل type إلى https://docs.segmnt.cloud/errors/{code}.

الحالة code المعنى ما تفعله
400 invalid_request حقل ناقص أو خاطئ، أو cursor غير صحيح صحّح الطلب. لا تُعِد المحاولة.
400 invalid_state انتهت صلاحية تدفّق تسجيل الدخول أو تغيّر ابدأ تسجيل الدخول من جديد.
400 auth_denied ألغيت تسجيل الدخول عند المزوّد ابدأ تسجيل الدخول من جديد.
401 unauthorized جلسة أو مفتاح ناقص أو خاطئ أو منتهي أو مُبطَل سجّل الدخول من جديد، أو تحقّق من المفتاح.
403 plan_limit_reached تجاوزت حدّ خطتك (مثلاً نطاق موثّق واحد في المجانية) أزل شيئاً أو ترقَّ.
403 domain_not_verified طُلب التشغيل على نطاق لم توثّقه وثّق النطاق أولاً.
404 not_found معرّف خاطئ، أو هو في حساب آخر تحقّق من المعرّف.
404 not_found مزوّد تسجيل دخول غير معروف أو معطّل استخدم مزوّداً من /auth/providers.
409 project_not_empty حاولت حذف مشروع يحتوي فيديوهات احذف الفيديوهات أولاً.
409 hostname_taken المضيف مضاف بالفعل استخدم مضيفاً آخر، أو طالب مالكه به.
500 internal_error لم نستطع إنشاء جلستك أعد المحاولة.
502 provider_error أعاد مزوّد تسجيل الدخول خطأً أعد المحاولة.
503 not_configured تسجيل الدخول معطّل في هذه البيئة لا شيء لتصلحه من جانبك.

فُحص ضد https://test-api.segmnt.cloud في 12 أكتوبر 2026:

  • GET /auth/providers ← 200 مع google وgithub.
  • GET /auth/google/start?return_to=/videos ← 302 إلى Google، مع كوكي التدفّق segmnt_auth (Path=/auth, Max-Age=600, HttpOnly, Secure, SameSite=Lax).
  • GET /v1/me وGET /v1/projects بدون كوكي ← 401 unauthorized.
  • POST /auth/logout بدون كوكي ← 204.
  • GET /auth/google/callback بدون state ← 400 invalid_state.
  • GET /v1/projects/{projectId}/domains بدون كوكي ← 401 (فمسارات النطاقات مباشرة في TEST؛ والمسار غير المنشور يعطي 404).

كما جرّبنا مسارات الجلسة من الطرف إلى الطرف في TEST بجلسة حقيقية. وفحص ذلك التشغيل: /v1/me؛ إنشاء مشروع وسرده وإعادة تسميته وحذفه؛ خطأ 409 للمشروع غير الفارغ؛ صيغة المفتاح sk_{8}_{64 hex}؛ أن السرّ غير موجود في القائمة؛ أن المفتاح يعمل لرفوعات ذلك المشروع؛ أن مفتاحاً من مشروع آخر يعطي 404؛ أن المفتاح المُبطَل يعطي 401؛ أن انعدام الجلسة يعطي 401؛ وأن مسارات النطاقات (إضافة نطاق pending مع سجل TXT، ويبقى التحقّق pending بدون DNS، والحذف يعطي 204). ويُلغي التشغيل الرفع المفتوح بمفتاح API ويؤكد أن حذفي المشروع يعطيان 204، فلا يترك صفّ فيديو ولا رفعاً متعدّد الأجزاء في R2.

وسلوك مسارات المشاريع ومفاتيح API وSSO مغطّى أيضاً باختبارات الوحدة في API.