Skip to main content
The DSAR API handles data subject access requests for GDPR, CCPA, and other privacy regulations. Requests are processed asynchronously via a background job queue. Admin only.

GET /api/v1/dsar

List DSAR requests for the tenant.

Query Parameters

Response


POST /api/v1/dsar

Create and enqueue a DSAR request. Returns 202 Accepted — the request is processed asynchronously. Rate limited to 10 requests/min. Admin only.

Request Body

Example

Response (202)

Poll GET /api/v1/dsar?status=completed to check when the request finishes processing. Once the status is completed, download the export payload with GET /api/v1/dsar/{id}/download.
A delete request runs the same erasure path as GDPR Erasure (eraseSubjectData). It removes the full category set — interaction history, interaction summaries, suppressions, decision traces, attribution results, variant assignments, identity links, journey enrollments, channel deliveries, stored DSAR export payloads, and customer-type dynamic schema rows. The DsarRequest row, ConsentRecord history, and hash-chained audit log are deliberately retained as legal-obligation proof.

GET /api/v1/dsar//download

Download the portable export payload for a completed DSAR export request. Admin only. Returns the persisted export as a plain JSON file attachment (Content-Disposition: attachment; filename="dsar-export-{subjectId}-{date}.json").
This endpoint is only available for requests with requestType = "export". Calling it on a delete request returns 404 with detail "Download is only available for export requests".
Encrypted at rest, decrypted on download (SOC 2 Phase 0). dsar_exports.payload is encrypted (AES-256-GCM) at rest by default — every DSAR export generated by the worker (WORKER_INPROCESS=1), the drain-queues cron path, and the Shopify customers/data_request GDPR webhook persists a { ciphertext, format: "encrypted-aes-256-gcm" } envelope, not plaintext PII. This endpoint decrypts server-side (the caller already passed the admin-role + tenant-scope check above) and always returns plain JSON — there is no client-side decryption step, and the X-Kaireon-Payload-Encrypted response header has been removed since it no longer describes anything the caller needs to act on. Exports persisted before this change (plain JSON) are served unchanged.

Path Parameters

Response (200)

The response body is always the plain export JSON (decrypted server-side if the stored payload was encrypted). Headers:

Error responses

How exports age out

Export payloads are stored in the dsar_exports table and age out on the decisions retention class (configurable per tenant in Settings → Retention). DsarRequest rows are never purged — only the payload in dsar_exports is removed by the GET /api/v1/cron/dsar-purge cron. After purge, the download endpoint returns the 404 detail above and the export must be re-run. Exports work in both the in-process (single-instance) and worker-mode deployment configurations.
Exports completed before 2026-06-07 (migration 28) were not persisted to dsar_exports — they are not downloadable. Re-run the export from the DSAR queue to get a downloadable payload.