# Create Feedback of Ticket

> Reply to an existing ticket (add your feedback to the conversation).

## Endpoint

| Environment | URL |
| --- | --- |
| Production | `https://online-gateway.ghn.vn/shiip/public-api/ticket/reply` |
| Staging | `https://dev-online-gateway.ghn.vn/shiip/public-api/ticket/reply` |

**Method**: `POST`

## Headers

| Header | Required | Description |
| --- | --- | --- |
| `Content-Type` | Yes | A **form** encoding: `multipart/form-data` (required to send attachments) or `application/x-www-form-urlencoded`. Do **not** send `application/json` — a JSON body is silently ignored |
| `Token` | Yes | Shop token (issued by GHN). Your account must also hold the ticket permission, otherwise the reply is rejected with HTTP 403 — [get a token](https://developer.ghn.vn/en/docs/token/get-token.md) |
| `ShopId` | No | Shop ID (int). Defaults to your account's main shop. The ticket must belong to the resolved shop's account — to reply to a ticket of a non-default shop, send its `ShopId` |

## Parameters

Send every field as a **form value** (multipart or URL-encoded). Values placed in a JSON body or the query string are not read.

- **ticket_id** (Int): Ticket ID returned by [Create Ticket](https://developer.ghn.vn/en/docs/ticket/create.md). Must be numeric (a non-numeric value is treated as `0` and rejected). The ticket must belong to the acting shop's account
- **description** (String): Your reply content (max 2000 characters). Recorded on the ticket as a customer reply
- **attachments** (File(s)): Files to attach (multipart only). Max **10 files**, each up to **~2 MB**. Allowed extensions: `.docx` `.doc` `.xls` `.xlsx` `.pdf` `.jpg` `.jpeg` `.png` `.zip` `.pptx`. `.csv` is **not** allowed

> **NOTE**
> This request is **form-data, not JSON** — send it with `--form`/`-F` or `--data-urlencode`, never `--data '{...}'`. A JSON body reads as empty and fails validation.

## Request Example

```bash
curl -X POST https://dev-online-gateway.ghn.vn/shiip/public-api/ticket/reply \
  -H "Token: 5c1d8a9e-2f4b-11ed-..." \
  -H "ShopId: 92837" \
  -F "ticket_id=1234567" \
  -F "description=Thanks, please deliver in the morning" \
  -F "attachments=@/path/to/photo.jpg"
```

## Response

### Success (HTTP 200)

`data` is the conversation entry that was created. The reply is always recorded as sent by you (the customer); replying does **not** change the ticket's `status`/`status_id` in this response.

```json
{
  "code": 200,
  "message": "Success",
  "data": {
    "body": "Thanks, please deliver in the morning",
    "from_email": "cskh@ghn.vn",
    "user_id": 45678,
    "created_at": "2026-07-15T04:55:00Z",
    "updated_at": "2026-07-15T04:55:00Z"
  }
}
```

### Response Fields

| Field | Type | Description |
| --- | --- | --- |
| `code` | Int | HTTP code (`200` on success) |
| `message` | String | Result message (`Success`) |
| `data.body` | String | Reply content |
| `data.from_email` | String | Sender email label (omitted when empty) |
| `data.user_id` | Int | Internal user ID of the reply author (omitted when `0`) |
| `data.created_at` | String | Creation timestamp (omitted when empty) |
| `data.updated_at` | String | Last-update timestamp (omitted when empty) |
| `data.attachments` | Array | Attachment descriptors of the reply (omitted when empty) |
| `data.cc_emails` | String[] | CC list (omitted when empty) |
| `data.bcc_emails` | String[] | BCC list (omitted when empty) |
| `data.private` | Bool | Whether the entry is an internal note; replies you create are public (omitted when `false`) |

### Error — missing ticket_id (HTTP 400)

_Captured from a real Staging-environment call._

```json
{
  "code": 400,
  "message": "Key: 'myRequest.TicketID' Error:Field validation for 'TicketID' failed on the 'required' tag",
  "data": null
}
```

## Error Codes

| Condition | HTTP | Meaning |
| --- | --- | --- |
| Missing/non-numeric `ticket_id`, or missing/too-long `description` | 400 | A required form field is missing or fails validation |
| Attachment rejected | 400 | Too many files (>10), a file over ~2 MB, or a disallowed extension (e.g. `.csv`) |
| Not authorized (`Bạn không có quyền trả lời ticket này`) | 403 | The ticket does not belong to the acting shop's account |
| No ticket permission (`Bạn không có quyền thực hiện thao tác...`) | 403 | Your account lacks the ticket permission — contact GHN |
