Chuyển tới nội dung chính

Tham chiếu API

Địa chỉ gốc: https://api.i-catholic.org/v2/public/cms/{siteSlug}. Có đúng bốn đường dẫn:

Phương thứcĐường dẫnDùng để
GET/siteThông tin trang web, ngôn ngữ, danh mục, thẻ, menu
GET/entriesDanh sách bài viết (lọc theo danh mục, thẻ, tìm kiếm, «Đọc nhiều»)
GET/entries/{entrySlug}Một bài viết hoặc một trang
POST/entries/{entrySlug}/viewTín hiệu đếm một lượt xem

Quy tắc chung:

  • Không cần xác thực. API bỏ qua mọi header Authorization; gửi token cũng không làm thay đổi kết quả.
  • Tham số là tập đóng. Một tham số không có trong bảng của đường dẫn đó bị từ chối với 400 (ví dụ ?preview=1).
  • siteSlug: chữ thường a-z, số và -, 1–64 ký tự. entrySlug: chữ thường và số, nối bằng một dấu - (ví dụ le-bon-mang), tối đa 120 ký tự. Slug sai dạng nhận về cùng 404 như slug không tồn tại.
  • Dữ liệu trả về không bao giờ chứa mã số nội bộ, trạng thái, tác giả hay bản nháp.

Lấy thông tin trang web​

GET /v2/public/cms/{siteSlug}/site?locale=vi
Tham sốBắt buộcGiá trị
localekhôngvi, en, es, pt, fr, it. Bỏ trống thì dùng ngôn ngữ chính của trang web. Nên luôn ghi rõ (xem cache).

Phản hồi 200, dạng { data: PublicCmsSite }:

TrườngKiểuGhi chú
slugstringMã trang web.
primaryLocalestringNgôn ngữ chính.
localesstring[]Các ngôn ngữ đã bật. Chỉ những ngôn ngữ này được phục vụ.
localestringNgôn ngữ mà khối info thực sự được trả về (xem Đa ngôn ngữ).
infoobject | nullThông tin đơn vị. null khi nhân sự chưa từng lưu thông tin: hãy có nội dung dự phòng.
categoriesobject[]Mọi danh mục, theo thứ tự cây: mỗi danh mục cấp 1, rồi các con của nó.
tagsobject[]Mọi thẻ, xếp theo tên. Bài viết chỉ mang slug của thẻ; tên thẻ đọc ở đây.
menusobjectLuôn có primary và footer (mảng, có thể rỗng).

info (chuỗi văn bản thuần, không phải HTML; hãy in ra như văn bản):

TrườngKiểu
namestring (luôn có nội dung)
shortName, legalName, tagline, motto, mottoRef, description, address, email, copyrightstring (có thể rỗng)
phonesstring[] (tối đa 5)
officeHoursstring[] (tối đa 10 dòng)
mapEmbedUrlstring | null. Khi có, luôn là một địa chỉ nhúng Google Maps (https://www.google.com/maps… hoặc https://maps.google.com/…), dùng làm src của <iframe>.

Danh mục { slug, parent, name, position }: parent là slug của danh mục cha hoặc null; cây có tối đa hai cấp. Thẻ { slug, name }.

Mục menu:

TrườngKiểuGhi chú
labelstringNhãn hiển thị.
kindentry | term | urlMục trỏ tới đâu.
slugstringVới entry và term.
entryTypepost | pageVới entry.
categorystringVới entry là bài viết: slug danh mục chính, để bạn dựng đường dẫn đúng chuyên mục.
taxonomycategory | tagVới term.
urlstringVới url: hoặc đường dẫn trong trang web của bạn bắt đầu bằng /, hoặc một địa chỉ https:// đầy đủ.
childrenobject[]Mục con (menu tối đa hai cấp).

Mục entry và term không có sẵn đường dẫn: bạn tự dựng đường dẫn theo cấu trúc trang web của mình từ slug (ví dụ /trang/{slug} cho trang, /tin-tuc/{slug} cho bài, /tin-tuc?category={slug} cho danh mục). Mục trỏ tới nội dung đã gỡ, chưa xuất bản hay không có bản dịch phù hợp đã được bỏ sẵn khỏi menu (cùng các mục con).

function menuHref(item: MenuItem): string {
switch (item.kind) {
case 'entry':
return item.entryType === 'page' ? `/trang/${item.slug}` : `/tin-tuc/${item.slug}`
case 'term':
return `/tin-tuc?${item.taxonomy === 'tag' ? 'tag' : 'category'}=${encodeURIComponent(item.slug!)}`
case 'url':
return item.url! // starts with "/" (your site) or "https://" (external)
}
}

Lỗi: 404 (trang web không có, chưa bật, ngôn ngữ chưa bật), 400 (locale ngoài sáu ngôn ngữ, tham số lạ), 429.

Lấy danh sách bài viết​

GET /v2/public/cms/{siteSlug}/entries?locale=vi&page=1&limit=12

Chỉ trả về bài viết (post) đã xuất bản và có bản dịch đúng ngôn ngữ locale. Trang tĩnh (page) không bao giờ nằm trong danh sách.

Tham sốBắt buộcGiá trị
localecóMột trong các ngôn ngữ đã bật của trang web.
categorykhôngSlug danh mục. Danh mục cha bao gồm cả bài của danh mục con.
tagkhôngSlug thẻ.
qkhôngTừ khóa tìm kiếm, 2–100 ký tự sau khi cắt khoảng trắng. Xem Tìm kiếm.
sortkhôngChỉ nhận popular («Đọc nhiều»): khi đó page phải là 1 và limit là 3, 6 hoặc 12.
pagecóSố nguyên 1–100000.
limitcóĐúng một trong 3, 6, 12, 24, 100.

category, tag, q, sort loại trừ nhau: gửi hai cái trở lên nhận 400 với message: "CMS_FILTER_CONFLICT". Viết tham số theo thứ tự locale, category, tag, q, sort, page, limit.

Thứ tự kết quả (khi không tìm kiếm và không sort): các bài nổi bật của chính danh sách đó đứng đầu (theo thứ tự nhân sự sắp, tối đa 10), sau đó là bài mới nhất theo publishedAt. Danh sách chung (không lọc) dùng bài nổi bật của trang chủ; danh sách theo danh mục dùng bài nổi bật của danh mục đó; danh sách theo thẻ không có bài nổi bật.

Bài của loại nội dung «không liệt kê»

Nhân sự có thể đánh dấu một loại nội dung là không liệt kê (ví dụ một loại chỉ dùng cho mục riêng). Bài của loại đó không xuất hiện trong danh sách chung, «Đọc nhiều» và kết quả tìm kiếm, nhưng vẫn xuất hiện trong danh sách theo danh mục, theo thẻ, và mở được theo slug.

Phản hồi 200:

{
"data": [
{
"slug": "le-bon-mang",
"category": "tin-tuc",
"categories": ["tin-tuc"],
"tags": ["gioi-tre"],
"title": "Thánh lễ Bổn mạng",
"excerpt": "Đoạn tóm tắt ngắn…",
"publishedAt": "2026-10-12T01:30:00.000Z",
"featured": true,
"cover": { "url": "https://…/anh-bia.webp", "alt": "Cộng đoàn dâng lễ" },
"locale": "vi",
"contentType": null,
"meta": {}
}
],
"meta": { "page": 1, "limit": 12, "total": 37, "pageCount": 4 }
}

Mục trong danh sách không có trường type: mọi mục đều là bài viết.

TrườngKiểuGhi chú
slugstring
categorystringSlug danh mục chính.
categoriesstring[]Mọi danh mục của bài.
tagsstring[]Slug các thẻ; tên đọc ở /site.
title, excerptstringVăn bản thuần. excerpt có thể rỗng.
publishedAtstringISO 8601, giờ UTC. Hiển thị theo múi giờ của bạn.
featuredbooleanNổi bật trong danh sách này. Luôn false khi tìm kiếm và «Đọc nhiều».
coverobject | nullẢnh bìa { url, alt }; url là địa chỉ https:// đầy đủ, alt có thể rỗng.
localestringLuôn bằng locale bạn hỏi.
contentTypestring | nullSlug loại nội dung; null với bài thường.
metaobjectTrường tùy chỉnh. Xem Trường tùy chỉnh.

meta của danh sách: { page, limit, total, pageCount }. Một trang vượt quá pageCount trả về data rỗng. Với sort=popular, total là số mục thực trả về.

Lỗi: 404 (trang web/ngôn ngữ như trên, hoặc slug danh mục/thẻ không tồn tại), 400 (thiếu locale/page/limit, limit ngoài danh sách, CMS_FILTER_CONFLICT, CMS_SEARCH_QUERY_INVALID, CMS_POPULAR_QUERY_INVALID, tham số lạ), 429.

Lấy một entry​

GET /v2/public/cms/{siteSlug}/entries/{entrySlug}?locale=vi
Tham sốBắt buộcGiá trị
localecóMột ngôn ngữ đã bật. Entry phải có bản dịch đúng ngôn ngữ này, nếu không là 404.

Trả về bài viết hoặc trang. Ngoài mọi trường của mục danh sách, có thêm:

TrườngKiểuGhi chú
typepost | page
categorystring | nullnull với trang (trang không có danh mục, categories và tags là []).
bodyHtmlstringNội dung HTML.
seoobject{ title, description, auto }.
featuredbooleanỞ đây là cờ nổi bật của danh sách trang chủ.

slug trong phản hồi có thể khác slug bạn hỏi: khi nhân sự đổi slug, slug cũ vẫn trả 200 với entry hiện tại. Xem Slug cũ.

seo: nếu nhân sự không nhập, máy chủ tự tạo khi đọc: title từ tiêu đề (cắt ở 70 ký tự), description từ tóm tắt hoặc thân bài (cắt ở 160 ký tự, theo từ); khi đó auto là true. Trong thực tế cả hai luôn là chuỗi, nhưng kiểu khai báo cho phép null, nên hãy dự phòng.

bodyHtml đã được máy chủ lọc theo danh sách cho phép:

  • thẻ: p br strong b em i u a ul ol li h2 h3 blockquote hr img;
  • a: chỉ href dạng http:, https:, mailto:, luôn kèm rel="noopener noreferrer";
  • img: chỉ src dạng https:// và alt;
  • không có style, class, id, on* hay bất kỳ thuộc tính nào khác.

Dù vậy, hãy lọc lại ở phía bạn (ví dụ DOMPurify với cùng danh sách) trước khi chèn bằng innerHTML / dangerouslySetInnerHTML: đừng tin tuyệt đối một phản hồi mạng. Đây cũng là chỗ tốt để thêm loading="lazy" cho ảnh và target="_blank" cho liên kết ra ngoài. Ảnh trong thân bài có thể nằm trên bất kỳ máy chủ https nào; nếu trang của bạn có Content Security Policy, hãy cho phép img-src https:.

Lỗi: 404 (trang web/ngôn ngữ như trên, entry không có, chưa xuất bản, hẹn giờ chưa tới, đã xóa, hoặc không có bản dịch ngôn ngữ này), 400 (thiếu hoặc sai locale, tham số lạ), 429.

Gửi tín hiệu lượt xem​

POST /v2/public/cms/{siteSlug}/entries/{entrySlug}/view

Không tham số, không thân yêu cầu, không header. Luôn trả 204 không có nội dung, kể cả khi lượt đó không được đếm. Cách gọi đúng và quy tắc đếm: Lượt xem.

Dạng lỗi​

Mọi lỗi có cùng dạng:

{
"statusCode": 400,
"errorCode": "VALIDATION_ERROR",
"message": "limit must be one of the following values: 3, 6, 12, 24, 100",
"timestamp": "2026-10-19T12:34:26.516Z",
"requestId": "oaf24ltjxmpxia9x4dedtn4b"
}
statusCodeerrorCodemessage
404NOT_FOUNDLuôn đúng "Not found". Không phân biệt được trang web sai, nội dung không có hay ngôn ngữ chưa bật.
400VALIDATION_ERRORMột mã như CMS_FILTER_CONFLICT, CMS_SEARCH_QUERY_INVALID, CMS_POPULAR_QUERY_INVALID, hoặc câu mô tả lỗi tham số (nhiều lỗi nối bằng ; ).
429RATE_LIMITEDVượt giới hạn tần suất. Xem Giới hạn.
5xxví dụ INTERNAL_ERRORLỗi phía máy chủ; thử lại sau.

Hãy rẽ nhánh theo statusCode và (với 400) theo message; ghi lại requestId khi báo lỗi cho chúng tôi.