# Data Protection

## API Limitations

The API is restricted as such:

* Max. 1 request per second
* Max. 500 entries in `emailList`
* Max. 100 entries in `customerNoList`

## Request Payload for All Data Protection APIs

Requests against the following endpoints `/wipe` and `/disclose` expect data to be provided in the following format as a JSON payload:

```json
{
  "emailList": [ ... ],
  "customerNoList": [ ... ]
}
```

Both the `emailList` as well as the `customerNoList` keys are arrays of strings. For `emailList`, the API enforces a valid email address format. Both keys are optional and can be used in parallel.

The following limitations are applied to the keys:

* `emailList`
  * Max. 500 email address per API request
  * All entries are required to be valid email addresses
  * Selects all records related to data provided with same key in `email`
* `customerNoList`
  * Max. 100 customer numbers per API request
  * Selects all records related to data provided with same key in `customerNo`

### **Dealing with Invalid Requests (API status code `400`)**

If the request has an invalid payload, the API will respond with status code `400` and provide payload validation errors in the response body:

```json
{
  "type": "invalid_request",
  "code": "validation.fail",
  "message": "Provided data is not valid",
  "context": {
    "errors": [
      { ... } // AJV Validation Error, see below
    ]
  }
}
```

In the response, key `context.errors` is an array of validation errors as provided by [Ajv](https://ajv.js.org/). For details, please refer to Ajv spec here:

{% embed url="<https://ajv.js.org/api.html#validation-errors>" %}
Spec for Ajv validation errors
{% endembed %}

## Right to Erasure, API `/wipe`

To comply with the right to erasure according to GDPR Art. 17 (also known as *right to be forgotten*) or CCPA, this API offers the wipe of PII from records in parcelLab using the `wipe` endpoint. This is a synchronous operation, in which data will be deleted from the production database and backups and confirmed with the API response.

The following data will be removed:

* PII removed from `trackings`, but the records themselves are kept for logistics analysis
  * `email` and `customerNo`
  * `recipient` and `recipient_notification`
  * `street`, `city`
  * complete object in `customFields`
* All sent `emails` are completely deleted
* All sent `sms` are completely deleted

Details of how the `wipe` endpoint can be used to wipe PII from records in the parcelLab system are described below.

<details>

<summary><mark style="color:green;">POST</mark> Remove all PII from Records in parcelLab</summary>

You can synchronously remove all PII from records identified by customer email address or customer number with the `wipe` endpoint. To use this API, you need your parcelLab `user_id` and `API token` for authentication.

The details of the Remove all PII from Records in parcelLab API are described in the following section.

**API Details**

<mark style="color:green;">`POST`</mark> `https://api.parcellab.com/wipe`

**Header**

| Name                                    | Type   | Description                            |
| --------------------------------------- | ------ | -------------------------------------- |
| user<mark style="color:red;">\*</mark>  | Number | parcelLab user ID                      |
| token<mark style="color:red;">\*</mark> | String | parcelLab API token with `write` scope |

**Request Body**

| Name           | Type           | Description                         |
| -------------- | -------------- | ----------------------------------- |
| emailList      | Array\<String> | Array of customer `email` addresses |
| customerNoList | Array\<String> | Array of `customerNo`s              |

**Responses**

* 200 - OK: wipe operation was successful

```javascript
{
  "modified": { // number of affected records by category
    "trackingsUpdate": {
      "modifiedCount": 1 // number of trackings updated
    },
    "emailsUpdate": {
      "deletedCount": 0 // number of emails deleted
    },
    "smsUpdate": {
      "deletedCount": 0 // number of sms deleted
    }
  },
  "signature": "", // SHA265 signature of request
  "emails": [], // ⚠️ DEPRECATED  
  "customerNos": [] // ⚠️ DEPRECATED
}
```

* 400 - bad request: invalid request

{% code overflow="wrap" %}

```javascript
{
  "type": "invalid_request",
  "code": "validation.fail",
  "message": "Provided data is not valid",
  "context": {
    "errors": [
      { ... } // AJV Validation Error, see: https://ajv.js.org/api.html#validation-errors
    ]
  }
}
```

{% endcode %}

* 500 - internal server error wipe operation failed, please retry

```bash
{
  "code": "database.operation.fail",
  "message": "Database operation failed, please retry",
  "type": "api_failure"
}
```

</details>

After a successful `/wipe` operation the API response body contains the following metadata:

```json
{
  "modified": { // number of affected records by category
    "trackingsUpdate": { "modifiedCount": 1 },
    "emailsUpdate": { "deletedCount": 0 },
    "smsUpdate": { "deletedCount": 0 }
  },
  "signature": "" // SHA265 signature of request
}
```

The `modified` key features the number of affected records:

* `trackingsUpdate.modifiedCount` is the number of trackings for which PII was removed
* `emailsUpdate.deletedCount` and `smsUpdate.deletedCount` are the number of records deleted respectively

The `signature` is a SHA256 signature of the request operation. It does not include or expose any PII, but can be used afterward to verify whether the request payload was executed. As parcelLab cannot store logs or records on wipe requests, please keep this reference.

{% hint style="info" %}
The `emails` and `customerNos` keys in the response are deprecated and will be no longer included starting January 1st, 2023. Please disregard those.
{% endhint %}

## Right of Access, API `/disclose`

This API allows you to synchronously generate a set of .csv files that lists all PII stored of customers using the `disclose` endpoint. Requests with both email address and customer number in parallel are possible and supported. Due to the response structure, individual requests by customers are strongly recommended.

Details of how the `disclose` endpoint can be used to generate .csv files listing PII information from records in the parcelLab system are described below.

<details>

<summary><mark style="color:green;">POST</mark> Disclose PII of Customers and Provide as CSV</summary>

You can synchronously list all PII from records identified by customer email address or customer number and transform into .csv format with the `disclose` endpoint. To use this API, you need your parcelLab `user_id` and `API token` for authentication.

The details of the Disclose PII of Customers and Provide as CSV API are described in the following section.

**API Details**

<mark style="color:green;">`POST`</mark> `https://api.parcellab.com/disclose`

**Header**

| Name                                    | Type   | Description                            |
| --------------------------------------- | ------ | -------------------------------------- |
| user<mark style="color:red;">\*</mark>  | Number | parcelLab user ID                      |
| token<mark style="color:red;">\*</mark> | String | parcelLab API token with `write` scope |

**Responses**

* 200 - OK: successful export

```javascript
{
  "trackings": "...",
  "emails": "...",
  "sms": "..."
}
```

* 400 - bad request: invalid request

{% code overflow="wrap" %}

```javascript
{
  "type": "invalid_request",
  "code": "validation.fail",
  "message": "Provided data is not valid",
  "context": {
    "errors": [
      { ... } // AJV Validation Error, see: https://ajv.js.org/api.html#validation-errors
    ]
  }
}
```

{% endcode %}

* 500 - internal server error operation failed, please retry

```bash
{
  "code": "database.operation.fail",
  "message": "Database operation failed, please retry",
  "type": "api_failure"
}
```

</details>

Each key (that is: `trackings`, `emails` and `sms)` contains a .csv formatted string of all records selected by the request (even if spanning multiple customers) grouped by type.

Format of the CSV:

* Includes headers
* Row delimiter is `\n`
* Column delimiter is `;`
* Charset is UTF-8


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.parcellab.com/docs/developers/v2/security/data-protection.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
