Bắt đầu
Mọi endpoint nằm dưới địa chỉ gốc:
https://api.dybiweb.com/api/public/v1
- Đăng nhập CMS bằng tài khoản có quyền quản trị cấu hình, vào Cấu hình → Kết nối → API.
- Tạo API key: đặt tên gợi nhớ, chọn quyền cần dùng và thời hạn (30 ngày đến 2 năm).
- Sao chép key ngay khi tạo. Key chỉ hiển thị một lần; hệ thống không lưu bản gốc.
- Gọi thử endpoint kiểm tra key:
curl https://api.dybiweb.com/api/public/v1/me \
-H "X-Api-Key: dybi_live_xxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
{
"companyId": "5b0c…",
"companyName": "Tên doanh nghiệp",
"keyName": "Công cụ đăng bài",
"scopes": ["articles:read", "articles:write", "files:read", "files:write"],
"expiresUtc": "2027-10-28T04:37:31Z"
}
Xác thực và quyền
Gửi key trong header X-Api-Key ở mọi yêu cầu, chỉ qua HTTPS. Không đặt key trên địa chỉ URL hoặc trong mã chạy trên trình duyệt: yêu cầu có header Origin của trình duyệt sẽ bị từ chối.
Key thuộc về một doanh nghiệp và hoạt động với danh nghĩa người đã tạo key: bài tạo qua API ghi người đó là người tạo. Key chỉ đọc, ghi dữ liệu của doanh nghiệp mình.
| Quyền (scope) | Cho phép |
|---|---|
articles:read | Xem danh mục và bài viết |
articles:write | Thêm và sửa bài viết |
files:read | Xem danh sách ảnh trong thư viện |
files:write | Upload ảnh |
Key ngừng hoạt động ngay khi bị thu hồi trong CMS, hết hạn, hoặc khi người tạo bị khóa tài khoản hay không còn quyền quản trị cấu hình. Khi đó hãy tạo key mới. Nếu nghi key bị lộ, thu hồi ngay; lịch sử sử dụng key xem ở tab Lịch sử cùng màn hình.
Key chỉ sửa được bài do người tạo key viết. Muốn sửa bài của người khác, người tạo key cần quyền sửa nội dung của người khác trong CMS.
Giới hạn
| Mục | Giới hạn |
|---|---|
| Số yêu cầu | 60 yêu cầu/phút cho mỗi key |
| Upload ảnh | 20 file/phút cho mỗi key |
| Xác thực sai | 30 lần/phút cho mỗi địa chỉ IP, sau đó tạm chặn 1 phút |
| File ảnh | JPG, PNG, WEBP, GIF; tối đa 5 MB; tối đa 8000px mỗi chiều, 25 triệu điểm ảnh, 300 khung hình |
| Bài viết | Tiêu đề 300 ký tự; mô tả ngắn 2000 ký tự; nội dung 1.000.000 ký tự; tối đa 20 thẻ, mỗi thẻ 100 ký tự |
| Phân trang | pageSize tối đa 100 |
Vượt giới hạn tần suất nhận mã 429 kèm header Retry-After (số giây cần chờ). Hãy chờ đúng thời gian đó rồi gửi lại.
Đăng bài có ảnh
- Upload từng ảnh bằng
POST /files. Kết quả cóurl(ảnh gốc) vàwebpUrl(bản WebP do hệ thống tạo). - Chèn
urlvào nội dung bài, ví dụ<img src="…" alt="Mô tả ảnh">. - Lấy
iddanh mục bằngGET /categories. - Tạo bài bằng
POST /articles; dùngcoverFilelàfileNamecủa ảnh muốn làm ảnh đại diện. Bài mới mặc định là nháp. - Kiểm tra trong CMS, rồi đăng bằng
PATCH /articles/{id}với"isPublished": true(hoặc gửi luôn khi tạo bài).
Danh sách endpoint
| Method | Đường dẫn | Quyền | Mô tả |
|---|---|---|---|
| GET | /me | bất kỳ | Thông tin key và doanh nghiệp |
| GET | /categories | articles:read | Danh mục bài viết |
| GET | /articles | articles:read | Danh sách bài viết |
| GET | /articles/{id} | articles:read | Chi tiết bài viết |
| POST | /articles | articles:write | Thêm bài viết |
| PATCH | /articles/{id} | articles:write | Sửa bài viết |
| POST | /files | files:write | Upload ảnh |
| GET | /files | files:read | Danh sách ảnh, kèm link |
Bài viết
GET /categories
Tham số tùy chọn: language (mặc định vi) để lấy tên danh mục theo ngôn ngữ.
[
{ "id": "8f0e…", "parentId": null, "title": "Tin tức", "isPublished": true, "order": 1 }
]
GET /articles
Tham số tùy chọn: categoryId, q (tìm theo tiêu đề, gõ có dấu hoặc không dấu), language, page (mặc định 1), pageSize (mặc định 20). Bài mới nhất theo ngày hiển thị đứng trước.
{
"items": [{
"id": "3c1d…", "categoryId": "8f0e…", "title": "Bài viết đầu tiên",
"isPublished": false, "displayDate": "2026-10-28T10:00:00", "order": 50,
"coverUrl": "https://api.dybiweb.com/Files/…/Article/bai-viet-dau-tien_638….jpg",
"path": "/bai-viet-dau-tien", "url": "https://ten-mien-cua-ban/bai-viet-dau-tien",
"languages": ["vi"]
}],
"total": 1, "page": 1, "pageSize": 20
}
GET /articles/{id}
Tham số tùy chọn language. Trả về tiêu đề, mô tả ngắn, nội dung HTML, thẻ, ngày hiển thị, trạng thái đăng, ảnh đại diện, đường dẫn trên website và các ngôn ngữ đã có. Trả 404 nếu bài chưa có bản ngôn ngữ được yêu cầu.
POST /articles
curl -X POST https://api.dybiweb.com/api/public/v1/articles \
-H "X-Api-Key: $DYBI_API_KEY" -H "Content-Type: application/json" \
-d '{
"categoryId": "8f0e…",
"title": "Bài viết đầu tiên",
"brief": "Tóm tắt ngắn hiển thị ở danh sách bài.",
"content": "<h2>Mở đầu</h2><p>Nội dung…</p>",
"tags": ["website", "seo"],
"coverFile": "20261028103000_a1b2c3d4_anh-bia.jpg",
"isPublished": false
}'
| Trường | Bắt buộc | Ghi chú |
|---|---|---|
categoryId | Có | Danh mục bài viết lấy từ GET /categories |
title | Có | Văn bản thuần, tối đa 300 ký tự; dùng để tạo đường dẫn SEO |
brief | Có | Văn bản thuần, thẻ HTML sẽ bị bỏ |
content | Không | HTML, được làm sạch theo quy tắc nội dung |
language | Không | Mặc định vi; phải là ngôn ngữ đã bật cho website |
tags | Không | Danh sách thẻ; thẻ trùng sẽ được gộp |
displayDate | Không | Ngày hiển thị, mặc định là thời điểm tạo |
isPublished | Không | Mặc định false (nháp) |
order | Không | Thứ tự sắp xếp, mặc định 50 |
coverFile | Không | fileName trả về từ POST /files; dùng làm ảnh đại diện |
id | Không | GUID do bạn chọn. Gửi lại cùng id sau khi mất kết nối sẽ nhận 409 thay vì tạo bài trùng |
Thành công trả 201, header Location và nội dung bài như GET /articles/{id}, gồm cả path/url trên website.
PATCH /articles/{id}
Chỉ gửi những trường cần đổi; trường không gửi hoặc null giữ nguyên. Gửi "content": "" để xóa nội dung, "tags": [] để xóa thẻ. Trường language chọn bản ngôn ngữ cần sửa (mặc định vi); gửi một ngôn ngữ bài chưa có để thêm bản dịch, khi đó cần title và brief.
curl -X PATCH https://api.dybiweb.com/api/public/v1/articles/3c1d… \
-H "X-Api-Key: $DYBI_API_KEY" -H "Content-Type: application/json" \
-d '{ "isPublished": true }'
File ảnh
POST /files
Gửi multipart/form-data với đúng một file trong trường file. Ảnh được kiểm tra nội dung thật, bỏ thông tin EXIF/vị trí và lưu với tên do hệ thống đặt.
curl -X POST https://api.dybiweb.com/api/public/v1/files \
-H "X-Api-Key: $DYBI_API_KEY" \
-F "[email protected]"
{
"fileName": "20261028103000_a1b2c3d4_anh-bia.jpg",
"url": "https://api.dybiweb.com/Files/…/20261028103000_a1b2c3d4_anh-bia.jpg",
"webpUrl": "https://api.dybiweb.com/Files/…/20261028103000_a1b2c3d4_anh-bia.jpg.webp",
"size": 182344, "contentType": "image/jpeg", "width": 1600, "height": 900,
"modifiedUtc": "2026-10-28T03:30:00Z"
}
File lớn hơn giới hạn nhận 413. Với file lớn, curl tự gửi Expect: 100-continue nên nhận được thông báo lỗi trước khi gửi hết dữ liệu; thư viện khác nên bật tùy chọn tương tự hoặc kiểm tra kích thước trước khi gửi.
GET /files
Danh sách ảnh trong thư viện của website (cùng thư viện với trình chọn ảnh trong CMS), mới nhất trước. Tham số tùy chọn: q (tìm theo tên file), page, pageSize (mặc định 50). Mỗi ảnh có fileName, url, webpUrl, size, modifiedUtc.
HTML được phép trong nội dung
Nội dung được làm sạch về đúng định dạng trình soạn thảo của CMS để có thể tiếp tục sửa trong CMS:
- Giữ: đoạn văn, tiêu đề
h2–h6, in đậm/nghiêng/gạch chân/gạch ngang, chỉ số trên/dưới, danh sách, trích dẫn, khối mã, liên kết, ảnh và video YouTube/Vimeo nhúng. h1được đổi thànhh2vì tiêu đề bài là H1 duy nhất của trang.- Ảnh phải dùng địa chỉ
https://; nên dùngurlnhận từPOST /filesvà luôn cóalt. - Chỉ giữ class căn lề/thụt lề của trình soạn thảo (
ql-align-*,ql-indent-*…) và màu chữ/màu nền. - Bỏ: script, style, form, iframe khác YouTube/Vimeo, thuộc tính sự kiện (
onclick…), liên kếtjavascript:. Thẻ bọc nhưdiv,sectionđược bỏ nhưng giữ chữ bên trong.
Mã lỗi
Lỗi trả về JSON thống nhất; hiển thị hoặc ghi log trường message:
{ "codeResponse": 422, "codeError": 0, "message": "Danh mục bài viết … không tồn tại. Lấy danh sách bằng GET /categories." }
| Mã | Ý nghĩa |
|---|---|
400 | Dữ liệu thiếu hoặc sai định dạng |
401 | Thiếu key, key sai, hết hạn, đã thu hồi, gọi qua HTTP hoặc từ trình duyệt |
403 | Key thiếu quyền cho thao tác, hoặc sửa bài của người khác |
404 | Không có bài viết hoặc bản ngôn ngữ (kể cả bài của doanh nghiệp khác) |
409 | Đã có bài với id gửi lên |
413 | File vượt quá 5 MB |
415 | Không phải ảnh JPG/PNG/WEBP/GIF hợp lệ, hoặc không gửi multipart |
422 | Danh mục, ngôn ngữ hoặc file ảnh đại diện không hợp lệ; ảnh quá lớn |
429 | Vượt giới hạn tần suất; chờ theo Retry-After |
502 | Không lưu được file vào kho lưu trữ; thử lại sau |
Lịch sử thay đổi
v1 (28/10/2026): phát hành API key theo doanh nghiệp, bài viết (danh mục, danh sách, chi tiết, thêm, sửa) và file ảnh (upload, danh sách). Mô tả máy đọc được: OpenAPI public-v1.