GET /datasets/{dataset_id}/sample/redacted. The underlying sample is not modified — deleting the redaction leaves the sample untouched, and GET /datasets/{dataset_id}/sample continues to return unmasked rows.
Writing or deleting a redaction requires an API key with write access on datasets. See API key permissions.
Prerequisites
- A dataset with a stored sample. Call
POST /datasets/{dataset_id}/request-samplefirst if one does not exist. - An API key with write access on datasets.
The four endpoints
Upload a redaction
SendPUT /datasets/{dataset_id}/redaction with one entry per column that holds personal data. Each entry names the column’s dot-separated path in the sample, an optional category, and a masking_strategy.
PUT returns 200 and replaces whatever was stored before. Uploading also brings back a redaction that was previously deleted. The stored redaction records who wrote it from your access token, so a written_by field in the request body is ignored.
A single redaction may name at most 20,480 columns. A path that does not resolve in a row leaves that row untouched, so a redaction naming a since-renamed column quietly stops masking it.
Masking strategies
Seven strategies are available. Each is a JSON object tagged withtype.
keep_last_digits requires a count between 1 and 4:
@, a non-IPv4 address, a non-coordinate, a value with no four-digit run) is masked completely.
Personal data categories
category classifies what kind of personal data the column holds. It does not affect masking — only masking_strategy does. Nine values are accepted:
account_numberotherprivate_addressprivate_dateprivate_emailprivate_personprivate_phoneprivate_urlsecret
category is optional. Send null or leave the key out for a column you don’t want to classify.
Read the redacted sample
GET /datasets/{dataset_id}/sample/redacted returns the sample with every named column masked and every other column untouched.
400 when no sample or no redaction is stored for the dataset. Use POST /v2/datasets/{dataset_id}/request-sample to sample the dataset and have Narrative’s privacy model write a redaction in a single call.
Delete a redaction
DELETE /datasets/{dataset_id}/redaction clears the stored redaction. GET /datasets/{dataset_id}/redaction then reports it as missing, and GET /datasets/{dataset_id}/sample/redacted stops returning rows until a new redaction is stored. Deleting when there is no redaction succeeds and does nothing. The underlying sample is not affected.
Errors
PUT /datasets/{dataset_id}/redaction returns 400 when a request body is malformed. error_description points at the offending column by its position in columns:
500 if the stored redaction cannot be decoded — for example, a stored masking_strategy this API no longer recognises. The body is an RFC 7807 problem document with title: "Stored Redaction Unreadable". Quote the log_id when reporting the failure to support.
Related content
Sample Data
How samples move from data planes to the control plane
Hashing PII for Upload
Prepare identifiers before uploading them

