Erasure API
Erase one person from your backend, then check the request until it completes. Request and response fields, scope, errors and server setup.
Use these endpoints to erase a person when your own system receives the deletion request. They do what the console does. For what erasure deletes and keeps, see Erasing a person.
| Method and path | Purpose |
|---|---|
POST /v1/privacy/erase |
Start an erasure. |
GET /v1/privacy/requests/:id |
Read the state of one request. |
Before you start
- Use a server or data API key whose scope includes
data.gdpr_delete(shown as GDPR Delete in the key's scope tree). SDK keys cannot call these endpoints. See Authentication and API keys. - The key's environment decides where the person is erased. Test keys erase in Test, Live keys in Live.
- Each key can make 60 requests a minute, and each environment is capped per hour. See Errors.
Erase a person
curl -X POST https://api.true-engage.com/v1/privacy/erase \
-H "Authorization: Bearer $TRUEENGAGE_SERVER_KEY" \
-H "Idempotency-Key: dsr-2207" \
-H "Content-Type: application/json" \
-d '{
"subject": { "type": "external_id", "value": "user-1042" },
"reason": "Customer asked to be deleted, ticket 4821",
"reference": "DSR-2207",
"confirm": true
}'
Request
| Field | Required | Notes |
|---|---|---|
subject.type |
Yes | external_id, user_id, email or phone. user_id is the id TrueEngage gives the profile. |
subject.value |
Yes | The identifier. It is never stored; only a keyed hash is. |
reason |
Yes | 5 to 500 characters, with no personal data. Stored with the request and in the audit log. |
reference |
No | Your ticket reference, up to 128 characters. |
confirm |
Yes | Must be true. It stands in for the confirmation a console user gives by typing the workspace name. |
Send an Idempotency-Key header so a retry cannot start a second request. A repeat with the same key returns the existing request.
An email or phone number matches the profile however it is written, for example with or without the + and country code. Every form of the identifier is blocked afterwards.
Response
202 for a new request, 200 for an existing one. The body is the standard envelope; data holds:
{
"requestId": "01a17000-0000-7000-8000-000000000001",
"status": "processing",
"stage": "awaiting_audiences",
"deadlineAt": "2026-11-21T09:12:00.000Z",
"subjectsFound": 1,
"requestedBy": { "type": "api_key", "id": "01a17000-0000-7000-8000-0000000000b2", "name": "Backend server key" },
"reason": "Customer asked to be deleted, ticket 4821",
"created": true
}
You get 200 and created: false when the same Idempotency-Key is reused, when an open request already covers the person, or when the person was already erased.
When no profile matches, the answer is 202 with status completed, subjectsFound 0 and notFound true. The identifier is still blocked from being re-created. This does not apply to user_id.
subjectsFound can be more than 1. TrueEngage follows merged profiles and erases them together, up to 20 profiles. More than that returns PRIVACY_SUBJECT_AMBIGUOUS.
Read a request
curl https://api.true-engage.com/v1/privacy/requests/01a17000-0000-7000-8000-000000000001 \
-H "Authorization: Bearer $TRUEENGAGE_SERVER_KEY"
data holds:
| Field | Meaning |
|---|---|
requestId |
The request id. |
status |
received, processing, completed or rejected. |
stage |
received, awaiting_audiences, purging, scrub_pending, completed or rejected. |
requestedAt, deadlineAt, completedAt |
Timestamps. completedAt is null until done. |
via |
console or api. |
requestedBy |
{ type, id, name }. type is user, api_key or system. Who made the request is always recorded. |
reason, reference |
What you sent. |
audienceOutcome |
null while waiting, then none, removed or partly_abandoned. |
waitingOn |
Ad audiences still holding the request, each with platform and a cause. Empty when none. |
steps |
Counts of what was removed. |
residuals |
What stays for now: { area, until }. until is null when it has no end date. |
notFound |
true when no profile matched. |
Nothing in the response identifies the person. Poll until status is completed, at an interval of a minute or more. A request that waits on an ad platform can take up to 14 days. GET also needs the same scope.
Errors
Errors use the standard shape. The codes specific to erasure:
| Status | Code | Meaning |
|---|---|---|
| 400 | ERASURE_CONFIRMATION_REQUIRED |
confirm: true is missing. |
| 400 | ERASURE_REASON_REQUIRED |
reason is missing, shorter than 5 or longer than 500 characters. |
| 403 | INSUFFICIENT_SCOPE |
The key does not have data.gdpr_delete. |
| 404 | PRIVACY_REQUEST_NOT_FOUND |
No request with that id in this environment. |
| 422 | PRIVACY_SUBJECT_INVALID |
The value does not fit the subject.type, or reference is too long. |
| 422 | PRIVACY_SUBJECT_AMBIGUOUS |
The identifier matched more than 20 profiles. |
| 422 | IDEMPOTENCY_KEY_REUSED |
That Idempotency-Key was already used for another person. |
| 429 | ERASURE_RATE_LIMITED |
Too many erasures in this environment this hour. Nothing was erased. Wait, then retry. |
| 503 | PRIVACY_NOT_CONFIGURED |
Erasure is not set up on this server. See the operator note below. |
Other endpoints answer 410 USER_ERASED when you name a person who was erased, for example Promote an identity. Events and imports for an erased person's identifiers are dropped quietly for the retention period.
Operator note: self-hosted setup
If you run TrueEngage yourself, set these before you use erasure. Hosted workspaces need nothing.
| Variable | Default | Meaning |
|---|---|---|
PRIVACY_TOMBSTONE_KEY |
None | Secret of at least 32 bytes. Set the same value on the API and on the worker. Without it POST /v1/privacy/erase answers 503 PRIVACY_NOT_CONFIGURED, and outside development the API and worker refuse to start. Blocked identifiers are keyed hashes, so changing the key stops earlier blocks from matching. |
ERASURE_TOMBSTONE_DAYS |
90 | How long identifiers stay blocked. Between 7 and 365. |
ERASURE_AUDIENCE_WAIT_DAYS |
14 | How long to wait for ad platforms before going ahead. Keep it at or below ADS_REMOVAL_MAX_WAIT_DAYS. |
ADS_REMOVAL_MAX_WAIT_DAYS |
14 | How long an audience removal is retried before it is given up on and reported as a warning on the audience. Minimum 3. |
ERASURE_SETTLE_SECONDS |
15 | Pause between erasure steps. |
ERASURE_MAX_PER_HOUR |
200 | Erasure requests per environment per hour. |
Run the database updates first, then set the secret, then deploy the worker, then the API. If you pin which queues the worker consumes, add privacy.erasure. Keys that already hold the data.gdpr_delete scope gain the endpoint on deploy, so list them first.
Related
Was this page helpful?