Mô tả máy đọc được (OpenAPI 3.0): https://vidgen.vn/api/v1/openapi.json.
Bắt đầu
- Đăng nhập, mở trang API (mục «API» ở chân trang của ứng dụng, địa chỉ
#api), bấm «Tạo khoá». Khoávg_live_…và bí mật webhook chỉ hiện một lần: lưu ngay. Gói của tổ chức (Đội nhóm, Doanh nghiệp): chọn tổ chức trước rồi mới tạo khoá. - Mọi yêu cầu gửi tới địa chỉ gốc
https://vidgen.vn/api/v1, thân và kết quả là JSON UTF-8. - Thử ngay bằng một dòng:
POST /quickvới{"text": "…"}(mục Tạo nhanh).
Xác thực
Gửi tiêu đề Authorization: Bearer vg_live_… trong mọi yêu cầu. Không cần cookie hay tiêu đề chống giả mạo yêu cầu khi dùng khoá.
Khoá có quyền như tài khoản của bạn (hạn mức, gói, giọng đọc): chỉ dùng ở máy chủ, không nhúng vào trang web hay ứng dụng di động; lộ thì thu hồi ngay ở trang API.
Tối đa 10 khoá mỗi tài khoản (hoặc mỗi tổ chức), 120 yêu cầu mỗi phút mỗi khoá. Máy chủ chỉ lưu bản băm SHA-256 của khoá.
Khoá của tổ chức: tạo khi đang chọn tổ chức (chỉ Chủ tổ chức, Quản trị). Video, dự án tạo bằng khoá này thuộc tổ chức, tính vào gói, số video và lượt API của tổ chức,
và theo cài đặt của tổ chức (giới hạn mỗi thành viên, «Duyệt trước khi dựng»: video giải thích dừng ở review). Người tạo khoá rời tổ chức, thôi quyền quản trị
hoặc tổ chức bị khoá thì khoá trả 401.
curl -s "https://vidgen.vn/api/v1/me" -H "Authorization: Bearer vg_live_..."
Hạn mức
Mỗi video tạo thành công qua khoá API (POST /videos, POST /quick, làm bản khác …/duplicate, bản ngôn ngữ khác …/translate) tính một lượt API của tháng, đồng thời tính vào số video của gói. Yêu cầu lỗi (400, 402…) và lần gọi lại cùng external_id không tốn lượt. Nhiều biến thể trong một lần gọi tính một lượt API, mỗi biến thể một video.
| Gói | Lượt API | Video mỗi tháng |
|---|---|---|
| Miễn phí | Không dùng API | 3 |
| Cơ bản | Không dùng API | 20 |
| Chuyên nghiệp | 200 lượt/tháng | 60 |
| Đội nhóm | 1.000 lượt/tháng | 250 |
| Doanh nghiệp | 10.000 lượt/tháng | 1.000 |
Gói không có API: không tạo được khoá; khoá tạo khi còn gói cao rồi hạ gói thì mọi điểm cuối trả 402 (trừ GET /me để xem gói). Gói Đội nhóm và Doanh nghiệp mua cho tổ chức: Chủ tổ chức hoặc Quản trị chọn tổ chức rồi tạo khoá của tổ chức (mục Xác thực); khoá cá nhân theo gói cá nhân.
Xem chi tiết và nâng gói ở bảng giá. Lượt đã dùng: api.used, api.limit của GET /me và trang Tài khoản.
Tạo nhanh một dòng: POST /quick
«Viết một dòng. Nhận một video.» Vidgen tự đoán loại video (quảng cáo, hướng dẫn, bài giảng), chọn mẫu gần chủ đề nhất, khổ, độ dài, giọng đọc,
soạn kịch bản rồi dựng luôn. Đi qua đúng các kiểm tra như POST /videos: gói, lượt API, số video của tháng, bảo trì.
| Khoá | Ý nghĩa |
|---|---|
text | Bắt buộc. Một dòng mô tả, 5 đến 600 ký tự |
purpose | marketing, huong-dan hoặc kien-thuc; bỏ trống thì đoán từ câu chữ |
layout | short (dọc 9:16, tối đa 60 giây) hoặc long (ngang 16:9); bỏ trống: quảng cáo dọc, còn lại ngang |
external_id, callback_url | Như ở POST /videos |
curl -s -X POST "https://vidgen.vn/api/v1/quick" -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"text": "Giải thích định lý Pythagoras cho học sinh lớp 8", "external_id": "toan-8-pytago"}'
Kết quả giống POST /videos: 202 kèm video (request.template, request.layout, request.seconds cho biết lựa chọn tự động).
Tạo, hỏi tiến độ, tải
Việc dựng chạy nền vài phút. POST /videos trả ngay 202 với id; hỏi GET /videos/{id} mỗi 5 đến 15 giây
hoặc chờ webhook; khi status là done thì tải /videos/{id}/video.
curl
KEY=vg_live_... # khoá của bạn
B=https://vidgen.vn/api/v1
# 1. Tạo video giải thích 45 giây, nhận webhook khi xong
curl -s -X POST "$B/videos" -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -d '{
"kind": "explainer", "brief": "Cache là gì và vì sao website nhanh hơn", "seconds": 45,
"external_id": "bai-viet-42", "callback_url": "https://ung-dung.cua-ban.vn/hooks/vidgen"}'
# -> 202 {"id": "3f2a…", "status": "queued", ...}
# 2. Hỏi tiến độ (vài giây một lần, hoặc chờ webhook)
curl -s "$B/videos/3f2a…" -H "Authorization: Bearer $KEY"
# 3. Tải mp4 và phụ đề khi status = done
curl -sL "$B/videos/3f2a…/video" -H "Authorization: Bearer $KEY" -o video.mp4
curl -sL "$B/videos/3f2a…/srt" -H "Authorization: Bearer $KEY" -o video.srt
Python
import os, time, requests
B = "https://vidgen.vn/api/v1"
H = {"Authorization": "Bearer " + os.environ["VIDGEN_KEY"]}
r = requests.post(B + "/quick", headers=H, json={"text": "Quảng cáo quán cà phê Mộc giảm 20% tuần này",
"external_id": "cafe-moc-1"})
if r.status_code == 402: # hết lượt hoặc gói chưa có API: r.json()["upgrade"] là gói gợi ý
raise SystemExit(r.json()["error"])
r.raise_for_status()
vid = r.json()["id"]
while True:
v = requests.get(f"{B}/videos/{vid}", headers=H).json()
if v["status"] in ("done", "failed", "canceled"):
break
print(v["status"], v.get("stage"), round((v.get("progress") or 0) * 100), "%")
time.sleep(10)
if v["status"] == "done":
with open("video.mp4", "wb") as f:
f.write(requests.get(f"{B}/videos/{vid}/video", headers=H).content)
else:
print("Lỗi:", v["error"])
JavaScript
// Node.js 18+ (có sẵn fetch)
const B = "https://vidgen.vn/api/v1";
const H = {"Authorization": `Bearer ${process.env.VIDGEN_KEY}`, "Content-Type": "application/json"};
const r = await fetch(`${B}/videos`, {method: "POST", headers: H, body: JSON.stringify({
kind: "explainer", brief: "Hướng dẫn đăng ký tài khoản trên ứng dụng của chúng tôi", layout: "long", seconds: 60,
external_id: "huong-dan-dang-ky"})});
const v = await r.json();
if (!r.ok) throw new Error(`${r.status}: ${v.error}`);
let s;
do {
await new Promise(ok => setTimeout(ok, 10000));
s = await (await fetch(`${B}/videos/${v.id}`, {headers: H})).json();
} while (!["done", "failed", "canceled"].includes(s.status));
console.log(s.status, s.result?.video_url ?? s.error);
Tham số tạo video: POST /videos
| Khoá | Ý nghĩa |
|---|---|
kind | explainer (video giải thích, marketing tự vẽ) hoặc screen (mặc định: AI quay màn hình một ứng dụng web công khai) |
brief | Chủ đề (explainer) hoặc điều cần trình diễn (screen); 10 đến 1500 ký tự (explainer từ 5) |
seconds, layout | explainer: 30, 40, 45, 50, 60, 75, 90, 120, 150 hoặc 180 giây (mặc định 45), không vượt độ dài tối đa của gói (plan_features.max_seconds của GET /me); short dọc 9:16 (mặc định, tối đa 60 giây) hoặc long ngang 16:9 |
source | explainer: bài viết nguồn để video bám đúng nội dung (tối đa 20.000 ký tự) |
look, style, cinema | explainer: kiểu hình auto, motion, classic; phong cách và lớp điện ảnh khi dùng motion (giá trị hợp lệ: styles, cinemas của GET /config) |
review_first | explainer: true thì dừng ở review để bạn sửa kịch bản (PUT /videos/{id}/script) rồi POST /videos/{id}/render |
voice | Giọng đọc, một trong voices của GET /me (neu, vbee, dry); bỏ trống thì dùng giọng đầu danh sách |
url, format, quality, max_scenes, auth | screen: địa chỉ công cộng cần quay, long/shorts, 1080/4k, số cảnh, phiên đăng nhập (xoá ngay khi quay xong) |
project_id, name | Lưu vào dự án; đặt tên video |
marketing, variants, angles | Video marketing theo brief sản phẩm và bộ nhận diện của dự án; 1 đến 3 biến thể; góc mở đầu |
external_id | Khoá của bạn, tối đa 100 ký tự A-Za-z0-9._:@/- (xem mục dưới) |
callback_url | https://… công cộng nhận webhook |
Nhiều biến thể trả thêm variants[], mỗi biến thể một video. Chi tiết kiểu dữ liệu ở OpenAPI.
Không tạo trùng: external_id
Gắn mã của bạn (vd. mã bài viết, mã đơn) vào external_id. Gọi lại với cùng mã thì nhận 200 kèm video cũ và "reused": true:
không tạo video mới, không tốn hạn mức hay lượt API. Nhờ vậy gửi lại an toàn khi mất kết nối. Video cũ đã lỗi hoặc bị huỷ thì lần gọi sau tạo video mới.
Mã riêng theo tài khoản; nhiều biến thể nhận mã <mã>#1, <mã>#2…
Webhook
Khi gửi kèm callback_url (bằng khoá API), Vidgen POST JSON tới địa chỉ đó khi video tới done, failed hoặc review:
{"event": "video.done",
"video": {"id": "3f2a…", "status": "done", "external_id": "bai-viet-42", "kind": "explainer", "name": null, "project_id": null, "error": null,
"result": {"title": "Cache là gì", "seconds": 48.2, "bytes": 8435270, "scenes": [{"title": "…", "say": ["…"]}],
"video_url": "/api/v1/videos/3f2a…/video", "srt_url": "/api/v1/videos/3f2a…/srt"}}}
| Tiêu đề | Ý nghĩa |
|---|---|
X-Vidgen-Event | video.done, video.failed, video.review |
X-Vidgen-Signature | sha256=<hex>: HMAC-SHA256 của THÂN yêu cầu bằng bí mật webhook của khoá đã tạo video |
X-Vidgen-Delivery | Mã lần gửi; lưu lại để không xử lý trùng |
Kiểm chữ ký (Python)
import hashlib, hmac, json
from flask import Flask, request, abort
SECRET = "bí mật webhook hiện cùng khoá API"
app = Flask(__name__)
@app.post("/hooks/vidgen")
def vidgen_hook():
raw = request.get_data() # THÂN GỐC, chưa phân tích JSON
want = "sha256=" + hmac.new(SECRET.encode(), raw, hashlib.sha256).hexdigest()
if not hmac.compare_digest(want, request.headers.get("X-Vidgen-Signature", "")):
abort(401)
ev = json.loads(raw)
# chống xử lý trùng: lưu X-Vidgen-Delivery đã xử lý, gặp lại thì bỏ qua
print(ev["event"], ev["video"]["external_id"])
return "", 204
Kiểm chữ ký (JavaScript)
// Express: lấy thân gốc bằng express.raw, KHÔNG dùng express.json trước khi kiểm chữ ký
import crypto from "node:crypto";
import express from "express";
const SECRET = process.env.VIDGEN_WEBHOOK_SECRET;
const app = express();
app.post("/hooks/vidgen", express.raw({type: "application/json"}), (req, res) => {
const want = "sha256=" + crypto.createHmac("sha256", SECRET).update(req.body).digest("hex");
const got = req.get("X-Vidgen-Signature") || "";
if (want.length !== got.length || !crypto.timingSafeEqual(Buffer.from(want), Buffer.from(got))) return res.sendStatus(401);
const ev = JSON.parse(req.body);
console.log(ev.event, ev.video.external_id);
res.sendStatus(204);
});
- Trả mã
2xxtrong 10 giây là thành công; mã khác hoặc lỗi kết nối thì Vidgen thử lại sau 1, 5, 30 giây (tối đa 4 lần). - Vidgen không theo chuyển hướng: địa chỉ trả
3xxbị coi là thất bại. Đặt đúng địa chỉ cuối cùng. callback_urlphải làhttps://tới máy chủ trên Internet công cộng; địa chỉ nội bộ, localhost bị từ chối, và Vidgen nối thẳng tới đúng địa chỉ IP đã kiểm.- Đường dẫn trong webhook là tương đối: ghép với
https://vidgen.vn; tải video vẫn cần khoá API. - Webhook là «cố gắng hết sức»: lâu không thấy thì hỏi lại
GET /videos/{id}.
Mã lỗi
Lỗi trả JSON {"error": "…"} bằng tiếng Việt, nói rõ cần sửa gì.
| Mã | Khi nào |
|---|---|
400 | Yêu cầu sai: thiếu hoặc sai tham số, địa chỉ nội bộ, external_id sai dạng. Đọc error để sửa. |
401 | Thiếu khoá, khoá sai hoặc đã thu hồi, tài khoản bị khoá. Có khoá sai thì KHÔNG quay về phiên đăng nhập web. |
402 | Gói chưa có API (khoá tạo khi còn gói cao, sau đó hạ gói), hết lượt API của tháng, hết video, hoặc tính năng không có trong gói. upgrade là mã gói gợi ý, feature cho biết giới hạn nào; buy_pack: true thì mua thêm video được. |
403 | Thao tác chỉ làm được trên web (quản lý khoá, thanh toán, đổi mật khẩu, Video demo) hoặc vượt giới hạn video mỗi thành viên của tổ chức. |
404 | Không có video, dự án này (hoặc của tài khoản khác). |
409 | Video chưa xong (tải mp4, SRT) hoặc đang chạy (xoá). |
429 | Quá 120 yêu cầu mỗi phút cho một khoá. Chờ rồi gọi lại, nên lùi dần. |
503 | Hệ thống đang bảo trì; đọc tiêu đề Retry-After (giây) rồi gửi lại. Xem và tải video vẫn được. |
Ví dụ 402
{"error": "Đã dùng hết 200 lượt tạo video qua API của tháng này (gói «Chuyên nghiệp»). Nâng cấp lên gói «Đội nhóm» để dùng.",
"upgrade": "team", "feature": "api", "plan": "pro"}
Các điểm cuối khác
| Phương thức | Đường dẫn | Ý nghĩa |
|---|---|---|
| GET | /videos?project=<id|none> | Danh sách video của bạn |
| GET | /videos/{id} | Trạng thái queued, running, review, done, failed, canceled; stage, progress (0 đến 1), result |
| GET | /videos/{id}/video, /srt, /scorm | Tải mp4 (hỗ trợ Range), phụ đề SRT, gói SCORM cho LMS (theo gói) |
| GET/PUT | /videos/{id}/script | Xem, sửa kịch bản khi status là review |
| POST | /videos/{id}/render | Duyệt xong: xếp dựng từ kịch bản đã sửa |
| POST | /videos/{id}/translate | Bản ngôn ngữ khác ({"lang": "en"}): video mới chờ duyệt |
| POST | /videos/{id}/cancel | Huỷ video đang chờ, đang chạy (hoàn hạn mức) |
| PATCH/DELETE | /videos/{id} | Đổi tên, chuyển dự án; xoá |
| GET/POST | /projects; PATCH/DELETE /projects/{id} | Dự án, kèm brief sản phẩm (product) và bộ nhận diện (brand) |
| GET | /me | Gói, hạn mức và số video đã dùng, lượt API (api.limit, api.used), giọng dùng được (voices) |
| GET | /config | Tuỳ chọn hợp lệ: phong cách, lớp điện ảnh, độ dài, ngôn ngữ dịch |
Quản lý khoá API chỉ làm được khi đăng nhập trên web. Cần hỗ trợ tích hợp: liên hệ.