# API ลบข้อมูล

Data Erasure API คือวิธี self-serve สำหรับลบข้อมูลส่วนบุคคลของหัวเรื่องออกจาก Pushwoosh (สิทธิ์การลบข้อมูลตาม GDPR) การลบไม่สามารถยกเลิกได้: ใช้เพื่อจำลองหน้า [คำขอข้อมูล](/th/product/account-management-and-security/data-requests/) ของ Control Panel และการดำเนินการ [ลบข้อมูลส่วนบุคคล](/th/product/audience-data-and-segmentation/user-explorer/#erase-personal-data) บนการ์ดของผู้สมัครสมาชิกจากระบบของคุณเอง

## URL พื้นฐาน

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

Endpoints ทั้งหมดให้บริการผ่าน HTTPS คำขอและการตอบกลับใช้ `application/json` ยกเว้น [Upload](#upload) ซึ่งใช้ `multipart/form-data`

## การยืนยันตัวตน

ทุกคำขอต้องมีเฮดเดอร์ `Authorization` พร้อมกับ [โทเค็น Server API](/th/developer/api-reference/api-access-token/#server-api-token) ของคุณ:

```
Authorization: Api YOUR_API_TOKEN
```

โทเค็นต้องมีสิทธิ์แก้ไขสำหรับทุกแอปพลิเคชันที่ระบุใน `application_codes` ซึ่งเป็นสิทธิ์เดียวกับที่โทเค็นต้องใช้ในการเขียนข้อมูลอุปกรณ์บนแอปพลิเคชันเหล่านั้น

<span id="conventions" />

## ข้อตกลง

*   **การตั้งชื่อฟิลด์:** request bodies ยอมรับ `lowerCamelCase` (ตัวอย่างเช่น `applicationCodes`, `identifierType`) การตอบกลับจะถูก marshal โดยใช้ชื่อฟิลด์ของ proto เสมอ ในรูปแบบ `snake_case` (`task_id`, `identifier_hash` และอื่นๆ) ตัวอย่างและข้อมูลอ้างอิงออบเจ็กต์ด้านล่างใช้รูปแบบตัวพิมพ์นั้น
*   **ตัวระบุ (Identifiers):** หัวเรื่องจะถูกระบุด้วย `identifier_type` (`SUBJECT_IDENTIFIER_USER_ID`, `SUBJECT_IDENTIFIER_HWID` หรือ `SUBJECT_IDENTIFIER_EMAIL`) ร่วมกับรายการ `identifiers` ของประเภทนั้นเพียงประเภทเดียว ตัวระบุแบบอีเมลจะจับคู่แบบไม่สนตัวพิมพ์เล็ก-ใหญ่
*   **Dry run ก่อน แล้วค่อยอ้างอิง:** [Create](#create) ด้วย `dry_run: true` จะนับเฉพาะสิ่งที่จะถูกลบเท่านั้นและไม่เขียนข้อมูลใดๆ การอ้างอิง `task_id` ของ dry run นั้นเป็น `confirmation_dry_run_task_id` ในการเรียกจริงเป็นทางเลือก แต่หากคุณอ้างอิง ต้องตรงกับแอปพลิเคชันและตัวระบุของ dry run นั้นทุกประการ และต้องเรียกภายใน 15 นาทีหลังจาก dry run เสร็จสิ้น มิฉะนั้นคำขอจะถูกปฏิเสธ
*   **รายงานจะไม่มีตัวระบุแบบข้อความธรรมดาปรากฏอยู่เลย** ทั้ง [GetTaskReport](#gettaskreport) และ [GetJournalReport](#getjournalreport) จะรายงานตัวระบุแต่ละตัวเป็นค่า sha256 hash (`identifier_hash`) และเนื้อหารายงานเป็น CSV ที่เข้ารหัสแบบ base64 อยู่ในการตอบกลับแบบ JSON

### การตอบกลับข้อผิดพลาด

| สถานะ HTTP | ความหมาย |
| :---- | :---- |
| `400 Bad Request` | อาร์กิวเมนต์ไม่ถูกต้อง เช่น `identifier_type`, `identifiers` หรือ `application_codes` ว่างเปล่า, ตัวระบุมากกว่า 10,000 รายการ, แอปพลิเคชันมากกว่า 50 รายการ, ตัวระบุ × แอปพลิเคชันเกิน 50,000, สตริงตัวระบุว่างเปล่า หรือ (เฉพาะ Upload) ไฟล์ CSV หายไป/ไม่สามารถอ่านได้ นอกจากนี้ยังส่งคืนเป็น `FailedPrecondition` บน wire เมื่อ `confirmation_dry_run_task_id` ที่อ้างอิงไม่ตรงกับ dry run ที่เสร็จสิ้นซึ่งระบุไว้, เก่าเกินไป (มากกว่า 15 นาที) หรือไม่ใช่ dry run ที่เสร็จสิ้นเลย |
| `401 Unauthorized` | เฮดเดอร์ `Authorization` หายไปหรือไม่ถูกต้อง |
| `403 Forbidden` | โทเค็นไม่มีสิทธิ์ modify/device-data บนแอปพลิเคชันที่ร้องขอรายการใดรายการหนึ่ง หรือผู้เรียกไม่มีสิทธิ์อ่าน task/report ที่ร้องขอ |
| `404 Not Found` | ไม่พบ task หรือ task ไม่ได้เป็นของบัญชีของผู้เรียก |
| `413 Payload Too Large` | (เฉพาะ Upload) ไฟล์ที่อัปโหลดมีขนาดเกิน 5 MB |
| `429 Too Many Requests` | บัญชีเริ่มงานลบข้อมูลไปแล้ว 20 งาน (รวม dry run) ใน 24 ชั่วโมงที่ผ่านมา |

## Endpoints

| เมธอด | เส้นทาง | คำอธิบาย |
| :---- | :---- | :---- |
| `POST` | `/api/data_erasure/tasks` | สร้างงานลบข้อมูล (หรือ dry-run) |
| `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 | ใช่ | [รหัสแอปพลิเคชัน](/th/developer/api-reference/api-identifiers/#application-code) ที่จะลบข้อมูลออก สูงสุด 50 รายการ ไม่มีวิธีลบข้อมูลจากทุกแอปพลิเคชันของบัญชีในการเรียกครั้งเดียว จึงต้องระบุแต่ละรายการอย่างชัดเจน `identifiers.length × applicationCodes.length` ต้องไม่เกิน 50,000 เนื่องจากรายงานมีหนึ่งแถวต่อตัวระบุต่อแอปพลิเคชัน |
| `dryRun` | boolean | ไม่ | นับสิ่งที่จะถูกลบและไม่เขียนข้อมูลใดๆ ค่าเริ่มต้นคือ `false` |
| `confirmationDryRunTaskId` | integer | ไม่ | `task_id` ของ dry run ที่เสร็จสิ้นแล้วซึ่งวัดผลการลบนี้ไว้ตรงกัน ดูที่ [ข้อตกลง](#conventions) |

##### ตัวอย่างคำขอ

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

### การตอบกลับ

| ฟิลด์ | ประเภท | คำอธิบาย |
| :---- | :---- | :---- |
| `task_id` | integer | Id ของงานที่สร้างขึ้น ใช้ค่านี้กับ endpoint อื่นๆ ทั้งหมดในหน้านี้ |

<Aside type="danger">
การลบไม่สามารถยกเลิกได้ การลบหัวเรื่องหนึ่งจะลบข้อมูลของหัวเรื่องนั้นในทุกแอปพลิเคชันที่ระบุไว้ แต่จะไม่ยกเลิกข้อความที่ตั้งเวลาหรืออยู่ในคิวไว้แล้วสำหรับหัวเรื่องนั้น เช่น การส่งแบบดีเลย์หรือขั้นตอนถัดไปของ journey ที่กำลังทำงานอยู่
</Aside>

## Upload

สร้างงานประเภทเดียวกับ [Create](#create) แต่ตัวระบุมาจากไฟล์ CSV ที่อัปโหลดแทนที่จะเป็นอาร์เรย์ JSON ใช้วิธีนี้สำหรับรายการหัวเรื่องจำนวนมาก

`POST` `/api/data_erasure/upload`

### คำขอ (multipart/form-data)

| ฟิลด์ | จำเป็น | คำอธิบาย |
| :---- | :---- | :---- |
| `file` | ใช่ | ไฟล์ CSV ขนาดสูงสุด 5 MB หนึ่งตัวระบุต่อแถว ในคอลัมน์เดียว แถวแรกอาจตั้งชื่อคอลัมน์ (`user_id`, `userid`, `user id`, `hwid`, `email`, `identifier` หรือ `subject` โดยไม่สนตัวพิมพ์เล็ก-ใหญ่) แทนที่จะเก็บตัวระบุ แถวนั้นจะถูกข้ามในฐานะ header โดยไม่นับรวม แถวว่างจะถูกข้ามและนับแยกต่างหาก ตัวระบุที่ซ้ำกัน (ไม่สนตัวพิมพ์เล็ก-ใหญ่ สำหรับอีเมล) จะถูกรวมเป็นหนึ่งและนับแยกต่างหาก |
| `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

แสดงรายการการลบข้อมูลของบัญชี เรียงจากล่าสุดก่อน: บันทึกการตรวจสอบว่าใครลบอะไรและเมื่อไร Dry run จะถูกละไว้เว้นแต่จะตั้งค่า `includeDryRuns`

`GET` `/api/data_erasure/tasks`

### พารามิเตอร์ของ Query

| พารามิเตอร์ | ประเภท | คำอธิบาย |
| :---- | :---- | :---- |
| `limit` / `offset` | integer | การแบ่งหน้า |
| `includeDryRuns` | boolean | รวมงานแบบ dry-run (วัดผลอย่างเดียว) ด้วย |
| `from` / `to` | string (RFC 3339) | เก็บเฉพาะงานที่เริ่มในช่วง `[from, to)` |
| `applicationCode` | string | เก็บเฉพาะงานที่ครอบคลุมแอปพลิเคชันนี้ |
| `initiatorUserId` | integer | เก็บเฉพาะงานที่เริ่มโดยผู้ใช้ Control Panel รายนี้ `0` (ค่าเริ่มต้น) จะเก็บทุกผู้เริ่มงาน |
| `initiatorTokenId` | integer | เก็บเฉพาะงานที่เริ่มโดย API token นี้ `0` (ค่าเริ่มต้น) จะเก็บทุกผู้เริ่มงาน |
| `initiatorEmail` | string | เก็บเฉพาะงานที่เริ่มโดยผู้ใช้ Control Panel รายนี้ จับคู่ด้วยอีเมล โดยไม่สนตัวพิมพ์เล็ก-ใหญ่ |

### การตอบกลับ

| ฟิลด์ | ประเภท | คำอธิบาย |
| :---- | :---- | :---- |
| `tasks` | array of [ออบเจ็กต์ Data erasure task](#data-erasure-task-object) | งานที่ตรงกัน |

## GetTask

ส่งคืนงานลบข้อมูลหนึ่งงานพร้อมสถานะและตัวนับ ใช้เพื่อติดตามงานที่เริ่มโดย [Create](#create) หรือ [Upload](#upload)

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

### การตอบกลับ

| ฟิลด์ | ประเภท | คำอธิบาย |
| :---- | :---- | :---- |
| `task` | [ออบเจ็กต์ Data erasure task](#data-erasure-task-object) | งานที่ร้องขอ |

## ListTaskRows

ส่งคืนผลลัพธ์รายตัวระบุของงานหนึ่งงาน: อะไรถูกลบ ไม่พบ ข้าม หรือล้มเหลว ตัวระบุจะถูกรายงานเป็นค่า sha256 hash

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

### พารามิเตอร์ของ Query

| พารามิเตอร์ | ประเภท | คำอธิบาย |
| :---- | :---- | :---- |
| `limit` / `offset` | integer | การแบ่งหน้า |

### การตอบกลับ

| ฟิลด์ | ประเภท | คำอธิบาย |
| :---- | :---- | :---- |
| `rows` | array of [ออบเจ็กต์แถวของ Data erasure task](#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`

### พารามิเตอร์ของ Query

| พารามิเตอร์ | ประเภท | จำเป็น | คำอธิบาย |
| :---- | :---- | :---- | :---- |
| `from` | string (RFC 3339) | ใช่ | จุดเริ่มต้นของช่วงเวลา |
| `to` | string (RFC 3339) | ไม่ | จุดสิ้นสุดของช่วงเวลา ค่าเริ่มต้นคือปัจจุบัน |
| `includeDryRuns` | boolean | ไม่ | รวมงานแบบ dry-run ด้วย |

<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" />

## ออบเจ็กต์ Data erasure task

| ฟิลด์ | ประเภท | คำอธิบาย |
| :---- | :---- | :---- |
| `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 | จำนวนที่ถูกลบ (หรือสำหรับ dry run คือจำนวนที่จะถูกลบ) |
| `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 token เป็นผู้เริ่ม |
| `initiator_token_id` | integer | API token ที่เริ่มงาน `0` เมื่อผู้ใช้ Control Panel เป็นผู้เริ่ม |
| `initiator_email` | string | อีเมลของผู้ใช้ Control Panel ที่เริ่มงาน ว่างเปล่าสำหรับ API token |
| `created` | string (RFC 3339) | เวลาที่สร้างงาน |
| `started_at` | string (RFC 3339) | เวลาที่งานลบเริ่มทำงาน |
| `finished_at` | string (RFC 3339) | เวลาที่งานถึงสถานะสุดท้าย |

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

## ออบเจ็กต์แถวของ Data erasure task

| ฟิลด์ | ประเภท | คำอธิบาย |
| :---- | :---- | :---- |
| `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>