# Create Ticket

> Open a support ticket for one of your orders.

## Endpoint

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

**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 and every field will read as empty |
| `Token` | Yes | Shop token (issued by GHN) — [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. Ownership is checked against the order's shop, but the request still fails if the resolved shop is inactive or not yours |

## 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.

- **order_code** (String): GHN tracking code the ticket is about (1–32 chars). Must be an existing order that belongs to a shop your account owns. Creating a ticket is **not** idempotent — the same order can have multiple tickets
- **category** (String): Ticket category. Also forms the ticket title `<order_code> - <category>`. Stick to the canonical values:<br>`Tư vấn`: advice<br>`Khiếu nại`: complaint<br>`Hối Giao/Lấy/Trả hàng`: urge delivery/pickup/return<br>`Thay đổi thông tin`: change information
- **description** (String): Ticket description (max 2000 characters). Copied into the ticket's `reason` at creation
- **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**. This is the most common integration mistake on this endpoint — the request must be sent with `--form`/`-F` or `--data-urlencode`, never `--data '{...}'`.

## Request Example

```bash
curl -X POST https://dev-online-gateway.ghn.vn/shiip/public-api/ticket/create \
  -H "Token: 5c1d8a9e-2f4b-11ed-..." \
  -H "ShopId: 92837" \
  -F "order_code=LADH94" \
  -F "category=Tư vấn" \
  -F "description=Need advice on the delivery time" \
  -F "attachments=@/path/to/photo.jpg"
```

> **NOTE**
> With `-F`, curl sets `Content-Type: multipart/form-data` (with the correct boundary) automatically — do not set it by hand. For a request with no attachments you can use `application/x-www-form-urlencoded` instead: `--data-urlencode "order_code=LADH94" --data-urlencode "category=Tư vấn" --data-urlencode "description=..."`.

## Response

### Success (HTTP 200)

`data` is the created ticket. Keep `data.id` — you need it for [Get Ticket](https://developer.ghn.vn/en/docs/ticket/detail.md) and [Create Feedback of Ticket](https://developer.ghn.vn/en/docs/ticket/create-feedback.md).

```json
{
  "code": 200,
  "message": "Success",
  "data": {
    "id": 1234567,
    "type": "Tư vấn",
    "reason": "Need advice on the delivery time",
    "order_code": "LADH94",
    "description": "Need advice on the delivery time",
    "status": "Đang xử lý",
    "status_id": 1,
    "client_id": "2509893",
    "shop_id": "196560",
    "created_at": "2026-07-15T04:49:47Z",
    "created_by": 45678,
    "updated_at": "2026-07-15T04:49:47Z",
    "conversations": [],
    "attachments": []
  }
}
```

### Response Fields

| Field | Type | Description |
| --- | --- | --- |
| `code` | Int | HTTP code (`200` on success) |
| `message` | String | Result message (`Success`) |
| `data.id` | Int | Ticket ID — store this; required by Get Ticket and Create Feedback |
| `data.type` | String | Ticket category (the `category` you sent) |
| `data.reason` | String | Ticket reason (omitted when empty); a copy of `description` at creation |
| `data.order_code` | String | Order code the ticket is about |
| `data.description` | String | Ticket description |
| `data.status` | String | Vietnamese status label matching `status_id` |
| `data.status_id` | Int | Ticket state:<br>`1`: `Đang xử lý` (in progress)<br>`2`: `Chờ KH phản hồi` (waiting for customer reply)<br>`3`: `Hoàn thành` (done) |
| `data.client_id` | String | Your client ID (omitted when empty) |
| `data.shop_id` | String | Shop the ticket belongs to (omitted when empty) |
| `data.created_at` | String | Creation timestamp (RFC 3339) |
| `data.created_by` | Int | Internal user ID recorded as the requester |
| `data.updated_at` | String | Last-update timestamp (RFC 3339) |
| `data.conversations` | Array | Reply entries; empty on a fresh ticket |
| `data.attachments` | Array | Attachment descriptors |

### Error — missing order_code (HTTP 400)

_Captured from a real Staging-environment call._

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

### Error — order not found (HTTP 404)

_Captured from a real Staging-environment call (unknown order code)._

```json
{
  "code": 404,
  "message": "Có lỗi xảy ra khi lấy thông tin đơn hàng",
  "data": null
}
```

## Error Codes

| Condition | HTTP | Meaning |
| --- | --- | --- |
| Missing/invalid `order_code`, `category`, or `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`) |
| Order not found (`Có lỗi xảy ra khi lấy thông tin đơn hàng` / `Không tìm thấy thông tin đơn hàng`) | 404 | The order code is unknown |
| Not authorized (`Bạn không có quyền tạo yêu cầu cho đơn hàng này`) | 403 | The order does not belong to a shop your account owns |
