---
title: "Prune aged auth, token, and support rows (GDPR retention)"
method: POST
path: "/api/v1/admin/prune-auth-data"
tags: ["admin"]
---

# Prune aged auth, token, and support rows (GDPR retention)

`POST /api/v1/admin/prune-auth-data`

## Request

- Base URL: `https://api.badgeia.com`
- URL: `https://api.badgeia.com/api/v1/admin/prune-auth-data`
- Auth: none declared

Bound retention on auth personal/security data. Returns rows deleted.

GDPR follow-up to SEC-AUTH-014 (`auth_audit_log` stores client IPs —
personal data, Art. 6(1)(f) legitimate-interest basis) and SEC-AUTH-013/
012 (single-use `password_reset_tokens` / `email_verification_tokens`
accumulate spent rows). Runs both pruners from
`services/auth_retention_service.py`:

  - deletes `auth_audit_log` rows older than
    ``settings.AUTH_AUDIT_RETENTION_DAYS`` (default 90d);
  - deletes spent (used OR expired) reset/verification tokens older than
    ``settings.AUTH_TOKEN_GRACE_DAYS`` (default 7d). Live tokens are
    never pruned.
  - deletes inbound and outbound support rows older than
    ``settings.SUPPORT_MESSAGE_RETENTION_DAYS`` (default 365d), including
    outbound provider replay HTML on the enclosing row.

The production lifespan worker runs the same aggregate once per day behind
a cross-worker Redis lease. This endpoint remains the authenticated manual
path, and ``python -m scripts.prune_auth_data`` is the dry-run-first
standalone path. See docs/RUNBOOK-data-retention.md.

Authorization:
    - Anonymous → 401 (handled by the auth dep on `require_admin`).
    - Authenticated non-admin → 403 (handled by `require_admin`).
    - Admin (email in `ADMIN_EMAILS`) → 200.

Response shape:
    {
      "pruned": {
        "auth_audit_log": <int>,
        "password_reset_tokens": <int>,
        "email_verification_tokens": <int>,
        "support_messages": <int>,
        "enterprise_waitlist": <int>
      },
      "retention_days": <int>,
      "grace_days": <int>,
      "support_retention_days": <int>,
      "enterprise_waitlist_retention_days": <int>
    }

## Response `200`

Successful Response

- object

---

[API](https://skmtc.dev/badgeia/apis/badge.md) · [All operations](https://skmtc.dev/badgeia/apis/badge/llms.txt) · [OpenAPI document](https://skmtc.dev/badgeia/apis/badge/revisions/7e7f7fee8b77?raw)
