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

الواجهة البرمجية العامة

تتيح الواجهة البرمجية العامة لخوادمك استدعاء وكلائك. وهي منفصلة عن لوحة التحكم: لها مفاتيحها ووثائقها وحدودها الخاصة.

  • العنوان الأساسي: https://api.eu.backcrew.ai/v1 لمساحات العمل المستضافة في أوروبا، وتستخدمه الأمثلة أدناه. ولكل نشر إقليمي لـ backcrew عنوانه الخاص، وتعرض المقتطفات البرمجية في صفحة التضمين للوكيل دائمًا عنوان مساحة عملك.
  • المرجع التفاعلي: https://api.eu.backcrew.ai/v1/docs

أنشئ مفتاحًا سريًا من الإعدادات ثم مفاتيح API. يبدأ المفتاح بـ bk_live_ ولا يُعرض إلا مرة واحدة، فاحفظه في مكان آمن. أرسله مع كل طلب:

Authorization: Bearer bk_live_...

ويأتي مع كل مفتاح أيضًا سر توقيع (bks_...) يُعرض مرة واحدة بجانبه. ولا تحتاج إليه إلا للاستدعاءات الراجعة، إذ يتيح لخادمك التحقق من أن النتيجة صادرة فعلًا عن backcrew. وإن فقدته أو لم يكن لديك سر، فاختر سر توقيع جديد على المفتاح، فيتوقف السر القديم عن المطابقة فورًا.

نافذة طرفيّة
curl https://api.eu.backcrew.ai/v1/agents \
-H "Authorization: Bearer $BACKCREW_API_KEY"
[{ "id": "7c9f…", "name": "support-bot", "status": "deployed" }]

لا يجيب إلا الوكلاء بحالة deployed.

POST /v1/agents/{agent_id}/invoke

الحقل مطلوب المعنى
prompt نعم الرسالة.
session_id لا يجمع الرسائل في محادثة واحدة.
user_id لا معرّفك الخاص للشخص الذي تتصرف نيابةً عنه. عند تفعيل الذاكرة، يحصل كل user_id على ذاكرته الخاصة.
نافذة طرفيّة
curl -X POST https://api.eu.backcrew.ai/v1/agents/$AGENT_ID/invoke \
-H "Authorization: Bearer $BACKCREW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "أين طلبي؟", "user_id": "customer-123", "session_id": "conversation-1"}'
{
"response": "تم شحن طلبك أمس ومن المتوقع وصوله يوم الخميس.",
"usage": { "input_tokens": 1240, "output_tokens": 310, "credits_charged": 5, "unmetered": [] }
}

يصل الرد كاملًا عند انتهاء الوكيل، فالردود لا تُبث تدريجيًا.

قد تنتهي مهلة الطلب الذي يستغرق أكثر من 100 ثانية قبل وصول الرد. وإن كان وكيلك قد يستغرق وقتًا أطول، فابدأ تشغيلًا بدلًا من ذلك.

import os, requests
res = requests.post(
f"https://api.eu.backcrew.ai/v1/agents/{os.environ['AGENT_ID']}/invoke",
headers={"Authorization": f"Bearer {os.environ['BACKCREW_API_KEY']}"},
json={"prompt": "أين طلبي؟", "user_id": "customer-123"},
timeout=120,
)
res.raise_for_status()
print(res.json()["response"])
const res = await fetch(`https://api.eu.backcrew.ai/v1/agents/${agentId}/invoke`, {
method: "POST",
headers: { Authorization: `Bearer ${process.env.BACKCREW_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ prompt: "أين طلبي؟", user_id: "customer-123" }),
});
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
console.log((await res.json()).response);

الطلبات الطويلة: عمليات التشغيل والاستدعاءات الراجعة

Section titled “الطلبات الطويلة: عمليات التشغيل والاستدعاءات الراجعة”

يمكن للوكيل أن يعمل مدةً تصل إلى 5 دقائق، غير أن الطلب الواحد الذي يبقى مفتوحًا أكثر من 100 ثانية قد ينقطع قبل وصول الرد. ويتجنب التشغيل ذلك: تبدؤه فيجيبك backcrew فورًا، ويعمل الوكيل في الخلفية. ثم إما أن تستعلم عن التشغيل، وإما أن تحدد callback_url فيرسل إليك backcrew النتيجة عند الانتهاء.

تخضع عمليات التشغيل للتكلفة والفحوصات نفسها التي يخضع لها invoke: فإن لم يكن الوكيل منشورًا (409)، أو نفدت الأرصدة أو بُلغ الحد الشهري (402)، يُرفض التشغيل عند بدئه دون أي خصم. وتُحفظ عمليات التشغيل لمدة ساعة.

يقبل POST /v1/agents/{agent_id}/runs الحقول نفسها التي يقبلها invoke، إضافةً إلى callback_url الاختياري، ويجيب بالرمز 202:

نافذة طرفيّة
curl -X POST https://api.eu.backcrew.ai/v1/agents/$AGENT_ID/runs \
-H "Authorization: Bearer $BACKCREW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "طابق فواتير شهر أكتوبر", "user_id": "finance-team"}'
{ "id": "3f1c…", "agent_id": "7c9f…", "status": "running", "started_at": "2026-10-22T09:00:00+00:00",
"finished_at": null, "response": null, "usage": null, "error": null }

يعيد GET /v1/agents/{agent_id}/runs/{run_id} الكائن نفسه، وتكون قيمة status إحدى ما يلي:

الحالة المعنى
running لا يزال الوكيل يعمل. أعد السؤال بعد بضع ثوانٍ.
answered اكتمل: يحتوي response وusage على النتيجة.
failed لم يُجب: يوضح error السبب (مثل نفاد الأرصدة أو تعطل شيفرة الوكيل).
lost توقف دون إجابة. راجع سجل نشاط الوكيل، ثم أعد المحاولة.

يُحتسب الاستعلام ضمن حد المعدل لمفتاحك، لذا يكفي الاستعلام كل ثانيتين إلى خمس ثوانٍ. ويُعد معرّف التشغيل التابع لمساحة عمل أخرى أو لوكيل آخر غير موجود (404).

import os, time, requests
API = f"https://api.eu.backcrew.ai/v1/agents/{os.environ['AGENT_ID']}"
HEADERS = {"Authorization": f"Bearer {os.environ['BACKCREW_API_KEY']}"}
run = requests.post(f"{API}/runs", headers=HEADERS, json={"prompt": "طابق فواتير شهر أكتوبر"}, timeout=30)
run.raise_for_status()
run = run.json()
while run["status"] == "running":
time.sleep(3)
run = requests.get(f"{API}/runs/{run['id']}", headers=HEADERS, timeout=30).json()
if run["status"] == "answered":
print(run["response"])
else:
print(f"{run['status']}: {run['error']}")

استلام النتيجة على خادمك

Section titled “استلام النتيجة على خادمك”

أضف "callback_url": "https://your-server.example.com/backcrew" عند بدء التشغيل. وعند انتهائه (answered أو failed)، يرسل backcrew طلب POST إلى ذلك العنوان، ويكون متن الطلب كائن التشغيل بصيغة JSON. أجب بأي رمز 2xx. وإن صادف الإرسال خطأً، أو تلقى ردًا غير 2xx، أو لم يتلقَّ ردًا خلال 10 ثوانٍ، فإنه يُعاد بعد 5 ثوانٍ ثم بعد 30 ثانية: 3 محاولات في المجموع. ولا تُتبع عمليات إعادة التوجيه.

يجب أن يبدأ العنوان بـ https:// وأن يكون متاحًا على الإنترنت العام: إذ تُرفض العناوين الخاصة والمحلية والمحجوزة بالرمز 422 عند بدء التشغيل.

ويحمل كل إرسال توقيعًا مُنشأً بسر التوقيع الخاص بمفتاحك:

X-Backcrew-Signature: t=1792659600,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd

قيمة v1 هي HMAC-SHA256 بالترميز الست عشري للطابع الزمني متبوعًا بنقطة ثم متن الطلب الخام ("{t}.{body}"). تحقق منه قبل الوثوق بالمتن، مستخدمًا البايتات الخام التي استلمتها (لا JSON معاد ترميزه)، وارفض الطابع الزمني القديم كي لا يُعاد إرسال طلب مُعترَض:

import hashlib, hmac, os, time
def verify(body: bytes, header: str, secret: str = os.environ["BACKCREW_SIGNING_SECRET"]) -> bool:
try:
fields = dict(part.split("=", 1) for part in header.split(","))
timestamp = int(fields["t"])
except (KeyError, ValueError):
return False
if abs(time.time() - timestamp) > 300: # أقدم من 5 دقائق
return False
expected = hmac.new(secret.encode(), f"{timestamp}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, fields.get("v1", ""))
# في إطار الويب لديك، مثل Flask:
# if not verify(request.get_data(), request.headers.get("X-Backcrew-Signature", "")): abort(401)
import crypto from "node:crypto";
// `body` هو متن الطلب الخام بصيغة Buffer، مثل express.raw({ type: "application/json" }).
function verify(body, header, secret = process.env.BACKCREW_SIGNING_SECRET) {
const fields = Object.fromEntries((header || "").split(",").map((part) => part.split("=", 2)));
const timestamp = Number(fields.t);
if (!timestamp || Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.`).update(body).digest("hex");
const given = Buffer.from(fields.v1 || "", "utf8");
return given.length === expected.length && crypto.timingSafeEqual(given, Buffer.from(expected, "utf8"));
}

قد تصل نتيجة التشغيل أكثر من مرة (مثلًا إذا تأخر خادمك في الرد)، لذا استخدم معرّف التشغيل id لمعالجة كل نتيجة مرة واحدة. ولا يُرسل استدعاء راجع لمفتاح أُلغي قبل انتهاء التشغيل، ولا لتشغيل بحالة lost: فاستعلم عن التشغيل إن لم تصلك النتيجة.

الرمز المعنى
401 المفتاح مفقود أو غير معروف أو ملغى.
402 نفدت أرصدة مساحة العمل (أو تجاوزت حدها الشهري).
404 لا يوجد وكيل بهذا المعرّف في مساحة عمل هذا المفتاح، أو لا يوجد تشغيل كهذا (تُحفظ عمليات التشغيل لمدة ساعة).
409 الوكيل غير منشور حاليًا (مثلًا: قيد التحديث).
422 قيمة callback_url ليست عنوان https:// عامًا، أو ليس للمفتاح سر توقيع بعد.
429 بلغت حد المعدل؛ انتظر عدد الثواني في Retry-After.
502 تعذّر على الوكيل الإجابة.
504 تجاوز الوكيل الحد الأقصى لمدة الطلب (5 دقائق).
  • 60 طلبًا في الدقيقة لكل مفتاح، بما في ذلك بدء عمليات التشغيل والاستعلام عنها.
  • يستهلك كل استدعاء أرصدة تمامًا كطلب من لوحة التحكم. راجع الأرصدة.