Privacy and data-subject requests
Export or erase a customer or partner, look a person up by email, and run access or erasure requests from a rights orchestrator.
Referalli gives you the tools to answer data-subject requests (GDPR, CCPA and similar) for the data it holds on your behalf: customers you attributed, and partners in your program. Every call on this page needs the owner or admin role, or a full API key.
Erasure pseudonymizes. Identity is removed, but commission and payout amounts stay, because financial records have their own legal retention period. Balances and the ledger don't change.
Find someone by email
Customers are stored by email hash, not email, so you can't search them by address directly. lookup hashes the email for you (lowercase hex SHA-256 of the trimmed, lowercased address) and never stores it.
curl -X POST https://referalli.com/v1/privacy/lookup \
-H "Authorization: Bearer $KEY" \
-H "content-type: application/json" \
-d '{"email": "dana@example.com"}'
# { "found": true, "customerRefs": ["cus_123"], "partnerId": "ptr_..." }customerRefs lists every customer whose signup or identify call carried that email hash. partnerId is the partner in your org with that email, or null.
Export
curl "https://referalli.com/v1/privacy/export?customerRef=cus_123" \
-H "Authorization: Bearer $KEY"This returns every row that references the customer: referrals, associations, identityLinks, billingEvents and conversionEvents. To export a partner, or everything behind an email, open an access request.
Erase
POST /v1/privacy/forget takes exactly one of these:
Body | Erases | Response |
|---|---|---|
| One customer |
|
| One partner |
|
| The partner with that email and every customer stored under its hash |
|
If nothing matches a customerRef or email, the call fails with 400. An unknown partnerId returns 404.
Erasing a customer replaces the customer id with a forgotten_… pseudonym on referrals, associations, identity links, billing events, referee rewards, agent recommendations and consent records. It also:
clears the email hash, IP hash, user agent and anonymous id on their associations and identity links;
clears the IP hash and user agent on the visits and clicks of the browsers they were seen on (the clicks stay, as the partner's click history);
clears the provider metadata on their billing events, which can carry names or emails (amounts, dates and ids stay);
clears the email hash and declared data on their consent record.
Erasing a partner does the following:
Replaces the email with a
forgotten-…@redacted.invalidaddress and the display name with "Erased partner", and clears notes and tags.Clears the payout details and tax form data.
Renames their link and coupon codes, so they stop attributing (
/go/{token}/{code}returns404).Deletes their postback.
Clears the free text they wrote in disputes and deal notes. A deal's company and contact are the prospect's business details and stay.
Payout invoices hold no partner identity (only numbers, dates and amounts; names are read live from the pseudonymised partner), so they need no change.
Unlinks their partner account, so they lose portal access to your program. Their account with other merchants is untouched.
Sets their status to
banned, so nothing new is attributed or paid to the pseudonym.
The partner's commission lines, balances and payout history keep their amounts. Erasing a partner twice is safe: the second call returns alreadyForgotten: true.
Every erasure writes an audit log entry (privacy.forgotten or privacy.partner_forgotten).
Data-subject requests
Rights orchestrators work by opening a request and polling it. Referalli supports that pattern, so an orchestrator can register it as a connected system.
curl -X POST https://referalli.com/v1/privacy/requests \
-H "Authorization: Bearer $KEY" \
-H "content-type: application/json" \
-d '{"subject": {"email": "dana@example.com"}, "type": "access"}'
# 202 { "id": "prq_01JB...", "status": "completed" }typeisaccessorerasure.subjecttakes exactly one ofemail,customerReforpartnerId. Anemailresolves exactly like lookup. The request stores only the email's hash, assubject.emailHash.Requests are processed straight away, so
statusis usually alreadycompleted. Poll anyway; the contract allows a request to start aspending.
curl https://referalli.com/v1/privacy/requests/prq_01JB... \
-H "Authorization: Bearer $KEY"{
"id": "prq_01JB...",
"type": "erasure",
"subject": { "emailHash": "b4c9a2..." },
"status": "completed",
"error": null,
"createdAt": "2026-10-21T12:00:00.000Z",
"completedAt": "2026-10-21T12:00:00.000Z",
"resultUrl": "/v1/privacy/requests/prq_01JB.../result",
"result": { "found": true, "partners": [...], "customers": [...] }
}Field | Meaning |
|---|---|
|
|
| Included here for erasure requests: the same |
|
|
When nobody matches the subject, the request still completes, with result.found: false. That's the answer an orchestrator needs; it isn't an error.
GET /v1/privacy/requests lists requests, newest first and paginated (the latest 200 under 2026-10-21), without their results.
Each finished request emits the privacy.request_completed webhook with requestId, type, status and, when completed, found.
Data retention
Referalli deletes raw data once it is older than your retention settings. A nightly job does it; each org is purged at most once a day. The commission ledger (earned, approved, paid, reversed and adjusted lines) is never purged.
Setting | What is purged | Default | Minimum |
|---|---|---|---|
| Raw clicks. Counts are kept as daily totals, so reports don't change, and a click a referral points at is kept. | forever | 400 days |
| Anonymous visit records. | 400 days | 30 days |
| The raw provider payload on billing events (amounts, ids and dates stay). | forever | 90 days |
| Delivered or failed outbound webhook attempts. Pending ones are never purged. | 30 days | 7 days |
| Dashboard and portal notifications. | 180 days | 30 days |
| Audit log entries. | forever | 365 days |
curl -X PUT $BASE/v1/org/retention \
-H "Authorization: Bearer $KEY" -H "content-type: application/json" \
-d '{"clicks": 730, "auditLog": 2555}'null keeps data forever; a value below the minimum returns 400. GET /v1/org/retention returns the policy, each kind's minimum and default, and when the purge last ran for your org. Owners and admins can change it, and every change is audited.