# API стирания данных

API стирания данных — это самостоятельный способ стереть персональные данные субъекта из Pushwoosh (право на стирание по GDPR). Стирание необратимо: используйте этот API, чтобы воспроизвести из ваших собственных систем действие страницы [Запросы данных](/ru/product/account-management-and-security/data-requests/) в Control Panel и действие [Стереть персональные данные](/ru/product/audience-data-and-segmentation/user-explorer/#erase-personal-data) на карточке подписчика.

## Базовый URL

```
https://rpc-api.svc-nue.pushwoosh.com
```

Все эндпоинты обслуживаются по HTTPS. Запросы и ответы используют `application/json`, кроме [Upload](#upload), который принимает `multipart/form-data`.

## Аутентификация

Каждый запрос должен содержать заголовок `Authorization` с вашим [токеном Server API](/ru/developer/api-reference/api-access-token/#server-api-token):

```
Authorization: Api YOUR_API_TOKEN
```

Токен должен иметь право на изменение (modify) для каждого приложения, указанного в `application_codes`. Это то же право, которое нужно токену для записи данных об устройствах в этих приложениях.

<span id="conventions" />

## Соглашения

* **Именование полей:** тела запросов принимают `lowerCamelCase` (например, `applicationCodes`, `identifierType`). Ответы сериализуются с использованием имен полей proto в `snake_case` (`task_id`, `identifier_hash` и так далее). В примерах и справочниках по объектам ниже используется этот регистр.
* **Идентификаторы:** субъект адресуется по `identifier_type` (`SUBJECT_IDENTIFIER_USER_ID`, `SUBJECT_IDENTIFIER_HWID` или `SUBJECT_IDENTIFIER_EMAIL`) и списку `identifiers` этого одного типа. Идентификатор email сопоставляется без учета регистра.
* **Сначала пробный запуск, потом ссылка на него:** [Create](#create) с `dry_run: true` только подсчитывает, что было бы стерто, и ничего не записывает. Указывать `task_id` этого пробного запуска в `confirmation_dry_run_task_id` при реальном вызове необязательно, но если вы его указываете, он должен в точности совпадать по приложениям и идентификаторам с этим пробным запуском и быть вызван в течение 15 минут после его завершения. Иначе вызов будет отклонен.
* **Отчеты никогда не содержат идентификатор в открытом виде.** И [GetTaskReport](#gettaskreport), и [GetJournalReport](#getjournalreport) указывают каждый идентификатор в виде его sha256-хэша (`identifier_hash`), а тело отчета — это CSV, закодированный в base64 внутри JSON-ответа.

### Ответы об ошибках

| HTTP-статус | Значение |
| :---- | :---- |
| `400 Bad Request` | Недопустимый аргумент: пустой `identifier_type`, `identifiers` или `application_codes`, более 10 000 идентификаторов, более 50 приложений, идентификаторы × приложения свыше 50 000, пустая строка идентификатора, или (только для Upload) отсутствующий/нечитаемый CSV-файл. Также возвращается как `FailedPrecondition` при передаче, когда указанный `confirmation_dry_run_task_id` не совпадает с завершенным пробным запуском, который он называет, слишком устарел (более 15 минут) или вообще не является завершенным пробным запуском. |
| `401 Unauthorized` | Отсутствует или недействителен заголовок `Authorization`. |
| `403 Forbidden` | У токена нет права на изменение/данные устройства (modify/device-data) для одного из запрошенных приложений, либо вызывающая сторона не может читать запрошенную задачу/отчет. |
| `404 Not Found` | Задача не найдена или не принадлежит аккаунту вызывающей стороны. |
| `413 Payload Too Large` | (только для Upload) загруженный файл превышает 5 МБ. |
| `429 Too Many Requests` | Аккаунт уже запустил 20 задач стирания данных (включая пробные запуски) за последние 24 часа. |

## Эндпоинты

| Метод | Путь | Описание |
| :---- | :---- | :---- |
| `POST` | `/api/data_erasure/tasks` | Создать задачу стирания (или пробного запуска) |
| `POST` | `/api/data_erasure/upload` | Создать задачу стирания из загруженного CSV с идентификаторами |
| `GET` | `/api/data_erasure/tasks` | Получить список задач стирания аккаунта |
| `GET` | `/api/data_erasure/tasks/{task_id}` | Получить одну задачу стирания |
| `GET` | `/api/data_erasure/tasks/{task_id}/rows` | Получить список результатов задачи по каждому идентификатору |
| `GET` | `/api/data_erasure/tasks/{task_id}/report` | Скачать отчет по задаче в формате CSV |
| `GET` | `/api/data_erasure/report` | Скачать все задачи за период одним CSV-файлом |

## Create

Начинает стирание персональных данных перечисленных субъектов в перечисленных приложениях. С `dry_run: true` задача только подсчитывает, что было бы стерто.

`POST` `/api/data_erasure/tasks`

### Тело запроса

| Параметр | Тип | Обязательный | Описание |
| :---- | :---- | :---- | :---- |
| `identifierType` | string | Да | `SUBJECT_IDENTIFIER_USER_ID`, `SUBJECT_IDENTIFIER_HWID` или `SUBJECT_IDENTIFIER_EMAIL`. |
| `identifiers` | array of strings | Да | Идентификаторы субъекта этого одного типа, до 10 000 на задачу, без пустых значений. |
| `applicationCodes` | array of strings | Да | [Коды приложений](/ru/developer/api-reference/api-identifiers/#application-code), из которых нужно стереть данные, до 50. Стереть данные из всех приложений аккаунта одним вызовом нельзя, поэтому указывайте каждое явно. `identifiers.length × applicationCodes.length` не должно превышать 50 000, потому что отчет содержит одну строку на каждый идентификатор в каждом приложении. |
| `dryRun` | boolean | Нет | Подсчитывает, что было бы стерто, и ничего не записывает. По умолчанию `false`. |
| `confirmationDryRunTaskId` | integer | Нет | `task_id` завершенного пробного запуска, который измерил именно это стирание. См. [Соглашения](#conventions). |

##### Пример запроса

```json
{
  "identifierType": "SUBJECT_IDENTIFIER_EMAIL",
  "identifiers": ["subject@example.com"],
  "applicationCodes": ["XXXXX-XXXXX"],
  "dryRun": true
}
```

### Ответ

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `task_id` | integer | Id созданной задачи. Используйте его во всех остальных эндпоинтах на этой странице. |

<Aside type="danger">
Стирание нельзя отменить. Стирание данных субъекта удаляет его данные во всех указанных приложениях, но не отменяет сообщения, уже запланированные или поставленные в очередь для этого субъекта, например отложенную отправку или следующий шаг выполняющегося Journey.
</Aside>

## Upload

Создает такую же задачу, как [Create](#create), но идентификаторы берутся из загруженного CSV, а не из JSON-массива. Используйте это для массового списка субъектов.

`POST` `/api/data_erasure/upload`

### Запрос (multipart/form-data)

| Поле | Обязательный | Описание |
| :---- | :---- | :---- |
| `file` | Да | CSV-файл, до 5 МБ, один идентификатор на строку, в единственном столбце. Первая строка может называть столбец (`user_id`, `userid`, `user id`, `hwid`, `email`, `identifier` или `subject`, без учета регистра) вместо хранения идентификатора. Такая строка пропускается как заголовок и не учитывается. Пустые строки пропускаются и учитываются отдельно. Повторяющиеся идентификаторы (без учета регистра для email) объединяются в один и учитываются отдельно. |
| `identifier_type` | Да | `user_id`, `hwid` или `email`, в нижнем регистре — регистр отличается от значений enum `identifierType` в JSON, используемых в остальной части этой страницы. Один тип применяется ко всему файлу. |
| `application_codes` | Да | Коды приложений через запятую. |
| `dry_run` | Нет | `true`/`false`. |
| `confirmation_dry_run_task_id` | Нет | То же, что в `Create`. |

### Ответ

```json
{
  "task_id": 123,
  "identifier_count": 480,
  "duplicate_count": 3,
  "skipped_rows": 1
}
```

## ListTasks

Возвращает список стираний аккаунта, сначала самые новые: журнал аудита того, кто, что и когда стер. Пробные запуски исключаются, если не установлен `includeDryRuns`.

`GET` `/api/data_erasure/tasks`

### Параметры запроса

| Параметр | Тип | Описание |
| :---- | :---- | :---- |
| `limit` / `offset` | integer | Постраничная навигация. |
| `includeDryRuns` | boolean | Включить задачи пробных запусков (только для измерения). |
| `from` / `to` | string (RFC 3339) | Оставить задачи, начатые в интервале `[from, to)`. |
| `applicationCode` | string | Оставить задачи, которые охватывают это приложение. |
| `initiatorUserId` | integer | Оставить задачи, начатые этим пользователем Control Panel. `0` (по умолчанию) оставляет всех инициаторов. |
| `initiatorTokenId` | integer | Оставить задачи, начатые этим API-токеном. `0` (по умолчанию) оставляет всех инициаторов. |
| `initiatorEmail` | string | Оставить задачи, начатые пользователем Control Panel, определенным по email без учета регистра. |

### Ответ

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `tasks` | array of [объектов задачи стирания данных](#data-erasure-task-object) | Подходящие задачи. |

## GetTask

Возвращает одну задачу стирания с ее статусом и счетчиками. Используйте это, чтобы отслеживать задачу, начатую через [Create](#create) или [Upload](#upload).

`GET` `/api/data_erasure/tasks/{task_id}`

### Ответ

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `task` | [Объект задачи стирания данных](#data-erasure-task-object) | Запрошенная задача. |

## ListTaskRows

Возвращает результат задачи по каждому идентификатору: что было удалено, не найдено, пропущено или завершилось ошибкой. Идентификаторы указываются в виде их sha256-хэша.

`GET` `/api/data_erasure/tasks/{task_id}/rows`

### Параметры запроса

| Параметр | Тип | Описание |
| :---- | :---- | :---- |
| `limit` / `offset` | integer | Постраничная навигация. |

### Ответ

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `rows` | array of [объектов строки задачи стирания данных](#data-erasure-task-row-object) | Эта страница результатов. |

## GetTaskReport

Возвращает весь отчет по задаче в виде CSV-файла: одна строка на идентификатор в каждом приложении с результатом. [ListTaskRows](#listtaskrows) вместо этого показывает те же строки постранично.

`GET` `/api/data_erasure/tasks/{task_id}/report`

### Ответ

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `filename` | string | Предлагаемое имя файла, например `data-erasure-task-42.csv`. |
| `content_type` | string | `text/csv`. |
| `content` | string (base64) | CSV-файл. Столбцы: `task_id`, `created`, `identifier_type`, `identifier_hash`, `application_code`, `result`, `detail`. |

## GetJournalReport

Возвращает все стирания за период в виде одного CSV-файла: строка на идентификатор в каждом приложении, с задачей и ее инициатором в каждой строке. Именно это аккаунт передает аудитору.

`GET` `/api/data_erasure/report`

### Параметры запроса

| Параметр | Тип | Обязательный | Описание |
| :---- | :---- | :---- | :---- |
| `from` | string (RFC 3339) | Да | Начало периода. |
| `to` | string (RFC 3339) | Нет | Конец периода. По умолчанию — текущий момент. |
| `includeDryRuns` | boolean | Нет | Включить задачи пробных запусков. |

<Aside type="caution">
Период с более чем 2 000 задач стирания отклоняется, а не обрезается. Сузьте период и повторите вызов.
</Aside>

### Ответ

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `filename` | string | Предлагаемое имя файла, например `data-erasure-2026-01-01-2026-04-01.csv`. |
| `content_type` | string | `text/csv`. |
| `content` | string (base64) | CSV-файл. Столбцы: `task_id`, `task_created`, `initiator_user_id`, `initiator_email`, `initiator_token_id`, `dry_run`, `identifier_type`, `identifier_hash`, `application_code`, `result`, `detail`, `row_created`. |

<span id="data-erasure-task-object" />

## Объект задачи стирания данных

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `task_id` | integer | Id задачи. |
| `identifier_type` | string | `SUBJECT_IDENTIFIER_USER_ID`, `SUBJECT_IDENTIFIER_HWID` или `SUBJECT_IDENTIFIER_EMAIL`. |
| `application_codes` | array of strings | Приложения, которые охватывает задача. |
| `dry_run` | boolean | Только ли эта задача измеряла объем. |
| `status` | string | `ERASURE_TASK_STATUS_PENDING`, `_IN_PROGRESS`, `_DONE` или `_FAILED`. |
| `total_count` | integer | Идентификаторы × приложения, которые охватывает эта задача. |
| `deleted_count` | integer | Сколько было стерто (или было бы стерто, для пробного запуска). |
| `not_found_count` | integer | Сколько не совпало ни с чем. |
| `failed_count` | integer | Сколько завершилось ошибкой. Причину см. в [ListTaskRows](#listtaskrows) или в отчете. |
| `fail_reason` | string | Устанавливается, когда `status` равен `ERASURE_TASK_STATUS_FAILED`. |
| `initiator_user_id` | integer | Пользователь Control Panel, начавший задачу. `0`, если ее начал API-токен. |
| `initiator_token_id` | integer | API-токен, начавший задачу. `0`, если ее начал пользователь Control Panel. |
| `initiator_email` | string | Адрес пользователя Control Panel, начавшего задачу. Пусто для API-токена. |
| `created` | string (RFC 3339) | Когда задача была создана. |
| `started_at` | string (RFC 3339) | Когда началась работа по стиранию. |
| `finished_at` | string (RFC 3339) | Когда задача достигла финального статуса. |

<span id="data-erasure-task-row-object" />

## Объект строки задачи стирания данных

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `identifier_hash` | string | sha256 идентификатора. Отчет никогда не хранит и не возвращает сам идентификатор. |
| `application_code` | string | Приложение, к которому относится результат этой строки. |
| `result` | string | `ERASURE_ROW_RESULT_DELETED`, `_NOT_FOUND`, `_SKIPPED` или `_FAILED`. |
| `detail` | string | Техническая подробность, устанавливается в основном при ошибке. |
| `created` | string (RFC 3339) | Когда эта строка была записана. |

## Связанные материалы

<CardGrid>
  <LinkCard title="Запросы данных (руководство по продукту)" href="/product/account-management-and-security/data-requests/" />
  <LinkCard title="Стереть персональные данные из User Explorer" href="/product/audience-data-and-segmentation/user-explorer/#erase-personal-data" />
</CardGrid>