GDPR anonymize
What “anonymize” means
Section titled “What “anonymize” means”TwistCue’s anonymize operation:
- Nulls PII on
users:email,phone_e164,display_name,avatar_url,auth_provider(set toanonymized). - Nulls PII on
devices:ip_last,fingerprint,device_model. - Marks
users.status = 'deleted': full API lockout. - Keeps
id,country_code,created_at, and the entire coin ledger + purchase history (money doesn’t disappear; regulators need this). - Support notes about this user are kept (audit trail): the note author’s identity is preserved.
- Writes an
AuditLogentry withaction='user.anonymize'.
Approval flow
Section titled “Approval flow”Anonymization is approval-gated by default:
- Initiator (usually a compliance-flagged admin) calls
POST /admin/users/:id/anonymizewith a reason. - Service creates an
admin_approvalrow withaction_type='user.anonymize',status=pending. - A second admin with
users:anonymizereviews and approves. - On approval, the service executes the destructive nulling in a transaction.
- Audit entries land on both the approval decision and the execute.
Fields
Section titled “Fields”- Reason: required, 5–500 chars. Ticket URL or written-request reference goes here.
What survives
Section titled “What survives”| Data | After anonymize |
|---|---|
| User row | Exists, PII nulled, status=deleted |
| Email / phone / name / avatar | Nulled |
| Country + language | Kept (aggregate stats need it) |
| Devices | Kept, but IPs/fingerprints nulled |
| Coin ledger | Kept: legal + reconciliation |
| Purchase history | Kept: accounting + refund windows |
| Subscriptions | Kept, but auto-renew must be canceled separately |
| Comments | Author changed to “Deleted user”, body kept unless the request also asks for content deletion |
| Support notes | Kept |
| Audit log entries | Kept forever |
Gotchas
Section titled “Gotchas”- Anonymize does NOT cancel subscriptions. The billing rail keeps charging. Cancel via the appropriate provider (App Store, Google Play, dLocal, card MID) before anonymizing, or the user will keep being billed and you’ll owe refunds.
- Anonymize is one-way. There is no un-anonymize. If you’re wrong, the data is gone.
- The user’s coin balance still exists: just no one can log in as them. In practice this is fine (regulators care about PII, not spend numbers).
- New signup on the same email works fine: the anonymized row is de-linked from that email.
API call
Section titled “API call”# Step 1: Initiator requestscurl -X POST https://api.twistcue.local/v1/admin/users/{userId}/anonymize \ -H "Authorization: Bearer $INITIATOR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"reason": "GDPR request, ticket #7841"}'
# → {"kind": "approval_pending", "approvalId": "..."}
# Step 2: Second admin (different admin_id) approvescurl -X POST https://api.twistcue.local/v1/admin/approvals/{approvalId}/approve \ -H "Authorization: Bearer $APPROVER_TOKEN" \ -d '{}'
# → user is anonymized inside the approval-execution transaction.Full details in API, Users and API, System (for the approvals endpoint).