مرجع API

نموذج المصادقة، تنسيق الأخطاء، وأمثلة مطابقة لعقود التشغيل (cURL + Node + Python).

العناوين الأساسية

  • بروكسي الويب: `https://dcp.sa/api/dc1`
  • API المباشر (للعمليات/التحقق): `https://api.dcp.sa/api`

نموذج المصادقة

  • **المزود**: ترويسة `x-provider-key` أو `?key=`
  • **المستأجر**: ترويسة `x-renter-key` أو `?key=`
  • **المدير**: ترويسة `x-admin-token` أو `Authorization: Bearer <token>`

تنسيق الأخطاء

كل الأخطاء تعود بصيغة JSON:

{ "error": "descriptive message" }

مثال (`400`):

{ "error": "Missing required fields: job_type, duration_minutes" }

أمثلة النقاط الحرجة (مطابقة EN)

1) تسجيل مستأجر — `POST /renters/register`

curl -s -X POST "https://dcp.sa/api/dc1/renters/register" \
  -H "Content-Type: application/json" \
  -d &#;{
    "name": "Fatima Al-Saud",
    "email": "fatima@example.sa",
    "organization": "Riyadh AI Lab",
    "use_case": "llm_inference",
    "phone": "+"
  }&#;
const res = await fetch(&#;https://dcp.sa/api/dc1/renters/register&#;, {
  method: &#;POST&#;,
  headers: { &#;Content-Type&#;: &#;application/json&#; },
  body: JSON.stringify({
    name: &#;Fatima Al-Saud&#;,
    email: &#;fatima@example.sa&#;,
    organization: &#;Riyadh AI Lab&#;,
    use_case: &#;llm_inference&#;,
    phone: &#;+&#;,
  }),
})
const data = await res.json()
if (!res.ok) throw new Error(data.error)
import requests

res = requests.post(
    "https://dcp.sa/api/dc1/renters/register",
    json={
        "name": "Fatima Al-Saud",
        "email": "fatima@example.sa",
        "organization": "Riyadh AI Lab",
        "use_case": "llm_inference",
        "phone": "+",
    },
    timeout=,
)
res.raise_for_status()
print(res.json())

استجابة النجاح (`201`):

{
  "success": true,
  "renter_id": ,
  "api_key": "dc1-renter-abc123...",
  "message": "Welcome Fatima Al-Saud! Save your API key — it won&#;t be shown again."
}

2) نبض المزود — `POST /providers/heartbeat`

curl -s -X POST "https://dcp.sa/api/dc1/providers/heartbeat" \
  -H "Content-Type: application/json" \
  -d &#;{
    "api_key": "dc1-provider-abc123...",
    "gpu_status": {
      "gpu_name": "NVIDIA RTX ",
      "gpu_vram_mib": ,
      "gpu_util_pct": ,
      "temp_c": ,
      "daemon_version": ".3."
    }
  }&#;
const hb = await fetch(&#;https://dcp.sa/api/dc1/providers/heartbeat&#;, {
  method: &#;POST&#;,
  headers: { &#;Content-Type&#;: &#;application/json&#; },
  body: JSON.stringify({
    api_key: process.env.DC1_PROVIDER_KEY,
    gpu_status: {
      gpu_name: &#;NVIDIA RTX &#;,
      gpu_vram_mib: ,
      gpu_util_pct: ,
      temp_c: ,
      daemon_version: &#;.3.&#;,
    },
  }),
})
const hbData = await hb.json()
if (!hb.ok) throw new Error(hbData.error)
import requests

hb = requests.post(
    "https://dcp.sa/api/dc1/providers/heartbeat",
    json={
        "api_key": "dc1-provider-abc123...",
        "gpu_status": {
            "gpu_name": "NVIDIA RTX ",
            "gpu_vram_mib": ,
            "gpu_util_pct": ,
            "temp_c": ,
            "daemon_version": ".3.",
        },
    },
    timeout=,
)
hb.raise_for_status()
print(hb.json())

استجابة النجاح (`200`):

{
  "success": true,
  "message": "Heartbeat received",
  "timestamp": "--22T19::.000Z",
  "needs_update": false,
  "latest_version": ".3.",
  "update_available": false,
  "min_version": ".3.",
  "approval_status": "approved",
  "approved": true,
  "preload_model": null
}

3) إرسال مهمة — `POST /jobs/submit`

curl -s -X POST "https://dcp.sa/api/dc1/jobs/submit" \
  -H "Content-Type: application/json" \
  -H "x-renter-key: $RENTER_KEY" \
  -d &#;{
    "provider_id": ,
    "job_type": "llm_inference",
    "duration_minutes": ,
    "max_duration_seconds": ,
    "container_spec": { "image_type": "vllm-serve" },
    "params": {
      "model": "TinyLlama/TinyLlama-.1B-Chat-v1.",
      "prompt": "لخص منصة DCP في ثلاث نقاط"
    }
  }&#;
const submit = await fetch(&#;https://dcp.sa/api/dc1/jobs/submit&#;, {
  method: &#;POST&#;,
  headers: {
    &#;Content-Type&#;: &#;application/json&#;,
    &#;x-renter-key&#;: process.env.DC1_RENTER_KEY!,
  },
  body: JSON.stringify({
    provider_id: ,
    job_type: &#;llm_inference&#;,
    duration_minutes: ,
    max_duration_seconds: ,
    container_spec: { image_type: &#;vllm-serve&#; },
    params: {
      model: &#;TinyLlama/TinyLlama-.1B-Chat-v1.&#;,
      prompt: &#;لخص منصة DCP في ثلاث نقاط&#;,
    },
  }),
})
const submitted = await submit.json()
if (!submit.ok) throw new Error(submitted.error)
import requests

submitted = requests.post(
    "https://dcp.sa/api/dc1/jobs/submit",
    headers={
        "Content-Type": "application/json",
        "x-renter-key": "dc1-renter-abc123...",
    },
    json={
        "provider_id": ,
        "job_type": "llm_inference",
        "duration_minutes": ,
        "max_duration_seconds": ,
        "container_spec": {"image_type": "vllm-serve"},
        "params": {
            "model": "TinyLlama/TinyLlama-.1B-Chat-v1.",
            "prompt": "لخص منصة DCP في ثلاث نقاط",
        },
    },
    timeout=,
)
submitted.raise_for_status()
print(submitted.json())

استجابة النجاح (`201`) — نفس البنية في EN:

{
  "success": true,
  "job": {
    "id": ,
    "job_id": "job--ab12cd",
    "provider_id": ,
    "renter_id": ,
    "job_type": "llm_inference",
    "model": "TinyLlama/TinyLlama-.1B-Chat-v1.",
    "status": "pending"
  }
}

4) لوحة الإدارة — `GET /admin/dashboard`

curl -s "https://dcp.sa/api/dc1/admin/dashboard" \
  -H "x-admin-token: $DC1_ADMIN_TOKEN"
const dash = await fetch(&#;https://dcp.sa/api/dc1/admin/dashboard&#;, {
  headers: { &#;x-admin-token&#;: process.env.DC1_ADMIN_TOKEN! },
})
const dashboard = await dash.json()
if (!dash.ok) throw new Error(dashboard.error)
import requests

dashboard = requests.get(
    "https://dcp.sa/api/dc1/admin/dashboard",
    headers={"x-admin-token": "<DC1_ADMIN_TOKEN>"},
    timeout=,
)
dashboard.raise_for_status()
print(dashboard.json())

مصدر OpenAPI

  • صفحة مرجعية: صفحة API
  • ملف آلي: `/docs/openapi.yaml`