# Callback Ticket (Webhook)

> **Chiều: GHN → server của bạn.** Khi một ticket hỗ trợ được tạo hoặc thay đổi, GHN POST ticket dưới dạng JSON đến webhook URL bạn đã đăng ký.

## Thiết lập

Webhook ticket do GHN cấu hình. **Liên hệ bộ phận hỗ trợ/admin của GHN** và cung cấp:

- **Client ID** của bạn
- **URL callback ticket** của bạn
- **môi trường** (Staging hoặc Production)
- một **tên** cho tích hợp

## Gửi (Delivery)

- Method: **POST**, body JSON, đến URL bạn đăng ký.
- **Xác nhận bằng HTTP 200.** Với bất kỳ mã non-200, GHN retry **10 lần, cách nhau 5 giây**.
- Hãy làm endpoint **idempotent** — retry nghĩa là bạn có thể nhận cùng một sự kiện nhiều lần.

## Payload

Khóa dạng **PascalCase**.

```json
{
  "TicketId": 123456,
  "ClientID": "102110",
  "OrderCode": "LADFYR",
  "Type": "Khiếu nại",
  "Status": "Đang xử lý",
  "StatusID": 1,
  "Description": "Khách phản ánh giao chậm",
  "CreatedBy": 70021,
  "CreatedAt": "2026-07-15T04:49:47Z",
  "UpdatedAt": "2026-07-15T05:10:00Z",
  "Attachments": [],
  "Conversations": [
    {
      "Body": "Chào bạn, GHN đang kiểm tra đơn hàng.",
      "FromEmail": "cskh@ghn.vn",
      "UserId": 70021,
      "Private": false,
      "CcEmails": null,
      "BccEmails": null,
      "Attachments": [],
      "CreatedAt": "2026-07-15T05:10:00Z",
      "UpdatedAt": "2026-07-15T05:10:00Z"
    }
  ]
}
```

_(Giá trị minh họa; tên trường là chính xác.)_

| Trường | Kiểu | Ý nghĩa |
| --- | --- | --- |
| `TicketId` | Int | Mã ticket |
| `ClientID` | String | Client ID của bạn (**chuỗi**, ví dụ `"102110"`) |
| `OrderCode` | String | Mã đơn GHN liên quan |
| `Type` | String | Loại ticket (xem bên dưới) |
| `Status` | String | Nhãn trạng thái tiếng Việt (text hiển thị) |
| `StatusID` | Int | Mã trạng thái (xem bên dưới) — dùng làm tín hiệu trạng thái đáng tin cậy |
| `Description` | String | Mô tả ticket |
| `CreatedBy` | Int | Mã người tạo (người yêu cầu) |
| `CreatedAt` | String | Thời điểm tạo ticket (ISO 8601) |
| `UpdatedAt` | String | Thời điểm cập nhật cuối (ISO 8601) |
| `Attachments` | Array | Tệp đính kèm ticket (ảnh / excel / csv) |
| `Conversations` | Array | Luồng trả lời (các trả lời nội bộ/riêng tư bị lọc bỏ trước khi gửi) |
| `Conversations[].Body` | String | Nội dung trả lời |
| `Conversations[].FromEmail` | String | Email người gửi của trả lời |
| `Conversations[].UserId` | Int | Mã người trả lời |
| `Conversations[].CcEmails` / `BccEmails` | Array/null | CC / BCC |
| `Conversations[].Attachments` | Array | Tệp đính kèm của trả lời |
| `Conversations[].CreatedAt` / `UpdatedAt` | String | Mốc thời gian của trả lời |

### Giá trị Type

`Tư vấn`, `Hối Giao/Lấy/Trả hàng`, `Thay đổi thông tin`, `Khiếu nại`. Khớp linh hoạt — GHN cũng dùng các biến thể nhãn mới hơn của các loại này.

### Giá trị StatusID

| StatusID | Status | Ý nghĩa |
| --- | --- | --- |
| 1 | Đang xử lý | Đang xử lý |
| 2 | Chờ KH phản hồi | Chờ khách phản hồi |
| 3 | Hoàn thành | Hoàn thành (kết thúc) |

Coi `StatusID != 3` là "vẫn đang mở".

## Lưu ý tích hợp

- **Parse linh hoạt**: chấp nhận các trường lạ/thừa (ví dụ `Reason`, `ShopID` có thể xuất hiện) và không dựa vào thứ tự trường.
- Các trường PII của khách (email/điện thoại/tên) **không được gửi** vì lý do bảo mật.
- Dùng `StatusID` (không phải nhãn `Status` tiếng Việt) làm tín hiệu trạng thái.
- Trả HTTP 200 nhanh chóng và khử trùng lặp theo `TicketId` + `UpdatedAt`.
