POST /api/v1/gdpr/erasure
Permanently deletes all records associated with a customer ID across ten interaction and decision tables, plus any customer-type dynamic schema tables. This implements the GDPR “right to erasure” (right to be forgotten) as defined in Article 17 of the General Data Protection Regulation.
The ten Prisma-modeled tables are deleted in a single transaction — either all of them are cleaned or none are. The dynamic-schema (ds_*) deletes run outside that transaction on purpose: a failing raw statement inside an interactive transaction would abort it and roll back the modeled deletes. When a ds_* table has no customer_id column (or its delete fails), the erasure continues and records the issue in the top-level warnings[] array rather than failing. An audit log entry is recorded after erasure to maintain a compliance trail (the audit entry records that an erasure occurred but does not retain the deleted data).
This is the single source of truth for erasure: the admin endpoint below and the DSAR delete-request workflow both run the same eraseSubjectData path, so a subject deleted through either route has the identical set of categories erased.
ConsentRecord, the DsarRequest row itself, and hash-chained AuditLog entries are deliberately not erased here — they are retained as legal-obligation proof (consent history, the audit trail of who requested what) and are purged only by the retention cron on their own clock. The stored DSAR export payload (DsarExport) is erased.
Authentication
Requires a valid tenant and the admin role.
| Header | Required | Description |
|---|
X-API-Key | Yes | Admin-scoped API key (starts with krn_). Identifies the caller and the tenant. |
Content-Type | Yes | application/json |
This operation is irreversible. All interaction history, decision traces, suppressions, attribution results, interaction summaries, variant assignments, identity links, journey enrollments, and dynamic schema rows for the specified customer will be permanently deleted. There is no undo.
Request Body
| Field | Type | Required | Description |
|---|
customerId | string | Yes | The unique identifier of the customer whose data should be erased |
Example Request
Example Response
Response Fields
| Field | Type | Description |
|---|
success | boolean | true if the erasure completed successfully |
customerId | string | The customer ID that was erased |
deletedCounts | object | Breakdown of records deleted per table |
deletedCounts.interactionHistory | integer | Number of interaction history records deleted (impressions, clicks, outcomes) |
deletedCounts.interactionSummary | integer | Number of interaction summary records deleted (aggregated interaction stats) |
deletedCounts.suppression | integer | Number of suppression records deleted (frequency cap and cooldown entries) |
deletedCounts.decisionTrace | integer | Number of decision trace records deleted (forensic traces of pipeline execution) |
deletedCounts.attributionResult | integer | Number of attribution result records deleted (outcome-to-recommendation mappings) |
deletedCounts.variantAssignment | integer | Number of experiment variant assignment records deleted |
deletedCounts.identityLink | integer | Number of identity cluster link records deleted |
deletedCounts.journeyEnrollment | integer | Number of journey enrollment records deleted |
deletedCounts.channelDelivery | integer | Number of channel-delivery records deleted (outbound-message delivery attempts) |
deletedCounts.dsarExports | integer | Number of stored DSAR export payloads deleted (the export bundles that contained the subject’s full data) |
deletedCounts.dynamicSchemaRows | integer | Number of rows deleted from customer-type dynamic schema tables |
totalDeleted | integer | Sum of all deleted records across all tables |
warnings | string[] | Non-fatal issues encountered during erasure (e.g. a ds_* table without a customer_id column, or dynamic tables that could not be enumerated). Empty when everything erased cleanly. |
Data Categories Affected
The erasure targets these customer-scoped categories within the tenant boundary:
| Category | Description |
|---|
| Interaction history | Raw interaction events (impressions, clicks, conversions, dismissals) |
| Interaction summaries | Aggregated interaction statistics per customer-offer pair |
| Suppressions | Active suppression rules (frequency caps, cooldown periods) |
| Decision traces | Forensic traces of the decision pipeline for debugging and auditing |
| Attribution results | Links between outcomes and the recommendations that generated them |
| Variant assignments | Experiment variant assignments for A/B tests |
| Identity links | Identity-cluster membership records (cross-device/cross-channel identity resolution) |
| Journey enrollments | Customer-journey enrollment records |
| Channel deliveries | Outbound channel-delivery attempt records |
| DSAR export payloads | Stored DSAR export bundles for the customer (the request row itself is retained; only the payload is erased) |
| Dynamic schema rows | Rows from all active customer-type schema tables (prefixed with ds_) where customer_id matches |
All deletions are scoped to both the tenantId and customerId, so no cross-tenant data is affected.
Audit Trail
After a successful erasure, an audit log entry is created with:
- action:
gdpr_erasure
- entityType:
customer
- entityId: The erased customer ID
- changes: The
deletedCounts breakdown
This entry appears in the Change History feed and can be filtered with action=gdpr_erasure.
Error Responses
| Status | Cause |
|---|
400 | Missing customerId, invalid JSON body, or customerId is not a string |
401 | Missing or invalid authentication credentials |
403 | Insufficient role (requires admin) |
500 | Erasure transaction failed (no data was deleted — the transaction rolls back entirely) |
If the customer has no data in any of the tables, the endpoint still returns success: true with all counts at 0 and an empty warnings array. This is expected behavior — the erasure request is idempotent.
The GDPR erasure endpoint automatically deletes rows from customer-type dynamic schema tables (those with entityType: "customer" and table names prefixed with ds_). However, data stored in external data sources (e.g., upstream systems connected via connectors or pipelines) is not affected — you must handle erasure in those systems separately.
See also: Change History | Interaction History | Decision Traces