List CMS Pages
Public list of admin-managed CMS pages (slug + title + locale + publishedAt). PUBLISHED-only filter — DRAFT and ARCHIVED never leak. CDN-cached 5min/10min SWR.
GET /api/v1/public/pages — 🌐 Public · Rate limit: 60 req / minute
Returns the admin-managed CMS page catalog as a lightweight list — slug + title + locale + publishedAt only. The full HTML body is served by GET /public/pages/:slug. PUBLISHED-only filter is enforced server-side: DRAFT and ARCHIVED pages never leak. Internal fields (publishedBy, authorId, internal IDs, status) are stripped from the response.
Use for footer/sitemap discovery. This is the right endpoint for building a "static pages" navigation menu or a sitemap — small payload (no body), fast to load, CDN-cacheable. To render the actual page content, follow up with GET /public/pages/:slug per slug.
Cap is 500. The server takes at most 500 pages per request. There is no pagination — if your platform has more than 500 published pages, only the most recently updated 500 are returned. (orderBy: updatedAt desc.)
Request
No body, no params, no headers required.
Response headers
| Header | Value |
|---|---|
Cache-Control | public, s-maxage=300, stale-while-revalidate=600 |
Response
200 OK — ArrayApiResponseOf<PublicCmsPageListItemDto>
{
"success": true,
"data": [
{
"slug": "about-us",
"title": "About Us",
"locale": "en",
"publishedAt": "2026-04-29T20:00:00.000Z"
},
{
"slug": "careers",
"title": "Careers",
"locale": "en",
"publishedAt": "2026-04-15T10:00:00.000Z"
}
]
}Item fields
| Field | Type | Notes |
|---|---|---|
slug | string | Pass to GET /public/pages/:slug to fetch the body |
title | string | Display title |
locale | string | Locale code (e.g. en, tr) — there can be multiple rows per slug, one per locale |
publishedAt | string (ISO 8601) | null | When the page transitioned to PUBLISHED |
Stripped fields
The following exist on the underlying CMSPage model but are excluded from this response: id, content, status, publishedBy, authorId, createdAt, updatedAt. They're either internal-only (security) or too heavy (content HTML body served separately).
Errors
| HTTP | code / i18nKey | Reason |
|---|---|---|
429 | (throttle) | Rate limit exceeded (60 req/min) |
Side effects
prisma.cMSPage.findMany({ where: { status: PUBLISHED }, select: { slug, title, locale, publishedAt }, orderBy: { updatedAt: 'desc' }, take: 500 }).- Return the array as-is. No mutations, no auth, no per-user state.
Code samples
curl https://api.bio.re/api/v1/public/pagestype PublicCmsPageListItem = {
slug: string;
title: string;
locale: string;
publishedAt: string | null;
};
async function listCmsPages(): Promise<PublicCmsPageListItem[]> {
const res = await fetch('https://api.bio.re/api/v1/public/pages');
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Pages list fetch failed'), {
code: json?.error?.code,
});
}
return json.data;
}import { useQuery } from '@tanstack/react-query';
export const contentKeys = {
pagesList: () => ['content', 'pages', 'list'] as const,
};
export function useCmsPagesList() {
return useQuery({
queryKey: contentKeys.pagesList(),
queryFn: async () => {
const res = await fetch('/api/v1/public/pages');
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Pages list fetch failed'), {
code: json?.error?.code,
i18nKey: json?.error?.i18nKey,
});
}
return json.data as PublicCmsPageListItem[];
},
// CDN cache window
staleTime: 5 * 60_000,
});
}Try it
Response Body
application/json
curl -X GET "https://loading/api/v1/public/pages"{
"success": true,
"data": [
{
"slug": "about-us",
"title": "About Us",
"locale": "en",
"publishedAt": "2019-08-24T14:15:22Z"
}
]
}Source
| Source | Path | Lines |
|---|---|---|
| Controller | apps/api-core/src/modules/content/public-content.controller.ts | 63–70 (listPages) |
| DTO (response item) | apps/api-core/src/modules/content/dto/content-public-response.dto.ts | 42–54 (PublicCmsPageListItemDto) |
| Service | apps/api-core/src/modules/content/content.service.ts | 97–104 (listPublicPages) |
| Prisma model | packages/prisma/prisma/schema.prisma | CMSPage (filter status = PUBLISHED, enum ContentStatus) |
Get 2FA Status
Read whether 2FA is currently enabled on the calling user. Read-only — useful for rendering the right UI on settings screens.
Get CMS Page (by slug)
Public read of a single CMS page by slug. Optional locale selector (default 'en'). HTML body server-side sanitized (script / style / on* / iframe stripped). 404 on missing or DRAFT.