# คำขอ

คำขอคือการเรียกใช้โมเดลหนึ่งครั้ง โดยมี id (`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` | คำทั้งหมดที่ต้องปรากฏในชื่อ, id, ผู้สร้าง หรือแท็ก เช่น `kling 3` |
| `category` | id ของหมวดหมู่หนึ่งรายการ เช่น `text-to-video` หรือ `upscale` `GET https://api.doitong.ru/v1/categories` จะแสดงทั้ง 21 รายการพร้อมจำนวนของแต่ละรายการ |
| `lab` | ผู้สร้างโมเดล โดยใช้ชื่อหรือ id เช่น `Google` หรือ `black-forest-labs` |
| `family` | id ของ `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 Schema อินพุตและเอาต์พุตฉบับเต็ม ชื่อพารามิเตอร์มาตรฐาน กฎราคา และตัวอย่างอินพุต หากไม่รู้จัก `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 ที่ลงลายเซ็นไปยัง URL ดังกล่าวเมื่อคำขอเสร็จสิ้น (ดู [เว็บฮุก](https://doitong.com/developers/docs/webhooks))
- `?storage=permanent` หรือ `?storage=temporary` ใช้เลือกว่าจะเก็บไฟล์เอาต์พุตไว้นานเท่าใด หากไม่ระบุ จะใช้การตั้งค่าบัญชี (ดู [ที่เก็บไฟล์](#storage))

การตอบกลับจะเป็น `202 Accepted` ขณะที่คำขอยังทำงานอยู่ และเป็น `200 OK` เมื่อเสร็จสิ้นภายในเวลาที่รอ (หรือเมื่อเป็นการเล่นซ้ำ ดูด้านล่าง) ส่วนหัว `Location` และ `Doitong-Request-Id` จะมี URL และ id ของคำขอ

## สถานะ

วงจรการทำงานของคำขอ: `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.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 วินาที) จะทำ long-polling: การเรียกใช้จะส่งกลับทันทีที่คำขอสิ้นสุด หรือหลังจาก N วินาทีพร้อมสถานะปัจจุบัน การวนเรียกวิธีนี้เป็นวิธีที่ง่ายที่สุดในการรอผลลัพธ์
- `?logs=1` จะเพิ่มบรรทัดบันทึกความคืบหน้าของโมเดล (50 รายการล่าสุด) ในรูป `logs`

คุณอ่านได้เฉพาะคำขอของบัญชีของคุณเองเท่านั้น หากเป็น id อื่นจะส่งคืน `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: ลองใหม่โดยไม่จ่ายซ้ำ

เครือข่ายอาจล้มเหลว หากต้องการลองทำงานใหม่อย่างปลอดภัย ให้ส่งส่วนหัว `Idempotency-Key` (สตริงใดๆ ยาวไม่เกิน 255 อักขระ ต้องไม่ซ้ำกันต่อการดำเนินการ เช่น id คำสั่งซื้อของคุณเอง):

- คีย์เดิมและเนื้อหาคำขอเดิม: คุณจะได้รับคำขอเดิมกลับมา (`200`, ส่วนหัว `Idempotent-Replayed: true`) และไม่มีการเรียกเก็บเงินซ้ำ
- คีย์เดิมและเนื้อหาคำขอเดิมหลังจากการทำงานล้มเหลวก่อนถึงโมเดล (`upstream_error` หรือ `internal_error` ขณะส่ง, `insufficient_credits`, `budget_exceeded`, `too_many_inflight`): ไม่มีการสร้างผลลัพธ์และไม่มีการเรียกเก็บเงิน ดังนั้นการลองใหม่จะเรียกใช้โมเดลอีกครั้งแทนการส่งคืนข้อผิดพลาด
- คีย์เดิมแต่เนื้อหาคำขอต่างกัน: `409 idempotency_mismatch`
- คีย์จะมีขอบเขตตามคีย์ API ที่ส่งคีย์นั้น

## ที่เก็บไฟล์

ไฟล์เอาต์พุตทุกไฟล์จะถูกคัดลอกไปยังพื้นที่จัดเก็บของเราก่อนทำเครื่องหมายว่าคำขอ `succeeded` ดังนั้น URL ใน `outputs` จึงอยู่บนโฮสต์ของเราเอง และคุณสามารถใช้ลิงก์ไปยัง URL เหล่านั้นได้โดยตรง ระยะเวลาที่เก็บไว้ขึ้นอยู่กับคุณ:

| โหมด | ระยะเวลา | ราคา |
|---|---|---|
| `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 จะเป็น URL ต้นฉบับที่มีอายุสั้น: ให้ดาวน์โหลดโดยเร็ว
