{"openapi":"3.0.3","info":{"title":"Chợ.video API","version":"1.0.0","description":"Public, self-serve API for Creators (post prompts, receive videos) and Makers (claim prompts, deliver videos). Create keys in the workspace → API. Docs: https://cho.video/docs.html"},"servers":[{"url":"https://cho.video"}],"security":[{"bearer":[]}],"tags":[{"name":"Account"},{"name":"Webhooks"},{"name":"Creator"},{"name":"Maker"}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"cvapi_…"}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","example":"NOT_FOUND"},"message":{"type":"string"}}}}},"Slot":{"type":"object","properties":{"slot":{"type":"integer","minimum":1,"maximum":3},"slotCode":{"type":"string"},"status":{"type":"string","enum":["open","claimed","review","accepted","cancelled","closed"]},"rawStatus":{"type":"string"},"assignmentId":{"type":"integer"},"expiresAt":{"type":"string","format":"date-time","nullable":true},"reason":{"type":"string","nullable":true},"lastResult":{"type":"string","description":"When the slot went back to the market: released | expired | revoked | exhausted | rejected | reported"},"submissionId":{"type":"integer","description":"Accepted video"}}},"PromptInput":{"type":"object","required":["prompt","secs"],"properties":{"externalRef":{"type":"string","pattern":"^[A-Za-z0-9:._-]{3,120}$","description":"Your own id. Unique per account; sending the same ref again is an upsert (same content → reused, changed content → updated while no Maker has claimed a slot, else 409 LOCKED)."},"prompt":{"type":"string","maxLength":20000},"secs":{"type":"integer","enum":[15,30]},"videos":{"type":"integer","minimum":1,"maximum":3,"description":"Number of video slots (V1–V3)"},"title":{"type":"string","maxLength":80,"description":"Shown on the market before claiming — never put the full prompt here"},"short":{"type":"string","maxLength":160},"script":{"type":"string","maxLength":40},"stt":{"type":"integer"},"ctvPay":{"type":"integer","description":"Pay per video in VND (default from settings; must be ≥ the floor price)"},"special":{"type":"boolean"},"confirmations":{"type":"array","items":{"type":"boolean"},"description":"4 × true, required when special = true"},"refs":{"type":"array","maxItems":4,"items":{"type":"object","properties":{"base64":{"type":"string","description":"JPG/PNG/WEBP, ≤ 1 MB each, ≤ 1.4 MB total. Larger images: POST /creator/prompts/{id}/refs"}}}}}},"Prompt":{"type":"object","properties":{"code":{"type":"string"},"externalRef":{"type":"string","nullable":true},"lot":{"type":"object","nullable":true},"title":{"type":"string"},"secs":{"type":"integer"},"videos":{"type":"integer"},"ctvPay":{"type":"integer"},"status":{"type":"string","enum":["open","held","done","paused","removed"]},"cancelled":{"type":"boolean"},"slots":{"type":"array","items":{"$ref":"#/components/schemas/Slot"}},"prompt":{"type":"string","description":"Only on single-prompt responses"},"refs":{"type":"array","items":{"type":"object"}},"reused":{"type":"boolean"},"updated":{"type":"boolean"},"created":{"type":"boolean"}}},"Lot":{"type":"object","properties":{"id":{"type":"integer"},"code":{"type":"string"},"key":{"type":"string","nullable":true},"title":{"type":"string"},"status":{"type":"string","enum":["draft","open","closed","deleted"]},"deadlineAt":{"type":"string","format":"date-time","nullable":true}}},"Video":{"type":"object","properties":{"submissionId":{"type":"integer"},"jobCode":{"type":"string"},"externalRef":{"type":"string","nullable":true},"slot":{"type":"integer"},"slotCode":{"type":"string"},"acceptedAt":{"type":"string","format":"date-time"},"sha256":{"type":"string"},"bytes":{"type":"integer"},"duration":{"type":"number"},"width":{"type":"integer"},"height":{"type":"integer"},"downloadUrl":{"type":"string","nullable":true,"description":"Signed URL, valid 1 hour"}}},"MarketItem":{"type":"object","description":"Same fields the market page shows. Never contains the full prompt.","properties":{"code":{"type":"string"},"title":{"type":"string"},"short":{"type":"string"},"secs":{"type":"integer"},"videos":{"type":"integer"},"ctvPay":{"type":"integer"},"remaining":{"type":"integer"},"refs":{"type":"integer"},"blocked":{"type":"boolean","description":"You released / let this prompt expire before; ask a manager to allow a re-claim"},"lot":{"type":"object","nullable":true},"mine":{"type":"array","items":{"type":"object"}}}},"Assignment":{"type":"object","properties":{"assignmentId":{"type":"integer"},"jobCode":{"type":"string"},"slot":{"type":"integer"},"slotCode":{"type":"string"},"status":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"}}},"Webhook":{"type":"object","properties":{"id":{"type":"integer"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"lastSuccessAt":{"type":"string","nullable":true},"lastError":{"type":"string","nullable":true}}},"Event":{"type":"object","description":"Webhook body = one event. Headers: X-ChoVideo-Event, X-ChoVideo-Event-Id, X-ChoVideo-Timestamp, X-ChoVideo-Signature (sha256=HMAC-SHA256(secret, \"<timestamp>.<raw body>\")).","properties":{"id":{"type":"integer"},"kind":{"type":"string","enum":["slot.status","video.accepted","job.cancelled","assignment.status","submission.result","ping"]},"createdAt":{"type":"string","format":"date-time"}},"additionalProperties":true}}},"paths":{"/api/v1/me":{"get":{"tags":["Account"],"summary":"Who am I: account, key, effective scopes, limits","x-summary-vi":"Tài khoản, khoá, phạm vi đang dùng được, giới hạn","x-scope":"any","responses":{"200":{"description":"Account","content":{"application/json":{"schema":{"type":"object"},"example":{"account":{"id":7,"username":"nv.lan","name":"Lan","role":"staff","locale":"vi"},"key":{"id":4,"name":"CMS","prefix":"cvapi_Ab12Cd","scopes":["creator:*"],"effectiveScopes":["creator:*"]},"limits":{"perMinute":120,"claimsPerHour":30},"events":["slot.status","video.accepted","job.cancelled"]}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/events":{"get":{"tags":["Webhooks"],"summary":"Pull your own events (reconciliation if a webhook was missed)","x-summary-vi":"Kéo lại sự kiện của chính bạn (khi lỡ webhook)","x-scope":"any","parameters":[{"name":"after","in":"query","required":false,"description":"Return events with id > after","schema":{"type":"integer"}},{"name":"limit","in":"query","required":false,"description":"1–200 (default 100)","schema":{"type":"integer"}}],"responses":{"200":{"description":"Events","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"nextAfter":{"type":"string"}}},"example":{"data":[{"id":901,"kind":"slot.status","createdAt":"2026-10-15T09:00:00.000Z","externalRef":"story-77:scene-3","jobCode":"CV-1042","slot":2,"slotCode":"CV-1042-V2","status":"claimed","rawStatus":"holding"}],"nextAfter":"901"}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/webhooks":{"get":{"tags":["Webhooks"],"summary":"List webhooks","x-summary-vi":"Danh sách webhook","x-scope":"any","responses":{"200":{"description":"Webhooks","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}}},"example":{"data":[{"id":3,"url":"https://example.com/hooks/chovideo","events":["slot.status","video.accepted","job.cancelled"],"createdAt":"2026-10-15T08:00:00.000Z","lastSuccessAt":null,"lastError":null}]}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}},"post":{"tags":["Webhooks"],"summary":"Register a webhook (URL + secret + events)","x-summary-vi":"Đăng ký webhook (URL + bí mật + loại sự kiện)","x-scope":"any","x-idempotent":true,"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe key (8–128 chars). Same key + same body within 24 h replays the first successful response (header Idempotent-Replayed: true).","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","secret"],"properties":{"url":{"type":"string","description":"https:// public host"},"secret":{"type":"string","minLength":16,"maxLength":200},"events":{"type":"array","items":{"type":"string"},"description":"Default: every event your scopes allow"}}},"example":{"url":"https://example.com/hooks/chovideo","secret":"a-long-random-secret-you-keep","events":["slot.status","video.accepted","job.cancelled"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"},"example":{"id":3,"url":"https://example.com/hooks/chovideo","events":["slot.status","video.accepted","job.cancelled"],"createdAt":"2026-10-15T08:00:00.000Z","lastSuccessAt":null,"lastError":null}}}},"400":{"description":"Bad URL / secret / event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"BAD_INPUT","message":"Webhook phải dùng https://"}}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/webhooks/{id}":{"delete":{"tags":["Webhooks"],"summary":"Delete a webhook","x-summary-vi":"Xoá webhook","x-scope":"any","parameters":[{"name":"id","in":"path","required":true,"description":"Webhook id","schema":{"type":"string"},"example":"3"}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object"},"example":{"id":3,"deleted":true}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/webhooks/{id}/test":{"post":{"tags":["Webhooks"],"summary":"Send a signed \"ping\" event now","x-summary-vi":"Gửi thử sự kiện \"ping\" có chữ ký","x-scope":"any","parameters":[{"name":"id","in":"path","required":true,"description":"Webhook id","schema":{"type":"string"},"example":"3"}],"responses":{"200":{"description":"Result","content":{"application/json":{"schema":{"type":"object"},"example":{"eventId":950,"delivered":true,"error":null}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/creator/prompts":{"post":{"tags":["Creator"],"summary":"Create or upsert one prompt (idempotent by externalRef)","x-summary-vi":"Tạo hoặc cập nhật một prompt (theo externalRef)","x-scope":"creator:*","x-idempotent":true,"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe key (8–128 chars). Same key + same body within 24 h replays the first successful response (header Idempotent-Replayed: true).","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptInput"},"example":{"externalRef":"story-77:scene-3","title":"Cảnh 3 · chợ đêm","short":"Phố đêm, mưa nhẹ","prompt":"A rainy night market in Hanoi, handheld camera, 9:16…","secs":15,"videos":3,"script":"ST-77","stt":3}}}},"responses":{"200":{"description":"Same externalRef: reused (same content) or updated (changed content, nobody claimed yet)"},"201":{"description":"Created (201) or reused / updated (200)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Prompt"},"example":{"code":"CV-1042","externalRef":"story-77:scene-3","lot":{"id":12,"code":"LO-00012","title":"API"},"title":"Cảnh 3 · chợ đêm","short":"Phố đêm, mưa nhẹ","script":"ST-77","stt":3,"secs":15,"videos":3,"ctvPay":120000,"special":false,"status":"held","cancelled":false,"createdAt":"2026-10-15T08:00:00.000Z","slots":[{"slot":1,"slotCode":"CV-1042-V1","status":"accepted","rawStatus":"accepted","assignmentId":881,"expiresAt":null,"reason":null,"submissionId":5120},{"slot":2,"slotCode":"CV-1042-V2","status":"claimed","rawStatus":"holding","assignmentId":902,"expiresAt":"2026-10-16T09:00:00.000Z","reason":null},{"slot":3,"slotCode":"CV-1042-V3","status":"open"}],"refs":[{"id":31,"url":"https://storage.example/ref/....jpg?X-Amz-Signature=...","contentType":"image/jpeg"}],"prompt":"A rainy night market in Hanoi, handheld camera, 9:16…","created":true}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"BAD_INPUT","message":"Thời lượng chỉ 15 hoặc 30 giây"}}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"409":{"description":"externalRef locked (already claimed) or cancelled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"LOCKED","message":"The prompt already has a claimed slot and can no longer be changed"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}},"get":{"tags":["Creator"],"summary":"List your prompts with per-slot V1–V3 status","x-summary-vi":"Danh sách prompt của bạn kèm trạng thái từng suất V1–V3","x-scope":"creator:read","parameters":[{"name":"status","in":"query","required":false,"description":"open | held | done | paused | removed","schema":{"type":"string"}},{"name":"lot","in":"query","required":false,"description":"Lot id, LO-code or lot key","schema":{"type":"string"}},{"name":"externalRef","in":"query","required":false,"description":"Exact externalRef","schema":{"type":"string"}},{"name":"cursor","in":"query","required":false,"description":"nextCursor from the previous page","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1–100 (default 50)","schema":{"type":"integer"}}],"responses":{"200":{"description":"Page","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Prompt"}},"nextCursor":{"type":"string","nullable":true}}},"example":{"data":[{"code":"CV-1042","externalRef":"story-77:scene-3","lot":{"id":12,"code":"LO-00012","title":"API"},"title":"Cảnh 3 · chợ đêm","short":"Phố đêm, mưa nhẹ","script":"ST-77","stt":3,"secs":15,"videos":3,"ctvPay":120000,"special":false,"status":"held","cancelled":false,"createdAt":"2026-10-15T08:00:00.000Z","slots":[{"slot":1,"slotCode":"CV-1042-V1","status":"accepted","rawStatus":"accepted","assignmentId":881,"expiresAt":null,"reason":null,"submissionId":5120},{"slot":2,"slotCode":"CV-1042-V2","status":"claimed","rawStatus":"holding","assignmentId":902,"expiresAt":"2026-10-16T09:00:00.000Z","reason":null},{"slot":3,"slotCode":"CV-1042-V3","status":"open"}]}],"nextCursor":null}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/creator/prompts/{id}":{"get":{"tags":["Creator"],"summary":"Get one prompt (code CV-123 or your externalRef)","x-summary-vi":"Xem một prompt (mã CV-123 hoặc externalRef)","x-scope":"creator:read","parameters":[{"name":"id","in":"path","required":true,"description":"CV-code or externalRef","schema":{"type":"string"},"example":"story-77:scene-3"}],"responses":{"200":{"description":"Prompt","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Prompt"},"example":{"code":"CV-1042","externalRef":"story-77:scene-3","lot":{"id":12,"code":"LO-00012","title":"API"},"title":"Cảnh 3 · chợ đêm","short":"Phố đêm, mưa nhẹ","script":"ST-77","stt":3,"secs":15,"videos":3,"ctvPay":120000,"special":false,"status":"held","cancelled":false,"createdAt":"2026-10-15T08:00:00.000Z","slots":[{"slot":1,"slotCode":"CV-1042-V1","status":"accepted","rawStatus":"accepted","assignmentId":881,"expiresAt":null,"reason":null,"submissionId":5120},{"slot":2,"slotCode":"CV-1042-V2","status":"claimed","rawStatus":"holding","assignmentId":902,"expiresAt":"2026-10-16T09:00:00.000Z","reason":null},{"slot":3,"slotCode":"CV-1042-V3","status":"open"}],"refs":[{"id":31,"url":"https://storage.example/ref/....jpg?X-Amz-Signature=...","contentType":"image/jpeg"}],"prompt":"A rainy night market in Hanoi, handheld camera, 9:16…"}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"404":{"description":"Not yours / not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"NOT_FOUND","message":"Not found"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/creator/prompts/{id}/cancel":{"post":{"tags":["Creator"],"summary":"Cancel: close open slots (force: also cancel held slots, unpaid; refused while a video awaits review)","x-summary-vi":"Huỷ: đóng suất còn trống (force: huỷ cả suất đang giữ, không tính tiền; bị từ chối khi còn video chờ duyệt)","x-scope":"creator:*","x-idempotent":true,"parameters":[{"name":"id","in":"path","required":true,"description":"CV-code or externalRef","schema":{"type":"string"},"example":"CV-1042"},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe key (8–128 chars). Same key + same body within 24 h replays the first successful response (header Idempotent-Replayed: true).","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string"},"force":{"type":"boolean"}}},"example":{"reason":"Script changed","force":false}}}},"responses":{"200":{"description":"Prompt after cancel","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Prompt"},"example":{"code":"CV-1042","externalRef":"story-77:scene-3","lot":{"id":12,"code":"LO-00012","title":"API"},"title":"Cảnh 3 · chợ đêm","short":"Phố đêm, mưa nhẹ","script":"ST-77","stt":3,"secs":15,"videos":2,"ctvPay":120000,"special":false,"status":"held","cancelled":true,"createdAt":"2026-10-15T08:00:00.000Z","slots":[{"slot":1,"slotCode":"CV-1042-V1","status":"accepted","rawStatus":"accepted","assignmentId":881,"expiresAt":null,"reason":null,"submissionId":5120},{"slot":2,"slotCode":"CV-1042-V2","status":"claimed","rawStatus":"holding","assignmentId":902,"expiresAt":"2026-10-16T09:00:00.000Z","reason":null},{"slot":3,"slotCode":"CV-1042-V3","status":"open"}],"refs":[{"id":31,"url":"https://storage.example/ref/....jpg?X-Amz-Signature=...","contentType":"image/jpeg"}],"prompt":"A rainy night market in Hanoi, handheld camera, 9:16…"}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/creator/prompts/{id}/refs":{"post":{"tags":["Creator"],"summary":"Start a large reference image upload (presigned PUT, ≤ 10 MB)","x-summary-vi":"Bắt đầu tải ảnh tham chiếu lớn (link PUT ký sẵn, ≤ 10 MB)","x-scope":"creator:*","x-idempotent":true,"parameters":[{"name":"id","in":"path","required":true,"description":"CV-code or externalRef","schema":{"type":"string"},"example":"CV-1042"},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe key (8–128 chars). Same key + same body within 24 h replays the first successful response (header Idempotent-Replayed: true).","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["bytes","contentType"],"properties":{"bytes":{"type":"integer"},"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp"]}}},"example":{"bytes":2400000,"contentType":"image/jpeg"}}}},"responses":{"200":{"description":"PUT the file to uploadUrl with uploadHeaders, then call /creator/refs/{refId}/complete","content":{"application/json":{"schema":{"type":"object"},"example":{"refId":31,"uploadUrl":"https://storage.example/ref/…","uploadHeaders":{"Content-Type":"image/jpeg"},"expiresInSec":600}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/creator/refs/{refId}/complete":{"post":{"tags":["Creator"],"summary":"Finish a reference image upload (server re-checks size and type)","x-summary-vi":"Hoàn tất ảnh tham chiếu (máy chủ kiểm lại dung lượng và loại ảnh)","x-scope":"creator:*","x-idempotent":true,"parameters":[{"name":"refId","in":"path","required":true,"description":"Ref id","schema":{"type":"string"},"example":"31"},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe key (8–128 chars). Same key + same body within 24 h replays the first successful response (header Idempotent-Replayed: true).","schema":{"type":"string"}}],"responses":{"200":{"description":"Ready","content":{"application/json":{"schema":{"type":"object"},"example":{"refId":31,"status":"ready"}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/creator/lots":{"post":{"tags":["Creator"],"summary":"Create a lot of 1–100 prompts (idempotent by lot key; each item by externalRef, default \"<key>:<n>\")","x-summary-vi":"Tạo lô 1–100 prompt (theo key của lô; mỗi prompt theo externalRef)","x-scope":"creator:*","x-idempotent":true,"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe key (8–128 chars). Same key + same body within 24 h replays the first successful response (header Idempotent-Replayed: true).","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["key","title","items"],"properties":{"key":{"type":"string"},"title":{"type":"string"},"deadlineAt":{"type":"string","format":"date-time"},"publish":{"type":"boolean","default":true},"items":{"type":"array","items":{"$ref":"#/components/schemas/PromptInput"},"maxItems":100}}},"example":{"key":"story-77","title":"Story 77 — episode 1","deadlineAt":"2026-10-20T12:00:00Z","items":[{"externalRef":"story-77:scene-1","prompt":"…","secs":15,"videos":2},{"prompt":"…","secs":30}]}}}},"responses":{"201":{"description":"Lot + per-item result (ok / error)","content":{"application/json":{"schema":{"type":"object"},"example":{"lot":{"id":12,"code":"LO-00012","key":"story-77","title":"Story 77 — episode 1","status":"open","deadlineAt":"2026-10-20T12:00:00.000Z"},"items":[{"ok":true,"code":"CV-1042","externalRef":"story-77:scene-3","lot":{"id":12,"code":"LO-00012","title":"API"},"title":"Cảnh 3 · chợ đêm","short":"Phố đêm, mưa nhẹ","script":"ST-77","stt":3,"secs":15,"videos":3,"ctvPay":120000,"special":false,"status":"held","cancelled":false,"createdAt":"2026-10-15T08:00:00.000Z","slots":[{"slot":1,"slotCode":"CV-1042-V1","status":"accepted","rawStatus":"accepted","assignmentId":881,"expiresAt":null,"reason":null,"submissionId":5120},{"slot":2,"slotCode":"CV-1042-V2","status":"claimed","rawStatus":"holding","assignmentId":902,"expiresAt":"2026-10-16T09:00:00.000Z","reason":null},{"slot":3,"slotCode":"CV-1042-V3","status":"open"}],"refs":[{"id":31,"url":"https://storage.example/ref/....jpg?X-Amz-Signature=...","contentType":"image/jpeg"}],"prompt":"A rainy night market in Hanoi, handheld camera, 9:16…","created":true},{"ok":false,"externalRef":"story-77:2","error":{"code":"BAD_PRICE","message":"…"}}],"created":true}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}},"get":{"tags":["Creator"],"summary":"List your lots","x-summary-vi":"Danh sách lô của bạn","x-scope":"creator:read","parameters":[{"name":"limit","in":"query","required":false,"description":"1–200","schema":{"type":"integer"}}],"responses":{"200":{"description":"Lots","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Lot"}}}},"example":{"data":[{"id":12,"code":"LO-00012","key":"story-77","title":"Story 77","status":"open","deadlineAt":null,"prompts":2}]}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/creator/lots/{id}/publish":{"post":{"tags":["Creator"],"summary":"Open a lot on the market","x-summary-vi":"Mở lô lên chợ","x-scope":"creator:*","parameters":[{"name":"id","in":"path","required":true,"description":"Lot id, LO-code or key","schema":{"type":"string"},"example":"story-77"}],"responses":{"200":{"description":"Lot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Lot"},"example":{"id":12,"code":"LO-00012","key":"story-77","status":"open"}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/creator/lots/{id}/close":{"post":{"tags":["Creator"],"summary":"Close a lot (hidden from the market; slots in progress continue)","x-summary-vi":"Đóng lô (ẩn khỏi chợ; suất đang làm vẫn tiếp tục)","x-scope":"creator:*","parameters":[{"name":"id","in":"path","required":true,"description":"Lot id, LO-code or key","schema":{"type":"string"},"example":"story-77"}],"responses":{"200":{"description":"Lot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Lot"},"example":{"id":12,"code":"LO-00012","key":"story-77","status":"closed"}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/creator/videos":{"get":{"tags":["Creator"],"summary":"Accepted videos with signed download URLs (1 hour)","x-summary-vi":"Video đã đạt kèm link tải ký sẵn (1 giờ)","x-scope":"creator:read","parameters":[{"name":"prompt","in":"query","required":false,"description":"CV-code or externalRef","schema":{"type":"string"}},{"name":"cursor","in":"query","required":false,"description":"nextCursor","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1–100","schema":{"type":"integer"}},{"name":"includeDeleted","in":"query","required":false,"description":"true to include deleted files (no URL)","schema":{"type":"string"}}],"responses":{"200":{"description":"Page","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Video"}},"nextCursor":{"type":"string","nullable":true}}},"example":{"data":[{"submissionId":5120,"jobCode":"CV-1042","externalRef":"story-77:scene-3","lotCode":"LO-00012","slot":1,"slotCode":"CV-1042-V1","acceptedAt":"2026-10-15T10:12:00.000Z","sha256":"9f2c…","bytes":18234123,"duration":15.02,"width":1080,"height":1920,"fileDeleted":false,"downloadUrl":"https://storage.example/video/....mp4?X-Amz-Signature=...","urlExpiresInSec":3600}],"nextCursor":null}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/creator/videos/{id}":{"get":{"tags":["Creator"],"summary":"One accepted video with a fresh download URL","x-summary-vi":"Một video đạt kèm link tải mới","x-scope":"creator:read","parameters":[{"name":"id","in":"path","required":true,"description":"submissionId","schema":{"type":"string"},"example":"5120"}],"responses":{"200":{"description":"Video","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Video"},"example":{"submissionId":5120,"jobCode":"CV-1042","externalRef":"story-77:scene-3","lotCode":"LO-00012","slot":1,"slotCode":"CV-1042-V1","acceptedAt":"2026-10-15T10:12:00.000Z","sha256":"9f2c…","bytes":18234123,"duration":15.02,"width":1080,"height":1920,"fileDeleted":false,"downloadUrl":"https://storage.example/video/....mp4?X-Amz-Signature=...","urlExpiresInSec":3600}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"410":{"description":"File deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"VIDEO_DELETED","message":"Video đã bị xoá"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/maker/market":{"get":{"tags":["Maker"],"summary":"Open market (same fields as the market page; no full prompt before claiming)","x-summary-vi":"Chợ việc (giống trang Nhận việc; không có prompt đầy đủ trước khi nhận)","x-scope":"maker:read","responses":{"200":{"description":"Market","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MarketItem"}}}},"example":{"data":[{"code":"CV-1042","title":"Cảnh 3 · chợ đêm","short":"Phố đêm, mưa nhẹ","secs":15,"videos":3,"special":false,"script":"ST-77","stt":3,"ctvPay":120000,"remaining":1,"refs":2,"blocked":false,"lot":{"id":12,"code":"LO-00012","title":"API","deadlineAt":null},"mine":[],"createdAt":"2026-10-15T08:00:00.000Z"}]}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/maker/market/{code}":{"get":{"tags":["Maker"],"summary":"Preview one market item: summary, requirements, reference images (no prompt)","x-summary-vi":"Xem trước một việc: tóm tắt, yêu cầu, ảnh tham chiếu (không có prompt)","x-scope":"maker:read","parameters":[{"name":"code","in":"path","required":true,"description":"CV-code","schema":{"type":"string"},"example":"CV-1042"}],"responses":{"200":{"description":"Preview","content":{"application/json":{"schema":{"type":"object"},"example":{"code":"CV-1042","title":"Cảnh 3 · chợ đêm","short":"Phố đêm, mưa nhẹ","secs":15,"videos":3,"special":false,"ctvPay":120000,"remaining":1,"requirements":{"ratio":"9:16","secs":15,"tolerance":0.5,"dialogue":true,"noText":true},"refs":[]}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/maker/claims":{"post":{"tags":["Maker"],"summary":"Claim slots (same hold limit as the UI + claims-per-hour cap). All or nothing.","x-summary-vi":"Nhận suất (cùng hạn mức giữ việc như giao diện + trần số suất mỗi giờ). Tất cả hoặc không gì.","x-scope":"maker:*","x-idempotent":true,"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe key (8–128 chars). Same key + same body within 24 h replays the first successful response (header Idempotent-Replayed: true).","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string"},"count":{"type":"integer","minimum":1,"maximum":3},"items":{"type":"array","maxItems":10,"items":{"type":"object","properties":{"code":{"type":"string"},"count":{"type":"integer"}}}}}},"example":{"items":[{"code":"CV-1042","count":1},{"code":"CV-1043","count":2}]}}}},"responses":{"201":{"description":"Claimed","content":{"application/json":{"schema":{"type":"object","properties":{"assignments":{"type":"array","items":{"$ref":"#/components/schemas/Assignment"}}}},"example":{"assignments":[{"assignmentId":902,"jobCode":"CV-1042","slot":2,"slotCode":"CV-1042-V2","status":"holding","expiresAt":"2026-10-16T09:00:00.000Z","claimedAt":"2026-10-15T09:00:00.000Z"}],"created":true}}}},"400":{"description":"Hold limit / taken / closed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"LIMIT","message":"Bạn đang giữ đủ 20 prompt. Nộp hoặc trả bớt việc trước."}}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/maker/assignments":{"get":{"tags":["Maker"],"summary":"Your slots (active, or all from the last 7 days)","x-summary-vi":"Suất của bạn (đang làm, hoặc mọi suất 7 ngày qua)","x-scope":"maker:read","parameters":[{"name":"status","in":"query","required":false,"description":"active (default) | all","schema":{"type":"string"}}],"responses":{"200":{"description":"Assignments","content":{"application/json":{"schema":{"type":"object"},"example":{"data":[{"assignmentId":902,"jobCode":"CV-1042","slot":2,"slotCode":"CV-1042-V2","status":"holding","expiresAt":"2026-10-16T09:00:00.000Z","claimedAt":"2026-10-15T09:00:00.000Z","title":"Cảnh 3 · chợ đêm","secs":15,"ctvPay":120000,"uploadId":null,"dialogue":true}]}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/maker/assignments/{id}":{"get":{"tags":["Maker"],"summary":"Full prompt + reference images of a slot you hold","x-summary-vi":"Prompt đầy đủ + ảnh tham chiếu của suất bạn đang giữ","x-scope":"maker:read","parameters":[{"name":"id","in":"path","required":true,"description":"assignmentId","schema":{"type":"string"},"example":"902"}],"responses":{"200":{"description":"Content","content":{"application/json":{"schema":{"type":"object"},"example":{"assignmentId":902,"jobCode":"CV-1042","slot":2,"slotCode":"CV-1042-V2","status":"holding","expiresAt":"2026-10-16T09:00:00.000Z","claimedAt":"2026-10-15T09:00:00.000Z","title":"Cảnh 3 · chợ đêm","secs":15,"special":false,"prompt":"A rainy night market in Hanoi…","refs":[{"id":31,"url":"https://storage.example/…","contentType":"image/jpeg"}]}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/maker/assignments/{id}/uploads":{"post":{"tags":["Maker"],"summary":"Start a video upload (presigned PUT, MP4 ≤ 200 MB)","x-summary-vi":"Bắt đầu tải video (link PUT ký sẵn, MP4 ≤ 200 MB)","x-scope":"maker:*","x-idempotent":true,"parameters":[{"name":"id","in":"path","required":true,"description":"assignmentId","schema":{"type":"string"},"example":"902"},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe key (8–128 chars). Same key + same body within 24 h replays the first successful response (header Idempotent-Replayed: true).","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["bytes"],"properties":{"bytes":{"type":"integer"}}},"example":{"bytes":18234123}}}},"responses":{"201":{"description":"PUT the file to uploadUrl (with uploadHeaders), then call /maker/uploads/{uploadId}/complete","content":{"application/json":{"schema":{"type":"object"},"example":{"uploadId":5121,"uploadUrl":"https://storage.example/sub/….mp4?X-Amz-Signature=…","uploadHeaders":{"Content-Type":"video/mp4"},"maxBytes":209715200,"expiresInSec":900,"created":true}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/maker/assignments/{id}/release":{"post":{"tags":["Maker"],"summary":"Release a slot back to the market","x-summary-vi":"Trả suất về chợ","x-scope":"maker:*","parameters":[{"name":"id","in":"path","required":true,"description":"assignmentId","schema":{"type":"string"},"example":"902"}],"responses":{"200":{"description":"Released","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Assignment"},"example":{"assignmentId":902,"jobCode":"CV-1042","slot":2,"slotCode":"CV-1042-V2","status":"released","expiresAt":"2026-10-16T09:00:00.000Z","claimedAt":"2026-10-15T09:00:00.000Z"}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/maker/uploads/{id}/complete":{"post":{"tags":["Maker"],"summary":"Finish an upload: same validation + QC/AI path as the UI","x-summary-vi":"Hoàn tất tải: cùng kiểm tra + QC/AI như giao diện","x-scope":"maker:*","x-idempotent":true,"parameters":[{"name":"id","in":"path","required":true,"description":"uploadId","schema":{"type":"string"},"example":"5121"},{"name":"Idempotency-Key","in":"header","required":false,"description":"Retry-safe key (8–128 chars). Same key + same body within 24 h replays the first successful response (header Idempotent-Replayed: true).","schema":{"type":"string"}}],"responses":{"200":{"description":"Submitted","content":{"application/json":{"schema":{"type":"object"},"example":{"uploadId":5121,"submissionId":5121,"attempt":1,"status":"submitted","reused":false}}}},"400":{"description":"Bad file (does not count as an attempt)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"BAD_FILE","message":"Tệp không phải video MP4. Lần này không tính lượt."}}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/maker/uploads/{id}/cancel":{"post":{"tags":["Maker"],"summary":"Cancel an unfinished upload","x-summary-vi":"Huỷ lần tải chưa xong","x-scope":"maker:*","parameters":[{"name":"id","in":"path","required":true,"description":"uploadId","schema":{"type":"string"},"example":"5121"}],"responses":{"200":{"description":"Cancelled","content":{"application/json":{"schema":{"type":"object"},"example":{"uploadId":5121,"status":"cancelled"}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/maker/submissions":{"get":{"tags":["Maker"],"summary":"Your submissions: checks, AI feedback, decisions","x-summary-vi":"Các lần nộp: kiểm tra, nhận xét AI, quyết định","x-scope":"maker:read","parameters":[{"name":"assignment","in":"query","required":false,"description":"Only this assignmentId","schema":{"type":"integer"}},{"name":"limit","in":"query","required":false,"description":"1–300","schema":{"type":"integer"}}],"responses":{"200":{"description":"Submissions","content":{"application/json":{"schema":{"type":"object"},"example":{"data":[{"id":5121,"assignmentId":902,"job":"CV-1042","title":"Cảnh 3 · chợ đêm","secs":15,"slot":2,"slotCode":"CV-1042-V2","attempt":1,"status":"rework","error":null,"verdict":"rework","note":"AI chấm 54 điểm. Nhân vật: thiếu áo mưa (0:04)","decidedBy":"auto","decidedAt":"2026-10-15T11:00:00.000Z","duration":15,"frame":"1080×1920","checks":[{"key":"dup","pass":true,"detail":""},{"key":"duration","pass":true,"detail":"15.00 giây, cần 15 ± 0,5"}],"ai":{"score":54,"summary":"…","result":"fail","criteria":[]},"aiFrames":null,"at":"2026-10-15T10:58:00.000Z","fileDeleted":false,"videoUrl":"https://storage.example/…"}]}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}},"/api/v1/maker/wallet":{"get":{"tags":["Maker"],"summary":"Earnings and payouts (VND)","x-summary-vi":"Tiền công và chi trả (VNĐ)","x-scope":"maker:read","responses":{"200":{"description":"Wallet","content":{"application/json":{"schema":{"type":"object"},"example":{"summary":{"holdDays":3,"waiting":240000,"waitingCount":2,"nextReleaseAt":"2026-10-18T10:12:00.000Z","locked":0,"payable":120000,"inBatch":0,"paid":1800000,"deducted":0,"toOffset":0},"earns":[],"items":[],"debits":[],"deductions":[],"totals":{}}}}},"401":{"description":"Missing / invalid / revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"UNAUTHENTICATED","message":"Missing or invalid API key"}}}}},"403":{"description":"Wrong scope or inactive account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"INSUFFICIENT_SCOPE","message":"This API key does not have the required scope"}}}}},"429":{"description":"Rate limited (see Retry-After header)","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many requests for this API key; retry after the Retry-After seconds"}}}}}}}}}}