Dành cho AI agent
Đọc hướng dẫn cho agent, OpenAPI 3.1 và chỉ mục llms.txt. Dùng CLI nếu có shell; MCP dành cho ứng dụng hỗ trợ stdio. Agent chỉ có HTTP dùng REST bên dưới; dịch vụ không có remote MCP.
1. Hỏi người dùng đường dẫn video, nơi lưu kết quả và video có hình ảnh/giọng nói của chính họ không. Không đoán self-likeness.
2. Cần API key Upscaler đã mở quyền.
3. Có shell: đặt UP4K_API_KEY rồi chạy:
npx -y up4k@latest upscale <path> --self-likeness no|yes --json
Thay no|yes bằng câu trả lời. Với yes, phải xin đồng ý hình ảnh/giọng nói rõ ràng; chỉ sau đó mới thêm --yes-self-likeness-consent khi chạy không tương tác.
4. Đọc từng dòng JSON (NDJSON). Theo dõi created, queued, progress, done/failed và summary. Chỉ báo thành công khi có kết quả done và đường dẫn đầu ra; exit 1 là có lỗi hoặc dừng sớm.
5. Với no_credits, duration_limit, api_locked, rate_limited hoặc active_limit sau khi CLI dừng: báo người dùng, không chạy vòng lặp thử lại. Bảo toàn .up4k-state.json để nối tiếp.
6. Chỉ có HTTP: GET /api/v1/me, hỏi self-likeness và xin đồng ý hình ảnh/giọng nói nếu có, POST /jobs với Idempotency-Key, PUT upload_url, submit, poll, download. Video dài (`kind:"long"`) thay PUT và submit bằng các bước multipart. Không đưa Bearer key vào request tới upload_url hoặc URL từng phần.
Tổng quan và giới hạn
API tải video lên, chờ xử lý và tải file 4K về. Job API dùng chung ví và hàng đợi với web. Base URL: https://up4k.io. Mọi route v1 dùng Authorization: Bearer cx_live_..., không dùng cookie, không bật CORS, phản hồi có Cache-Control: no-store. Giữ key ở máy chủ hoặc máy cá nhân.
Quyền API mở sau một đơn nạp đã thanh toán từ 199.000đ; nhiều đơn nhỏ không cộng dồn. Tài khoản Creator được mở tự động. Nếu đơn mở quyền được hoàn tiền và huỷ credit, quyền API đóng lại. access trong /api/v1/me luôn cho biết trạng thái hiện tại.
| Mục | Mức |
|---|---|
| Giá | 4K Fast: 1 credit cho video dài tối đa 35 giây. Gói Pro tính đúng từng 0,1 credit theo thời lượng: 1080p Pro mỗi 5 giây = 1 credit, 4K Pro mỗi 4,5 giây = 1 credit (tối thiểu 2,0 credit), 4K Max mỗi 2,5 giây, 4K Ultra mỗi 1,5 giây. Trừ một lần khi job vào hàng đợi; lỗi, từ chối, huỷ khi còn chờ, quá hạn hoặc hết phiên xử lý được hoàn đủ |
| Xử lý mỗi ngày | Tài khoản dùng ví không có cap xử lý hằng ngày; số credit trong ví giới hạn sử dụng. Chương trình cấp credit miễn phí là cơ chế riêng |
| Job active | Thường 20; Creator 50, tính chung web và API; xem max_active, active_count trong /me |
| Tốc độ gọi | 120 request/phút/key; vượt trả 429 và Retry-After |
| Lưu kết quả | 24 giờ sau khi xong (OUTPUT_TTL_MINUTES=1440); tải về trước khi hết hạn |
| API key | Tối đa 5 key; tên 1–40 ký tự |
| Đầu vào | MP4/MOV, tối đa 500 MiB (524288000 byte), cạnh dài 500–2560 px với 4K Fast; gói Pro chọn theo cạnh ngắn của nguồn: 1080p Pro và 4K Pro nhận cạnh ngắn tối đa 720 px với tỉ lệ khung tối đa 21:9, 4K Max nhận 480–1080 px, 4K Ultra nhận trên 960 px đến 1080 px; sai luật trả source_short_side, source_aspect_ratio hoặc source_dimensions_missing khi thiếu kích thước. Tốc độ khung hình trung bình tối đa 30 fps. Gửi fps = avg_frame_rate của ffprobe (không dùng r_frame_rate: nhiều video điện thoại ghi 60 nhưng thực tế ~24 fps) để được báo frame_rate_limit sớm; không chắc thì bỏ trường này, máy xử lý sẽ đo lại và từ chối với input_frame_rate_high (hoàn credit) |
| Thời lượng | Đọc max_seconds từ /api/v1/me trước mỗi lượt chạy |
Theo cấu hình hạng thông thường: Miễn phí 11 giây, Cơ bản 16, Nâng cao 30, Pro và Creator 35. Trong giai đoạn mở đầu, mức có thể là 35 giây cho mọi hạng. /me luôn trả mức đang áp dụng; không suy ra thời lượng chỉ từ gói nạp. API key được upload hàng loạt, vẫn phải tuân theo giới hạn tài khoản. Video dài trên 35 giây (4K Fast đến 60 phút; 1080p Pro, 4K Pro và 4K Max đến 5 phút; 4K Ultra đến 4 phút, tính credit theo công thức của gói) nhận qua cả web và API cho tài khoản đã mua credit; xem mục Video dài trong phần REST API.
Bắt đầu trong 2 phút
- Mở Tài khoản › API, tạo key rồi sao chép ngay. Bạn không xem lại được key đầy đủ.
- Cần Node.js 20 trở lên. Đăng nhập CLI một lần: lệnh hỏi và lưu API key.
npx -y up4k@latest login
- Hỏi người dùng video có mặt hoặc giọng của họ không. Ví dụ dưới dùng
nochỉ khi họ trả lời không:
npx -y up4k@latest upscale ./videos --self-likeness no --json
CLI quét đệ quy MP4/MOV; clip.mov tạo clip 4K.mp4 cạnh file gốc. --out ./results chọn thư mục khác, giữ cấu trúc cây. File đã có kết quả được bỏ qua; .part chưa được coi là hoàn tất. --wait là mặc định; --no-wait trả job id để xem sau bằng npx -y up4k@latest status JOB_ID. Xem số credit bằng npx -y up4k@latest credits.
up4k@latest luôn chạy bản mới nhất, nên bạn nhận bản sửa lỗi mà không phải đổi lệnh. Nếu bạn ghim một phiên bản (ví dụ trong cấu hình MCP), CLI sẽ in nhắc trên stderr khi có bản mới; bản quá cũ bị từ chối với upgrade_required.
CLI có bộ đọc metadata MP4/QuickTime; cần ffprobe trên PATH nếu file phải dùng cách đọc dự phòng. Giữ .up4k-state.json để chạy lại cùng lệnh sau gián đoạn, không tự xoá hay tạo job trùng. resume_ambiguous cần người dùng kiểm tra job cũ.
Dùng với AI agent
Agent/script không tương tác: đặt UP4K_API_KEY. Không cần up4k login hay config file trong chế độ này. API, CLI và MCP không yêu cầu chấp nhận điều khoản chung; xác nhận hình ảnh/giọng nói vẫn bắt buộc nếu có self-likeness.
export UP4K_API_KEY='cx_live_...'
npx -y up4k@latest upscale ./clip.mp4 --self-likeness no --json
PowerShell:
$env:UP4K_API_KEY = "cx_live_..."
npx -y up4k@latest upscale "D:\videos\clip.mov" --self-likeness no --json
Với yes, CLI hiển thị statement hình ảnh/giọng nói để xác nhận. Script chỉ thêm --yes-self-likeness-consent sau khi đã xin đồng ý rõ ràng. MCP không đồng ý thay người dùng.
Claude Code
claude mcp add up4k -e UP4K_API_KEY=cx_live_... -- npx -y up4k@latest mcp
Claude Desktop và Cursor
Thêm cấu hình dưới vào claude_desktop_config.json (Claude Desktop: Settings › Developer › Edit Config) hoặc .cursor/mcp.json, rồi khởi động lại ứng dụng. Config chứa key phải được giữ riêng tư.
{
"mcpServers": {
"up4k": {
"command": "npx",
"args": ["-y", "up4k@latest", "mcp"],
"env": { "UP4K_API_KEY": "cx_live_..." }
}
}
}
Windows nếu host không tìm được npx, dùng "command": "cmd", "args": ["/c", "npx", "-y", "up4k@latest", "mcp"], giữ nguyên env.
Năm tool: upscale_video({path,self_likeness,self_likeness_consent?,output_dir?,wait?}), get_job({job_id}), list_jobs({state?,limit?}), get_account(), download_result({job_id,output_dir}). Mọi tool trả structuredContent, cùng giá trị ở JSON text. Upscale mặc định chờ và trả {results:[{source,output_path|job_id,state,error?}]}. Có progress notification nếu client gửi progress token.
Codex và agent có shell đọc NDJSON từ --json: mỗi dòng một object, các sự kiện scan, skipped, created, uploaded, queued, progress, done, failed, summary. Prompts/statement nằm ở stderr; đừng parse cả stdout như một JSON duy nhất. Exit code 1 khi có file lỗi hoặc dừng sớm; worker đang chạy có thể hoàn tất sau khi dừng. Concurrency mặc định 3, từ 1–100. CLI đã có retry hữu hạn cho lỗi mạng và rate limit; nếu vẫn dừng thì báo người dùng, không tự bọc thêm vòng lặp.
REST API từng bước
Các route hiện hành (schema và response đầy đủ trong OpenAPI):
GET /api/v1/mePOST /api/v1/jobsGET /api/v1/jobsPOST /api/v1/jobs/{id}/multipartPOST /api/v1/jobs/{id}/submitGET /api/v1/jobs/{id}POST /api/v1/jobs/{id}/cancelPOST /api/v1/jobs/{id}/retryGET /api/v1/jobs/{id}/download
POST /api/v1/jobs nhận engine (runway-4k, colab-1080p, colab-4k-pro, colab-4k-max hoặc colab-4k-ultra; mặc định runway-4k) và chỉ chấp nhận gói có trong engines của /api/v1/me. Trường sharpness chọn mức độ nét cho gói Pro: cuc-net, net, can-bang (mặc định), mem, tu-nhien; 4K Fast bỏ qua trường này. Phản hồi tạo job có credits (số nguyên đặt chỗ) và charge (credit thực trừ, có thể lẻ, ví dụ 6.7); mỗi job trong danh sách và chi tiết có engine, sharpness, credits, charge, stage. Lỗi engine_unavailable trả HTTP 403 với message Gói <tên gói> chưa mở; nguồn không hợp gói trả 400 với source_dimensions_missing, source_short_side hoặc source_aspect_ratio.
Danh sách job nhận state, limit (1–100, mặc định 20) và cursor opaque; trả jobs, next_cursor. Trạng thái: uploading, queued, claimed, running, done, rejected, failed, canceled, expired. Cancel chỉ khi uploading/queued. Retry tạo job mới từ nguồn còn tồn tại và cần Idempotency-Key mới cho ý định mới; không tự retry chỉ vì poll lâu.
GET /me trả email, tier, engines, credits {free,mine}, api_daily_jobs: {used,limit}, các giới hạn (cả ở cấp gốc và limits), access và consent. Metadata điều khoản cũ trong consent chỉ mang tính thông tin. Request tạo job dùng camelCase trong object consent; response /me dùng snake_case. Luôn gửi selfLikeness theo câu trả lời của người dùng. Nếu họ chọn selfLikeness:true, phải thêm selfLikenessConsent:true sau khi họ đồng ý consent.self_likeness_statement hiện hành. Không tự đồng ý thay người dùng. Các trường terms, termsVersion, policyVersion không bắt buộc; server bỏ qua chúng nếu client cũ vẫn gửi.
curl · Bash
Ví dụ cần curl, jq, ffprobe; dùng clip MP4/MOV thật. Chỉ dùng false dưới đây khi người dùng trả lời video không có hình ảnh/giọng của chính họ. Với câu trả lời có, xin đồng ý statement hình ảnh/giọng nói từ /me rồi gửi selfLikeness:true,selfLikenessConsent:true.
export UP4K_API_KEY='cx_live_...'
BASE=https://up4k.io
FILE=./clip.mp4
curl --fail-with-body -sS -H "Authorization: Bearer $UP4K_API_KEY" "$BASE/api/v1/me" > me.json
jq '{max_seconds, max_active, credits, self_likeness_statement: .consent.self_likeness_statement}' me.json
# Hỏi self-likeness; ví dụ này chỉ dùng khi người dùng trả lời không.
ffprobe -v error -select_streams v:0 -show_entries stream=width,height,avg_frame_rate -show_entries format=duration -of json "$FILE" > metadata.json
# fps lấy từ avg_frame_rate (trung bình thực tế), không dùng r_frame_rate.
jq -n --arg filename "$(basename "$FILE")" --argjson size "$(wc -c < "$FILE")" \
--slurpfile meta metadata.json \
'{filename:$filename,size:$size,duration:($meta[0].format.duration|tonumber),width:$meta[0].streams[0].width,height:$meta[0].streams[0].height,consent:{selfLikeness:false}}
+ (($meta[0].streams[0].avg_frame_rate // "0/0" | split("/") | map(tonumber)) as $r | if ($r[1] // 0) > 0 and $r[0] > 0 then {fps:($r[0]/$r[1])} else {} end)' > request.json
IDEMPOTENCY_KEY="create-$(date +%s)-$RANDOM"
# Giữ nguyên key và request.json khi gửi lại cùng yêu cầu (lưu 24 giờ).
curl --fail-with-body -sS -X POST "$BASE/api/v1/jobs" \
-H "Authorization: Bearer $UP4K_API_KEY" -H 'Content-Type: application/json' \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" --data-binary @request.json > job.json
JOB_ID=$(jq -r .id job.json)
UPLOAD_URL=$(jq -r '.upload_url // empty' job.json)
if [ -n "$UPLOAD_URL" ]; then
mapfile -t UPLOAD_HEADERS < <(jq -r '.upload_headers | to_entries[] | "-H", "\(.key): \(.value)"' job.json)
curl --fail-with-body -sS -X PUT "${UPLOAD_HEADERS[@]}" --upload-file "$FILE" "$UPLOAD_URL"
fi
curl --fail-with-body -sS -X POST -H "Authorization: Bearer $UP4K_API_KEY" "$BASE/api/v1/jobs/$JOB_ID/submit"
while true; do
curl --fail-with-body -sS -H "Authorization: Bearer $UP4K_API_KEY" "$BASE/api/v1/jobs/$JOB_ID" > status.json || break
STATE=$(jq -r .state status.json)
case "$STATE" in done|failed|rejected|canceled|expired) break;; esac
sleep 5
done
if [ "$(jq -r .state status.json)" = done ]; then
curl --fail-with-body -sS -L -H "Authorization: Bearer $UP4K_API_KEY" \
"$BASE/api/v1/jobs/$JOB_ID/download" -o 'clip 4K.mp4'
else
cat status.json
fi
Create trả 201 với id, state, upload_url, upload_method:"PUT", upload_headers, expires_in, credits, charge. Khi replay sau upload, upload_url có thể null. PUT đúng URL và headers trả về, không gửi Bearer key tới kho upload. Submit trả 200 với state, queue_position; replay submit an toàn trả trạng thái hiện tại. Poll trả id, filename, state, progress (ước lượng: running 50, done 100, còn lại 0), queue_position, error:{code,message}|null, duration, size, created_at, expires_at, download_url, credits, charge, engine, sharpness, stage. Các thời điểm này tính bằng millisecond Unix. Download trả dữ liệu nhị phân; download_url là đường dẫn tương đối cần Bearer key.
PowerShell · Windows
Ví dụ cần ffprobe trên PATH. Hỏi người dùng về hình ảnh/giọng nói của chính họ; selfLikeness=$false chỉ dành cho câu trả lời không. Với câu trả lời có, xin đồng ý statement hình ảnh/giọng nói trước khi gửi selfLikeness=$true; selfLikenessConsent=$true.
$env:UP4K_API_KEY = "cx_live_..."
$base = "https://up4k.io"
$auth = @{ Authorization = "Bearer $env:UP4K_API_KEY" }
$me = Invoke-RestMethod "$base/api/v1/me" -Headers $auth
$me | Select-Object max_seconds, max_active, credits
$me.consent.self_likeness_statement
# Hỏi self-likeness; ví dụ này chỉ dùng khi người dùng trả lời không.
$file = Get-Item ".\clip.mp4"
$meta = (& ffprobe -v error -select_streams v:0 -show_entries stream=width,height,avg_frame_rate -show_entries format=duration -of json $file.FullName) | ConvertFrom-Json
$body = @{
filename = $file.Name; size = $file.Length
duration = [double]::Parse($meta.format.duration, [Globalization.CultureInfo]::InvariantCulture)
width = $meta.streams[0].width; height = $meta.streams[0].height
consent = @{ selfLikeness = $false }
}
# fps lấy từ avg_frame_rate (trung bình thực tế), không dùng r_frame_rate.
$num, $den = "$($meta.streams[0].avg_frame_rate)".Split("/")
if ([double]$den -gt 0 -and [double]$num -gt 0) { $body.fps = [double]$num / [double]$den }
$request = $body | ConvertTo-Json -Depth 5
$createHeaders = @{ Authorization = $auth.Authorization; "Idempotency-Key" = [guid]::NewGuid().ToString() }
# Giữ $request và Idempotency-Key nếu gửi lại cùng yêu cầu.
$job = Invoke-RestMethod "$base/api/v1/jobs" -Method Post -Headers $createHeaders -ContentType "application/json" -Body ([Text.Encoding]::UTF8.GetBytes($request))
if ($job.upload_url) {
$uploadHeaders = @{}
$job.upload_headers.psobject.Properties | ForEach-Object { $uploadHeaders[$_.Name] = $_.Value }
Invoke-WebRequest $job.upload_url -Method Put -Headers $uploadHeaders -InFile $file.FullName
}
Invoke-RestMethod "$base/api/v1/jobs/$($job.id)/submit" -Method Post -Headers $auth
do {
$status = Invoke-RestMethod "$base/api/v1/jobs/$($job.id)" -Headers $auth
if ($status.state -in @("done", "failed", "rejected", "canceled", "expired")) { break }
Start-Sleep -Seconds 5
} while ($true)
if ($status.state -eq "done") {
Invoke-WebRequest "$base/api/v1/jobs/$($job.id)/download" -Headers $auth -OutFile ".\clip 4K.mp4"
} else { $status | ConvertTo-Json -Depth 5 }
Video dài
Video dài hơn long_video.min_seconds (35 giây) cần long_video.eligible: true trong /api/v1/me, đủ credit đã mua và dung lượng tối đa long_video.max_upload_bytes (mặc định 10 GiB). long_video.max_seconds cho thời lượng tối đa của từng engine. Tạo job như bình thường; server trả kind:"long", upload_method:"multipart", multipart_url và upload_url:null. Sau đó gọi POST multipart_url với Bearer key:
{"action":"create"}trảupload_idvàpart_size(byte mỗi phần; phần cuối ngắn hơn).{"action":"sign","upload_id":"…","parts":[1,2,…]}trảurlscho tối đa 20 phần mỗi lần. PUT đúng số byte của từng phần tới URL đó, không gửi Bearer key, và giữ headerETagcủa phản hồi.{"action":"complete","upload_id":"…","parts":[{"part":1,"etag":"…"},…]}ghép file, trừ credit và trả{"ok":true,"state":"queued"}. Không gọisubmitcho video dài. Gửi lạicompletevới cùng danh sách là an toàn. Nếucompletebáo lỗi nhưno_creditssau khi file đã ghép, nạp thêm credit rồi gọi lạicreate: server trảcompleted: true, khi đó gọicompletevớiparts: []mà không tải lại.
Phiên tải lên hết hạn sau 30 phút không có lệnh multipart nào; mỗi lệnh create, sign hoặc complete gia hạn lại. Ký từng nhóm nhỏ khi tải chậm. {"action":"abort","upload_id":"…"} huỷ job đang tải. Lỗi kho lưu trữ tạm thời trả 503 storage_unavailable; thử lại đúng thao tác. Poll, webhook và download giống video thường.
Lỗi REST có dạng {"error":{"code":"no_credits","message":"…"}}; đọc error.code để quyết định, hiển thị error.message cho người dùng. Không gửi lại POST tạo job với key mới chỉ vì mất kết nối. Tải kết quả trước thời hạn; có thể dùng Range cho download, 416 khi khoảng byte sai.
Webhook
Trong Tài khoản › API, lưu URL HTTPS công khai (tối đa 500 ký tự). Không nhận địa chỉ IP, localhost, .local, .internal hay URL chứa username/password. Secret chỉ hiển thị khi tạo hoặc xoay; đổi URL giữ nguyên secret. “Tạo secret mới” cần xác nhận, secret cũ ngừng dùng ngay, kể cả delivery đang chờ sẽ ký bằng secret hiện tại.
Sự kiện job.done hoặc job.failed; job bị từ chối nội dung cũng gửi job.failed với reason:"input_rejected". Các lỗi khác dùng mã lỗi công khai hoặc processing_failed. job trong webhook có credits, charge, engine, sharpness và stage cùng thông tin poll. Payload mẫu khi hoàn tất:
{
"id": "event-id",
"event": "job.done",
"created_at": 1793000000000,
"job": {
"id": "job-id", "filename": "clip.mp4", "state": "done", "progress": 100,
"queue_position": null, "error": null, "duration": 8, "size": 1048576,
"created_at": 1792999900000, "expires_at": 1793007200000,
"credits": 1, "charge": 1, "engine": "runway-4k", "sharpness": "can-bang", "stage": 1,
"download_url": "/api/v1/jobs/job-id/download"
}
}
download_url tương đối với https://up4k.io, vẫn cần Bearer API key để tải. Không phải link công khai. Header:
| Header | Ý nghĩa |
|---|---|
ChugAx-Webhook-Id |
id sự kiện/delivery, giữ nguyên qua retry; dùng để lọc trùng |
ChugAx-Webhook-Timestamp |
Unix seconds tại lúc gửi |
ChugAx-Signature |
v1=<hex HMAC-SHA256(secret, timestamp + "." + raw body)> |
Content-Type |
application/json |
User-Agent |
ChugAx-Webhooks/1 |
Ký bằng nguyên chuỗi secret whsec_..., không giải mã base64. Kiểm tra chữ ký trên raw body trước khi parse JSON; không stringify lại. Kiểm tra timestamp trong cửa sổ 5 phút và lưu id đã nhận bền vững để chống phát lại. Chỉ trả 2xx sau khi đã lưu công việc; xử lý nặng ở worker của bạn. Không coi receipt thành công là đã tải file về.
Xác minh · Node.js
Hàm nhận rawBody là Buffer nguyên bản và headers là Headers. Lưu secret ở biến môi trường trên máy nhận.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verify(rawBody, headers) {
const timestamp = headers.get('ChugAx-Webhook-Timestamp') ?? '';
const signature = headers.get('ChugAx-Signature') ?? '';
if (!/^\d+$/.test(timestamp) || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) throw Error('timestamp');
if (!/^v1=[a-f0-9]{64}$/.test(signature)) throw Error('signature');
const secret = process.env.UP4K_WEBHOOK_SECRET;
if (!secret) throw Error('missing secret');
const expected = createHmac('sha256', secret).update(timestamp + '.').update(rawBody).digest();
if (!timingSafeEqual(expected, Buffer.from(signature.slice(3), 'hex'))) throw Error('signature');
const payload = JSON.parse(rawBody.toString('utf8'));
if (payload.id !== headers.get('ChugAx-Webhook-Id')) throw Error('id');
return payload; // Dedupe id trong database trước khi enqueue và trả 2xx.
}
Xác minh · Python
import hashlib, hmac, json, os, re, time
def verify(raw_body: bytes, headers):
timestamp = headers.get('ChugAx-Webhook-Timestamp', '')
signature = headers.get('ChugAx-Signature', '')
if not re.fullmatch(r'\d+', timestamp) or abs(time.time() - int(timestamp)) > 300:
raise ValueError('timestamp')
if not re.fullmatch(r'v1=[a-f0-9]{64}', signature):
raise ValueError('signature')
secret = os.environ['UP4K_WEBHOOK_SECRET'].encode()
expected = 'v1=' + hmac.new(secret, timestamp.encode() + b'.' + raw_body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, signature):
raise ValueError('signature')
payload = json.loads(raw_body)
if payload['id'] != headers.get('ChugAx-Webhook-Id'):
raise ValueError('id')
return payload # Dedupe id bền vững trước khi enqueue và trả 2xx.
Giao ít nhất một lần, tối đa 6 lần thử. Sau thất bại, khoảng chờ lần lượt 1 phút, 5 phút, 30 phút, 2 giờ, 6 giờ; cron có thể làm chậm hơn. Retry dùng cùng event id nên bên nhận phải deduplicate. Tự tắt sau 20 delivery lỗi liên tiếp và có thông báo trong tài khoản. Lưu lại URL sẽ bật lại endpoint và bắt đầu chuỗi đếm lỗi mới.
“Gửi thử” tối đa 5 lần/phút theo tài khoản; quá mức trả 429 rate_limited kèm Retry-After (giây). Test gửi đồng bộ job.done với job id test_..., không lưu thành last delivery; UI hiển thị HTTP máy nhận. Lỗi truyền tải trả 502 và status_code:null. Đây không phải job xử lý thật. Receiver trả lỗi HTTP vẫn được UI báo đúng HTTP đó.
n8n và Make
Luồng HTTP Request: GET /api/v1/me → hỏi self-likeness và xin đồng ý hình ảnh/giọng nói nếu có → POST /api/v1/jobs với metadata và consent → PUT file binary tới upload_url với upload_headers → POST submit → Webhook node nhận job.done/job.failed hoặc poll GET job → HTTP Request tải https://up4k.io + job.download_url với Bearer key → lưu file vào kho của bạn.
Lưu Idempotency-Key cùng input của lần chạy để nối tiếp không trùng. Đặt API key trong credential riêng của automation, không trong workflow công khai. Bật chế độ raw body của webhook node để xác minh chữ ký, hoặc đặt receiver xác minh phía trước node. Dedupe theo ChugAx-Webhook-Id; lọc job id test_... trong luồng thử. Khi job.failed, báo message/reason cho chủ workflow; đừng tự tạo vòng lặp retry không giới hạn.
Mã lỗi
Một mã có thể trả về nhiều mã HTTP tuỳ thao tác. Mỗi tài khoản được nhận tối đa 1.000 job API/ngày, gộp tất cả API key; Creator không giới hạn. Ngày tính từ 00:00 giờ Việt Nam đến trước 00:00 ngày kế tiếp. Chỉ tính job đã được nhận vào hàng chờ theo thời điểm queued_at, kể cả sau đó thất bại, bị hủy, từ chối, hết hạn hoặc hoàn credit. Upload chưa submit và gửi lại cùng yêu cầu thành công không tăng số đếm. Retry thành công tạo job mới và tính thêm một credit; job upload trên web không dùng hạn mức API.
GET /api/v1/me trả api_daily_jobs: {used,limit}: used là số job API đã nhận hôm nay; limit là 1000, hoặc null cho Creator. Các trường ví và limits giữ nguyên ý nghĩa. Khi submit hoặc retry vượt hạn mức API, server trả 429 với error.code: "daily_limit" và header Retry-After là số giây đến 00:00 giờ Việt Nam kế tiếp. Hiển thị error.message cho người dùng và chờ đủ thời gian này trước khi thử lại. Replay thành công vẫn trả kết quả gốc khi đã chạm hạn mức.
| Mã | HTTP | Ý nghĩa | Cách xử lý |
|---|---|---|---|
invalid_api_key |
401 | Key thiếu, sai hoặc đã thu hồi. | Kiểm tra Authorization; tạo key mới nếu cần. |
api_locked |
403 | API chưa được mở hoặc bị chặn. | Kiểm tra quyền tài khoản; cần một đơn nạp từ 199.000đ hoặc liên hệ hỗ trợ. |
account_suspended |
403 | Tài khoản đang bị hạn chế. | Liên hệ hỗ trợ. |
rate_limited |
429 | Quá 120 request/phút/key hoặc quá 5 lần gửi thử webhook/phút. | Chờ theo Retry-After; báo người dùng nếu CLI đã hết số lần thử. |
validation_error |
400 | Dữ liệu hoặc bộ lọc không hợp lệ. | Đọc message, sửa trường sai rồi gửi lại. |
engine_unavailable |
403 / 503 | “Gói 1080p Pro chưa mở” hoặc “Gói 4K Pro chưa mở”. | Chọn engine có trong /api/v1/me → engines hoặc liên hệ quản trị viên. |
duration_limit |
400 | Không đọc được thời lượng hoặc vượt max_seconds. | Báo người dùng; chọn video đúng giới hạn, không lặp lại yêu cầu cũ. |
resolution_limit |
400 | Cạnh dài ngoài 500–2560 px. | Đổi kích thước video trước khi gửi. |
frame_rate_limit |
400 | Tốc độ khung hình trung bình trên 30 fps (trường fps tùy chọn trong body tạo job). | Xuất lại video ở 30 fps trở xuống rồi gửi lại. |
no_credits |
402 | Ví không đủ credit. | Báo người dùng nạp thêm; không tự lặp. |
daily_limit |
429 | Chạm hạn mức ngày của cơ chế tài khoản áp dụng. | Báo người dùng; tài khoản dùng ví không có cap xử lý hằng ngày. |
active_limit |
409 | Đã đủ job active (thường 20, Creator 50). | Báo người dùng, giảm concurrency hoặc chờ job cũ xong; không tự lặp. |
source_dimensions_missing |
400 | Không đọc được kích thước nguồn cho gói đã chọn. | Xuất lại MP4/MOV rồi tải lên. |
source_short_side |
400 | Cạnh ngắn của nguồn không phù hợp với gói. | Chọn gói phù hợp với độ phân giải nguồn. |
source_aspect_ratio |
400 | Tỉ lệ khung nguồn vượt giới hạn của gói. | Chọn gói phù hợp hoặc xuất lại video với tỉ lệ được hỗ trợ. |
idempotency_required |
400 | Thiếu hoặc sai Idempotency-Key khi create/retry. | Dùng 1–128 ký tự A–Z, a–z, 0–9, _ hoặc -. |
idempotency_mismatch |
422 | Cùng key nhưng khác body hoặc job. | Giữ key và body cũ để nối tiếp; chỉ dùng key mới cho yêu cầu mới. |
not_found |
404 | Không tìm thấy job thuộc tài khoản. | Kiểm tra id và tài khoản của key. |
conflict |
409 / 400 | Trạng thái job không cho phép thao tác hoặc dữ liệu nguồn không còn hợp lệ. | Đọc lại job, message và trạng thái; không tạo bản trùng. |
expired |
410 | Nguồn hoặc kết quả đã hết hạn. | Kiểm tra job; chỉ tạo yêu cầu mới khi người dùng đồng ý. |
locked_for_review |
423 | Job đang bị khoá để xem xét. | Chờ kết quả hoặc liên hệ hỗ trợ. |
uploads_closed |
403 | Dịch vụ tạm ngừng nhận video mới. | Báo người dùng và xem thông báo trên web. |
consent_required |
400 | Thiếu khai báo hoặc đồng ý xử lý hình ảnh/giọng nói của chính bạn. | Hỏi người dùng về hình ảnh/giọng nói; với selfLikeness=true phải có selfLikenessConsent=true. |
consent_outdated |
409 | Mã tương thích từ phiên bản cũ; API hiện không kiểm tra phiên bản điều khoản. | Cập nhật CLI hoặc tích hợp lên bản hiện hành; không cần xác nhận điều khoản cho API. |
range_not_satisfiable |
416 | Range nằm ngoài file. | Bỏ Range để tải toàn bộ hoặc sửa khoảng byte. |
upgrade_required |
426 | Phiên bản CLI up4k quá cũ, server không còn hỗ trợ. | Chạy lại bằng npx -y up4k@latest (hoặc cập nhật bản ghim trong cấu hình MCP). |
storage_unavailable |
503 | Kho lưu trữ tạm thời không phản hồi khi tải lên theo từng phần. | Chờ vài giây rồi gửi lại đúng thao tác multipart với cùng upload_id. |
Bảo mật key
Không bao giờ commit API key vào mã nguồn; nếu nghi ngờ key đã bị lộ, hãy thu hồi key trong trang tài khoản và tạo key mới.
Key và secret webhook chỉ hiện một lần. Giữ trong biến môi trường, secret store hoặc config CLI riêng tư; không đưa vào frontend, URL, log, ảnh chụp màn hình hay Git. Ví dụ dùng cx_live_... là placeholder, phải thay bằng key đầy đủ. Quyền thuộc chủ tài khoản, các job chỉ xem và thao tác bằng key của chủ đó.
Thu hồi key tại Tài khoản › API; request dùng key đó bị từ chối ngay. Xoay webhook secret khi bị lộ và cập nhật receiver ngay. npx -y up4k@latest logout chỉ xoá đăng nhập local; phải xoá riêng biến môi trường và thu hồi key trên tài khoản nếu cần. Nếu chia sẻ config MCP, thay key bằng placeholder trước khi gửi.