BIO.RE
Legal

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 OKApiResponseOf<LegalDocumentDto>

{
  "success": true,
  "data": {
    "content": "<p>Terms of Service content...</p>",
    "lastUpdated": "2026-04-29T20:00:00.000Z"
  }
}
FieldTypeNotes
contentstringHTML body of the terms
lastUpdatedstring (ISO 8601) | nullLast admin update; null when never written

Errors

No documented 4xx — unconfigured keys return 200 with default fallback.

Side effects

  1. configService.getWithDefault('legal.terms_of_service', 'Terms of service not yet published.').
  2. configService.getEffective('legal.terms_of_service') → ISO-format definition.updatedAt or null.
  3. Return { content, lastUpdated }. No mutations, no auth, no per-user state.

Code samples

curl https://api.bio.re/api/v1/legal/terms
async 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

GET
/api/v1/legal/terms

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

SourcePathLines
Controllerapps/api-core/src/modules/legal/legal.controller.ts21–26 (getTermsOfService)
DTO (response)apps/api-core/src/modules/legal/dto/legal-response.dto.ts7–13 (LegalDocumentDto)
Serviceapps/api-core/src/modules/legal/legal.service.ts22–32 (getTermsOfService), 34–43 (getLastUpdated)
Config keys(admin-managed via ConfigService)legal.terms_of_service (string content; default 'Terms of service not yet published.')

On this page