Bắt đầu nhanh
Client chỉ cần một request để lấy toàn bộ cấu hình đang phục vụ. So version để biết có bản mới; assetVersion là mốc dump catalog tương ứng.
curl https://aov.anhvu.cc/api/config
{"version": 16,
"assetVersion": "2026-09-29T20:31:59Z",
"buttons": [{"name": "Maloch Bách Tướng Ma Nhân", "id": 85}, …],
"billboards": [{"name": "Gildur Jiji", "id": 65}, …],
"soldierSkins": [{"name": "lính thường", "id": 0}, …],
"excludedSkins": {"106": [11, 20], "190": [7, 9], …},
"bannedSkins": [10611, 10620, 59903, …],
"skinNames": {"10917": "Veera Momo", …}}
Thứ tự phần tử trong buttons / billboards / soldierSkins chính là thứ tự hiển thị trên client, nên hãy render theo đúng thứ tự mảng.
4 request còn lại để có đủ dữ liệu hiển thị
GET /api/runtime/thumbnails → ảnh cho buttons / billboards / soldierSkins
GET /api/heroes?limit=… → tướng + ảnh đại diện (160 tướng)
GET /api/hero-skills → nội tại, 3 chiêu mỗi tướng + phép bổ trợ
GET /api/items → trang bị: nhóm, bậc, giá, chỉ số, nội tại
GET /api/dump/runtime/status → số lượng + version từng bộ dữ liệu (field library)
Lấy ảnh và thông tin hiển thị
Có 3 cách lấy ảnh, tuỳ nhu cầu. Tất cả đều không cần token và ảnh CDN đều được server tải sẵn rồi cache — client không phải xử lý CORS.
Bảng nguồn ảnh — tất cả đường lấy ảnh
Cách 1 — Bản đồ ảnh cho danh sách config (nhanh nhất)
Trả về map id → ảnh cho đúng các mục trong /api/config. Dùng khi cần render danh sách Nút bấm / Thông báo hạ / Skin lính kèm ảnh.
GET /api/runtime/thumbnails
GET /api/runtime/thumbnails?types=buttons,billboards,soldierSkins
{"success": true, "available": true,
"catalogGeneratedAt": "2026-09-29T20:31:59Z",
"counts": {"buttons": 81, "billboards": 64, "soldierSkins": 6},
"images": {
"buttons": {"85": {"imageUrl": "/api/dump/runtime/image?type=buttons&id=85&variant=preview&v=…", "thumbnailUrl": ""}},
"billboards": {"65": {"imageUrl": "/api/dump/runtime/image?type=billboards&id=65&variant=preview&v=…", "thumbnailUrl": ""}},
"soldierSkins": {"0": {"imageUrl": "/api/dump/runtime/image?type=soldierSkins&id=93000&variant=share&v=…",
"thumbnailUrl": "/api/dump/runtime/image?type=soldierSkins&id=93000&variant=icon&v=…"}}}}
Khoá map = id trong config (buttons[].id, billboards[].id, soldierSkins[].id). Ưu tiên thumbnailUrl, nếu rỗng thì dùng imageUrl.
Cách 2 — Proxy ảnh theo loại và kích thước
Dùng khi cần ảnh lớn/nhỏ khác nhau, hoặc lấy ảnh skin tướng theo từng cfgId.
GET /api/dump/runtime/image?type=<type>&id=<id>&variant=<variant>
type / id variant nội dung
─────────────────────────────────────────────────────────────────────
heroSkins / cfgId picture ảnh lớn của skin tướng (jpg)
heroSkins / cfgId head ảnh chân dung (jpg, dùng làm avatar)
soldierSkins / id share ảnh share của skin lính (png)
soldierSkins / id icon icon skin lính (png)
buttons / buttonId preview ảnh nút bấm cá nhân (png)
billboards / billboardId preview ảnh thông báo hạ (png)
→ heroSkins LUÔN trả ảnh: nếu game chưa có ảnh thì server trả placeholder SVG (HTTP 200).
→ các loại khác trả 404 nếu CDN không có file ⇒ client tự hiển thị ảnh mặc định.
Cách 3 — Ảnh runtime đã tải sẵn trên máy
Với ranks, heroRanks, runtimeImages, field imageUrl trả về dạng tĩnh /runtime-assets/… — tải trực tiếp, không qua proxy:
GET /runtime-assets/heroRank/141611876719b0d4_legend_icon_5.png → 200 image/png
Ví dụ: render danh sách nút bấm kèm ảnh
const cfg = await (await fetch('/api/config')).json();
const map = (await (await fetch('/api/runtime/thumbnails')).json()).images.buttons;
for (const item of cfg.buttons) {
const image = map[item.id];
const src = image && (image.thumbnailUrl || image.imageUrl);
render({ id: item.id, name: item.name, image: src || null });
}
Dữ liệu có sẵn — lấy được những gì
Toàn bộ dữ liệu của web gom thành 6 bộ, tất cả đều đọc công khai. Cột “Số lượng” là số thật đang phục vụ (lấy từ /api/dump/runtime/status, field library).
Chẩn đoán & đồng bộ: GET /api/dump/runtime/status (số lượng + library), GET /api/dump/runtime/additions (mục chưa có trong config), GET /api/dump/runtime/devices (thiết bị debug đã gửi dump).
Toàn bộ endpoint GET — công khai, không cần token
19 endpoint dưới đây trả dữ liệu hiển thị. Có thể gọi trực tiếp từ client, web hay công cụ bên thứ ba. Các endpoint cần token nằm ở mục Ghi dữ liệu.
Cấu trúc /api/config
Quy ước key skin dùng xuyên suốt hệ thống: key = heroId × 100 + skinId (ví dụ hero 109 + skin 17 → 10917).
Tra cứu — 4 bộ dữ liệu, cùng một kiểu query
// ví dụ: lấy skin có ảnh thật, rồi lấy kỹ năng của tướng đó
const skins = await (await fetch('/api/skin-catalog?q=veera&sort=image&limit=24')).json();
const first = skins.results[0];
const hero = await (await fetch('/api/hero-skills?heroId=' + first.heroId)).json();
// first.thumbnailUrl | first.imageUrl → ảnh dùng trực tiếp (đã qua proxy + cache)
// first.hasImage === false → CDN không có ảnh, tự hiển thị ảnh mặc định
{"success": true, "page": 1, "limit": 36, "total": 2324, "pages": 65,
"results": [{ "key": 10917, "heroId": 109, "skinId": 17, "name": "Veera Momo",
"nameSource": "dump", "hasImage": true,
"thumbnailUrl": "/api/dump/runtime/image?type=heroSkins&id=10917&variant=head&v=…",
"imageUrl": "/api/dump/runtime/image?type=heroSkins&id=10917&variant=picture&v=…" }]}
nameSource: "dump" = tên lấy từ catalog · "manual" = do quản trị đặt tay
Runtime dump — nguồn dữ liệu gốc
Catalog là dữ liệu dump từ game (nút bấm, thông báo hạ, skin tướng, rank, ảnh…). Các endpoint bên dưới dùng để tra cứu và chẩn đoán.
GET /api/dump/runtime/items?type=heroSkins&q=veera&page=1&limit=36
GET /api/dump/runtime/items?type=buttons&status=new # new | renamed | changed | removed | same | missingName
GET /api/dump/runtime/status
GET /api/dump/runtime/additions
{"success": true, "type": "heroSkins", "page": 1, "limit": 36, "total": 3072, "pages": 86,
"results": [{
"id": 10917, "configId": 10917, "cfgId": 10917,
"name": "Veera Momo", "status": "same", "inConfig": true,
"heroId": 109, "skinId": 17,
"imageUrl": "/api/dump/runtime/image?type=heroSkins&id=10917&variant=picture&v=…",
"thumbnailUrl": "/api/dump/runtime/image?type=heroSkins&id=10917&variant=head&v=…"}]}
status: same (đã khớp config) · new (chưa có trong config) · renamed (tên khác)
changed (dữ liệu đổi) · removed (mất khỏi dump) · missingName (chưa có tên hợp lệ)
Con số nhanh: catalog hiện có
— nút bấm ·
— thông báo hạ ·
— skin tướng ·
— skin lính.
Ảnh sẵn sàng: — nút ·
— thông báo hạ ·
— skin lính.
Ghi dữ liệu — cần token quản trị
Mọi thao tác thay đổi dữ liệu đều yêu cầu header x-auth-token. Không có token sẽ nhận 401 {"error":"Chưa đăng nhập"}.
POST /zcx {"password": "…"} → {"success": true, "token": "…"}
Sau đó gửi kèm header: x-auth-token: <token>
Các nhóm endpoint ghi
Token được giữ trong bộ nhớ server: khởi động lại server là mọi phiên đăng nhập hết hiệu lực.
Lưu ý kỹ thuật
- Cache —
/api/config trả Cache-Control: no-store, luôn lấy bản mới. Ảnh qua proxy cache 1 ngày, ảnh /runtime-assets cache 1 ngày và immutable.
- Ảnh CDN — server tải hộ và lưu vào
data/runtime-image-cache/, client không cần quan tâm CORS hay link CDN.
- Phân trang —
/api/dump/runtime/items và /api/skin-catalog trả page, pages, total; limit tối đa 100.
- Thiếu ảnh — với
heroSkins server luôn trả ảnh (placeholder SVG nếu chưa có); các loại khác trả 404, hãy chuẩn bị ảnh mặc định trong app.
- Kỹ năng tướng — nội tại, 3 chiêu và danh sách phép bổ trợ lấy từ trang chủ chính thức (
lienquan.garena.vn) bằng node scripts/fetch-hero-skills.js. Icon được proxy + cache qua /api/skills/icon, không cần gọi thẳng CDN.
- Bổ trợ lệch bản — trang chủ cập nhật chậm hơn game (ảnh bổ trợ còn là bản S1/2026). Phần chênh lệch so với bản đang chạy (
Dịch Chuyển, giới hạn mùa Ma chủng hắc ám) và các bổ trợ đã bỏ nằm trong data/battle_spells_curated.json, được gộp tự động khi dump kèm nguồn (patch notes).
- Trang bị —
node scripts/fetch-items.js dump trang bị từ lienquan.garena.vn/hoc-vien/trang-bi/ (6 nhóm, 3 bậc, giá vàng, chỉ số, nội tại) vào data/items_catalog.json; icon qua /api/items/icon. Trang chủ dừng ở khoảng 07/2026 nên phần lệch của bản đang chạy (trang bị mới, trang bị làm lại) nằm trong data/items_curated.json và được gộp tự động khi dump — hiện là 114 trang bị theo bản 1.64 “Vết Nứt Thời Không”.
- Tên nút cá nhân — nút cá nhân hoá gắn với một skin; nếu skin chưa có tên tiếng Việt (bản VN chưa phát hành, vd nút 57 = skin 13 của Zephys) thì tên hiển thị kèm số skin:
Zephys - Nút cá nhân (skin 13), tên gốc tiếng Trung được trả riêng ở field skinNameCn.
- Ảnh thông báo hạ — nếu CDN Việt Nam (kgvn) không có ảnh, server tự lấy bản gốc từ CDN quốc tế. Header
X-Runtime-Image-Source: cdn-chs cho biết ảnh lấy từ bản đó (chữ trên ảnh có thể là tiếng Trung).
- Tên hiển thị — tên trong config là tên chốt để client hiển thị; tên trong catalog (
/api/dump/runtime/items) chỉ là dữ liệu tham chiếu để đối chiếu.
- Ghi dữ liệu — sau khi thay đổi qua API, gọi
POST /api/publish để tăng version, nếu không client cũ vẫn dùng bản cũ.
- Giới hạn — endpoint ghi không dành cho client phát hành; chỉ dùng từ công cụ quản trị nội bộ của bạn.