เอกสาร API
หน้านี้คือสัญญาที่ API ให้ไว้ — สำหรับตอนที่บางอย่างไม่เป็นอย่างที่คิด ส่วนหน้าคีย์คือจุดเริ่มต้นที่มีของให้ก๊อปไปวางได้เลย คำสั่งและชื่อฟิลด์เป็นภาษาอังกฤษเพราะมันมีคำสะกดที่ถูกอยู่แบบเดียว
ไปสร้างคีย์ทุกจำนวนเป็นเศษหนึ่งส่วนร้อยของดาว
50 หมายถึง 0.50 ดาว · 200 หมายถึง 2.00 · เป็นจำนวนเต็มเสมอ ไม่มีทศนิยม อย่าหารก่อนเทียบสองค่า และอย่าเดาราคา — อ่านจาก /api/catalog ทุกครั้ง
ราคา
อ่านสดจาก /api/catalog ตอนคุณเปิดหน้านี้ ราคาแก้ได้จากคอนโซลตลอดเวลา ตัวเลขที่พิมพ์ค้างไว้จึงยังถูกอยู่นานหลังจากเลิกเป็นความจริงแล้ว
ราคาของการขยายภาพไม่อยู่ในตารางนี้ — มันผูกกับผลงานที่เสร็จแล้วแต่ละชิ้น และกลับมาพร้อมผลงานนั้นใน upscales[] ของ GET /api/projects/<id> หรือจาก tool ชื่อ estimate ถ้าคุณต่อผ่าน MCP
สั่ง แล้วรอ แล้วเอาไฟล์
สามคำสั่งนี้คือทั้งหมด ก๊อปไปวางในเทอร์มินัลได้เลย เปลี่ยนแค่คีย์กับ job id
สั่งทำ
curl -X POST https://gentook.example/api/generate \
-H "Authorization: Bearer <วางคีย์ของคุณตรงนี้>" \
-H "Content-Type: application/json" \
-d '{"model":"image-nano2","prompt":"a red maple leaf on white paper"}'
# 202 {"jobs":[{"id":"cm…","status":"running","error":null}]}
# 502 the SAME shape, with a sentence in each job's "error".รอให้เสร็จ
# Holds the connection for up to about 50 seconds and answers either way.
# "done": false means carry on — not an error, not a timeout.
curl https://gentook.example/api/jobs/<id>/wait -H "Authorization: Bearer <วางคีย์ของคุณตรงนี้>"
# {"id":"cm…","status":"running","done":false, …}
# {"id":"cm…","status":"completed","done":true,"url":"…","availableUntil":"…"}
# The plain read, if you would rather run your own loop. Every 3 seconds; no faster.
curl https://gentook.example/api/jobs/<id> -H "Authorization: Bearer <วางคีย์ของคุณตรงนี้>"เอาไฟล์ออกมา
# Follow redirects — and be ready for the body to arrive directly instead,
# which is what happens for a result the provider serves with a credential.
curl -L https://gentook.example/api/jobs/<id>/url \
-H "Authorization: Bearer <วางคีย์ของคุณตรงนี้>" -o result.jpg
# 410 {"error":"…","code":"windowClosed"} once it is past availableUntilทำไมต้องอ่านซ้ำ
ที่นี่ไม่มีตัววิ่งงานเบื้องหลัง — การอ่านงานคือสิ่งที่ทำให้งานเดิน ยิงแล้วปล่อยทิ้งไว้ งานจะค้างจนหมดอายุ 20 นาทีแล้วถูกยกเลิก ใช้ /wait ดีที่สุดเพราะมันค้างสายรอให้แทน ถ้าอยากเขียนลูปเองให้อ่านทุก 3 วินาที อย่าถี่กว่านั้น · การรอไม่คิดเงิน และงานที่ล้มไม่หักดาว
หกอย่างที่สั่งได้
จำนวนภาพที่แนบคือสิ่งที่บอกว่ากำลังสั่งอะไร · ส่งชื่อโหมดมาใน params.mode และมันต้องตรงกับจำนวนภาพ ไม่ตรงคือถูกปฏิเสธก่อนหักดาว ไม่ใช่รู้ทีหลังตอนได้ของผิด
t2v 0 images a clip from words alone i2v 1 image that picture is the opening frame interp 2 images opening and closing frames; the clip travels between r2v 1-3 images things to look like t2i 0 images a picture from words alone r2i 1-10 images things to look like every clip runs 8 seconds, whichever mode made it
ทาง MCP ไม่ต้องบอกชื่อโหมด — ส่งภาพมาแล้วบอกว่าเอาไปทำอะไรด้วย use: frames (ภาพคือตำแหน่งในคลิป) หรือ references (ภาพคือสิ่งที่อยากให้หน้าตาเป็นแบบนั้น) ที่เหลือระบบนับให้เอง จึงสั่งชุดที่ไม่มีอยู่จริงไม่ได้เลย
ส่งภาพเข้าไป
ส่งเป็นลิงก์หรือเป็น handle ที่เก็บไว้แล้ว อย่าส่งเป็นไบต์ · เพดานคือ 3,670,016 ตัวอักษรรวมทุกใบในคำขอเดียว ไม่ใช่ต่อใบ และ base64 ทำให้ใหญ่ขึ้นราว 1.37 เท่า · เกินแล้วเราเป็นคนปฏิเสธเอง ด้วยคำของเราและรหัส imagesTooLarge ซึ่งตั้งใจให้ต่ำกว่าเพดานของโฮสต์ เพราะถ้าปล่อยให้โฮสต์ปฏิเสธ คุณจะได้หน้าเปล่าที่ไม่มีใครที่นี่เขียน
ระวังตรงนี้: ref:x โคลอนเดียว คือ handle ที่เก็บไว้ · ref://x สองสแลช คือ control string คนละความหมายกันคนละขั้ว ต่างกันแค่สแลช · ส่วนสตริงที่ไม่ตรง prefix ไหนเลย รวมลิงก์ https:// ธรรมดา จะถูกนับเป็นไฟล์อัปโหลด ซึ่งใช้ได้ปกติ — พออ่านงานครั้งแรก ระบบจะจำมันเป็น handle ให้เอง แล้วลองใหม่ได้ · ที่ลองใหม่ไม่ได้คืองานที่ตายก่อนผู้ให้บริการจะรายงานอะไรกลับมา เพราะไม่เหลืออะไรให้ส่งซ้ำ
ส่งรูปจากเครื่องเข้ามา
POST /api/uploads พร้อมไฟล์ · ส่งได้สองแบบ multipart ฟิลด์ชื่อ file หรือ raw body ที่ตั้ง content-type เป็น image/… · ตอบกลับเป็น {"id":"file:…"} เอา id นั้นใส่ใน images ได้เลย เหมือน ref: ทุกอย่าง · รับ JPEG PNG WebP GIF โดยดูจากเนื้อไฟล์จริง ไม่ใช่จากชนิดที่ประกาศมา
curl -F [email protected] -H "Authorization: Bearer <วางคีย์ของคุณตรงนี้>" https://gentook.example/api/uploads
-> {"id":"file:k7m2x9p…","size":812340,"mimeType":"image/jpeg"}ทำไมต้องมี: ทางเดิมคือใส่ base64 ลงในคำขอ ซึ่งเบราว์เซอร์ทำได้สบายเพราะหน้าเว็บถือไบต์ไว้ให้ แต่ agent ทำไม่ได้ — ทุก tool call คือตัวอักษรที่มันต้องพิมพ์เอง และรูป 768px คือหกหมื่นตัวอักษร · มีคนออกแบบคลิปใหม่ทั้งเรื่องให้ไม่มีหน้าคนสักเฟรม เพราะแนบรูปเดียวไม่ได้ · ทาง MCP ขอ transfer_ticket แบบ upload แล้วจะได้คำสั่ง curl ที่ไม่ต้องมีคีย์ ไฟล์วิ่งจากดิสก์มาที่เราตรงๆ ไม่ผ่านตัว agent เลย
รูปที่อัปเข้ามาเป็นห้องพักคอย ไม่ใช่คลัง · พองานแรกที่ใช้มันเสร็จ ผู้ให้บริการจะคืนรหัสมา ระบบสลับ handle เป็น ref: ให้เอง แล้วสำเนาฝั่งเราก็เลิกจำเป็น · เก็บได้พร้อมกันสูงสุด 20 ใบที่ยังไม่ได้ใช้ และของเก่ากว่าเจ็ดวันที่ไม่มีงานค้างอ้างถึงจะถูกกวาดทิ้ง
ไม่มีช่อง negative prompt
อยากไม่ให้มีอะไร เขียนลงในคำสั่งปกติเลย เช่น "ชามผลไม้บนโต๊ะไม้ ไม่เอาสีแดง" · ตัวเจนที่อยู่ข้างหลังนี่อ่านประโยคเดียว ไม่มีช่องที่สอง
ถามผู้ให้บริการตรง ๆ แล้ว: มันรับ negativePrompt โดยไม่บ่น แต่มันก็รับชื่อฟิลด์ที่ไม่มีใครเคยเขียนขึ้นมาเหมือนกัน การรับจึงแปลว่าอ่านบอดี้ออกเท่านั้น ไม่ได้แปลว่ารองรับ · ในเอกสารของมันก็ไม่มีคำนี้ และคำขอเดิมเป๊ะสองครั้งยังได้คนละภาพ จึงไม่มีทางวัดว่ามันทำอะไรหรือเปล่า · เขียนไว้ตรงนี้เพื่อจะได้ไม่มีใครต้องเสียเวลาไปหาซ้ำ
เมื่องานล้ม
อ่าน errorKind ไม่ใช่ error · error คือคำพูดของ gateway เอง เอาไว้ให้คนอ่าน ไม่ใช่เอาไว้ให้โปรแกรมแยกกรณี
- filtered
- คำที่ใช้ถูกปฏิเสธ ส่งซ้ำก็ถูกปฏิเสธอีก ต้องเปลี่ยนคำ อย่าลองใหม่
- busy
- ตัวเจนปฏิเสธรอบนี้ชั่วคราว รออีกนาทีแล้วลองใหม่ ไม่เกินสองครั้ง
- timeout
- ใช้เวลานานเกิน ลองใหม่หนึ่งครั้ง หรือขอของที่ง่ายกว่า
- refGone
- ภาพที่ใช้เป็นต้นทางหายถาวร อย่าลองใหม่ ให้เจนใหม่ทั้งชิ้น
- refUnreachable
- ดึงภาพต้นทางไม่ได้ในรอบนี้ ลองใหม่หนึ่งครั้งแล้วหยุด
- failed
- ไม่เข้ารูปแบบไหนเลย เอาข้อความใน error ให้คนอ่านแล้วหยุด
รหัสความผิดพลาด
ความล้มเหลวเป็น JSON ที่มี error เสมอ และ ส่วนใหญ่ มี code มาด้วย — แต่ไม่ใช่ทุกครั้ง การปฏิเสธเพราะคำขอผิดรูปทั่วไปมีแต่ error เปล่า ๆ · และ 502 ของ POST /api/generate เป็นอีกแบบ มันรายงานแยกรายงาน โดยใส่ไว้ใน jobs[].error ของแต่ละงาน ไม่ใช่ที่ระดับบนสุด · รหัสที่คุณไม่รู้จัก และกรณีที่ไม่มีรหัสมาเลย ให้ถือว่า “หยุดแล้วบอกคน” เสมอ ห้ามถือว่าลองใหม่ได้
- imagesTooLarge
- ภาพที่แนบมารวมกันใหญ่เกินเพดาน ส่งเป็นลิงก์หรือ handle แทนไบต์
- notEnoughStars
- ดาวไม่พอ ไปเติมที่หน้าเว็บ อย่าลองใหม่
- keyDailyCap
- คีย์ใบนี้ชนเพดานรายวันที่เจ้าของตั้งไว้ รอวันถัดไป
- maintenance
- ปิดปรับปรุงชั่วคราว คีย์ไม่ได้มีปัญหา ลองใหม่ทีหลัง
- signin
- อ่านคีย์จาก header ไม่ได้เลย ตรวจว่าเป็น Authorization: Bearer <คีย์> เป๊ะ ๆ
- apiKey
- คีย์ผิดหรือถูกเพิกถอนแล้ว หยุดแล้วบอกคน
- apiKeyScope
- คีย์ใบนี้ไม่ได้รับสิทธิ์นั้น หยุด อย่าลองใหม่
- suspended
- บัญชีนี้ถูกระงับ หยุดแล้วบอกคน
- windowClosed
- ผลงานพ้นหน้าต่างเวลาแล้ว ต้องเจนใหม่
- linkExpired
- ที่เก็บไฟล์ฝั่งผู้ให้บริการไม่ต่ออายุลิงก์ให้ รออีกนาทีแล้วอ่านงานใหม่ ถ้ายังเป็นอีกต้องเจนใหม่
- download
- ดึงไฟล์ไม่ได้ในตอนนี้ ลองใหม่หนึ่งครั้ง
- provider
- ตัวเจนกำลังยุ่ง ลองใหม่ในอีกนาที
- server
- ฝั่งเราพัง ลองใหม่หนึ่งครั้งแล้วหยุด
ต่อผ่าน MCP
ค่าที่ก๊อปไปวางได้อยู่ในหน้าคีย์ ทั้งของ Claude Code, Codex และแอปที่ตั้งค่าด้วยไฟล์ JSON · ส่วนแอปที่พูดได้แต่ stdio ให้ผ่านตัวกลางข้างล่างนี้ ไม่ต้องแก้อะไรฝั่งเรา
สำหรับแอปที่รองรับแต่ stdio
npx mcp-remote https://gentook.example/api/mcp --header "Authorization: Bearer <วางคีย์ของคุณตรงนี้>"