Skip to main content
When someone who uses your application asks you to delete or hand over their data, you can erase or export everything Zespan holds for them in a project. The person is identified by the userId or sessionId your SDK or OpenTelemetry spans carry — see Context enrichment for how those ids are set. This is different from your own Zespan account. To export or delete your account, see Privacy.

Endpoints

These endpoints authenticate with your dashboard session, not a project API key, and are refused while a Zespan staff member is impersonating you. Both POST bodies take exactly one of userId or sessionId — a non-blank string of at most 256 characters, matched exactly as your application sent it:
Sending both, neither, or any other field returns 400. You can make up to 10 requests per hour per project, across both kinds.

Request status

GET returns:

Errors

What an erase removes

Requests run in the background; an erase on a large project can take a few minutes. In that project only, Zespan deletes:
  • The end user’s spans and events — by userId or sessionId, and every trace they appear in
  • Prompt usage records and, for a user erase, per-user cost rollups
  • The evaluation scores and errors, outcomes, MCP tool spans, guardrail events, LLM errors, and policy signals of those traces and sessions
  • The analysis results recorded for those traces, such as findings and attributions. An export includes the same results
  • Older copies of the trace tables, where a deployment still keeps them. These copies are not included in an export
  • Earlier exports of the same end user
For 30 days afterwards, newly ingested events carrying that userId (or sessionId) in that project are dropped, so late SDK flushes and replays don’t bring the data back. Suppression follows the kind of id: erasing user x drops later events whose user id is x, not events whose session id happens to be x. Outcomes are matched by session id only, because an outcome carries no user id: after you erase a session, an outcome reported with that sessionId is dropped for those 30 days, and the outcome response reports how many were dropped (dropped). After you erase a user, later outcomes are not dropped, even ones that name one of that user’s sessions, and an outcome that carries only a trace id can’t be matched either way; both are stored. To keep a user’s late outcomes out, also erase their sessions, or stop reporting outcomes for them.

What an export contains

An export is one JSON file with a section per kind of record. If a section couldn’t be read, the file says so (partial: true and the list of failedSections). It stays available for 7 days through the GET endpoint. An export of an end user erased in the last 30 days fails with failureReason: "erased".

What is not erased

  • Records you curated that copy trace content: dataset items, dataset run items, regression replay results, evaluation runs and their results, annotation queue items, issues (their affected-trace lists), guardrail executions, and agent-to-agent tasks. A completed erase reports how many of each reference the end user in counts.notErased, so you can review and remove them in the dashboard.
  • Incident timelines, which aren’t stored per user (reported in counts.skipped).
  • Per-user cost rollups on a session erase, because they have no session key.
  • Backups, which are not edited. They expire on their own schedule (database backups after 30 days, trace-store backups after 42 days), and completed erasures are re-applied if a backup is ever restored.
Session ids must be unique per conversation. Session-based deletion removes every row of every session the end user appeared in — for a user erase, every session id seen with that userId. If your application reuses session ids across users (a constant, empty-like, or shared value), erasing one user also removes other users’ data in those sessions.
Guardrail records are written a few seconds after each check. If an erase runs immediately after live traffic for the same user, run it again a minute later to catch anything written in between.

Next steps