Get Terms of Service
Public read of the platform terms of service. Content is admin-managed via ConfigService. Same shape as the privacy policy endpoint.
GET /api/v1/legal/terms — 🌐 Public
Returns the platform's terms of service as a single document. Content is admin-managed via the legal.terms_of_service ConfigService key. Same response shape as GET /legal/privacy.
Identical shape, different key. This endpoint is the terms-of-service twin of GET /legal/privacy. Same response ({ content, lastUpdated }), same fallback semantics, same caching guidance — only the underlying config key differs (legal.terms_of_service vs legal.privacy_policy). Frontend can share a single hook with the key as a parameter.
Default fallback when unconfigured. If the admin has never set legal.terms_of_service, the response carries content: 'Terms of service not yet published.' and lastUpdated: null.
Request
No body, no params, no headers required.
Response
200 OK — ApiResponseOf<LegalDocumentDto>
{
"success": true,
"data": {
"content": "<p>Terms of Service content...</p>",
"lastUpdated": "2026-04-29T20:00:00.000Z"
}
}| Field | Type | Notes |
|---|---|---|
content | string | HTML body of the terms |
lastUpdated | string (ISO 8601) | null | Last admin update; null when never written |
Errors
No documented 4xx — unconfigured keys return 200 with default fallback.
Side effects
configService.getWithDefault('legal.terms_of_service', 'Terms of service not yet published.').configService.getEffective('legal.terms_of_service')→ ISO-formatdefinition.updatedAtornull.- Return
{ content, lastUpdated }. No mutations, no auth, no per-user state.
Code samples
curl https://api.bio.re/api/v1/legal/termsasync function getTermsOfService(): Promise<LegalDocument> {
const res = await fetch('https://api.bio.re/api/v1/legal/terms');
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Terms fetch failed'), {
code: json?.error?.code,
});
}
return json.data;
}import { useQuery } from '@tanstack/react-query';
export const legalKeys = {
terms: () => ['legal', 'terms'] as const,
};
export function useTermsOfService() {
return useQuery({
queryKey: legalKeys.terms(),
queryFn: async () => {
const res = await fetch('/api/v1/legal/terms');
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Terms fetch failed'), {
code: json?.error?.code,
i18nKey: json?.error?.i18nKey,
});
}
return json.data as LegalDocument;
},
staleTime: 60 * 60_000,
gcTime: 24 * 60 * 60_000,
});
}Try it
Response Body
application/json
curl -X GET "https://loading/api/v1/legal/terms"{
"success": true,
"data": {
"content": "<p>Privacy Policy content...</p>",
"lastUpdated": "2019-08-24T14:15:22Z"
}
}Source
| Source | Path | Lines |
|---|---|---|
| Controller | apps/api-core/src/modules/legal/legal.controller.ts | 21–26 (getTermsOfService) |
| DTO (response) | apps/api-core/src/modules/legal/dto/legal-response.dto.ts | 7–13 (LegalDocumentDto) |
| Service | apps/api-core/src/modules/legal/legal.service.ts | 22–32 (getTermsOfService), 34–43 (getLastUpdated) |
| Config keys | (admin-managed via ConfigService) | legal.terms_of_service (string content; default 'Terms of service not yet published.') |
Get Privacy Policy
Public read of the platform privacy policy. Content is admin-managed via ConfigService. Returns the body plus the last-updated timestamp.
List Messages (Inbox)
Paginated inbox / sent view. Filter by role (fan = sent, creator = received) and optionally by chat session. Content is decrypted server-side per row.