واجهة API — التكامل الأصلي
كل ما تفعله الواجهة الويب هو واجهة HTTP + SSE عادية. كل ما يمكنك فعله بالنقر يمكنك فعله من شيفرتك الخاصة: تشغيل وكيل، بثّ إجابته، الاستعلام من قاعدة معرفة، بناء وكلاء، جدولة المهام، واسترجاع النتائج.
| عنوان الأساس | https://ai.syctra.com/api/v1 |
| النقل | HTTPS فقط (يُعاد توجيه HTTP). TLS 1.2+ |
| الترميز | JSON، UTF-8. Content-Type: application/json في كل عملية كتابة |
| البثّ | Server-Sent Events (text/event-stream)، قابل للاستئناف |
| المصادقة | Authorization: Bearer <access_token> |
| الإصدار | البادئة /v1 مستقرّة. قد تُضاف حقول جديدة، ولا تُحذف الحقول القائمة دون بادئة جديدة |
١. المصادقة
هناك نوعان من بيانات الاعتماد. استخدم المناسب:
| مفتاح API | بريد + كلمة مرور | |
|---|---|---|
| لِـ | الخوادم، السكربتات، التكاملات، CI | التطبيقات التفاعلية التي يسجّل فيها إنسان الدخول |
| الحصول عليه | الإعدادات ← 🔑 مفاتيح API ← مفتاح جديد | POST /auth/register ثم /auth/login |
| الشكل | sk_live_… | زوج JWT (وصول + تحديث) |
| المدة | حتى الإبطال | الوصول ١٥ دقيقة · التحديث ٣٠ يوماً |
لا ترسل مفتاح API إلى متصفّح أو تطبيق جوّال أو مستودع عام أبداً. فهو يحمل كامل صلاحيات الحساب الذي أنشأه. كل ما يعمل على جهاز العميل يجب أن يمرّ عبر خادمك أنت، وهو من يحتفظ بالمفتاح.
١.١ مفتاح API ← رمز وصول
مفتاح API ليس رمز bearer: تستبدله برمز وصول قصير الأجل، ثم تستدعي أي نقطة نهاية بذلك الرمز.
export SYCTRA_API_KEY="sk_live_…"
TOKEN=$(curl -sS -X POST https://ai.syctra.com/api/v1/auth/token \
-H "X-API-Key: $SYCTRA_API_KEY" | jq -r .access_token)
POST /auth/token هي نقطة النهاية الوحيدة التي تقبل المفتاح نفسه. تقرأه بثلاث طرق —
X-API-Key: sk_live_… أو Authorization: Bearer sk_live_… أو {"api_key": "sk_live_…"} في
الجسم — وتُجيب:
{ "access_token": "eyJhbGciOiJSUzI1NiIs…", "token_type": "Bearer", "expires_in": 900 }
خزّن الرمز مؤقتاً طوال expires_in (٩٠٠ ثانية) وأعد التبادل عند انتهائه. لا تُبادل مع كل
طلب: النقطة محدودة بـ ٦٠ تبادلاً في الدقيقة لكل عنوان IP.
١.٢ إدارة المفاتيح
| الطريقة | المسار | الغرض |
|---|---|---|
POST | /api-keys | إنشاء مفتاح. {"name": "خادم-الإنتاج"}. النص الصريح يظهر في هذه الاستجابة فقط |
GET | /api-keys | سرد المفاتيح الفعّالة — المعرّف، الاسم، البادئة، created_at، last_used_at. لا السرّ أبداً |
DELETE | /api-keys/{key_id} | الإبطال. يمنع أي تبادل جديد فوراً |
حتى ٢٠ مفتاحاً فعّالاً لكل مستخدم. لا يُخزَّن سوى sha256(المفتاح)، فالمفتاح الضائع غير
قابل للاسترجاع — أبطله وأنشئ غيره. الإبطال يوقف التبادلات الجديدة فوراً؛ أما رمز الوصول الصادر
مسبقاً فيبقى صالحاً حتى انتهائه (≤ ١٥ دقيقة)، تماماً كتسجيل الخروج من المتصفّح.
١.٣ بريد + كلمة مرور (التطبيقات التفاعلية)
curl -X POST https://ai.syctra.com/api/v1/auth/register \
-H 'content-type: application/json' \
-d '{"email":"dev@acme.com","password":"…"}' # ← رمز من ٦ أرقام بالبريد
curl -X POST https://ai.syctra.com/api/v1/auth/verify \
-H 'content-type: application/json' \
-d '{"email":"dev@acme.com","code":"123456"}'
curl -X POST https://ai.syctra.com/api/v1/auth/login \
-H 'content-type: application/json' \
-d '{"email":"dev@acme.com","password":"…"}' # ← { access_token, refresh_token }
جدّد عبر POST /auth/refresh {"refresh_token": "…"}. الدخول عبر Google وOIDC/SAML متاح على
/auth/google/start و/auth/oidc/start. تسجيل الدخول محدود لكل حساب بعد محاولات فاشلة
متكرّرة، والتسجيلات الجديدة مسقوفة لكل IP.
٢. البداية السريعة — اسأل وكيلاً وابثّ الإجابة
النمط واحد دائماً: ابدأ تشغيلاً (run) ثم ابثّ أحداثه. التشغيل دائم — إن مات برنامجك، أعد الاتصال واسترجع من حيث توقفت.
# ١ — البدء
RUN=$(curl -sS -X POST https://ai.syctra.com/api/v1/chat \
-H "Authorization: Bearer $TOKEN" -H 'content-type: application/json' \
-d '{"message":"لخّص اتجاه رقم الأعمال 2024 وارسمه بيانياً","app_name":"data_copilot"}')
RUN_ID=$(echo "$RUN" | jq -r .run_id)
# ٢ — البثّ (قابل للاستئناف)
curl -N https://ai.syctra.com/api/v1/runs/$RUN_ID/events \
-H "Authorization: Bearer $TOKEN"
Python
import json, os, requests
BASE = "https://ai.syctra.com/api/v1"
token = requests.post(f"{BASE}/auth/token",
headers={"X-API-Key": os.environ["SYCTRA_API_KEY"]},
timeout=30).json()["access_token"]
H = {"Authorization": f"Bearer {token}"}
run = requests.post(f"{BASE}/chat", headers=H, timeout=30, json={
"message": "حرّر اتفاقية سرية متبادلة لشركة ذات مسؤولية محدودة جزائرية ثم صدّرها DOCX",
"app_name": "legal_drafting_dz",
}).json()
answer, cursor = [], 0
with requests.get(f"{BASE}/runs/{run['run_id']}/events", headers=H, stream=True) as r:
event = None
for line in r.iter_lines(decode_unicode=True):
if not line:
continue
if line.startswith("id:"):
cursor = int(line[3:].strip()) # احتفظ به: هذه نقطة الاستئناف
elif line.startswith("event:"):
event = line[6:].strip()
elif line.startswith("data:"):
payload = json.loads(line[5:].strip())
if event == "token":
answer.append(payload.get("text", ""))
elif event == "artifact":
print("ملف:", payload.get("artifact_id"), payload.get("filename"))
elif event in ("done", "error"):
break
print("".join(answer))
Node
const BASE = 'https://ai.syctra.com/api/v1';
const { access_token } = await (await fetch(`${BASE}/auth/token`, {
method: 'POST', headers: { 'X-API-Key': process.env.SYCTRA_API_KEY },
})).json();
const { run_id } = await (await fetch(`${BASE}/chat`, {
method: 'POST',
headers: { authorization: `Bearer ${access_token}`, 'content-type': 'application/json' },
body: JSON.stringify({ message: 'اذكر مخاطر هذا العقد', app_name: 'contract_review_dz' }),
})).json();
const res = await fetch(`${BASE}/runs/${run_id}/events`, {
headers: { authorization: `Bearer ${access_token}` },
});
for await (const chunk of res.body) process.stdout.write(Buffer.from(chunk).toString());
٣. الاصطلاحات
الأخطاء. رموز HTTP قياسية مع جسم JSON {"detail": "…"}.
| الرمز | المعنى | ما العمل |
|---|---|---|
400 | طلب غير صالح | صحّح الحمولة؛ الرسالة تُسمّي الحقل |
401 | رمز مفقود / منتهٍ / غير صالح | أعد تبادل المفتاح |
402 | رصيد غير كافٍ | اشحن؛ لم يبدأ التشغيل ولم يُحتسب |
403 | مُصادق عليه لكن غير مخوّل | مؤسسة خاطئة، أو وكيل غير ممنوح لفريقك، أو حساب موقوف |
404 | غير موجود أو ليس لك | المعرّفات محصورة بمؤسستك |
409 | تعارض (جلسة مشغولة…) | اقرأ الجسم؛ الإدراج في الطابور يظهر في POST /chat |
429 | تجاوز الحد | تراجع تصاعدي، واحترم Retry-After إن وُجد |
5xx | خطأ خادم | أعد المحاولة بتراجع؛ التشغيلات مُعادة الاستخدام مع idempotency_key |
عدم التكرار. أرسل idempotency_key مع POST /chat — إعادة المفتاح ذاته تُرجع التشغيل
الأصلي (resumed: true) بدل بدء وفوترة تشغيل ثانٍ.
المعرّفات UUID. الطوابع الزمنية ISO-8601 بتوقيت UTC. أرسل client_tz (IANA، مثل
"Africa/Algiers") مع POST /chat ليحسب الوكيل بتوقيتك المحلي.
حدود المعدّل.
| السطح | الحدّ |
|---|---|
POST /chat والتشغيلات | ٢٠ طلباً/ثانية، دفقة ٤٠، لكل مستخدم |
POST /auth/token | ٦٠/دقيقة لكل IP للعميل |
POST /auth/login | محدود لكل حساب بعد محاولات فاشلة |
POST /auth/register | مسقوف لكل IP في الساعة |
| جسم الطلب | ٣٠٠ ميغابايت (يشمل رفع base64) |
التزامن. التشغيلات متسلسلة لكل جلسة: رسالة ثانية أثناء تشغيل الأولى تُقبَل وتُدرَج في
طابور على الخادم وتُنفَّذ بعدها (status: "queued" مع queue_seq). استخدم session_id مختلفة
للتوازي.
٤. الفوترة
كل عملية ذكاء اصطناعي تخصم أرصدة من رصيد مؤسستك — الرصيد نفسه الظاهر في التطبيق، سواء جاء
العمل من متصفّح أو استدعاء API أو مهمة مجدولة أو أداة مدمجة. كل تشغيل يُصدر حدث usage بعدّاد
الرموز، وGET /balance يُرجع الرصيد الحالي. التشغيل غير القابل للدفع يُرفض بـ 402
قبل أي عمل.
٥. الأمن
ما تضمنه المنصّة:
- المفاتيح مخزَّنة مُجزّأة (SHA-256). النص الصريح يوجد مرة واحدة، في استجابة الإنشاء.
- رموز قصيرة الأجل. ١٥ دقيقة؛ تعطيل حساب أو رفع نسخة رمزه يُبطل جلساته ويمنع أي تبادل لاحق.
- حجب بيانات الاعتماد. لا يستطيع الوكلاء كشف أسرار المنصّة: مفاتيح API وكلمات مرور SMTP وسلاسل الاتصال والمفاتيح الخاصة تُزال من نتائج الأدوات وأخطائها ومن مخرجات النموذج بمرشّح حتمي — لا بقاعدة في المُوجّه يمكن الالتفاف عليها.
- احتواء حقن المُوجّهات. حالما يبتلع التشغيل محتوى غير موثوق (ملف مرفوع، صفحة مكشوطة، نتيجة بحث)، تُحجب الإجراءات الصادرة — إرسال بريد، نشر، كتابة في الذاكرة، HTTP حرّ — حتى تؤكّدها صراحة.
- تنفيذ في صندوق رملي. الشيفرة التي يكتبها الوكيل تعمل في حاوية gVisor أحادية الاستخدام، بلا أسرار وبلا شبكة مباشرة: المرور الصادر يمرّ عبر وسيط بمرشّح SSRF.
- عزل المستأجرين. كل معرّف مرتبط بمؤسستك ويُعاد التحقق منه على الخادم؛ الهوية تأتي دائماً من الرمز، لا من حقل في الطلب.
- قابلية التدقيق. كل استدعاء أداة يُسجَّل مع تشغيله ومؤسسته وحالته.
ما يقع على عاتقك:
- احتفظ بالمفاتيح على الخادم، في خزنة أسرار أو متغيّر بيئة — لا في متصفّح ولا حزمة جوّال ولا مستودع git ولا سجلّ CI.
- مفتاح لكل نظام، باسم ذلك النظام، لتتمكّن من إبطاله وحده.
- دوِّر المفاتيح دورياً: أنشئ الجديد، انشر، ثم أبطل القديم.
last_used_atيخبرك متى يمكن سحب مفتاح بأمان. - أي مفتاح ظهر في سجلّ أو لقطة شاشة أو تذكرة دعم يُعدّ مكشوفاً — أبطله.
- إن أعدت عرض الواجهة لمستخدميك، فطبّق تخويلك الخاص: مفتاح المنصّة لا يعرف مستخدميك النهائيين.
الفهرس الكامل: مرجع API.