# Ticket Callback (Webhook)

> **Direction: GHN → your server.** When a support ticket is created or changes, GHN POSTs the ticket as JSON to your registered callback URL.

## Setup

Ticket webhooks are configured by GHN. **Contact GHN support/admin** and provide:

- your **Client ID**
- your **ticket callback URL**
- **environment** (Staging or Production)
- a **name** for the integration

## Delivery

- Method: **POST**, JSON body, to your registered URL.
- **Acknowledge with HTTP 200.** On any non-200, GHN retries **10 times, 5 seconds apart**.
- Make your endpoint **idempotent** — retries mean you may receive the same event more than once.

## Payload

Keys are **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"
    }
  ]
}
```

_(Illustrative values; field names are exact.)_

| Field | Type | Meaning |
| --- | --- | --- |
| `TicketId` | Int | Ticket ID |
| `ClientID` | String | Your client ID (**string**, e.g. `"102110"`) |
| `OrderCode` | String | Related GHN order code |
| `Type` | String | Ticket type (see below) |
| `Status` | String | Status label in Vietnamese (display text) |
| `StatusID` | Int | Status ID (see below) — use this as the reliable state signal |
| `Description` | String | Ticket description |
| `CreatedBy` | Int | Creator (requester) ID |
| `CreatedAt` | String | Ticket creation time (ISO 8601) |
| `UpdatedAt` | String | Last update time (ISO 8601) |
| `Attachments` | Array | Ticket file attachments (image / excel / csv) |
| `Conversations` | Array | Reply thread (internal/private replies are filtered out before delivery) |
| `Conversations[].Body` | String | Reply text |
| `Conversations[].FromEmail` | String | Sender email of the reply |
| `Conversations[].UserId` | Int | Replying user ID |
| `Conversations[].CcEmails` / `BccEmails` | Array/null | CC / BCC |
| `Conversations[].Attachments` | Array | Reply attachments |
| `Conversations[].CreatedAt` / `UpdatedAt` | String | Reply timestamps |

### Type values

`Tư vấn`, `Hối Giao/Lấy/Trả hàng`, `Thay đổi thông tin`, `Khiếu nại`. Match loosely — GHN uses newer label variants of these too.

### StatusID values

| StatusID | Status | Meaning |
| --- | --- | --- |
| 1 | Đang xử lý | In progress |
| 2 | Chờ KH phản hồi | Waiting for customer |
| 3 | Hoàn thành | Done (terminal) |

Treat `StatusID != 3` as "still open".

## Integration notes

- **Parse tolerantly**: accept unknown/extra fields (e.g. `Reason`, `ShopID` may appear) and don't rely on field ordering.
- Customer PII fields (email/phone/name) are **not sent** for privacy reasons.
- Use `StatusID` (not the Vietnamese `Status` label) as the state signal.
- Return HTTP 200 promptly and deduplicate on `TicketId` + `UpdatedAt`.
