> For the complete documentation index, see [llms.txt](https://docs.neox.vn/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.neox.vn/docs/global/global-collections/integration/collections/api-create-trade-order.md).

# Create Trade Order

#### Endpoint: POST /v2/gc/trade-orders

#### Description: Create or update a PI/CI trade-contract order that provides the commercial background for collection funds.

## Request

#### Request Body Field Descriptions (JSON)

**Core fields (always relevant):**

| Field Name       | Type         | Required    | Description                                                                                                                                                                     |
| ---------------- | ------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| requestId        | string(32)   | No          | Merchant-generated unique request ID. Used for idempotency. If omitted, the server auto-generates one — supplying your own value is still recommended for reliable idempotency. |
| subMerchantId    | string(32)   | Conditional | Sub-merchant identifier that the trade order is created under. Optional in general; **required when the merchant operates in PSP mode.**                                        |
| tradeType        | string       | Yes         | Type of trade. Enum: `GOODS_TRADE_COLLECTION` \| `SERVICES_TRADE_COLLECTION`.                                                                                                   |
| isExchange       | boolean      | Yes         | Whether this trade order should also create a foreign-exchange settlement statement. This is the central switch that drives many of the conditional fields below.               |
| orderReferenceId | string(64)   | Yes         | Merchant-side reference number for the trade order (e.g. PI or CI number). Checked for duplicates per `subMerchantId`.                                                          |
| currency         | string       | Yes         | Currency of the trade order (e.g. `USD`, `EUR`, `HKD`). Must be a three-letter uppercase ISO 4217 code; `CNY` is not supported.                                                 |
| amount           | number       | Yes         | Total trade amount in the specified `currency`. Minimum `0.01`, at most two decimal places.                                                                                     |
| operate          | string       | No          | Enum: `ADD` \| `UPDATE`. Defaults to `ADD`.                                                                                                                                     |
| saveType         | string       | No          | Enum: `NORMAL` \| `IGNORE_FILE`. Use `IGNORE_FILE` to update order data without re-uploading documents. Defaults to `NORMAL`.                                                   |
| tradeRemark      | string(256)  | No          | Free-text remark.                                                                                                                                                               |
| partnerSite      | string(1024) | No          | Partner/marketplace site identifier. Must start with `http://` or `https://` if provided.                                                                                       |
| otherFiles       | array        | No          | Additional supporting document file paths (each a `path` from `POST /v2/gc/files/upload`).                                                                                      |
| id               | string(32)   | No          | Internal entity ID. Optional on create (auto-generated as a UUID if omitted); used to identify the trade order being modified on Update Trade Order.                            |
| riskInfo         | string(2048) | No          | JSON string containing risk information such as `contractType`.                                                                                                                 |

**Goods-trade fields** (`tradeType=GOODS_TRADE_COLLECTION`):

| Field Name            | Type                | Required | Description                                                                                                                                                  |
| --------------------- | ------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| buyerName             | string(256)         | No       | Name of the overseas buyer. See conditional-requirement logic below.                                                                                         |
| buyerArea             | string              | No       | Country/region of the buyer (ISO 3166-1 alpha-3). See conditional-requirement logic below.                                                                   |
| contractFiles         | array (max 6 items) | No       | Contract document file paths. Always required in practice — see conditional-requirement logic below.                                                         |
| productName           | string(1024)        | No       | Name of the traded product. If not written in Chinese characters, must be at least 3 characters long. See conditional-requirement logic below.               |
| productCount          | number              | No       | Quantity of the traded product. See conditional-requirement logic below.                                                                                     |
| productUnit           | string              | No       | Unit used for the product quantity. See `productUnit` enumeration below. See conditional-requirement logic below.                                            |
| tradePlatformName     | string(128)         | No       | Name of the e-commerce/trading platform. Subject to an anti-fraud denylist — see hint below. See conditional-requirement logic below.                        |
| productUrl            | string(1024)        | No       | URL of the product listing. Must start with `http://` or `https://` if provided. See conditional-requirement logic below.                                    |
| logisticsStatus       | string              | No       | Enum: `UNSHIPPED` \| `SHIPPED`. See conditional-requirement logic below.                                                                                     |
| logisticsCompany      | string(1024)        | No       | Name of the logistics/courier company. See conditional-requirement logic below.                                                                              |
| logisticsNumber       | string(1024)        | No       | Tracking/waybill number. See conditional-requirement logic below.                                                                                            |
| logisticsFiles        | array               | No       | Logistics document file paths. See conditional-requirement logic below.                                                                                      |
| logisticsExpectedTime | date string         | No       | Expected delivery date. See conditional-requirement logic below.                                                                                             |
| logisticsType         | string              | No       | Enum: `SEA_TRANSPORT` \| `AIR_TRANSPORT` \| `LAND_TRANSPORT` \| `POSTAL_PARCEL`. Required only for services trade — see conditional-requirement logic below. |
| receiverArea          | string              | No       | Country/region of the goods receiver (ISO 3166-1 alpha-3). Required only for services trade — see conditional-requirement logic below.                       |

**Services-trade fields** (`tradeType=SERVICES_TRADE_COLLECTION`):

| Field Name      | Type   | Required | Description                                                                                                                                                                                        |
| --------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| serviceCategory | string | No       | Enum: `GENERAL_TRADE` \| `LOGISTICS_COSTS` \| `TICKET_PURCHASE` \| `SOFTWARE` \| `EMPLOYEE_SALARY`. Required when `tradeType=SERVICES_TRADE_COLLECTION` — see conditional-requirement logic below. |
| fundsNature     | string | No       | Nature of the service funds. Valid options depend on `serviceCategory` — see hint below. Required when `tradeType=SERVICES_TRADE_COLLECTION` — see conditional-requirement logic below.            |

**Cross-border / customs fields:**

| Field Name              | Type        | Required | Description                                                                                                                                                                                                   |
| ----------------------- | ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| tradeDateTime           | date string | No       | Trade date. Required when `isExchange=true` — see conditional-requirement logic below.                                                                                                                        |
| declareType             | string      | No       | Customs declaration type. Enum: `0110` \| `1210` \| `1239` \| `9610` \| `9710` \| `9810`.                                                                                                                     |
| declareList             | array       | No       | Customs declaration entries: `{declareAmount, declareCurrency, declareNo, declareDateTime, declareLogisticsStatus, customsDeclarationFiles?}`. `declareLogisticsStatus` enum: `0000`–`0005`.                  |
| settlementType          | string      | No       | Enum: `SETTLEMENT_WITHDRAWAL` \| `CORPORATE_CROSS_BORDER_SETTLEMENT`. The customs `declareList` block is only relevant when this is `CORPORATE_CROSS_BORDER_SETTLEMENT`. Defaults to `SETTLEMENT_WITHDRAWAL`. |
| advanceReceiptsRatio    | number      | No       | Advance-receipts ratio. Required when the advance-receipts block applies — see conditional-requirement logic below.                                                                                           |
| advanceReceiptsCurrency | string      | No       | Advance-receipts currency. Required when the advance-receipts block applies — see conditional-requirement logic below.                                                                                        |
| advanceReceiptsAmount   | number      | No       | Advance-receipts amount. Required when the advance-receipts block applies — see conditional-requirement logic below.                                                                                          |
| billingPeriod           | number      | No       | Billing period, in days. Required when the advance-receipts block applies — see conditional-requirement logic below.                                                                                          |

**Software fields** (relevant when `serviceCategory=SOFTWARE`):

| Field Name          | Type        | Required | Description                                                                                                                                                                                                                         |
| ------------------- | ----------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| applicationPlatform | string      | No       | Enum: `GOOGLE_PLAY` \| `APP_STORE`. Required when `serviceCategory=SOFTWARE` and `isExchange=true` — see conditional-requirement logic below.                                                                                       |
| softwareNumber      | string(256) | No       | Software package/bundle identifier (e.g. `com.example.app`). Must be a dot-separated identifier with at least 3 segments. Required when `serviceCategory=SOFTWARE` and `isExchange=true` — see conditional-requirement logic below. |
| softwareName        | string(256) | No       | Software name. Required when `serviceCategory=SOFTWARE` and `isExchange=true` — see conditional-requirement logic below.                                                                                                            |
| releaseDate         | date string | No       | Release date. Required when `serviceCategory=SOFTWARE` and `isExchange=true` — see conditional-requirement logic below.                                                                                                             |

**Payroll fields:**

| Field Name   | Type  | Required | Description                                                                                                                                                                                                  |
| ------------ | ----- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| employeeList | array | No       | `{empName, empIdCardNo}[]` — each row requires both fields if present. No minimum row count enforced. Required when `serviceCategory=EMPLOYEE_SALARY`, `fundsNature=EMPLOYEE_SALARY`, and `isExchange=true`. |

<details>

<summary><strong>Conditional-requirement logic (UI-enforced, from the Merchant Portal's create-trade-order form)</strong></summary>

{% hint style="info" %}
The backend **does** perform schema validation on this endpoint: a Zod schema plus a cross-field business-rule refinement enforce the conditions below server-side. These rules originally documented the Merchant Portal UI's own form validation; they have been cross-checked against the backend's `trade-order.refinement.ts` rules and corrected below where the two disagreed (noted inline). Where no discrepancy is noted, UI and backend behavior match.
{% endhint %}

* `contractFiles` is always required.
* `serviceCategory` and `fundsNature` are required whenever `tradeType=SERVICES_TRADE_COLLECTION`.
* Many fields are required **only if `isExchange=true`**: `tradeDateTime`, `productUrl`, `tradePlatformName`, `productCount`, `productUnit`, `logisticsStatus`, and — only if additionally `serviceCategory=SOFTWARE` — `applicationPlatform`/`softwareNumber`/`softwareName`/`releaseDate`.
* `logisticsType` is required only when `tradeType=SERVICES_TRADE_COLLECTION` **and** `isExchange=true` (not for goods trade, despite being listed in the goods-trade table above for grouping purposes).
* `buyerName` required if `tradeType=GOODS_TRADE_COLLECTION`, or if `tradeType=SERVICES_TRADE_COLLECTION` and `fundsNature !== 'RELATED_PAYMENT'`.
* `buyerArea` required when `(isServices && fundsNature !== 'RELATED_PAYMENT') || (isGoods && fundsNature === 'PARTNERS_PAYMENT') || (isGoods && isExchange)`. (The backend refinement includes the third `isGoods && isExchange` condition; an earlier version of this note, based on the Merchant Portal UI only, omitted it.)
* `productName` required unconditionally for goods trade; for services trade, only required when `isExchange && fundsNature === 'LOGISTICS_COSTS'`.
* `fundsNature` options are filtered by `serviceCategory`: `TICKET_PURCHASE` → `PARTNERS_PAYMENT` | `RELATED_PAYMENT`; `LOGISTICS_COSTS` → `GENERAL_TRADE` | `LOGISTICS_COSTS`; `GENERAL_TRADE` → `GENERAL_TRADE` | `LOGISTICS_COSTS`; `SOFTWARE` → `CLOUD_SERVICE`; `EMPLOYEE_SALARY` → `EMPLOYEE_SALARY`.
* `logisticsCompany`/`logisticsNumber` required when (goods && isExchange && logisticsStatus=SHIPPED) or (services && isExchange).
* `logisticsExpectedTime` required when (goods && isExchange && logisticsStatus=UNSHIPPED) or (services && isExchange). Dates must be within +365 days (services) / +180 days (goods) of today, and not in the past.
* `logisticsFiles` required only for goods, when isExchange && logisticsStatus=SHIPPED.
* The customs `declareList` block is rendered/required only when `settlementType=CORPORATE_CROSS_BORDER_SETTLEMENT`, and needs at least one row.
* The advance-receipts block (`advanceReceiptsRatio`, `advanceReceiptsCurrency`, `advanceReceiptsAmount`, `billingPeriod`) is required only when `settlementType=CORPORATE_CROSS_BORDER_SETTLEMENT` && `logisticsStatus=UNSHIPPED`.
* `receiverArea` required only when services && isExchange.
* `employeeList` required only when `serviceCategory=EMPLOYEE_SALARY` && `fundsNature=EMPLOYEE_SALARY` && `isExchange=true`.
* **Anti-fraud denylist**: when `isExchange`, `tradePlatformName` is rejected by the UI if it contains (case-insensitive substring match) any of: `.`, `cn`, `com`, `limited`, `ltd`, `company`, `wechat`, `无`, `网络购物`, `网购收入`, `独立站`, `自建站`. This is a real UI-level compliance rule, unlikely to be independently enforced server-side identically.

</details>

<details>

<summary><strong>productUnit enumeration</strong></summary>

* Name: Product unit
* Type: `string`
* Required: No
* Description: Unit used for the product quantity.

| Value   | Description |
| ------- | ----------- |
| `PCS`   | Pieces      |
| `KG`    | Kilograms   |
| `SETS`  | Sets        |
| `G`     | Grams       |
| `MT`    | Metric tons |
| `TON`   | Tons        |
| `YARDS` | Yards       |
| `ROLLS` | Rolls       |
| `PAIRS` | Pairs       |

</details>

#### Request sample

No real captured sample is available for this exact endpoint — field names/shape above are derived from code; example values below are placeholders (not fabricated business data).

```json
{
  "requestId": "",
  "subMerchantId": "",
  "tradeType": "GOODS_TRADE_COLLECTION",
  "isExchange": false,
  "orderReferenceId": "",
  "currency": "",
  "amount": 0,
  "buyerName": "",
  "buyerArea": "",
  "contractFiles": []
}
```

### Response

#### Response Field Descriptions

| Field Name    | Type   | Description                                        |
| ------------- | ------ | -------------------------------------------------- |
| code          | number | Response code.                                     |
| data          | object | Created trade order result (narrowed — see below). |
| message       | string | Response message.                                  |
| neoResponseId | string | Unique NeoX response identifier.                   |

{% hint style="warning" %}
There is no `state` field in the response envelope. The `data` object on create is intentionally narrow — it does not return the full trade order record, only the fields below.
{% endhint %}

#### `data` object fields:

| Field Name       | Type   | Description                                      |
| ---------------- | ------ | ------------------------------------------------ |
| id               | string | NeoX identifier assigned to the trade order.     |
| requestId        | string | Echoes the merchant-supplied `requestId`.        |
| orderReferenceId | string | Echoes the merchant-supplied `orderReferenceId`. |
| status           | string | Current status of the trade order.               |

#### Response sample

```json
{
  "code": 1,
  "data": {
    "id": "",
    "requestId": "",
    "orderReferenceId": "",
    "status": ""
  },
  "message": "Successful"
}
```

## Update Trade Order

#### Endpoint: PUT /v2/gc/trade-orders

Same field shape as create (all effectively optional except an identifier in practice). Response is a **full passthrough** of the trade order entity (not narrowed like the create response). No real captured sample is available.

### Notes

* Requires Bearer token in the Authorization header.
* The Accept-Language header can be used to specify the response language (Support: "vi", "en").
* Use a unique `requestId` for each new trade order.
* All file-reference fields must contain `path` values returned by the File Upload API (`POST /v2/gc/files/upload`).
* Set `operate=UPDATE` (or use `PUT /v2/gc/trade-orders`) and the original identifier to modify an existing trade order. Use `saveType=IGNORE_FILE` to update non-file fields without re-uploading documents.
* There is no `GET` endpoint for standalone trade-order status — see the notice on [Get Detail Trade Order](https://github.com/neopayvn/neox-gitbook-documents-v2/tree/main/global-collections/integration/collections/get-detail-trade-order.md).
