Data Retention and Legal Holds
- Base path
/api/panel/v1/wallet- Identity
- Panel session (JWT) —
Authorization: Bearer <panel access token>. The token comes from panel login; an s2s signing key does NOT open these endpoints. - Authorization
- RBAC permission:
wallet:legal-hold:manage·wallet:legal-hold:approve - Cross-surface
- The endpoints on this page have NO equivalent in the s2s API; you cannot call them from your own panel. These capabilities exist only in the merchant panel, behind a panel session.
Wallet records are kept for a period that depends on the record class. When the period ends, the scheduled deletion job deletes or anonymises the record. Records under a legal hold are never deleted, even after their period ends.
Retention periods
| Record class | Period | When the period ends |
|---|---|---|
| Money movements, end-user and recipient records | 8 years | Personal fields are anonymised; auxiliary records are deleted |
| One-time passcode (OTP) records | 90 days | Deleted |
| Webhook and notification delivery records | 1 year | Deleted |
| Configuration without personal data (programs, fees, limits, campaign definitions, etc.) | — | Not deleted |
You can see the current periods and the per-table decision in the panel under Wallet → Data Retention and Legal Holds.
When the period starts
| Record | The period starts |
|---|---|
| Money movement | When the operation reaches its final status (completed, failed, reversed, expired) |
| End user | At the later of account closure and the end user's last operation (as sender or recipient) |
| OTP record | At the code's last use or expiry |
| Webhook / notification | At delivery; for permanent delivery failures, at the last attempt |
An operation that has not reached a final status, an end user with an open account and a notification that has not been delivered are never deleted.
What anonymisation keeps
Money movement and end-user records are not deleted so that the books stay consistent; only their personal fields are irreversibly overwritten.
| Kept | Overwritten |
|---|---|
| Amount, fee, currency, status, dates | Recipient name and account reference (IBAN, masked wallet number) |
| Operation, wallet and account IDs | Sender name and mask |
| Your order / payment reference | Phone number hash and mask, display name |
| Operation history (status transitions) | externalCustomerId, identity link, card token and last four digits |
When you query an anonymised operation through the API, amount and status are returned unchanged; recipient and sender fields are empty. The end user's saved contacts and segment memberships are deleted.
Legal holds
A legal hold stops the deletion of the records it covers until it is released. A hold has one of three scopes:
| Scope | Records covered |
|---|---|
TENANT | All wallet records of your organisation |
END_USER | One end user's records (and records where they are a party) |
OPERATION | One operation, its related records and the identity data of its parties |
- Adding a hold takes effect immediately and requires
wallet:legal-hold:manage. The person who added it, the reason and the official reference are recorded. - Releasing is four-eyes: one authorised person creates a request (
wallet:legal-hold:manage) and a different authorised person approves it (wallet:legal-hold:approve). You cannot approve your own request. - Holds are never deleted; a released hold stays in the list together with who requested and who approved the release.
GET retention/status # periods, per-table decision, job state
GET legal-holds?activeOnly=true # list holds
POST legal-holds # add a hold (immediate)
POST legal-holds/:id/release-requests # request release (four-eyes)
POST intervention-requests/:id/approve # approve the request (different person)
POST intervention-requests/:id/reject # reject the requestPOST legal-holds body:
{
"scope": "END_USER",
"targetId": "8c1f0f7e-3b9a-4c62-9d1e-2b6a0a6f4c11",
"reason": "Records preserved under an official request",
"reference": "2026/1234"
}Do not send targetId for the TENANT scope. A second hold on a target that already has an active hold returns 409 WALLET_LEGAL_HOLD_CONFLICT.
Deletion job
The deletion job runs every day. The panel shows its state:
| State | Meaning |
|---|---|
| Off | The job is not running; no record is deleted or anonymised |
| Count only | The job only counts records whose period has ended; no record is changed |
| Active | Records whose period has ended and that are not under a hold are deleted or anonymised |