Back to slim.io

Privacy Rights · GDPR

GDPR Article 15 & 17,
built in.

Data Subject Access Requests handled end-to-end. slim.io compiles subject access records and, on erasure, anonymizes its own findings metadata in place, revokes the tokens it issued, writes a zero-PII ledger row, and returns a cryptographically signed receipt — all via a single API call. Plus tracked, evidence-backed handling for rectification, restriction, objection, and CCPA opt-out.

Article 15

Right of Access

Any data subject can request a full record of what personal data an organization holds about them. slim.io aggregates a SubjectAccessRecord from the findings its scanners have already detected across your connected stores, and returns it in a single response.

ART. 15

Subject access query

Identify a subject by email, SSN, phone, or a custom customer ID. slim.io runs a subject-hash lookup over the findings its scanners have detected and aggregates a complete SubjectAccessRecord. Subject identifiers are HMAC-hashed before storage — the raw identifier never persists.

1
Identifier normalization. The submitted identifier (email, SSN, phone, or custom ID) is normalised and HMAC-hashed into a deterministic subject_hash.
2
Candidate recall, then exact match. slim.io recalls candidate findings by blocking key, then narrows to an exact-string match on the normalized identifier. Variant forms are never silently matched — a request for one email address does not pull findings keyed on a different one.
3
Record assembly. A SubjectAccessRecord is built from the matched findings — one row per finding — plus a summary of the distinct resources and distinct PII types involved and the detection date range. Raw values are never included; each finding carries only masked evidence.
POST /api/v1/dsar/lookup
// Request body
{
  "subject_identifiers": [
    {"type": "email", "value": "alice@example.com"}
  ]
}
// Response — BatchAccessRecord (Article 15 is a pure read; no receipt is minted)
{
  "tenant_id": "tenant-acme",
  "identifier_count": 1,
  "records": [{
    "subject_hash": "hmac:sha256:a3f2c8...",
    "subject_type": "email",
    "tenant_id": "tenant-acme",
    "findings": [{
      "finding_id": "fnd_7f1a...", "pii_type": "EMAIL", "confidence": 0.98,
      "detected_at": "2026-05-28T14:32:00Z", "resource": "warehouse.customers",
      "masked_evidence": "a****@example.com"
    }],
    "summary": {
      "total_findings": 1, "distinct_resources": 1, "distinct_pii_types": ["EMAIL"],
      "date_range_first": "2026-05-28T14:32:00Z", "date_range_last": "2026-05-28T14:32:00Z",
      "candidate_pool_size": 4, "truncated": false, "truncated_count": 0, "window_days": 365
    }
  }],
  "summary": {
    "total_findings": 1, "candidate_pool_size_total": 4,
    "distinct_resources_union": 1, "distinct_pii_types_union": ["EMAIL"],
    "truncated_any": false, "window_days": 365
  }
}
Rate limiting: Access requests are rate-limited per tenant, per day. Once a tenant reaches its daily cap, further requests return a 429 until the window rolls over.

Article 17

Right to Erasure

A data subject can request that their personal data be erased. slim.io runs a graduated erasure over the findings metadata it holds for the subject — anonymized in place, never hard-deleted — revokes the tokens it issued, writes an immutable zero-PII ledger row, and returns a court-grade signed receipt.

ART. 17

Graduated erasure

A single API call runs the erasure over slim.io's own records for the subject. Detected findings are anonymized in place with EDPB-grade irreversibility — the personal data is replaced by a tombstone marker and is never recoverable. Tokens slim.io issued for the subject are revoked, with the vault looked up by the canonical form of the identifier. slim.io does not mutate, delete, or write to your source data stores.

1
Subject resolution & confirmation. The submitted identifiers are resolved to their subject hashes, and a confirmation_token bound to the batch is verified before any erasure runs.
2
Graduated anonymization. Every matched finding is anonymized in place — its personal data replaced by an irreversible tombstone marker, never hard-deleted. Tokens slim.io issued for the subject are revoked, with the vault looked up by the canonical form of the identifier.
3
Ledger entry & receipt. A single zero-PII row is written to the erasure ledger for the audit trail, and an Ed25519-signed receipt is returned as proof the request was processed.
POST /api/v1/dsar/erase
// Request body — multi-identifier intake (1–10 subjects per batch).
// `confirmation_token` is minted via POST /api/v1/dsar/confirmation-token
// and is bound to sha256(sorted(subject_hashes)) — order-independent.
{
  "subject_identifiers": [
    {"type": "email", "value": "jane@acme.co"}
  ],
  "confirmation_token": "f1a3...64-char-hex",
  "reason": "GDPR Art. 17 request #2026-0042"
}
// Response — BatchErasureResult; one per-subject `results` entry,
// all linked by a single `batch_id` for the audit trail.
{
  "tenant_id": "tenant-acme",
  "identifier_count": 1,
  "batch_id": "11111111-2222-4333-8444-555555555555",
  "results": [{
    "subject_hash": "hmac:sha256:a3f2c8...", "subject_type": "email",
    "tenant_id": "tenant-acme", "request_id": "9c2d...uuid",
    "erased": {"findings": 3, "findings_anonymized": 3, "entity_match_records": 1, "tokens_revoked": 1},
    "systems_touched": ["entity_match_records", "findings", "token_vault"],
    "receipt_id": "urn:slim-io:receipt:...", // null if signing is unwired
    "ledger": {"ledger_id": "9c2d...uuid", "tombstone_retention_days": 2557}
  }],
  "summary": {
    "findings_erased_total": 3, "entity_match_records_erased_total": 1,
    "tokens_revoked_total": 1,
    "systems_touched_union": ["entity_match_records", "findings", "token_vault"]
  },
  "errors": []
}
Error handling: Any per-subject error is surfaced verbatim in the response’s errors array for the privacy officer to review and re-run — the batch never fails silently.

Proof

Verifiable Receipts

Every Article 17 erasure generates an Ed25519-signed receipt with a three-tier chain-of-custody proof. (Article 15 access is a pure read and mints no receipt.) Receipts can be verified entirely offline — no network call, no dependency on slim.io infrastructure being reachable.

Tier 1
Action receipt
An Ed25519-signed record of the erasure action: who requested it, which identifier was erased, which internal systems were touched, and when. Generated immediately at action time.
Tier 2
Batch attestation
A Merkle-tree root over all DSAR receipts produced in a time window. Proves that the individual receipt is part of an unmodified batch and has not been inserted or deleted retroactively.
Tier 3
Transparency log
The batch root is appended to a tamper-evident transparency log. An auditor can prove that a receipt existed in the log at a given time without access to any other receipts in the batch.
Chain of custody
Offline verification

The receipt verifier is source-available at tools/verifier-py. Install it from source and run it against an evidence bundle exported by your operator — the tenant-offboarding evidence export packages receipts, Merkle proofs, and the public key — and verify the entire chain with no network access.

# Install the verifier from source (not yet published to a package index)
pip install ./tools/verifier-py
# Verify an exported evidence bundle offline
slim-receipts-verify bundle.zip
# Output
✓ T1 Ed25519 signature valid
✓ T2 Merkle inclusion proof valid
✓ T3 transparency log entry verified
✓ All 1 receipt(s) in bundle verified
Open source verifier: The slim-receipts-verify Python package is source-available at tools/verifier-py/ — early access, not yet published to any package index. It independently mirrors slim.io's signing primitives and imports nothing from the slim.io monorepo.

Quick reference

All DSAR endpoints

Authentication required. The three POST endpoints (confirmation-token, lookup, and erase) require a valid slim.io bearer token with the MANAGE_DSAR permission; the read-only erasure-history browse requires the read-only VIEW_DSAR_HISTORY permission. Designed for privacy officers and admin integrations, not customer-facing surfaces.

POST /api/v1/dsar/confirmation-token
Mint the short-lived confirmation_token required to authorize an erasure. Body: subject_identifiers. The token is bound to sha256(sorted(subject_hashes)) — order-independent — so it can only confirm the exact batch it was issued for.
POST /api/v1/dsar/lookup
Look up 1–10 subjects in a single batch. Body: subject_identifiers: [{type, value}, …] where type is one of email / ssn / phone / customer_id. Returns a BatchAccessRecord with per-subject records. No receipt is minted — Article 15 is a pure read.
POST /api/v1/dsar/erase
Run an Article 17 graduated erasure across a multi-identifier batch. Body: subject_identifiers, confirmation_token (minted via POST /api/v1/dsar/confirmation-token), optional reason. Returns a BatchErasureResult with per-subject ledger rows linked by a shared batch_id.
GET /api/v1/dsar/erasure-history
Browse the tenant's past erasures for the audit trail. Returns zero-PII ledger rows — each carries the request/batch IDs, counts, and retention window, never the personal data that was erased.