Data-Subject Requests
Technical reference. This page is for integrations, advanced configuration, or platform operations. For portal tasks, start with the user guide.
When a person asks for the personal data Orqestra holds about them — or asks you to correct it, delete it, restrict its processing, or objects to it — you handle that as a data-subject request (DSAR). Orqestra gives you a tenant-scoped, evidence-aware workflow that resolves the subject’s records inside one workspace, classifies them, produces a minimized and redacted export, and applies a deletion or restriction action without ever touching the immutable audit chain or crossing a tenant or subject boundary.
This guide walks the operator path: open a request, collect, review and export,
and action it. For the full data model, classifications, redaction contract, and
audit-action list, see the reference:
docs/reference/data-subject-requests.md.
Before you start
DSAR routes are workspace-scoped. You need:
data_subject_request.readto list and view requests.data_subject_request.manageto create, collect, export, and action them.
The manage permission is also the authority that erases the subject’s records — you do not need the platform-level retention-purge permission to action a DSAR. The two are deliberately separate: DSAR erases one subject’s records inside one tenant; retention purge is a platform-wide disposal control.
1. Open a request
Create a request with the subject’s bounded identifiers and the request type.
Supply at least one of email, actor_ref, or subject_ref — Orqestra stores
only these closed keys, never a free-form copy of the subject’s data.
The request type is one of:
access_export— return what is held (completed by export).correction— rectify inaccurate records.deletion— erase the subject’s deletable records.restriction— restrict processing without deleting.objection— object to processing.
from orqestra_sdk import OrqestraClient
client = OrqestraClient(base_url=..., token=...)
request = await client.data_subject_requests.create(
workspace_id,
request_type="deletion",
subject_identifiers={"email": "ada@example.com"},
subject_label="Ada L. (deletion request)",
reason="Subject requested erasure",
)
# request["state"] == "received"A new request starts in received. A request id that belongs to another
workspace is concealed as a 404 — you can only ever resolve a request inside
its own tenant.
2. Collect the subject’s records
Run collection to resolve the candidate records that belong to the subject across
the surfaces Orqestra can subject-scope. Collection advances the request through
scoped → collecting → ready_for_review, and is safe to re-run.
collection = await client.data_subject_requests.collect(workspace_id, request_id)
collection["manifest"]
# {
# "total_records": 12,
# "counts_by_surface": {"memory": 7, "execution": 4, "governance_audit": 1},
# "counts_by_classification": {"deletable": 7, "exportable": 4, "retained_by_obligation": 1},
# "deferred_surfaces": [
# {"surface": "retrieval", "reason": "no subject-scoped query wired: ..."},
# ...
# ]
# }What you get back is a bounded manifest — counts and classifications, never raw record content. Each query is tenant-scoped in SQL and filtered to the subject’s identifiers, so collection cannot reach another tenant’s or another subject’s records.
Read the deferred_surfaces list every time. Surfaces such as retrieval,
evidence, provider_metadata, and support_account are reported as honest
deferrals with a reason — Orqestra does not silently skip them, and it does not
yet subject-scope them. A complete subject-record picture may require resolving
those surfaces by other means.
3. Review and export
For an access_export request, run export once the request is
ready_for_review. Export builds a minimized, redacted package and advances the
request to exported.
export = await client.data_subject_requests.export(workspace_id, request_id)
export["package"]["manifest"]["countsBySurface"]The package is:
- Minimized — only this subject’s collected records, each reduced to its surface, classification, record ref, and a bounded summary. No raw content.
- Redacted — every value is run through the token-leak redactor and a secret-key guard, so no token, secret, password, or credential survives into the export.
- Manifested — per-surface and per-classification counts, the explicit
deferred-surface list, and a
truncatedflag with atruncatedSurfaceslist, so the package is honest about what it does and does not contain.
Review the manifest counts and the deferred list before you hand the package to
the subject or your privacy reviewer. Check manifest["truncated"]: when it
is true, a surface held more of the subject’s rows than the per-surface cap
returned, so the package contains a bounded subset of the subject’s records on
the named truncatedSurfaces only — it is not a complete export. Resolve the
remaining rows before treating the export as the subject’s full record set.
4. Action the request
For a correction, deletion, restriction, or objection request, run the action.
The action verb must match the request’s type (a mismatch is rejected with a
422). Orqestra re-collects fresh before acting, so the disposition is
decided on the current state, then applies it.
result = await client.data_subject_requests.action(
workspace_id, request_id, action="deletion",
)
result["result"]
# {
# "action_type": "deletion",
# "erased": 7,
# "restricted": 0,
# "retained_by_exception": 1,
# "skipped": 4,
# "counts_by_surface": {"memory": 7},
# "retained_by_surface": {"governance_audit": 1},
# "retention_reasons": ["immutable_audit_record"],
# "incomplete": False,
# "incomplete_surfaces": [],
# "drainable": False
# }What the action does, and does not do:
- Erases only the subject’s in-tenant deletable records. Deletion is bounded to the exact collected memory entry ids, resolved through the governed, workspace-scoped purge path. It can never reach a cross-tenant or cross-subject row.
- Never deletes the audit chain. Governance-audit / WORM rows and execution
governance metadata are obligation-bound: they are recorded as
retained_by_exceptionwith a bounded retention reason (immutable_audit_recordorlegal_or_security_obligation), never destroyed. The DSAR action itself is appended to the same tamper-evident chain. - Restriction never deletes. A restriction action records a processing restriction over the subject’s records instead of erasing them.
If everything in scope was retained under an obligation — nothing erased,
nothing restricted — the request lands in retained_by_exception rather than
actioned, and an extra data_subject_request.retained_exception audit event is
appended alongside the action event.
Capped (incomplete) deletions. If the subject owns more deletable rows on a
surface than the per-surface cap, the action erases only a capped batch and
reports incomplete: true with the capped surface in incomplete_surfaces. A
deletion is drainable: true — the request is then held at ready_for_review
instead of advancing to actioned, because re-running it erases the next batch.
Re-run the action until incomplete is false (the state then advances to
actioned); each run drains the next batch and the erasure completes across
calls. A capped restriction is reported incomplete: true but
drainable: false and still reaches actioned, since re-running removes no rows
— resolve its remaining rows out of band. (A capped correction or
objection records a single governance decision rather than processing memory
rows individually, so it is not flagged incomplete and reaches actioned
normally.) A capped action is never silently recorded as complete.
Every step writes a bounded data_subject_request.* governance-audit event whose
recorded state carries counts, the lifecycle state, and bounded reasons only —
never the subject’s personal data.
What this workflow is (and is not)
The DSAR workflow produces operational evidence of how you handled a request: what was searched, classified, exported, erased, restricted, and retained under an obligation, and why. It does not by itself constitute legal compliance or conformity. It does not decide a lawful basis, judge whether a request is valid, verify the requester’s identity, or cover personal data held outside the wired surfaces. Treat its output as input to your controller’s privacy process under appropriate legal review.