الصفحة الرئيسية/🔌 واجهة API والتكامل الأصلي

واجهة 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.