Deactivate Account
Temporarily deactivate the current account. Profile becomes hidden, all sessions revoked. Reversible via /users/reactivate.
POST /api/v1/users/deactivate โ ๐ Bearer ยท Rate limit: 3 req / hour
Sets User.status = DEACTIVATED and revokes every active session for this user. Reversible โ the user can come back via POST /users/reactivate (auth-session mode) or by clicking a reactivation link sent later (token-bearer mode).
All sessions are revoked, including the one calling this endpoint. The next request with the existing access token will succeed only until the JWT expires (auth.access_token_ttl_seconds); the refresh cookie is dead immediately. Plan a redirect to a logged-out landing page on success.
Deactivation is distinct from deletion. Deactivation is reversible and preserves all data. Deletion is POST /users/delete (or POST /gdpr/delete), which schedules permanent erasure after a grace period. Deactivation by itself does not start any deletion timer.
Request
No body, no params.
| Header | Required | Notes |
|---|---|---|
Authorization: Bearer <accessToken> | โ | JWT from POST /auth/login |
Response
200 OK โ SuccessOnlyResponseDto
{
"success": true
}| Field | Type | Notes |
|---|---|---|
success | boolean | Always true on 200 |
Errors
| HTTP | code / i18nKey | Reason |
|---|---|---|
400 | error.user.account_not_active | User.status is not ACTIVE (already DEACTIVATED, SUSPENDED, BANNED, or DELETED) |
401 | (guard) | Missing / invalid bearer token |
404 | error.user.not_found | Token decoded but user row missing |
429 | (throttle) | Rate limit exceeded (3 req/hour) |
Side effects
- Lookup
User; thrownot_foundif missing. - Reject if
User.status !== 'ACTIVE'โ no idempotent re-deactivation. - Inside one transaction:
User.status = DEACTIVATED.UPDATE Session SET revoked = true, revokedAt = now() WHERE userId = :userId AND revoked = false(every live session).
- Audit log:
[account] AUDIT: Deactivated by user {userId}(warn level). - No scheduled deletion is created โ that requires the separate
/users/deleteflow.
Code samples
curl -X POST https://api.bio.re/api/v1/users/deactivate \
-H "Authorization: Bearer $ACCESS_TOKEN"async function deactivateAccount(accessToken: string): Promise<void> {
const res = await fetch('https://api.bio.re/api/v1/users/deactivate', {
method: 'POST',
headers: { Authorization: `Bearer ${accessToken}` },
});
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Deactivate failed'), {
code: json?.error?.code,
});
}
}import { useMutation, useQueryClient } from '@tanstack/react-query';
export function useDeactivateAccount() {
const qc = useQueryClient();
return useMutation({
mutationFn: async () => {
const res = await fetch('/api/v1/users/deactivate', { method: 'POST' });
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Deactivate failed'), {
code: json?.error?.code,
i18nKey: json?.error?.i18nKey,
});
}
},
onSuccess: () => {
// Sessions revoked server-side โ drop all caches, force re-auth flow
qc.clear();
},
});
}Try it
Authorization
bearer In: header
Response Body
application/json
application/json
application/json
curl -X POST "https://loading/api/v1/users/deactivate"{
"success": true
}{
"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"
}
}{
"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/user/user.controller.ts | 158โ167 (deactivateAccount) |
| DTO (response) | apps/api-core/src/common/dto/common-response.dto.ts | SuccessOnlyResponseDto |
| Service | apps/api-core/src/modules/user/user.service.ts | 402โ421 (deactivateAccount) |
| Prisma models | packages/prisma/prisma/schema.prisma | User.status (UserStatus enum), Session.revoked |
Update User Settings
Sparse update of preferences (locale, theme, notification flags, digest mode). Locale changes also sync to the legacy User.locale field.
Reactivate Account
Bring a DEACTIVATED account back to ACTIVE. Two auth modes โ bearer JWT (logged-in user) OR opaque token from email link (no JWT required). Cancels any pending deletion in the same transaction.