# রিকোয়েস্ট

একটি রিকোয়েস্ট হলো একটি মডেলের একটি কল। এতে একটি আইডি (`req_…`), একটি স্ট্যাটাস, API ক্রেডিটে এর খরচ (1000 = 1 USD), এবং সফল হলে জেনারেট করা ফাইল থাকে। নিচের প্রতিটি এন্ডপয়েন্টে, প্রতিটি মডেলের জন্য একই অবজেক্ট ফেরত আসে।

## একটি মডেল খুঁজুন

সব ১,৪৯৬টি মডেলের ক্যাটালগ পাবলিক JSON (কোনো কী প্রয়োজন নেই):

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

| কোয়েরি প্যারামিটার | অর্থ |
|---|---|
| `q` | নাম, আইডি, নির্মাতা বা ট্যাগে অবশ্যই থাকা সব শব্দ; উদাহরণস্বরূপ `kling 3`। |
| `category` | একটি ক্যাটাগরি আইডি, যেমন `text-to-video` বা `upscale`। `GET https://api.doitong.com/v1/categories` তাদের সংখ্যা-সহ সব ২১টি তালিকাভুক্ত করে। |
| `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` অবজেক্ট থাকে ([Pricing](https://doitong.com/developers/docs/pricing#price-objects) দেখুন)। `GET https://api.doitong.com/v1/models/{model_id}` সম্পূর্ণ ইনপুট ও আউটপুট JSON Schema, ক্যানোনিক্যাল প্যারামিটারের নাম, মূল্যের নিয়ম এবং একটি উদাহরণ ইনপুট যোগ করে। অজানা `category` বা `mode` হলে `400 invalid_parameter` ফেরত আসে।

## একটি মডেল চালান

```bash
curl -X POST "https://api.doitong.com/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 অবজেক্ট। প্রতিটি মডেল পেজে এর প্যারামিটার তালিকাভুক্ত থাকে।
- কোনো কিছুতে চার্জ করার আগে ইনপুট যাচাই করা হয়। অবৈধ ইনপুট হলে আপত্তিকর `param`-সহ `422 invalid_input` ফেরত আসে এবং কোনো খরচ হয় না।
- `?wait=N` (সর্বোচ্চ 20 সেকেন্ড) রিকোয়েস্ট শেষ হওয়া বা সময় শেষ হওয়া পর্যন্ত কলটি ধরে রাখে।
- `?webhook_url=https://…` রিকোয়েস্ট শেষ হলে ওই URL-এ একটি স্বাক্ষরিত POST পাঠায় ([Webhooks](https://doitong.com/developers/docs/webhooks) দেখুন)।
- `?storage=permanent` বা `?storage=temporary` আউটপুট ফাইল কতক্ষণ রাখা হবে তা নির্ধারণ করে; এটি না দিলে অ্যাকাউন্টের সেটিং প্রযোজ্য হয় ([ফাইল কোথায় থাকে](#storage) দেখুন)।

রিকোয়েস্ট কাজ চলাকালীন রেসপন্স হলো `202 Accepted`, আর অপেক্ষার মধ্যে শেষ হলে (অথবা এটি রিপ্লে হলে, নিচে দেখুন) `200 OK`। `Location` এবং `Doitong-Request-Id` হেডারে রিকোয়েস্টের URL ও আইডি থাকে।

## স্ট্যাটাস

অনুরোধের জীবনচক্র: `queued` → `running` → `succeeded` | `failed` | `canceled` (চূড়ান্ত; ব্যর্থ ও বাতিল করা রিফান্ড করা হয়).

| স্ট্যাটাস | অর্থ | চূড়ান্ত |
|---|---|---|
| `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.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t",
    "cancel": "https://api.doitong.com/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.com/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.com/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.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/cancel" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

- মডেল শুরু হওয়ার আগে বাতিল হলে: স্ট্যাটাস `canceled` হয়, API ক্রেডিট ফেরত দেওয়া হয় এবং আপনি `200` পান।
- ইতিমধ্যে জেনারেট হলে: বাতিলের অনুরোধটি পাঠানো হয় এবং আপনি `"cancel_requested": true`-সহ `202` পান। মডেল তবুও শেষ হয়ে গেলে রিকোয়েস্ট স্বাভাবিকভাবে সফল হয় এবং চার্জ করা হয়।
- ইতিমধ্যে চূড়ান্ত হলে: `409 not_cancelable` (ইতিমধ্যে `canceled` হওয়া রিকোয়েস্ট শুধু `200` ফেরত দেয়)।

## একটি রিকোয়েস্টের ফাইল মুছুন

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

রিকোয়েস্টের আউটপুট ফাইলের আমাদের কপিগুলো এখনই মুছে দেয় এবং স্টোরেজ চার্জ বন্ধ করে। রেসপন্স হলো `storage.expired: true`-সহ রিকোয়েস্ট অবজেক্ট; রেকর্ডে URL থাকলেও সেগুলো আর কাজ করে না। আবার কল করলে কোনো পরিবর্তন হয় না (`200`)। `queued` বা `running` অবস্থার রিকোয়েস্টে এখনও কোনো ফাইল নেই: `409 request_active`। `models:run` প্রয়োজন।

## Idempotency: দুবার অর্থ না দিয়ে আবার চেষ্টা

নেটওয়ার্ক ব্যর্থ হতে পারে। নিরাপদে রান আবার চেষ্টা করতে `Idempotency-Key` হেডার পাঠান (255 অক্ষর পর্যন্ত যেকোনো স্ট্রিং, প্রতি অপারেশনের জন্য ইউনিক; যেমন আপনার নিজস্ব অর্ডার আইডি):

- আগের মতো একই কী ও একই বডি: মূল রিকোয়েস্টটি ফেরত পাবেন (`200`, হেডার `Idempotent-Replayed: true`) এবং আবার কোনো চার্জ হবে না।
- মডেলে পৌঁছানোর আগে ব্যর্থ হওয়া রানের পর একই কী ও বডি (`upstream_error` বা সাবমিটে `internal_error`, `insufficient_credits`, `budget_exceeded`, `too_many_inflight`): কিছু তৈরি হয়নি এবং কোনো চার্জ হয়নি, তাই ব্যর্থতা ফেরত না দিয়ে আবার মডেল চালানো হবে।
- ভিন্ন বডির সঙ্গে একই কী: `409 idempotency_mismatch`।
- কীগুলো যে API কী পাঠিয়েছে, তার আওতায় থাকে।

## ফাইল কোথায় থাকে

রিকোয়েস্টকে `succeeded` হিসেবে চিহ্নিত করার আগে প্রতিটি আউটপুট ফাইল আমাদের স্টোরেজে কপি করা হয়, তাই `outputs`-এর URL আমাদের নিজস্ব হোস্টে থাকে এবং আপনি সরাসরি সেগুলোর লিংক দিতে পারেন। কতক্ষণ থাকবে, তা আপনার পছন্দ:

| মোড | কতক্ষণ | মূল্য |
|---|---|---|
| `permanent` (ডিফল্ট) | আপনি মুছে ফেলা পর্যন্ত | প্রতি GB প্রতি মাসে ১০০ API ক্রেডিট (০.১০$), API ব্যালান্স থেকে দৈনিক চার্জ করা হয় |
| `temporary` | ৭ দিন, তারপর মুছে ফেলা হয় | বিনামূল্যে |

- নতুন রিকোয়েস্টের জন্য অ্যাকাউন্ট সেটিং নির্ধারক: [ড্যাশবোর্ড](https://doitong.com/developers/dashboard#balance)-এর "ফাইল চিরকাল সংরক্ষণ করুন" সুইচ, অথবা `PATCH https://api.doitong.com/v1/account/storage`-এ `{"mode": "temporary"}`। `GET https://api.doitong.com/v1/account`-এর `storage`-এর অধীনে এটি দেখা যায়, সঙ্গে রাখা বাইট ও মাসিক আনুমানিক খরচ।
- একটি রানে `?storage=permanent|temporary` (MCP `run` টুলের `storage` আর্গুমেন্ট) সেই রানের জন্য এটিকে ওভাররাইড করে।
- সেটিং পরিবর্তন করলে আগে থেকে থাকা ফাইলগুলোর ওপর কোনো প্রভাব পড়ে না; [`DELETE /requests/{id}/files`](#delete-files) দিয়ে সেগুলো মুছুন।
- স্টোরেজের মূল্য দেওয়ার মতো API ব্যালান্স না থাকলে কোনো চার্জ হয় না এবং আপনি একটি ইমেইল পান: ৩০ দিনের মধ্যে টপ-আপ করুন, অথবা রাখা ফাইলগুলো অস্থায়ী হয়ে যাবে এবং ৭ দিন পর মুছে ফেলা হবে।

বিরল ক্ষেত্রে আমাদের কপি ব্যর্থ হলে, এন্ট্রিতে `"stored": false` থাকে এবং URL-টি মূল, স্বল্পস্থায়ী URL হয়: দ্রুত ডাউনলোড করুন।
