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 /api/v1/auth/2fa/status — 🔑 Bearer · No throttle
Returns the current User.twoFactorEnabled value. No mutations — purely a read.
The same flag is also returned by GET /auth/me as twoFactorEnabled. Use this dedicated endpoint when you only need that single bit and want to keep the me cache untouched (e.g., to drive a "Two-Factor Authentication" toggle on a settings screen).
Request
No body, no params.
| Header | Required | Notes |
|---|---|---|
Authorization: Bearer <accessToken> | ✓ | JWT from POST /auth/login |
Response
200 OK — ApiResponseOf<TwoFactorStatusResponseDto>
{
"success": true,
"data": {
"enabled": true
}
}| Field | Type | Notes |
|---|---|---|
enabled | boolean | Mirrors User.twoFactorEnabled |
Errors
| HTTP | code / i18nKey | Reason |
|---|---|---|
401 | (guard) | Missing / invalid bearer token |
Side effects
- Lookup
User.twoFactorEnabled(single field select). - Return
{ enabled }. No mutations.
Code samples
curl https://api.bio.re/api/v1/auth/2fa/status \
-H "Authorization: Bearer $ACCESS_TOKEN"async function getTwoFactorStatus(accessToken: string): Promise<boolean> {
const res = await fetch('https://api.bio.re/api/v1/auth/2fa/status', {
headers: { Authorization: `Bearer ${accessToken}` },
});
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Status check failed'), {
code: json?.error?.code,
});
}
return json.data.enabled;
}import { useQuery } from '@tanstack/react-query';
export const twoFactorKeys = {
status: () => ['auth', '2fa', 'status'] as const,
};
export function useTwoFactorStatus() {
return useQuery({
queryKey: twoFactorKeys.status(),
queryFn: async () => {
const res = await fetch('/api/v1/auth/2fa/status');
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Status check failed'), {
code: json?.error?.code,
i18nKey: json?.error?.i18nKey,
});
}
return json.data.enabled as boolean;
},
staleTime: 60_000, // 1 min — flips rarely outside of explicit setup/disable
});
}Try it
Authorization
bearer In: header
Response Body
application/json
application/json
curl -X GET "https://loading/api/v1/auth/2fa/status"{
"success": true,
"data": {
"enabled": false
}
}{
"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/auth/two-factor.controller.ts | 88–95 (isEnabled) |
| DTO (response) | apps/api-core/src/modules/auth/dto/response.dto.ts | 132–135 (TwoFactorStatusResponseDto) |
| Service | apps/api-core/src/modules/auth/two-factor.service.ts | 166–172 (isEnabled) |
| Prisma model | packages/prisma/prisma/schema.prisma | User.twoFactorEnabled |
Regenerate Backup Codes
Issue a fresh set of backup codes after the user proves their authenticator still works (TOTP code, not backup code). Old codes are deleted atomically.
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.