Cancel Pending Deletion
Stop a previously scheduled GDPR deletion before the grace period ends. Reactivates the account in the same transaction. Sessions stay revoked — re-login required.
DELETE /api/v1/gdpr/delete — 🔑 Bearer
Cancels a pending deletion and reactivates the account in one transaction. Flips GDPRRequest.status = CANCELLED and User.status = ACTIVE. Existing sessions are not restored — they were revoked when the deletion was requested and remain revoked; the user must log in fresh.
The bearer token used here is typically issued after logging back in during the grace period — when the user changes their mind, they log in again (which works fine on a DEACTIVATED account because login bypasses the deactivation gate explicitly for this flow), then call this endpoint to abort the deletion.
Once GDPRRequest.status leaves PENDING (i.e., the worker has begun PROCESSING or already COMPLETED the purge), this endpoint is a 404 — there is no rollback for an in-flight or completed purge.
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 |
|---|---|---|
401 | (guard) | Missing / invalid bearer token |
404 | error.gdpr.no_pending_deletion | No GDPRRequest DELETION PENDING row exists for this user (already cancelled, already processed, or never existed) |
Side effects
- Look up the most recent
GDPRRequest { type: DELETION, status: PENDING }for this user. If absent →no_pending_deletion. - Inside one transaction:
GDPRRequest.status = CANCELLED(for the matched row).User.status = ACTIVE(reactivate the account).
- Audit log:
[gdpr] Deletion cancelled by user {userId}, request <id>. - Sessions are NOT touched — they were revoked at deletion-request time and remain so. The user must log in fresh.
Code samples
curl -X DELETE https://api.bio.re/api/v1/gdpr/delete \
-H "Authorization: Bearer $ACCESS_TOKEN"async function cancelGdprDeletion(accessToken: string): Promise<void> {
const res = await fetch('https://api.bio.re/api/v1/gdpr/delete', {
method: 'DELETE',
headers: { Authorization: `Bearer ${accessToken}` },
});
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Cancel failed'), {
code: json?.error?.code,
});
}
}import { useMutation, useQueryClient } from '@tanstack/react-query';
export function useCancelGdprDeletion() {
const qc = useQueryClient();
return useMutation({
mutationFn: async () => {
const res = await fetch('/api/v1/gdpr/delete', { method: 'DELETE' });
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Cancel failed'), {
code: json?.error?.code,
i18nKey: json?.error?.i18nKey,
});
}
},
onSuccess: () => {
// Account is ACTIVE again — invalidate identity caches
qc.invalidateQueries({ queryKey: ['users', 'profile'] });
qc.invalidateQueries({ queryKey: ['auth', 'me'] });
},
});
}Try it
Authorization
bearer In: header
Response Body
application/json
application/json
application/json
curl -X DELETE "https://loading/api/v1/gdpr/delete"{
"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/gdpr.controller.ts | 84–92 (cancelDeletion) |
| DTO (response) | apps/api-core/src/common/dto/common-response.dto.ts | SuccessOnlyResponseDto |
| Service | apps/api-core/src/modules/user/user.service.ts | 683–709 (gdprCancelDeletion) |
| Prisma models | packages/prisma/prisma/schema.prisma | GDPRRequest.status, User.status |
Request Account Deletion (GDPR)
Right-to-Erasure (Art. 17) — schedule the account for deletion after a grace period. Account is deactivated immediately and all sessions revoked.
Request Deletion (Legacy)
Older /users/delete endpoint — same effect as POST /gdpr/delete but additionally requires the current account password and returns only the scheduled date.