# الطلبات

الطلب هو استدعاء واحد لنموذج واحد. وله معرّف (`req_…`) وحالة وتكلفة بأرصدة API (1000 = 1 USD)، وعند نجاحه، الملفات المُنشأة. يعيد كل نقطة نهاية أدناه الكائن نفسه لكل نموذج.

## العثور على نموذج

كتالوج النماذج الـ1,496 الكامل هو JSON عام (لا حاجة إلى مفتاح):

```bash
curl "https://api.doitong.ru/v1/models?category=text-to-video&lab=Google&limit=20"
```

| معلمة الاستعلام | المعنى |
|---|---|
| `q` | كلمات يجب أن تظهر جميعها في الاسم أو المعرّف أو الجهة المطوّرة أو الوسوم، مثل `kling 3`. |
| `category` | معرّف فئة واحد، مثل `text-to-video` أو `upscale`. يعرض `GET https://api.doitong.ru/v1/categories` جميع الفئات الـ21 مع أعدادها. |
| `lab` | الجهة المطوّرة للنموذج، بالاسم أو المعرّف، مثل `Google` أو `black-forest-labs`. |
| `family` | معرّف `family` من صف سابق: كل متغيرات نموذج واحد (pro، fast، image-to-video، …). |
| `mode` | `exact` (تُحسب التكلفة من المدخل)، أو `measured` (من طول ملفات المدخل أو حجمها)، أو `estimate` (سعر تقديري لكل تشغيل)، أو `metered` (تُفرض التكلفة حسب الاستخدام الفعلي، حتى حد أقصى لكل تشغيل). |
| `limit`, `cursor` | حجم الصفحة (من 1 إلى 100، الافتراضي 50) و`next_cursor` للصفحة السابقة. |

يحتوي كل صف على `id` و`name` و`lab` و`category` و`family` و`summary` و`tags` و`output_kind` و`docs_url` وكائن `price` (راجع [التسعير](https://doitong.com/developers/docs/pricing#price-objects)). يضيف `GET https://api.doitong.ru/v1/models/{model_id}` مخطط JSON الكامل للمدخل والمخرج، وأسماء المعلمات الأساسية، وقواعد التسعير، ومدخلًا نموذجيًا. تؤدي `category` أو `mode` غير المعروفة إلى `400 invalid_parameter`.

## تشغيل نموذج

```bash
curl -X POST "https://api.doitong.ru/v1/run/{model_id}?wait=20" \
  -H "Authorization: Bearer $DOITONG_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1842-cover" \
  -d '{"prompt": "..."}'
```

- الجسم هو مدخل النموذج، وهو كائن JSON. تسرد صفحة كل نموذج معلماته.
- يُتحقق من المدخل قبل فرض أي تكلفة. يعيد المدخل غير الصالح `422 invalid_input` مع `param` المخالف، ولا يكلّف شيئًا.
- يعلّق `?wait=N` (حتى 20 ثانية) الاستدعاء حتى ينتهي الطلب أو ينقضي الوقت.
- يرسل `?webhook_url=https://…` طلب POST موقّعًا إلى ذلك العنوان عند انتهاء الطلب (راجع [Webhooks](https://doitong.com/developers/docs/webhooks)).
- يحدد `?storage=permanent` أو `?storage=temporary` مدة الاحتفاظ بملفات المخرج؛ وبدونه يُطبّق إعداد الحساب (راجع [مكان حفظ الملفات](#storage)).

تكون الاستجابة `202 Accepted` ما دام الطلب قيد التنفيذ، و`200 OK` عند انتهائه ضمن مدة الانتظار (أو عندما يكون إعادة تشغيل، راجع أدناه). تحمل ترويساتا `Location` و`Doitong-Request-Id` عنوان الطلب ومعرّفه.

## الحالات

دورة حياة الطلب: `queued` → `running` → `succeeded` | `failed` | `canceled` (نهائي؛ تُسترد أرصدة API للطلبات الفاشلة والملغاة).

| الحالة | المعنى | نهائية |
|---|---|---|
| `queued` | قُبل وفُرضت تكلفته، وينتظر عاملًا. قد يعرض `queue_position` موضعه في الصف. | لا |
| `running` | النموذج يُنشئ المخرج. | لا |
| `succeeded` | اكتمل. تسرد `outputs` الملفات. | نعم |
| `failed` | أوقفه النموذج أو أحد الحدود. يوضح `error` السبب. تُسترد أرصدة API. | نعم |
| `canceled` | أُلغي قبل إنتاج نتيجة. تُسترد أرصدة API. | نعم |

يفشل الطلب الذي يتجاوز حده الزمني بالرمز `timeout` وتُسترد تكلفته: 15 دقيقة للصور، و60 دقيقة للفيديو، و30 دقيقة للصوت وكل ما عدا ذلك.

## كائن الطلب

```json
{
  "id": "req_8k2m4q7x1z9c3v5b6n0p2r4t",
  "object": "request",
  "model": "flux/schnell",
  "status": "succeeded",
  "created_at": "2026-10-20T12:00:00Z",
  "started_at": "2026-10-20T12:00:01Z",
  "completed_at": "2026-10-20T12:00:02Z",
  "queue_position": null,
  "cost": { "credits": 3, "usd": "0.003", "charged": 3, "refunded": 0 },
  "input": { "prompt": "..." },
  "output": { "images": [ { "url": "https://content.doitong.com/dev-api/…/0-output.jpeg", "width": 1024, "height": 768 } ] },
  "outputs": [
    { "type": "image", "url": "https://content.doitong.com/dev-api/…/0-output.jpeg", "content_type": "image/jpeg",
      "width": 1024, "height": 768, "file_size": 183920, "stored": true }
  ],
  "error": null,
  "metrics": { "inference_seconds": 1.2 },
  "storage": { "mode": "permanent", "bytes": 183920, "expires_at": null, "expired": false },
  "urls": {
    "self": "https://api.doitong.ru/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t",
    "cancel": "https://api.doitong.ru/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/cancel"
  }
}
```

- تكون `outputs` متطابقة لكل نموذج: إدخال واحد لكل ملف مُنشأ مع `type` (`image` أو `video` أو `audio` أو `file` أو `3d`)، و`url` على تخزيننا، و`content_type`، وعند معرفتها، `file_size` و`width` و`height` و`duration`.
- تكون `output` كائن النتيجة الخاص بالنموذج (تُسرد حقوله في صفحة كل نموذج) مع عناوين URL نفسها.
- توضّح `storage` كيفية حفظ الملفات: `mode` (`permanent` أو `temporary`)، و`bytes` المخزنة، و`expires_at` (وقت حذف الملف المؤقت، و`null` للملفات الدائمة)، و`expired` (`true` بعد زوال الملفات).
- تمثل `cost.credits` سعر الاستدعاء بأرصدة API (`cost.usd` بوحدة USD)، وتمثل `cost.charged` ما خُصم من رصيد API، وتمثل `cost.refunded` ما أُعيد. في نموذج `metered`، تمثل `cost.credits` الحد الأقصى المحتجز في البداية (`cost.held`)؛ وبعد نجاح التشغيل، توضح `cost.settled` قيمة الاستخدام، ويكون باقي الحد الأقصى في `cost.refunded` (راجع [الفوترة حسب الاستخدام](https://doitong.com/developers/docs/pricing#metered)).
- عند فشل الطلب، تكون `error` هي `{ "type": …, "code": …, "message": … }`.

## قراءة طلب

```bash
curl "https://api.doitong.ru/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t?wait=20" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

- تنفذ `?wait=N` (حتى 20 ثانية) استطلاعًا طويلًا: يعيد الاستدعاء النتيجة فور وصول الطلب إلى حالة نهائية، أو بعد N ثانية مع الحالة الحالية. ويُعد تكرار ذلك أبسط طريقة لانتظار النتيجة.
- تضيف `?logs=1` أسطر سجل تقدم النموذج (آخر 50 سطرًا) باسم `logs`.

يمكنك قراءة طلبات حسابك فقط؛ وأي معرّف آخر يعيد `404 request_not_found`.

## سرد الطلبات

```bash
curl "https://api.doitong.ru/v1/requests?limit=20&status=succeeded&model=flux/schnell" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

من الأحدث إلى الأقدم. تتراوح `limit` من 1 إلى 100 (الافتراضي 20)، وتقوم `status` و`model` بالتصفية. تكون الاستجابة `{ "object": "list", "data": [ … ], "has_more": true, "next_cursor": "req_…" }`؛ مرّر `cursor=<next_cursor>` للصفحة التالية.

## إلغاء طلب

```bash
curl -X POST "https://api.doitong.ru/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/cancel" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

- إذا أُلغي قبل بدء النموذج: تصبح الحالة `canceled`، وتُسترد أرصدة API، وتحصل على `200`.
- إذا كان النموذج يُنشئ المخرج بالفعل: يُمرر الإلغاء وتحصل على `202` مع `"cancel_requested": true`. وإذا انتهى النموذج رغم ذلك، ينجح الطلب بصورة طبيعية وتُفرض تكلفته.
- إذا كان الطلب نهائيًا بالفعل: `409 not_cancelable` (أما الطلب الذي حالته `canceled` فيعيد `200` ببساطة).

## حذف ملفات طلب

```bash
curl -X DELETE "https://api.doitong.ru/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/files" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

يحذف نسخنا من ملفات مخرج الطلب فورًا ويوقف رسوم تخزينها. تكون الاستجابة كائن الطلب مع `storage.expired: true`؛ وتبقى عناوين URL الخاصة به في السجل لكنها لا تعود تعمل. لا يغيّر استدعاؤه مرة أخرى شيئًا (`200`). لا يملك الطلب الذي لا يزال `queued` أو `running` ملفات بعد: `409 request_active`. يتطلب `models:run`.

## قابلية التكرار: إعادة المحاولة دون الدفع مرتين

قد تفشل الشبكات. لإعادة محاولة تشغيل بأمان، أرسل ترويسة `Idempotency-Key` (أي سلسلة تصل إلى 255 حرفًا، وفريدة لكل عملية، مثل معرّف طلبك الخاص):

- المفتاح نفسه والجسم نفسه كما سبق: تحصل على الطلب الأصلي مجددًا (`200`، والترويسة `Idempotent-Replayed: true`)، ولا تُفرض أي تكلفة مرة أخرى.
- المفتاح نفسه والجسم نفسه بعد تشغيل فشل قبل وصوله إلى النموذج (`upstream_error` أو `internal_error` عند الإرسال، أو `insufficient_credits` أو `budget_exceeded` أو `too_many_inflight`): لم يُنتج شيء ولم تُفرض تكلفة، لذا تعيد المحاولة تشغيل النموذج بدلًا من إعادة الفشل.
- المفتاح نفسه مع جسم مختلف: `409 idempotency_mismatch`.
- ترتبط المفاتيح بمفتاح API الذي أرسلها.

## مكان حفظ الملفات

يُنسخ كل ملف مخرج إلى تخزيننا قبل وضع علامة `succeeded` على الطلب، لذلك تكون عناوين URL في `outputs` على مضيفاتنا ويمكنك الربط بها مباشرة. وتختار أنت مدة بقائها:

| الوضع | المدة | السعر |
|---|---|---|
| `permanent` (افتراضي) | حتى تحذفها | 100 أرصدة API (⁨‏0.10 $⁩) لكل GB شهريًا، تُفرض يوميًا من رصيد API |
| `temporary` | 7 يومًا، ثم تُحذف | مجانًا |

- يحدد إعداد الحساب ما يحدث للطلبات الجديدة: مفتاح التبديل "الاحتفاظ بالملفات إلى الأبد" في [لوحة التحكم](https://doitong.com/developers/dashboard#balance)، أو `PATCH https://api.doitong.ru/v1/account/storage` مع `{"mode": "temporary"}`. يعرض `GET https://api.doitong.ru/v1/account` الإعداد ضمن `storage`، مع وحدات البايت التي تحتفظ بها والتقدير الشهري.
- يتجاوز `?storage=permanent|temporary` في التشغيل (وسيطة `storage` لأداة MCP `run`) الإعداد لذلك التشغيل.
- لا يلمس تغيير الإعداد الملفات الموجودة لديك؛ احذفها باستخدام [`DELETE /requests/{id}/files`](#delete-files).
- عندما يتعذر على رصيد API دفع تكلفة التخزين، لا تُفرض أي تكلفة وتتلقى بريدًا إلكترونيًا: اشحن الرصيد خلال 30 يومًا، وإلا تصبح الملفات المحتفظ بها مؤقتة وتُحذف بعد 7 يومًا.

في الحالة النادرة التي تفشل فيها عملية النسخ لدينا، يحتوي الإدخال على `"stored": false` ويكون عنوان URL هو الأصلي قصير الصلاحية: نزّله قريبًا.
