> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kibocommerce.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Redaction Services

> Handle data subject erasure and right-to-deletion requests under GDPR, CCPA, DPDP, LGPD, LFPDPPP, and other privacy regulations using Kibo's two-phase redaction workflow

## Overview

Kibo's Redaction Services provide a **two-phase workflow** for processing data subject erasure requests as required by privacy regulations such as:

* **GDPR** (General Data Protection Regulation — EU/EEA)
* **CCPA / CPRA** (California Consumer Privacy Act / California Privacy Rights Act — US)
* **LGPD** (Lei Geral de Proteção de Dados — Brazil)
* **DPDP** (Digital Personal Data Protection Act — India)
* **PIPL** (Personal Information Protection Law — China)
* **PDPA** (Personal Data Protection Act — Thailand, Singapore, and others)
* **LFPDPPP** (Ley Federal de Protección de Datos Personales en Posesión de los Particulares — Mexico)

Regardless of the specific regulation, the workflow is the same: identify the data subject's PII, review the scope, and irreversibly remove it. The two phases are:

1. **Create a draft report** — Kibo scans the tenant's data for all PII associated with the subject and returns a report listing every affected record. No data is modified at this stage.
2. **Execute the redaction** — After reviewing the draft, you trigger the irreversible redaction that overwrites or removes the identified PII.

This separation exists to provide an auditable review step before any destructive action is taken. Your compliance team can inspect exactly what will be redacted before committing.

***

## How This Domain Fits Into Kibo

A single data subject's PII can exist across many parts of the Kibo platform. The redaction engine covers:

| Entity type      | What is redacted                                               |
| ---------------- | -------------------------------------------------------------- |
| Orders           | Billing/shipping addresses, contact details, custom attributes |
| Payments         | Payment method identifiers attached to orders                  |
| Checkouts        | In-progress or abandoned checkout PII                          |
| Returns          | Return contact and address details                             |
| Wishlists        | Wishlist owner identity                                        |
| Shipments        | Recipient contact and address details                          |
| Customer account | The account record itself (identified by `customerAccountId`)  |

The two-phase design lets you audit the scope of a deletion request before executing it — important both for regulatory compliance and for avoiding accidental data loss.

***

## Prerequisites

* Kibo API credentials (client ID and shared secret) with access to the `platform/data` namespace
* The `customerAccountId` (integer) or `userId` (string) of the data subject whose data must be erased
* An understanding of any custom attribute FQNs attached to orders, customers, returns, or shipments for your tenant, if you need those included in the redaction

***

## The Two-Phase Workflow

### Phase 1 — Create a Redaction Report (Draft)

**Endpoint:** `POST /platform/data/redaction/report` — [API reference](/api-reference/redaction/generate-redaction-report)

This call scans the tenant's data and returns a draft report. **No data is modified.**

#### Request body

```json theme={null}
{
  "customerAccountId": 4820193,
  "userId": null,
  "attributeFqns": {
    "order": ["tenant~gdpr-consent-date"],
    "customer": ["tenant~marketing-opt-in"],
    "return": null,
    "shipment": null
  },
  "clearDataNodes": {
    "orders": false,
    "checkouts": true,
    "shipments": false
  }
}
```

**Field descriptions:**

| Field                      | Type      | Description                                                                             |
| -------------------------- | --------- | --------------------------------------------------------------------------------------- |
| `customerAccountId`        | integer   | The Kibo customer account ID of the data subject. Required if `userId` is not provided. |
| `userId`                   | string    | The user ID of the data subject. Required if `customerAccountId` is not provided.       |
| `attributeFqns.order`      | string\[] | Fully-qualified names of custom order attributes to include in the redaction scope.     |
| `attributeFqns.customer`   | string\[] | Fully-qualified names of custom customer attributes to include.                         |
| `attributeFqns.return`     | string\[] | Fully-qualified names of custom return attributes to include.                           |
| `attributeFqns.shipment`   | string\[] | Fully-qualified names of custom shipment attributes to include.                         |
| `clearDataNodes.orders`    | boolean   | If `true`, wipes the entire order data node rather than field-level PII only.           |
| `clearDataNodes.checkouts` | boolean   | If `true`, wipes the entire checkout data node.                                         |
| `clearDataNodes.shipments` | boolean   | If `true`, wipes the entire shipment data node.                                         |

#### Example response

```json theme={null}
{
  "reportId": "a3f9c2d1-4e7b-4f8a-b2c3-9d0e1f2a3b4c",
  "schemaVersion": 1,
  "tenantId": 1000000,
  "status": "Draft",
  "subject": {
    "customerAccountId": 4820193,
    "userId": null,
    "resolvedEmailAddresses": ["jane.doe@example.com"]
  },
  "auditInfo": {
    "createBy": "840065bee668435b9d5346e60e6b1f88",
    "createDate": "2026-03-19T14:00:00Z",
    "updateBy": null,
    "updateDate": null
  },
  "request": {
    "correlationId": "corr-7f3a9b21",
    "attributeFqns": {
      "order": ["tenant~gdpr-consent-date"],
      "customer": ["tenant~marketing-opt-in"],
      "return": null,
      "shipment": null
    },
    "clearDataNodes": {
      "orders": false,
      "checkouts": true,
      "shipments": false
    }
  },
  "createdAt": "2026-03-19T14:00:00Z",
  "executionStartedAt": null,
  "executionCompletedAt": null,
  "affectedEntities": {
    "customerAccountId": 4820193,
    "orders": { "count": 3, "ids": ["1ab0edd566b26c0001ce7f1f000186e3", "2bc1fee677c37d1102df8g2g111297f4", "3cd2gff788d48e2213eg9h3h222308g5"] },
    "payments": { "count": 2, "ids": ["af6f5fd885de41c589f4b363012f78ef", "be7g6ge996ef52d69ag5c474123g89fg"] },
    "checkouts": { "count": 2, "ids": ["1ab0edd566b26c0001ce7f1f000186e3", "2bc1fee677c37d1102df8g2g111297f4"] },
    "returns": { "count": 1, "ids": ["3cd2gff788d48e2213eg9h3h222308g5"] },
    "wishlists": { "count": 1, "ids": ["4de3hgg899e59f3324fh0i4i333419h6"] },
    "shipments": { "count": 3, "ids": ["802", "803", "804"] }
  },
  "operationLog": null,
  "errorSummary": null
}
```

The key field to note is `status: "Draft"`. The report has been created and the affected entities have been identified, but nothing has been changed yet.

***

### Phase 2 — Review the Draft Report

**Endpoint:** `GET /platform/data/redaction/report/{reportId}` — [API reference](/api-reference/redaction/get-redaction-report)

Retrieve the draft report and verify the scope before committing to the redaction.

```
GET /platform/data/redaction/report/a3f9c2d1-4e7b-4f8a-b2c3-9d0e1f2a3b4c
```

Review the `affectedEntities` object carefully:

* `orders.count` / `orders.ids` — the orders that will have PII removed
* `payments.count` / `payments.ids` — payment records linked to those orders
* `checkouts.count` / `checkouts.ids` — any checkout records found
* `returns.count` / `returns.ids` — return records
* `wishlists.count` / `wishlists.ids` — wishlist records
* `shipments.count` / `shipments.ids` — shipment records
* `customerAccountId` — the resolved account ID of the subject

Confirm that `status` is `"Draft"` before proceeding to execution. A report with `status: "Executed"` cannot be executed again.

***

### Phase 3 — Execute the Redaction

**Endpoint:** `POST /platform/data/redaction/execute/{reportId}` — [API reference](/api-reference/redaction/execute-redaction)

<Warning>
  Execution is **irreversible**. Once you call this endpoint the identified PII is permanently removed or overwritten. There is no undo. Ensure the draft report has been reviewed and approved before proceeding.
</Warning>

```
POST /platform/data/redaction/execute/a3f9c2d1-4e7b-4f8a-b2c3-9d0e1f2a3b4c
```

This endpoint has no request body. The `reportId` in the path identifies which draft to execute.

#### Example response

```json theme={null}
{
  "reportId": "a3f9c2d1-4e7b-4f8a-b2c3-9d0e1f2a3b4c",
  "schemaVersion": 1,
  "tenantId": 1000000,
  "status": "Executed",
  "subject": {
    "customerAccountId": 4820193,
    "userId": null,
    "resolvedEmailAddresses": ["jane.doe@example.com"]
  },
  "createdAt": "2026-03-19T14:00:00Z",
  "executionStartedAt": "2026-03-19T14:05:00Z",
  "executionCompletedAt": "2026-03-19T14:05:03Z",
  "affectedEntities": {
    "customerAccountId": 4820193,
    "orders": { "count": 3, "ids": ["1ab0edd566b26c0001ce7f1f000186e3", "2bc1fee677c37d1102df8g2g111297f4", "3cd2gff788d48e2213eg9h3h222308g5"] },
    "payments": { "count": 2, "ids": ["af6f5fd885de41c589f4b363012f78ef", "be7g6ge996ef52d69ag5c474123g89fg"] },
    "checkouts": { "count": 2, "ids": ["1ab0edd566b26c0001ce7f1f000186e3", "2bc1fee677c37d1102df8g2g111297f4"] },
    "returns": { "count": 1, "ids": ["3cd2gff788d48e2213eg9h3h222308g5"] },
    "wishlists": { "count": 1, "ids": ["4de3hgg899e59f3324fh0i4i333419h6"] },
    "shipments": { "count": 3, "ids": ["802", "803", "804"] }
  },
  "operationLog": [
    {
      "timestamp": "2026-03-19T14:05:00Z",
      "phase": "Execution",
      "store": "main",
      "entityType": "Order",
      "entityId": "1ab0edd566b26c0001ce7f1f000186e3",
      "operation": "RedactPii",
      "status": "Success",
      "recordsAffected": 1,
      "durationMs": 42,
      "errorMessage": null
    },
    {
      "timestamp": "2026-03-19T14:05:01Z",
      "phase": "Execution",
      "store": "main",
      "entityType": "CustomerAccount",
      "entityId": "4820193",
      "operation": "RedactPii",
      "status": "Success",
      "recordsAffected": 1,
      "durationMs": 38,
      "errorMessage": null
    }
  ],
  "errorSummary": null
}
```

After execution, `status` changes to `"Executed"`, `executionCompletedAt` is populated, and `operationLog` contains one entry per operation performed.

#### Reading the operation log

| Field             | Description                                                        |
| ----------------- | ------------------------------------------------------------------ |
| `timestamp`       | When this individual operation ran                                 |
| `phase`           | Processing phase (e.g., `"Execution"`)                             |
| `store`           | The data store or context within the tenant                        |
| `entityType`      | The type of record affected (e.g., `"Order"`, `"CustomerAccount"`) |
| `entityId`        | The ID of the specific record                                      |
| `operation`       | The action taken (e.g., `"RedactPii"`)                             |
| `status`          | `"Success"` or `"Failed"` for this individual operation            |
| `recordsAffected` | Number of records modified by this operation                       |
| `durationMs`      | Time taken in milliseconds                                         |
| `errorMessage`    | Populated only on failure; describes what went wrong               |

If any entries have `status: "Failed"`, check `errorMessage` for details and review `errorSummary` on the report for a rolled-up description.

***

## Listing and Auditing Reports

**Endpoint:** `GET /platform/data/redaction/report` — [API reference](/api-reference/redaction/list-redaction-reports)

Use this endpoint to retrieve a paginated list of reports — useful for auditing which requests have been fulfilled and which drafts are awaiting execution.

#### Query parameters

| Parameter  | Type      | Description                                                        |
| ---------- | --------- | ------------------------------------------------------------------ |
| `status`   | string    | Filter by report status: `Draft` or `Executed`                     |
| `from`     | date-time | Return only reports created at or after this timestamp (ISO 8601)  |
| `to`       | date-time | Return only reports created at or before this timestamp (ISO 8601) |
| `page`     | integer   | Page number (1-based)                                              |
| `pageSize` | integer   | Number of results per page                                         |

#### Example request

```
GET /platform/data/redaction/report?status=Draft&page=1&pageSize=20
```

#### Example response

```json theme={null}
{
  "startIndex": 0,
  "pageSize": 20,
  "items": [
    {
      "reportId": "a3f9c2d1-4e7b-4f8a-b2c3-9d0e1f2a3b4c",
      "schemaVersion": 1,
      "tenantId": 1000000,
      "status": "Draft",
      "subject": {
        "customerAccountId": 4820193,
        "userId": null,
        "resolvedEmailAddresses": ["jane.doe@example.com"]
      },
      "createdAt": "2026-03-19T14:00:00Z",
      "executionStartedAt": null,
      "executionCompletedAt": null,
      "errorSummary": null
    }
  ]
}
```

Note that the list response returns `RedactionReportSummaryResponse` objects, which do **not** include `affectedEntities`, `request`, or `operationLog`. To get those fields, retrieve the individual report by ID.

***

## Field Reference

Key fields on `RedactionReportResponse`:

| Field                            | Type      | Description                                                  |
| -------------------------------- | --------- | ------------------------------------------------------------ |
| `reportId`                       | string    | Unique identifier for this redaction report                  |
| `status`                         | string    | `"Draft"` before execution, `"Executed"` after               |
| `tenantId`                       | integer   | The Kibo tenant this report belongs to                       |
| `subject.customerAccountId`      | integer   | Resolved customer account ID of the data subject             |
| `subject.resolvedEmailAddresses` | string\[] | Email addresses resolved from the subject's account          |
| `affectedEntities`               | object    | Counts and IDs of all records that will be / were redacted   |
| `operationLog`                   | array     | Per-record operation results; populated only after execution |
| `createdAt`                      | date-time | When the draft report was created                            |
| `executionStartedAt`             | date-time | When execution began (null on Draft)                         |
| `executionCompletedAt`           | date-time | When execution finished (null on Draft)                      |
| `errorSummary`                   | string    | High-level error description if any operations failed        |

***

## Troubleshooting

**Empty `affectedEntities` on a draft report**

The subject identifier provided (`customerAccountId` or `userId`) did not match any records. Verify the ID is correct for your tenant. Note that `customerAccountId` is a tenant-scoped integer, not a global Kibo user ID.

**`400` or `422` when creating a report**

Ensure you are providing at least one of `customerAccountId` or `userId`. Providing neither, or providing an `attributeFqns` array with invalid FQN strings, will result in a validation error.

**Attempting to execute an already-executed report**

Once a report has `status: "Executed"`, calling `POST /platform/data/redaction/execute/{reportId}` again will return an error. Each data subject erasure request requires a new draft report.

**Partial failures in the operation log**

If some `operationLog` entries show `status: "Failed"`, the redaction completed partially. Records that failed were not redacted. Review each failed entry's `errorMessage`. You may need to create and execute a new report to retry the affected records, or investigate the underlying data integrity issue before retrying.
