Chợ.video là chợ việc làm video AI theo prompt. API v1 cho phép phần mềm của bạn làm mọi việc chính mà khu làm việc làm được:
- Creator (nhà sáng tạo nội dung): đăng prompt hoặc cả lô prompt kèm ảnh tham chiếu, theo dõi từng suất V1–V3, huỷ, tải video đã đạt.
- Maker (người làm video): xem chợ việc, nhận suất, đọc prompt đầy đủ của suất đang giữ, tải video lên, trả việc, xem kết quả kiểm tra / nhận xét AI và tiền công.
Mọi thao tác qua API đi qua đúng các bước kiểm tra như trên web: cùng hạn mức giữ việc, cùng kiểm tra video (MP4, 9:16, thời lượng, trùng video, AI chấm), cùng cách tính tiền.
“Công khai” nghĩa là tài liệu mở và tài khoản nào đã được duyệt cũng tự tạo khoá được — không có nghĩa là gọi không cần khoá. Mọi đường dẫn (trừ
/api/v1/openapi.json) đều cần khoá API.
Bắt đầu trong 3 bước
- Đăng ký tài khoản Creator hoặc Maker trên khu làm việc và chờ duyệt.
- Vào mục API, bấm Tạo khoá, sao chép khoá
cvapi_…(chỉ hiện một lần) và lưu vào biến môi trường trên máy chủ của bạn. - Gọi thử:
Chợ.video is a marketplace for AI-generated videos made from prompts. API v1 lets your software do everything important the workspace can do:
- Creators post single prompts or whole lots with reference images, follow every slot V1–V3, cancel, and download accepted videos.
- Makers browse the market, claim slots, read the full prompt of slots they hold, upload videos, release work, and read QC results / AI feedback and earnings.
Everything you do through the API goes through exactly the same checks as the website: the same hold limits, the same video checks (MP4, 9:16, duration, duplicates, AI scoring), the same money rules.
“Public” means open documentation and self-serve keys for every approved account — not unauthenticated access. Every endpoint (except
/api/v1/openapi.json) needs an API key.
Start in 3 steps
- Sign up as a Creator or Maker in the workspace and wait for approval.
- Open API, click Create key, copy the
cvapi_…key (shown only once) and store it in an environment variable on your server. - Try it:
curl https://cho.video/api/v1/me \
-H "Authorization: Bearer $CHOVIDEO_API_KEY"
const r = await fetch('https://cho.video/api/v1/me', {
headers: { Authorization: `Bearer ${process.env.CHOVIDEO_API_KEY}` },
});
console.log(await r.json());
Xác thực & phạm viAuthentication & scopes
Gửi khoá trong header Authorization: Bearer cvapi_…. Không dùng cookie, không có CORS: chỉ gọi từ máy chủ của bạn, không bao giờ đặt khoá trong trình duyệt, ứng dụng di động hay kho mã công khai.
- Khoá chỉ hiện một lần lúc tạo; Chợ.video chỉ lưu bản băm SHA-256. Mất khoá: thu hồi và tạo khoá mới (tối đa 10 khoá đang dùng mỗi tài khoản).
- Thu hồi có hiệu lực ngay. Tài khoản bị khoá, đang chờ duyệt hoặc đã xoá: mọi khoá của tài khoản đó bị từ chối ngay (
403 ACCOUNT_INACTIVE). - Phạm vi được tính lại ở mỗi lần gọi: nếu chủ rút quyền đăng prompt của bạn, khoá
creator:*ngừng chạy ngay (403 INSUFFICIENT_SCOPE).
Send the key in the Authorization: Bearer cvapi_… header. No cookies and no CORS: call from your own server only and never put a key in a browser, a mobile app or a public repository.
- A key is shown once when created; Chợ.video stores only its SHA-256 hash. Lost a key? Revoke it and create a new one (up to 10 active keys per account).
- Revocation is immediate. If the account is locked, pending approval or deleted, all its keys are refused at once (
403 ACCOUNT_INACTIVE). - Scopes are re-checked on every call: if the owner removes your posting permission,
creator:*keys stop working immediately (403 INSUFFICIENT_SCOPE).
| Phạm viScope | Ai được cấpWho can have it | Cho phépAllows |
|---|---|---|
creator:* | Creator có quyền đăng prompt; chủCreators with posting permission; owner | Mọi đường dẫn /creator/… (đọc + ghi)All /creator/… endpoints (read + write) |
creator:read | như trênsame | Chỉ GET /creator/…GET /creator/… only |
maker:* | Maker (CTV) đã duyệt; chủ (chủ chỉ xem chợ)Approved Makers; owner (owner can only view the market) | Mọi đường dẫn /maker/…All /maker/… endpoints |
maker:read | như trênsame | Chỉ GET /maker/…GET /maker/… only |
/me, /webhooks và /events dùng được với mọi khoá hợp lệ; loại sự kiện đăng ký được tuỳ phạm vi của khoá.
/me, /webhooks and /events work with any valid key; the event types you can subscribe to depend on the key's scopes.
Quy ước chungConventions
- Địa chỉ gốc:
https://cho.video/api/v1. Gửi và nhận JSON (Content-Type: application/json, body tối đa 2 MB). Thời gian dạng ISO 8601 (UTC). - Tiền tính bằng VNĐ (số nguyên). Mã prompt dạng
CV-1042, mã suấtCV-1042-V2, mã lôLO-00012. - Lỗi luôn có dạng
{"error":{"code":"…","message":"…"}}. Dựa vàocode(ổn định);messagelà tiếng Việt, gửiAccept-Language: enđể nhận tiếng Anh cho các mã thường gặp. - Tạo mới trả
201; gửi lại cùng nội dung trả200kèm"reused": true. - Phân trang theo con trỏ: đọc
nextCursorvà gửi lại?cursor=…;nulllà hết. - Idempotency-Key: các đường dẫn tạo / nhận / tải lên nhận header
Idempotency-Key(8–128 ký tự). Cùng khoá + cùng body trong 24 giờ trả lại đúng kết quả thành công lần đầu (headerIdempotent-Replayed: true); khác body →422 IDEMPOTENCY_MISMATCH; đang xử lý →409 IDEMPOTENCY_IN_PROGRESS. Lỗi không được lưu, nên sửa rồi gửi lại cùng khoá được.
- Base URL:
https://cho.video/api/v1. JSON in and out (Content-Type: application/json, body ≤ 2 MB). Times are ISO 8601 (UTC). - Money is in VND (integers). Prompt codes look like
CV-1042, slot codesCV-1042-V2, lot codesLO-00012. - Errors are always
{"error":{"code":"…","message":"…"}}. Rely oncode(stable);messageis Vietnamese — sendAccept-Language: enfor English on common codes. - Creating returns
201; sending the same content again returns200with"reused": true. - Cursor pagination: read
nextCursorand send it back as?cursor=…;nullmeans the end. - Idempotency-Key: create / claim / upload endpoints accept an
Idempotency-Keyheader (8–128 chars). Same key + same body within 24 h replays the first successful response (headerIdempotent-Replayed: true); a different body →422 IDEMPOTENCY_MISMATCH; still running →409 IDEMPOTENCY_IN_PROGRESS. Errors are not stored, so you can fix the request and retry with the same key.
Creator: đăng prompt, nhận videoCreator: post prompts, receive videos
1. Tạo (hoặc cập nhật) một prompt1. Create (or upsert) a prompt
externalRef là mã của bạn (duy nhất trong tài khoản). Gửi lại cùng externalRef: cùng nội dung → trả bản cũ; nội dung khác → cập nhật nếu chưa Maker nào nhận, nếu đã nhận → 409 LOCKED (huỷ rồi tạo prompt mới với mã khác). title và short hiện công khai trên chợ trước khi nhận — đừng chép prompt vào đó. Ảnh nhỏ gửi kèm base64 (≤ 1 MB mỗi ảnh, tối đa 4); ảnh lớn dùng bước 4.
externalRef is your own id (unique per account). Sending the same externalRef again: same content → returns the existing prompt; changed content → updates it if no Maker has claimed a slot yet, otherwise 409 LOCKED (cancel and create a new prompt with a new ref). title and short are public on the market before claiming — never copy the prompt there. Small images can be sent inline as base64 (≤ 1 MB each, up to 4); larger images use step 4.
curl -X POST https://cho.video/api/v1/creator/prompts \
-H "Authorization: Bearer $CHOVIDEO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: story-77-scene-3-v1" \
-d '{
"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,
"refs": [{ "base64": "/9j/4AAQSkZJRg…" }]
}'
const api = (path, init = {}) => fetch('https://cho.video/api/v1' + path, {
...init,
headers: { Authorization: `Bearer ${process.env.CHOVIDEO_API_KEY}`, 'Content-Type': 'application/json', ...init.headers },
}).then(async (r) => { const j = await r.json(); if (!r.ok) throw Object.assign(new Error(j.error.message), j.error, { status: r.status }); return j; });
const prompt = await api('/creator/prompts', {
method: 'POST',
headers: { 'Idempotency-Key': 'story-77-scene-3-v1' },
body: JSON.stringify({ 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 }),
});
console.log(prompt.code, prompt.slots.map((s) => `${s.slotCode}: ${s.status}`));
201 Created
{ "code": "CV-1042", "externalRef": "story-77:scene-3", "lot": { "id": 12, "code": "LO-00012", "title": "API" },
"title": "Cảnh 3 · chợ đêm", "secs": 15, "videos": 3, "ctvPay": 120000, "status": "open", "cancelled": false,
"slots": [ { "slot": 1, "slotCode": "CV-1042-V1", "status": "open" }, { "slot": 2, … }, { "slot": 3, … } ],
"refs": [ { "id": 31, "url": "https://…", "contentType": "image/jpeg" } ], "prompt": "A rainy night market…", "created": true }
2. Tạo cả lô2. Create a lot
Một lô 1–100 prompt, có hạn nộp chung (tuỳ chọn, trong 30 ngày). key của lô là mã của bạn; prompt nào không có externalRef được đặt <key>:<thứ tự>, nên gửi lại cả lô không tạo trùng. Kết quả trả từng dòng ok / error.
A lot holds 1–100 prompts with an optional shared deadline (within 30 days). The lot key is your id; items without externalRef get <key>:<n>, so re-sending the whole lot never duplicates. Each item comes back as ok / error.
curl -X POST https://cho.video/api/v1/creator/lots -H "Authorization: Bearer $CHOVIDEO_API_KEY" -H "Content-Type: application/json" \
-d '{ "key": "story-77", "title": "Story 77 — episode 1", "deadlineAt": "2026-10-20T12:00:00Z",
"items": [ { "prompt": "…", "secs": 15, "videos": 2 }, { "prompt": "…", "secs": 30 } ] }'
3. Theo dõi suất V1–V3, huỷ3. Follow slots V1–V3, cancel
Mỗi suất có status: open (trên chợ), claimed (Maker đang làm), review (đã nộp, đang kiểm tra / chờ duyệt), accepted, cancelled, closed (prompt đã huỷ). Suất bị trả về chợ có thêm lastResult (rejected, expired, released…). Webhook slot.status báo mỗi lần đổi.
Each slot has a status: open (on the market), claimed (a Maker is working), review (submitted, being checked / awaiting review), accepted, cancelled, closed (prompt cancelled). A slot that went back to the market also has lastResult (rejected, expired, released…). The slot.status webhook fires on every change.
curl "https://cho.video/api/v1/creator/prompts?status=held&limit=50" -H "Authorization: Bearer $CHOVIDEO_API_KEY"
curl https://cho.video/api/v1/creator/prompts/story-77:scene-3 -H "Authorization: Bearer $CHOVIDEO_API_KEY"
# Huỷ: đóng suất còn trống; suất đang làm vẫn tiếp tục. "force": true huỷ cả suất đang giữ chưa nộp (không tính tiền); còn video chờ duyệt thì bị từ chối (409).Cancel: closes open slots; slots in progress continue. "force": true also cancels held slots not yet submitted (unpaid); refused (409) while a video awaits review.
curl -X POST https://cho.video/api/v1/creator/prompts/CV-1042/cancel -H "Authorization: Bearer $CHOVIDEO_API_KEY" \
-H "Content-Type: application/json" -d '{ "reason": "Script changed" }'
4. Ảnh tham chiếu lớn (≤ 10 MB)4. Large reference images (≤ 10 MB)
# 1) xin link tảiask for an upload URL
curl -X POST https://cho.video/api/v1/creator/prompts/CV-1042/refs -H "Authorization: Bearer $CHOVIDEO_API_KEY" \
-H "Content-Type: application/json" -d '{ "bytes": 2400000, "contentType": "image/jpeg" }'
# → { "refId": 31, "uploadUrl": "https://…", "uploadHeaders": { "Content-Type": "image/jpeg" }, "expiresInSec": 600 }
# 2) PUT tệp lên link (đúng dung lượng đã khai)PUT the file (exact declared size)
curl -X PUT "$UPLOAD_URL" -H "Content-Type: image/jpeg" --data-binary @ref.jpg
# 3) hoàn tất (máy chủ kiểm lại dung lượng và loại ảnh)complete (the server re-checks size and image type)
curl -X POST https://cho.video/api/v1/creator/refs/31/complete -H "Authorization: Bearer $CHOVIDEO_API_KEY"
Chỉ thêm ảnh được khi chưa Maker nào nhận prompt.
Images can only be added before any Maker claims the prompt.
5. Tải video đã đạt5. Download accepted videos
downloadUrl là link ký sẵn, hết hạn sau 1 giờ — gọi lại để lấy link mới. Chỉ thấy video từ prompt của chính bạn.
downloadUrl is a signed link valid for 1 hour — call again for a fresh link. You only see videos from your own prompts.
curl "https://cho.video/api/v1/creator/videos?limit=100" -H "Authorization: Bearer $CHOVIDEO_API_KEY"
curl https://cho.video/api/v1/creator/videos/5120 -H "Authorization: Bearer $CHOVIDEO_API_KEY"
let cursor = null;
do {
const page = await api('/creator/videos?limit=100' + (cursor ? '&cursor=' + cursor : ''));
for (const v of page.data) await saveVideo(v.slotCode + '.mp4', await (await fetch(v.downloadUrl)).arrayBuffer());
cursor = page.nextCursor;
} while (cursor);
Maker: nhận việc, trả videoMaker: take work, deliver videos
- Xem chợ —
GET /maker/market: cùng các trường trang Nhận việc hiện (tiêu đề, tóm tắt, giá, thời lượng, suất còn, số ảnh, lô, hạn). Không có prompt đầy đủ trước khi nhận.GET /maker/market/{code}xem trước yêu cầu và ảnh tham chiếu. - Nhận suất —
POST /maker/claims: một prompt (code,count1–3) hoặc tối đa 10 prompt (items). Tất cả hoặc không gì. Cùng hạn mức giữ việc như web (400 LIMIT), cộng trần số suất nhận mỗi giờ qua API (429 CLAIM_RATE_LIMIT+Retry-After) để chống ôm việc. - Đọc prompt —
GET /maker/assignments/{id}: prompt đầy đủ + link ảnh (15 phút), chỉ khi bạn đang giữ suất. - Tải video —
POST /maker/assignments/{id}/uploadsvớibytes→ PUT tệp MP4 lênuploadUrl(headerContent-Type: video/mp4, đúng dung lượng) →POST /maker/uploads/{uploadId}/complete. Máy chủ kiểm lại tệp; tệp sai (400 BAD_FILE) không tính lượt. - Kết quả —
GET /maker/submissions(kiểm tra, điểm AI, nhận xét, quyết định) hoặc webhooksubmission.result. Bị từ chối thì suất về chợ; muốn làm lại thì nhận lại. - Trả việc —
POST /maker/assignments/{id}/release. Tiền công —GET /maker/wallet.
- Browse —
GET /maker/market: the same fields the market page shows (title, summary, pay, duration, open slots, image count, lot, deadline). No full prompt before claiming.GET /maker/market/{code}previews requirements and reference images. - Claim —
POST /maker/claims: one prompt (code,count1–3) or up to 10 prompts (items). All or nothing. Same hold limit as the website (400 LIMIT) plus a claims-per-hour cap for the API (429 CLAIM_RATE_LIMIT+Retry-After) to prevent hoarding. - Read the prompt —
GET /maker/assignments/{id}: full prompt + image links (15 min), only while you hold the slot. - Upload —
POST /maker/assignments/{id}/uploadswithbytes→ PUT the MP4 touploadUrl(headerContent-Type: video/mp4, exact size) →POST /maker/uploads/{uploadId}/complete. The server re-checks the file; a bad file (400 BAD_FILE) does not count as an attempt. - Results —
GET /maker/submissions(checks, AI score, feedback, decision) or thesubmission.resultwebhook. A rejected slot goes back to the market; claim it again to retry. - Release —
POST /maker/assignments/{id}/release. Earnings —GET /maker/wallet.
curl https://cho.video/api/v1/maker/market -H "Authorization: Bearer $CHOVIDEO_API_KEY"
curl -X POST https://cho.video/api/v1/maker/claims -H "Authorization: Bearer $CHOVIDEO_API_KEY" \
-H "Content-Type: application/json" -H "Idempotency-Key: claim-2026-10-15-001" \
-d '{ "code": "CV-1042", "count": 1 }'
# → 201 { "assignments": [ { "assignmentId": 902, "slotCode": "CV-1042-V2", "status": "holding", "expiresAt": "…" } ] }
curl https://cho.video/api/v1/maker/assignments/902 -H "Authorization: Bearer $CHOVIDEO_API_KEY"
curl -X POST https://cho.video/api/v1/maker/assignments/902/uploads -H "Authorization: Bearer $CHOVIDEO_API_KEY" \
-H "Content-Type: application/json" -d "{ \"bytes\": $(stat -c%s video.mp4) }"
curl -X PUT "$UPLOAD_URL" -H "Content-Type: video/mp4" --data-binary @video.mp4
curl -X POST https://cho.video/api/v1/maker/uploads/5121/complete -H "Authorization: Bearer $CHOVIDEO_API_KEY" -H "Idempotency-Key: done-5121"
import { readFile } from 'node:fs/promises';
const [slot] = (await api('/maker/claims', { method: 'POST', headers: { 'Idempotency-Key': 'claim-CV-1042-1' },
body: JSON.stringify({ code: 'CV-1042', count: 1 }) })).assignments;
const { prompt, refs } = await api(`/maker/assignments/${slot.assignmentId}`);
const file = await readFile('video.mp4'); // video bạn đã làm từ promptthe video you made from the prompt
const up = await api(`/maker/assignments/${slot.assignmentId}/uploads`, { method: 'POST', body: JSON.stringify({ bytes: file.length }) });
const put = await fetch(up.uploadUrl, { method: 'PUT', headers: up.uploadHeaders, body: file });
if (!put.ok) throw new Error('upload failed ' + put.status);
const done = await api(`/maker/uploads/${up.uploadId}/complete`, { method: 'POST', headers: { 'Idempotency-Key': 'done-' + up.uploadId } });
console.log(done.status); // "submitted" → chờ kiểm trabeing checked
Webhooks
Đăng ký URL https:// công khai và một bí mật (16–200 ký tự) bằng POST /api/v1/webhooks; tối đa 5 webhook. Bí mật được mã hoá khi lưu và không bao giờ trả lại. POST /webhooks/{id}/test gửi một sự kiện ping.
Register a public https:// URL and a secret (16–200 chars) with POST /api/v1/webhooks; up to 5 webhooks. The secret is encrypted at rest and never returned. POST /webhooks/{id}/test sends a ping event.
curl -X POST https://cho.video/api/v1/webhooks -H "Authorization: Bearer $CHOVIDEO_API_KEY" -H "Content-Type: application/json" \
-d '{ "url": "https://example.com/hooks/chovideo", "secret": "'"$CHOVIDEO_WEBHOOK_SECRET"'", "events": ["slot.status","video.accepted","job.cancelled"] }'
| Sự kiệnEvent | Phạm viScope | Khi nàoWhen |
|---|---|---|
slot.status | creator | Một suất của prompt bạn đổi nhóm trạng thái: claimed, review, rejected, released, accepted, cancelledA slot of your prompt changes state group: claimed, review, rejected, released, accepted, cancelled |
video.accepted | creator | Video đạt; kèm downloadUrl (1 giờ)A video is accepted; includes downloadUrl (1 hour) |
job.cancelled | creator | Prompt bị huỷ (bạn huỷ, chủ xoá lô…)A prompt is cancelled (by you, owner deleted the lot…) |
assignment.status | maker | Suất của bạn đổi trạng thái (nhận, đang tải, đã nộp, chờ duyệt, đạt, bị từ chối, hết hạn, thu hồi, huỷ)Your slot changes status (holding, uploading, submitted, review, accepted, rejected, expired, revoked, cancelled) |
submission.result | maker | Lần nộp có kết quả, kèm ghi chú và điểm AIA submission gets a result, with note and AI score |
ping | — | Gửi thửTest delivery |
POST /hooks/chovideo
Content-Type: application/json
X-ChoVideo-Event: video.accepted
X-ChoVideo-Event-Id: 1207
X-ChoVideo-Timestamp: 1760522400
X-ChoVideo-Signature: sha256=5f0c…
{ "id": 1207, "kind": "video.accepted", "createdAt": "2026-10-15T10:12:00.000Z", "externalRef": "story-77:scene-3",
"jobCode": "CV-1042", "slot": 1, "slotCode": "CV-1042-V1", "submissionId": 5120, "sha256": "9f2c…", "bytes": 18234123,
"duration": 15.02, "width": 1080, "height": 1920, "acceptedAt": "2026-10-15T10:12:00.000Z", "downloadUrl": "https://…" }
Kiểm tra chữ kýVerify the signature
Chữ ký = "sha256=" + hex(HMAC-SHA256(secret, timestamp + "." + body gốc)) — cùng định dạng webhook StoryBridge. Dùng body gốc chưa parse, so sánh thời gian hằng, từ chối nếu lệch quá 5 phút. Trả 2xx trong 10 giây; xử lý nặng thì đưa vào hàng đợi. Có thể nhận trùng: chống trùng theo X-ChoVideo-Event-Id.
Signature = "sha256=" + hex(HMAC-SHA256(secret, timestamp + "." + raw body)) — the same format as the StoryBridge webhook. Use the raw, unparsed body, compare in constant time and reject timestamps older than 5 minutes. Return 2xx within 10 seconds; queue heavy work. Deliveries may repeat: de-duplicate on X-ChoVideo-Event-Id.
import crypto from 'node:crypto';
import express from 'express';
const app = express();
app.post('/hooks/chovideo', express.raw({ type: 'application/json' }), (req, res) => {
const ts = req.get('X-ChoVideo-Timestamp') || '', sig = req.get('X-ChoVideo-Signature') || '';
const want = 'sha256=' + crypto.createHmac('sha256', process.env.CHOVIDEO_WEBHOOK_SECRET).update(`${ts}.${req.body}`).digest('hex');
const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
if (!fresh || sig.length !== want.length || !crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(want))) return res.sendStatus(401);
const event = JSON.parse(req.body);
queue.push(event); // xử lý sau, chống trùng theo event.idprocess later, de-duplicate on event.id
res.sendStatus(204);
});
import hmac, hashlib, os, time
from flask import Flask, request, abort
app = Flask(__name__)
@app.post("/hooks/chovideo")
def hook():
ts = request.headers.get("X-ChoVideo-Timestamp", "")
sig = request.headers.get("X-ChoVideo-Signature", "")
raw = request.get_data() # raw bytes
want = "sha256=" + hmac.new(os.environ["CHOVIDEO_WEBHOOK_SECRET"].encode(), ts.encode() + b"." + raw, hashlib.sha256).hexdigest()
if not ts.isdigit() or abs(time.time() - int(ts)) > 300 or not hmac.compare_digest(sig, want):
abort(401)
event = request.get_json()
return "", 204
Thử lại và kéo lạiRetries and pulling
Gửi lỗi (không phải 2xx, quá hạn, lỗi mạng) được thử lại sau 1, 2, 4… phút, tối đa 6 giờ một lần, khoảng 20 lần (~4 ngày). Webhook chỉ gửi tới địa chỉ công khai (không gửi vào mạng nội bộ, không theo chuyển hướng). Lỡ sự kiện thì kéo lại: GET /api/v1/events?after=<id cuối đã xử lý>.
Failed deliveries (non-2xx, timeout, network error) are retried after 1, 2, 4… minutes, at most every 6 hours, about 20 times (~4 days). Webhooks only go to public addresses (no private networks, redirects are not followed). Missed something? Pull: GET /api/v1/events?after=<last processed id>.
Mã lỗiError codes
| HTTP | code | Ý nghĩaMeaning |
|---|---|---|
| 400 | BAD_INPUT, BAD_FILE, BAD_JSON, BAD_PRICE, RULES | Dữ liệu không hợp lệ (xem message)Invalid input (see message) |
| 400 | LIMIT, TAKEN, CLOSED, PAUSED, NO_RECLAIM, STATE, EXPIRED, NO_ATTEMPTS, BALANCE | Quy tắc nghiệp vụ: hạn mức giữ việc, hết suất, lô đóng, không tự nhận lại, sai trạng thái, hết hạn, hết lượt nộp, số dưBusiness rule: hold limit, no slots left, lot closed, no self re-claim, wrong state, expired, no attempts left, balance |
| 401 | UNAUTHENTICATED | Thiếu khoá, sai khoá hoặc khoá đã thu hồiMissing, wrong or revoked key |
| 403 | ACCOUNT_INACTIVE | Tài khoản chờ duyệt, bị khoá hoặc đã xoáAccount pending, locked or deleted |
| 403 | INSUFFICIENT_SCOPE, FORBIDDEN, MAKER_ONLY, CLAIM_LOCKED, ADULT | Khoá thiếu phạm vi, không có quyền, cần tài khoản Maker, đang bị tạm khoá nhận việc, cần xác nhận 18+ (trên web)Missing scope, not allowed, Maker account required, temporarily blocked from claiming, 18+ confirmation needed (on the website) |
| 404 / 405 | NOT_FOUND | Không có, hoặc không phải của bạn; sai phương thứcNot found or not yours; wrong method |
| 409 | LOCKED, CONFLICT, STATE, IDEMPOTENCY_IN_PROGRESS | Prompt đã có người nhận / đã huỷ, xung đột đồng thời, yêu cầu cùng khoá đang chạyPrompt already claimed / cancelled, concurrent conflict, same-key request still running |
| 410 | VIDEO_DELETED | Tệp video đã bị xoáVideo file was deleted |
| 415 | BAD_CONTENT_TYPE | Chỉ nhận application/jsonOnly application/json |
| 422 | IDEMPOTENCY_MISMATCH | Idempotency-Key đã dùng cho body khácIdempotency-Key reused with a different body |
| 429 | RATE_LIMITED, CLAIM_RATE_LIMIT | Quá giới hạn; chờ theo header Retry-After (giây)Over a limit; wait Retry-After seconds |
| 500 / 503 | INTERNAL, UNAVAILABLE | Lỗi máy chủ / dịch vụ kho chưa sẵn sàng; thử lại sau (dùng Idempotency-Key)Server error / storage unavailable; retry later (with an Idempotency-Key) |
Giới hạnLimits
| Yêu cầu mỗi khoáRequests per key | 120 / phút (thùng token; header X-RateLimit-Limit, X-RateLimit-Remaining)minute (token bucket; headers X-RateLimit-Limit, X-RateLimit-Remaining) |
| Maker nhận suất qua APIMaker claims via the API | 30 suất / giờ (tính cả suất nhận trên web), cộng hạn mức giữ việc của tài khoảnslots / hour (counting slots claimed on the website), plus the account hold limit |
| Mỗi lần nhậnPer claim call | tối đa 10 prompt, 1–3 suất mỗi promptup to 10 prompts, 1–3 slots each |
| Prompt / lôPrompts / lots | prompt ≤ 20.000 ký tự, 15 hoặc 30 giây, 1–3 video; lô ≤ 100 prompt, hạn nộp ≤ 30 ngày; ≤ 4 ảnh tham chiếuprompt ≤ 20,000 chars, 15 or 30 s, 1–3 videos; lot ≤ 100 prompts, deadline ≤ 30 days; ≤ 4 reference images |
| TệpFiles | video MP4 ≤ 200 MB, dọc 9:16; ảnh ≤ 10 MB (gửi kèm JSON ≤ 1 MB)MP4 video ≤ 200 MB, vertical 9:16; images ≤ 10 MB (inline JSON ≤ 1 MB) |
| Khoá / webhookKeys / webhooks | 10 khoá đang dùng, 5 webhook mỗi tài khoản10 active keys, 5 webhooks per account |
Mọi lần gọi được ghi nhật ký (khoá, tài khoản, đường dẫn, mã trạng thái); 20 lần gần nhất hiện ở trang API trong khu làm việc.
Every call is logged (key, account, route, status); the last 20 calls are shown on the API page in the workspace.
Danh sách đường dẫnEndpoint reference
Sinh từGenerated from /api/v1/openapi.json (OpenAPI 3). Bấm một dòng để xem tham số và ví dụ.Click a row for parameters and examples.
Đang tải đặc tả…Loading the spec…
Thay đổiChangelog
- v1.0.0 — 2026-10-15: bản đầu: khoá tự phục vụ, Creator (prompt, lô, ảnh, huỷ, video), Maker (chợ, nhận, prompt, tải lên, trả việc, kết quả, ví), webhook ký HMAC, Idempotency-Key, giới hạn tốc độ.first release: self-serve keys, Creator (prompts, lots, images, cancel, videos), Maker (market, claim, prompt, upload, release, results, wallet), HMAC-signed webhooks, Idempotency-Key, rate limits.
Trong v1 chỉ thêm trường / đường dẫn mới, không đổi hay bỏ trường có sẵn. Thay đổi phá vỡ sẽ ra /api/v2.
Within v1 we only add fields / endpoints and never change or remove existing ones. Breaking changes will ship as /api/v2.