Data erasure

Erase your messages to or from a person — or wipe an inbox — and get a signed certificate that states what was erased and what was not.

When someone exercises their right to be forgotten, delete their data and prove you did. An erasure job does both: it deletes your messages to or from a person (or wipes a whole inbox), and when it finishes it hands you a signed certificate that states what it erased and what it did not reach — your GDPR or CCPA evidence, pulled on demand instead of chased over email.

Erasure runs as a durable background job, so a large deletion completes reliably even if it takes a while. Reads use compliance:read; the deletion itself uses compliance:write and a key whose creator is an organization owner or admin. A key restricted to specific inboxes cannot start a subject erasure (403); it can purge, list, and read jobs for its own inboxes only.

What an erasure reaches

A subject erasure works on your own records in the key's project: the messages that belong to you (the member whose key starts the job) in that project whose from, to, cc or bcc address is the person's email. It deletes those messages, their attachments and raw message files, and the threads they leave empty. It also strips the content (addresses, subject, body, provider payload) from their entries in the event stream and from the matching sent-message records and their delivery events; those rows keep only their ids and join keys. An inbox purge does the same for every message of one inbox, plus the inbox's remaining events.

An erasure does not reach:

  • records of other members of the organization, including their messages about the same person
  • records in any other project
  • the person's name or address inside messages that did not match, for example in a body or a signature
  • database backups taken before the job completed: daily backups are kept for 35 days, monthly backups for 365 days, and the archive of the 2026-08-08 platform move until it is deleted
  • copies outside Dairo: mail already delivered to recipients, and data held by the person's or the recipients' own providers

The certificate states both lists, under scope.erased and scope.notCovered, so it never reads as a wider erasure than the one that ran.

Start an erasure

POST /v1/erasure-jobs takes a small body. Set type to subject with a subjectHandle to erase your messages to or from that person, or type to inbox with an inboxId to wipe an inbox. subjectHandle must be a plain email address (ada@example.com, not Ada <ada@example.com>); anything else is a 400. An inbox outside your organization, or outside the key's inboxes, is a 404. The job is accepted right away and comes back pending.

# Erase your messages to or from a person
curl -X POST https://api.dairo.app/v1/erasure-jobs \
  -H "Authorization: Bearer $DAIRO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: erase-ada-2026-06" \
  -d '{ "type": "subject", "subjectHandle": "ada@example.com" }'

# Or wipe an inbox wholesale
curl -X POST https://api.dairo.app/v1/erasure-jobs \
  -H "Authorization: Bearer $DAIRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "type": "inbox", "inboxId": "7c9e6679-7425-40de-944b-e07fc1f90ae7" }'
{
  "object": "erasure_job",
  "jobId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "kind": "erase_subject",
  "status": "pending",
  "createdAt": "2026-06-12T10:00:00Z"
}

Pass an Idempotency-Key. Retrying with the same key returns the same job instead of enqueuing a second erasure — so a network retry can never double-delete or spawn a duplicate. Reusing a key for a different subject or inbox is a 409. See idempotency.

Poll to completion

GET /v1/erasure-jobs/{jobId} returns the full job. Poll until status is terminal (completed or failed). Once it's completed, the job carries exact deletion tallies, the signed certificate and its signature, certificateSig.

curl https://api.dairo.app/v1/erasure-jobs/3fa85f64-5717-4562-b3fc-2c963f66afa6 \
  -H "Authorization: Bearer $DAIRO_API_KEY"
{
  "object": "erasure_job",
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "kind": "erase_subject",
  "subjectHandle": "ada@example.com",
  "inboxId": null,
  "status": "completed",
  "deleted": {
    "messages": 42,
    "threads": 7,
    "attachments": 11,
    "s3Objects": 53,
    "ledgerRowsRedacted": 96
  },
  "certificate": {
    "type": "dairo.deletion.certificate.v2",
    "issuer": "dairo.app",
    "jobId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "userId": "9b2f7c1e-4d3a-4f6b-8e21-5c0a7d9e3b14",
    "projectId": "5d1e8a3c-2b7f-4c9e-a6d0-8f3b1e7c4a29",
    "kind": "erase_subject",
    "subjectHandle": "ada@example.com",
    "inboxId": null,
    "region": "eu-north-1",
    "scope": {
      "searched": "Messages that belong to userId in projectId whose from, to, cc or bcc address is subjectHandle.",
      "erased": ["the matched messages and their threads once no message is left in them", "…"],
      "notCovered": ["records of other members of the organization, including their messages about the same subject", "records in any other project", "…"]
    },
    "deleted": { "messages": 42, "threads": 7, "attachments": 11, "s3Objects": 53, "ledgerRowsRedacted": 96 },
    "requestedAt": "2026-06-12T10:00:00Z",
    "completedAt": "2026-06-12T10:00:30Z",
    "alg": "EdDSA",
    "kid": "dairo-ed25519-2026-06",
    "signature": "…"
  },
  "certificateSig": "…",
  "error": null,
  "createdAt": "2026-06-12T10:00:00Z",
  "startedAt": "2026-06-12T10:00:05Z",
  "completedAt": "2026-06-12T10:00:30Z"
}

The deleted tallies count exactly what the job did: messages, threads and attachments deleted, s3Objects the stored files removed with them (attachments and raw messages), and ledgerRowsRedacted the event-stream entries, sent-message records and delivery events whose content was stripped. The certificate is a signed artifact: it repeats the tallies and the scope above, and its signature (also returned as certificateSig) verifies against the published JWKS, so you can prove to an auditor that the deletion happened, when, and at exactly what scope. Keep it with your compliance records.

List your jobs

GET /v1/erasure-jobs returns your jobs, newest first.

curl "https://api.dairo.app/v1/erasure-jobs?limit=25" \
  -H "Authorization: Bearer $DAIRO_API_KEY"

Next steps

On this page