List Help Categories
Public list of published help center categories with article counts. Optional locale filter. Ordered by admin-set sortOrder. CDN 5min/10min SWR.
GET /api/v1/public/help/categories โ ๐ Public ยท Rate limit: 60 req / minute
Returns published help center categories โ the top-level groupings shown on the help center landing page. Each category includes the count of published articles within it (so the UI can render "Payments (12)" without a second query). Optional ?locale= filter; otherwise returns categories across all locales.
Article count is published-only. The articleCount field counts only HelpArticle rows where status = PUBLISHED. Draft / archived articles aren't counted, so the number matches what the user will actually see when clicking into a category.
Request
Query parameters
| Param | Type | Default | Notes |
|---|---|---|---|
locale | string | โ | Filter by locale (e.g. en, tr). Omit for all locales. |
No headers required.
Response headers
| Header | Value |
|---|---|
Cache-Control | public, s-maxage=300, stale-while-revalidate=600 |
Response
200 OK โ ArrayApiResponseOf<PublicHelpCategoryDto>
{
"success": true,
"data": [
{
"id": "hc1a2b3c4-d5e6-7890-abcd-ef1234567890",
"slug": "payments",
"name": "Payments & Billing",
"description": "Wallet, payouts, refunds",
"icon": "credit-card",
"iconBackground": "#F0F4FF",
"sortOrder": 1,
"articleCount": 12
}
]
}Item fields
| Field | Type | Notes |
|---|---|---|
id | string (UUID) | HelpCategory.id |
slug | string | Pass to GET /public/help/articles?category=<slug> to drill in |
name | string | Display name |
description | string | null | Short description for the category card |
icon | string | null | Icon identifier (your design system maps this to a glyph) |
iconBackground | string | null | Hex color for the icon background tile |
sortOrder | number | Admin-set ordering โ server returns rows ordered sortOrder ASC |
articleCount | number | Count of HelpArticle rows where categoryId matches AND status = PUBLISHED |
Errors
| HTTP | code / i18nKey | Reason |
|---|---|---|
429 | (throttle) | Rate limit exceeded (60 req/min) |
Side effects
- Build
where = { status: PUBLISHED, ...(locale ? { locale } : {}) }. prisma.helpCategory.findMany({ where, orderBy: sortOrder asc, include: { _count: { select: { articles: { where: { status: PUBLISHED } } } } } }).- Project the
_count.articlesaggregate into the flatarticleCountfield. - Return the array. No mutations.
Code samples
curl https://api.bio.re/api/v1/public/help/categories
curl 'https://api.bio.re/api/v1/public/help/categories?locale=tr'type PublicHelpCategory = {
id: string;
slug: string;
name: string;
description: string | null;
icon: string | null;
iconBackground: string | null;
sortOrder: number;
articleCount: number;
};
async function listHelpCategories(locale?: string): Promise<PublicHelpCategory[]> {
const url = new URL('https://api.bio.re/api/v1/public/help/categories');
if (locale) url.searchParams.set('locale', locale);
const res = await fetch(url);
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Help categories fetch failed'), {
code: json?.error?.code,
});
}
return json.data;
}import { useQuery } from '@tanstack/react-query';
export const contentKeys = {
helpCategories: (locale?: string) =>
['content', 'help', 'categories', locale ?? 'all'] as const,
};
export function useHelpCategories(locale?: string) {
return useQuery({
queryKey: contentKeys.helpCategories(locale),
queryFn: async () => {
const url = new URL('/api/v1/public/help/categories', window.location.origin);
if (locale) url.searchParams.set('locale', locale);
const res = await fetch(url);
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Help categories fetch failed'), {
code: json?.error?.code,
i18nKey: json?.error?.i18nKey,
});
}
return json.data as PublicHelpCategory[];
},
staleTime: 5 * 60_000,
});
}Try it
curl -X GET "https://loading/api/v1/public/help/categories"{
"success": true,
"data": [
{
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"slug": "payments",
"name": "Payments & Billing",
"description": "string",
"icon": "credit-card",
"iconBackground": "#F0F4FF",
"sortOrder": 1,
"articleCount": 12
}
]
}Source
| Source | Path | Lines |
|---|---|---|
| Controller | apps/api-core/src/modules/content/public-content.controller.ts | 291โ308 (listPublishedHelpCategories) |
| DTO (response item) | apps/api-core/src/modules/content/dto/content-public-response.dto.ts | 172โ196 (PublicHelpCategoryDto) |
| Service | apps/api-core/src/modules/content/content.service.ts | 740โ749 (listPublishedHelpCategories) |
| Prisma model | packages/prisma/prisma/schema.prisma | HelpCategory (filter status = PUBLISHED), HelpArticle (joined for _count aggregate) |
Get Blog Post (by slug)
Public read of a single blog post by slug. PUBLISHED-only. HTML body server-side sanitized. Categories embedded as { name, slug } pairs. 404 on missing/draft.
List Help Articles
Public paginated list of published help articles. Filters by category slug, search term (title/content/excerpt ILIKE), featured-only, locale. Each item carries embedded category. CDN 5min/10min SWR.