List Bio Templates
Public catalog of active bio page templates. CDN-cached (5min). Used in the creator editor to render the template picker.
GET /api/v1/bio/templates — 🌐 Public · Rate limit: 60 req / minute
Returns all BioTemplate rows where active = true, ordered by sortOrder ASC. Public — no auth required because templates are part of the visible product catalog. CDN-cached with Cache-Control: public, s-maxage=300, stale-while-revalidate=600 (5min fresh, 10min stale-allowed).
The catalog is admin-managed — templates are created / activated / sorted via the admin dashboard. This endpoint is the read side; clients should call it on creator-editor mount and re-use the response throughout the session.
Request
No body, no params, no headers required.
Response headers
| Header | Value | Notes |
|---|---|---|
Cache-Control | public, s-maxage=300, stale-while-revalidate=600 | 5min fresh + 10min stale window for CDN |
Response
200 OK — ArrayApiResponseOf<BioTemplateListItemDto>
{
"success": true,
"data": [
{
"id": "t1a2b3c4-d5e6-7890-abcd-ef1234567890",
"name": "Minimal Dark",
"description": "Clean and minimal dark theme",
"tokens": { "color": { "bg": "#000", "text": "#fff" } },
"thumbnail": "https://cdn.bio.re/templates/minimal-dark.png"
}
]
}Item fields
| Field | Type | Notes |
|---|---|---|
id | string (UUID) | BioTemplate.id — pass to PATCH /creators/:creatorId/bio as templateId |
name | string | Display name |
description | string | null | Optional short description |
tokens | object | Theme token JSON — design system payload (colors, spacing, typography) |
thumbnail | string | null | CDN URL of the template preview image |
Errors
| HTTP | code / i18nKey | Reason |
|---|---|---|
429 | (throttle) | Rate limit exceeded (60 req/min) |
Side effects
prisma.bioTemplate.findMany({ where: { active: true }, orderBy: { sortOrder: 'asc' }, select: { id, name, description, tokens, thumbnail } }).- Return the array. No mutations, no auth, no per-user state.
Code samples
curl https://api.bio.re/api/v1/bio/templatestype BioTemplateListItem = {
id: string;
name: string;
description: string | null;
tokens: unknown;
thumbnail: string | null;
};
async function listBioTemplates(): Promise<BioTemplateListItem[]> {
const res = await fetch('https://api.bio.re/api/v1/bio/templates');
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Templates fetch failed'), {
code: json?.error?.code,
});
}
return json.data;
}import { useQuery } from '@tanstack/react-query';
export const bioKeys = {
templates: () => ['bio', 'templates'] as const,
};
export function useBioTemplates() {
return useQuery({
queryKey: bioKeys.templates(),
queryFn: async () => {
const res = await fetch('/api/v1/bio/templates');
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Templates fetch failed'), {
code: json?.error?.code,
i18nKey: json?.error?.i18nKey,
});
}
return json.data as BioTemplateListItem[];
},
// Catalog rarely changes within a session — match the CDN cache window
staleTime: 5 * 60_000,
gcTime: 60 * 60_000,
});
}Try it
Response Body
application/json
application/json
curl -X GET "https://loading/api/v1/bio/templates"{
"success": true,
"data": [
{
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"name": "Minimal Dark",
"description": "string",
"tokens": {},
"thumbnail": "https://cdn.bio.re/templates/minimal-dark.png"
}
]
}{
"success": false,
"error": {
"code": "AUTH_UNAUTHORIZED",
"message": "Invalid credentials",
"i18nKey": "auth.login.invalid_credentials",
"i18nVars": {
"field": "email"
},
"details": [
{
"message": "email must be an email"
}
],
"correlationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}Source
| Source | Path | Lines |
|---|---|---|
| Controller | apps/api-core/src/modules/creator/bio-analytics.controller.ts | 45–55 (listTemplates) |
| DTO (response item) | apps/api-core/src/modules/creator/dto/bio-analytics-response.dto.ts | 11–26 (BioTemplateListItemDto) |
| Service | apps/api-core/src/modules/creator/bio-analytics.service.ts | 37–43 (listTemplates) |
| Prisma model | packages/prisma/prisma/schema.prisma | BioTemplate (active, sortOrder) |
Update Bio Page
Sparse update of the BioPage. Bio strips HTML tags, customCss strips XSS vectors, bio body runs through trust-safety content moderation. Cache invalidated on success.
Get Public Bio Page (Fan-side)
SSR-friendly public bio page render by username. CDN + in-memory cache, status filter (suspended/banned/deactivated → 404), only published creators with active scheduled links.