# Create an order

Create a shipment, explicitly persist COD, and retain the complete response.

Company: Metfone Express
API version: v1
Requested language: en
Content language: en
Source: https://mfexpress-partner-docs.zhst.app/mfexpress/en/create-order

Endpoint: POST /order


```http
POST /tms-partner/api/v1/order
```

## Usage and important notes

Send top-level `moneyCollection` on this request. Pricing and creation are independent. If it is absent or null, the recorded response `cod` becomes 0 even if the quote included COD. Negative COD produces `INVALID_PRICE`. Do not send the obsolete request field `cod`: it is not read. Compare the returned `cod` against your intended collection amount.

Provide sender and recipient names, international-format phones, and addresses. The source describes `seller` as the fallback when shipper is empty, `buyer` when consignee is empty, and `returnContact` defaulting to shipper. Each parcel needs weight/weightUnit, dimensions, type, and at least one item with a name and positive weight. `measurementUnit` defaults to the literal `CENTIMET`. Only `payerType=CONSIGNEE` or `SELLER` is accepted; other values produce `PAYER_INVALID`.

`vas` containing GTN/NTN/VTT may override the submitted `receiveType`. `deliveryPostcode` is required unless `vas` contains GTN or VTT; with GTN it is forced to null. Source names and sender/receiver service labels are retained rather than reinterpreted.



`txId` supports partner-side reconciliation/deduplication; the source does **not** establish server-enforced idempotency, a deduplication window, or safe repeat-create behavior. Retain the initial response and reconcile an ambiguous timeout before submitting another create. Do not assume a repeated txId prevents a duplicate shipment.

**Response:** save `id` for label creation, status lookup, and cancellation. Creation uses textual `status=CONFIRMED` and `statusName`; status lookup/webhooks use numeric codes. `totalFees` includes VAT after discounts and `totalTax` is VAT. `estDeliveryTime.date` is DD/MM/YYYY. `partnerInfo` uses snake_case keys inside an otherwise camelCase order response. Addresses are reduced to `components` and `formattedAddress`; no address-level id/code/geometry or component typeName/typeLabel is echoed.

## Authentication headers



| Header | Requirement | Value / meaning |
| --- | --- | --- |
| X-Api-Token | Required | `${API_TOKEN}`: environment-specific token issued by TMS |
| X-Client-Source | Required | `${PARTNER_CODE}`: partner code paired with the token |
| Content-Type | With a JSON body | application/json |
| Accept | Required by source | application/json |
| Accept-Language | Optional | `vn`, `en`, `my`, `km`, `lo` |



## Request fields

Provide sender/recipient or documented seller/buyer fallback. Requiredness describes source business requirements, not guaranteed validation responses.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `receiveType` | string | See description | AT_HOME or AT_STORE; GTN/NTN/VTT in vas can cause recalculation and override. Values: `AT_HOME`, `AT_STORE`. |
| `shipper` | object | See description | ContactInfo. Sender and recipient need name, phone and address, subject to seller/buyer fallback. |
| `shipper.name` | string | See description | Contact name. Examples use synthetic people. |
| `shipper.phone` | string | See description | International format, e.g. Cambodia +855; replace the environment placeholder. |
| `shipper.type` | string | See description | Examples: PARTNER_WAREHOUSE, PERSON, HOME, OFFICE; complete enum not supplied. |
| `shipper.postOffice` | string | See description | Post-office code for drop-off at a branch. |
| `shipper.address` | object | See description | Address supplied by the partner. |
| `shipper.address.components` | array | When parent is present | Use current administrative API IDs and codes. |
| `shipper.address.components[].id` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `shipper.address.components[].code` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `shipper.address.components[].name` | string | See description | Location name or street address. |
| `shipper.address.components[].type` | string | See description | NATIONAL, PROVINCE, DISTRICT, VILLAGE or OTHER according to level. |
| `shipper.address.components[].level` | number | See description | 0 country; 1 province; 2 district; 3 village; 999 street/detail. |
| `consignee` | object | See description | ContactInfo. Sender and recipient need name, phone and address, subject to seller/buyer fallback. |
| `consignee.name` | string | See description | Contact name. Examples use synthetic people. |
| `consignee.phone` | string | See description | International format, e.g. Cambodia +855; replace the environment placeholder. |
| `consignee.type` | string | See description | Examples: PARTNER_WAREHOUSE, PERSON, HOME, OFFICE; complete enum not supplied. |
| `consignee.postOffice` | string | See description | Post-office code for drop-off at a branch. |
| `consignee.address` | object | See description | Address supplied by the partner. |
| `consignee.address.components` | array | When parent is present | Use current administrative API IDs and codes. |
| `consignee.address.components[].id` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `consignee.address.components[].code` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `consignee.address.components[].name` | string | See description | Location name or street address. |
| `consignee.address.components[].type` | string | See description | NATIONAL, PROVINCE, DISTRICT, VILLAGE or OTHER according to level. |
| `consignee.address.components[].level` | number | See description | 0 country; 1 province; 2 district; 3 village; 999 street/detail. |
| `seller` | object | See description | Optional seller, used if shipper is empty. |
| `seller.name` | string | See description | Contact name. Examples use synthetic people. |
| `seller.phone` | string | See description | International format, e.g. Cambodia +855; replace the environment placeholder. |
| `seller.type` | string | See description | Examples: PARTNER_WAREHOUSE, PERSON, HOME, OFFICE; complete enum not supplied. |
| `seller.postOffice` | string | See description | Post-office code for drop-off at a branch. |
| `seller.address` | object | See description | Address supplied by the partner. |
| `seller.address.components` | array | When parent is present | Use current administrative API IDs and codes. |
| `seller.address.components[].id` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `seller.address.components[].code` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `seller.address.components[].name` | string | See description | Location name or street address. |
| `seller.address.components[].type` | string | See description | NATIONAL, PROVINCE, DISTRICT, VILLAGE or OTHER according to level. |
| `seller.address.components[].level` | number | See description | 0 country; 1 province; 2 district; 3 village; 999 street/detail. |
| `buyer` | object | See description | Optional buyer, used if consignee is empty. |
| `buyer.name` | string | See description | Contact name. Examples use synthetic people. |
| `buyer.phone` | string | See description | International format, e.g. Cambodia +855; replace the environment placeholder. |
| `buyer.type` | string | See description | Examples: PARTNER_WAREHOUSE, PERSON, HOME, OFFICE; complete enum not supplied. |
| `buyer.postOffice` | string | See description | Post-office code for drop-off at a branch. |
| `buyer.address` | object | See description | Address supplied by the partner. |
| `buyer.address.components` | array | When parent is present | Use current administrative API IDs and codes. |
| `buyer.address.components[].id` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `buyer.address.components[].code` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `buyer.address.components[].name` | string | See description | Location name or street address. |
| `buyer.address.components[].type` | string | See description | NATIONAL, PROVINCE, DISTRICT, VILLAGE or OTHER according to level. |
| `buyer.address.components[].level` | number | See description | 0 country; 1 province; 2 district; 3 village; 999 street/detail. |
| `returnContact` | object | See description | Return contact; defaults to shipper. |
| `returnContact.name` | string | See description | Contact name. Examples use synthetic people. |
| `returnContact.phone` | string | See description | International format, e.g. Cambodia +855; replace the environment placeholder. |
| `returnContact.type` | string | See description | Examples: PARTNER_WAREHOUSE, PERSON, HOME, OFFICE; complete enum not supplied. |
| `returnContact.postOffice` | string | See description | Post-office code for drop-off at a branch. |
| `returnContact.address` | object | See description | Address supplied by the partner. |
| `returnContact.address.components` | array | When parent is present | Use current administrative API IDs and codes. |
| `returnContact.address.components[].id` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `returnContact.address.components[].code` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `returnContact.address.components[].name` | string | See description | Location name or street address. |
| `returnContact.address.components[].type` | string | See description | NATIONAL, PROVINCE, DISTRICT, VILLAGE or OTHER according to level. |
| `returnContact.address.components[].level` | number | See description | 0 country; 1 province; 2 district; 3 village; 999 street/detail. |
| `parcel` | object | Yes | Parcel dimensions and goods. |
| `parcel.weight` | number | Yes | Parcel weight. |
| `parcel.weightUnit` | string | Yes | Weight unit documented as GRAM. |
| `parcel.length` | number | Yes | Length, cm. |
| `parcel.width` | number | Yes | Width, cm. |
| `parcel.height` | number | Yes | Height, cm. |
| `parcel.measurementUnit` | string | See description | Defaults to CENTIMET (source spelling). Default: `CENTIMET`. |
| `parcel.type` | string | Yes | Parcel type. Values: `GOODS`, `DOCUMENT`. |
| `parcel.items` | array | Yes | At least one item. |
| `parcel.items[].name` | string | When parent is present | Item name. |
| `parcel.items[].type` | string | See description | Item type shown in the example. |
| `parcel.items[].value` | number | See description | Declared item value. |
| `parcel.items[].weight` | number | When parent is present | Item weight; must be greater than zero. |
| `parcel.items[].quantity` | number | See description | Item quantity. |
| `payerType` | string | Yes | Only CONSIGNEE and SELLER accepted; otherwise PAYER_INVALID. Values: `CONSIGNEE`, `SELLER`. |
| `service` | string | Yes | Main service code from get-service. |
| `vas` | array | See description | Extra service codes selected from available services. |
| `moneyCollection` | number | See description | COD must be resent here. Omitted/null becomes cod=0. Negative values produce INVALID_PRICE. |
| `detailedFees` | object | See description | Use the results returned by get-all. |
| `detailedFees.serviceFee` | array | See description | Recommended pricing details. |
| `detailedFees.serviceFee[].service` | string | See description | Service code from pricing. |
| `detailedFees.serviceFee[].name` | string | See description | Service name shown in the example. |
| `detailedFees.serviceFee[].fee` | number | See description | Use main/extra beforeVatPrice, not VAT-inclusive price. |
| `detailedFees.serviceFee[].surchargeType` | string | See description | Only valid values are retained, but the source does not list those values. Ask TMS. |
| `detailedFees.serviceFee[].type` | string | See description | Source example says VAS, conflicting with the prose surchargeType field. Not a confirmed substitute. |
| `voucher` | string | See description | Voucher code. |
| `reference` | string | See description | Partner internal reference. |
| `pickupAppointment` | object | See description | Optional appointment. Confirm day/time encoding before use. |
| `pickupAppointment.dayOfWeek` | array | See description | Days of week; item encoding not specified by the source. |
| `pickupAppointment.hours` | array | See description | Time slots; item encoding not specified by the source. |
| `pickupAppointment.note` | string | See description | Appointment note. |
| `deliveryAppointment` | object | See description | Optional appointment. Confirm day/time encoding before use. |
| `deliveryAppointment.dayOfWeek` | array | See description | Days of week; item encoding not specified by the source. |
| `deliveryAppointment.hours` | array | See description | Time slots; item encoding not specified by the source. |
| `deliveryAppointment.note` | string | See description | Appointment note. |
| `note` | string | See description | Order note. |
| `invoice` | string | See description | Invoice requested from sender or receiver. Values: `NONE`, `BY_SENDER`, `BY_RECEIVER`. Default: `NONE`. |
| `orderScope` | string | See description | Order scope. Values: `DOMESTIC`, `INTERNATIONAL`. Default: `DOMESTIC`. |
| `deliveryPostcode` | string | See description | Required unless vas contains GTN or VTT. GTN forces this field to null. |
| `txId` | string | See description | Partner transaction ID for reconciliation/client-side deduplication. Server idempotency is NOT established. |



## Example JSON body

Save as `request.json`. Replace every `${…}` string and example ID with actual environment values before sending. cURL with `--data @request.json` **does not interpolate variables inside JSON files**. Identities are synthetic.
```json
{
  "receiveType": "AT_HOME",
  "shipper": {
    "name": "Example Warehouse",
    "phone": "${SHIPPER_PHONE}",
    "type": "PARTNER_WAREHOUSE",
    "address": {
      "components": [
        {
          "name": "Example warehouse, Street A",
          "type": "OTHER",
          "level": 999
        },
        {
          "id": "5025963",
          "code": "120211",
          "name": "Voat Phnum",
          "type": "VILLAGE",
          "level": 3
        },
        {
          "id": "4059553",
          "code": "1202",
          "name": "Doun Penh",
          "type": "DISTRICT",
          "level": 2
        },
        {
          "id": "4025120",
          "code": "PNP",
          "name": "Phnom Penh",
          "type": "PROVINCE",
          "level": 1
        },
        {
          "type": "NATIONAL",
          "name": "Cambodia",
          "code": "KH",
          "level": 0
        }
      ]
    }
  },
  "consignee": {
    "name": "Example Recipient",
    "phone": "${CONSIGNEE_PHONE}",
    "address": {
      "components": [
        {
          "name": "Example recipient, Street B",
          "type": "OTHER",
          "level": 999
        },
        {
          "id": "5025109",
          "code": "010201",
          "name": "បន្ទាយនាង",
          "type": "VILLAGE",
          "level": 3
        },
        {
          "id": "4059452",
          "code": "0102",
          "name": "មង្គលបូរី",
          "type": "DISTRICT",
          "level": 2
        },
        {
          "id": "4025109",
          "code": "BAN",
          "name": "Banteay Meanchey",
          "type": "PROVINCE",
          "level": 1
        },
        {
          "type": "NATIONAL",
          "name": "Cambodia",
          "code": "KH",
          "level": 0
        }
      ]
    }
  },
  "parcel": {
    "weight": 100,
    "weightUnit": "GRAM",
    "length": 10,
    "width": 10,
    "height": 10,
    "measurementUnit": "CENTIMET",
    "type": "GOODS",
    "items": [
      {
        "name": "Example product",
        "type": "GOODS",
        "value": 50,
        "weight": 10,
        "quantity": 8
      }
    ]
  },
  "payerType": "CONSIGNEE",
  "service": "CCN",
  "vas": [
    "NTN",
    "VTT"
  ],
  "moneyCollection": 50,
  "invoice": "NONE",
  "reference": "EXAMPLE-REFERENCE-001",
  "txId": "00000000-0000-4000-8000-000000000001",
  "note": ""
}
```


## cURL example

`BASE_URL` must include `/tms-partner/api/v1`. Load the token and partner code from your private environment; never paste secrets into documentation or AI prompts.
```bash
curl --request POST "${BASE_URL}/order" \
  --header "X-Api-Token: ${API_TOKEN}" \
  --header "X-Client-Source: ${PARTNER_CODE}" \
  --header "Accept-Language: en" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --data @request.json
```


## Example response

```json
{
  "id": "EXAMPLE-ORDER-001",
  "status": "CONFIRMED",
  "statusName": "Awaiting acceptance",
  "service": "CCN",
  "serviceName": "Express",
  "orderScope": "DOMESTIC",
  "shipper": {
    "name": "Example Warehouse",
    "address": {
      "components": [
        {
          "name": "Example warehouse, Street A",
          "type": "OTHER",
          "level": 999
        },
        {
          "id": "5025963",
          "code": "120211",
          "name": "Voat Phnum",
          "type": "VILLAGE",
          "level": 3
        },
        {
          "id": "4059553",
          "code": "1202",
          "name": "Doun Penh",
          "type": "DISTRICT",
          "level": 2
        },
        {
          "id": "4025120",
          "code": "PNP",
          "name": "Phnom Penh",
          "type": "PROVINCE",
          "level": 1
        },
        {
          "type": "NATIONAL",
          "name": "Cambodia",
          "code": "KH",
          "level": 0
        }
      ],
      "formattedAddress": "Example warehouse, Phnom Penh, Cambodia"
    }
  },
  "consignee": {
    "name": "Example Recipient",
    "phone": "${CONSIGNEE_PHONE}",
    "address": {
      "components": [
        {
          "name": "Example recipient, Street B",
          "type": "OTHER",
          "level": 999
        },
        {
          "id": "5025109",
          "code": "010201",
          "name": "បន្ទាយនាង",
          "type": "VILLAGE",
          "level": 3
        },
        {
          "id": "4059452",
          "code": "0102",
          "name": "មង្គលបូរី",
          "type": "DISTRICT",
          "level": 2
        },
        {
          "id": "4025109",
          "code": "BAN",
          "name": "Banteay Meanchey",
          "type": "PROVINCE",
          "level": 1
        },
        {
          "type": "NATIONAL",
          "name": "Cambodia",
          "code": "KH",
          "level": 0
        }
      ],
      "formattedAddress": "Example recipient, Banteay Meanchey, Cambodia"
    }
  },
  "parcel": {
    "weight": 100,
    "weightUnit": "GRAM",
    "length": 10,
    "width": 10,
    "height": 10,
    "measurementUnit": "CENTIMET",
    "type": "GOODS",
    "items": [
      {
        "name": "Example product",
        "type": "GOODS",
        "value": 50,
        "weight": 10,
        "quantity": 8
      }
    ]
  },
  "cod": 50,
  "totalFees": 1.75,
  "totalTax": 0.16,
  "originalPrice": 1.59,
  "detailedFees": {
    "currency": "USD",
    "serviceFee": [
      {
        "service": "CCN",
        "fee": 1.44,
        "feeAfterVat": 1.59,
        "vatPrice": 0.14
      }
    ]
  },
  "payerType": "CONSIGNEE",
  "vas": [
    "NTN",
    "VTT"
  ],
  "estDeliveryTime": {
    "days": 1.5,
    "date": "15/10/2026"
  },
  "createdAt": "2026-10-14T09:00:00+00:00",
  "txId": "00000000-0000-4000-8000-000000000001",
  "invoice": "NONE",
  "receiveType": "AT_HOME",
  "partnerInfo": {
    "id": 900001,
    "partner_code": "EXAMPLE-PARTNER",
    "partner_name": "Example Partner",
    "type": "PARTNER"
  }
}
```


## Response fields



| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `status` | string | See description | Creation example uses CONFIRMED, unlike numeric lookup/webhook status. |
| `statusName` | string | See description | Creation status label: awaiting acceptance. |
| `service` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `serviceName` | string | See description | Main service name. |
| `orderScope` | string | See description | Order scope. |
| `shipper` | object | See description | Sender snapshot. |
| `shipper.name` | string | See description | Sender name. |
| `shipper.phone` | string | See description | Sender phone when returned. |
| `shipper.address` | object | See description | Simplified response address; components do not echo typeName/typeLabel. |
| `shipper.address.components` | array | See description | Use current administrative API IDs and codes. |
| `shipper.address.components[].id` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `shipper.address.components[].code` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `shipper.address.components[].name` | string | See description | Location name or street address. |
| `shipper.address.components[].type` | string | See description | NATIONAL, PROVINCE, DISTRICT, VILLAGE or OTHER according to level. |
| `shipper.address.components[].level` | number | See description | 0 country; 1 province; 2 district; 3 village; 999 street/detail. |
| `shipper.address.formattedAddress` | string | See description | Formatted address; no address-level id, code or geometry. |
| `consignee` | object | See description | Recipient snapshot. |
| `consignee.name` | string | See description | Recipient name. |
| `consignee.phone` | string | See description | Recipient phone. |
| `consignee.address` | object | See description | Simplified response address; components do not echo typeName/typeLabel. |
| `consignee.address.components` | array | See description | Use current administrative API IDs and codes. |
| `consignee.address.components[].id` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `consignee.address.components[].code` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `consignee.address.components[].name` | string | See description | Location name or street address. |
| `consignee.address.components[].type` | string | See description | NATIONAL, PROVINCE, DISTRICT, VILLAGE or OTHER according to level. |
| `consignee.address.components[].level` | number | See description | 0 country; 1 province; 2 district; 3 village; 999 street/detail. |
| `consignee.address.formattedAddress` | string | See description | Formatted address; no address-level id, code or geometry. |
| `parcel` | object | See description | Returned parcel may be partial; request requiredness is not a response guarantee. |
| `parcel.weight` | number | See description | Parcel weight. |
| `parcel.weightUnit` | string | See description | Weight unit documented as GRAM. |
| `parcel.length` | number | See description | Length, cm. |
| `parcel.width` | number | See description | Width, cm. |
| `parcel.height` | number | See description | Height, cm. |
| `parcel.measurementUnit` | string | See description | Defaults to CENTIMET (source spelling). Default: `CENTIMET`. |
| `parcel.type` | string | See description | Parcel type. Values: `GOODS`, `DOCUMENT`. |
| `parcel.items` | array | See description | Returned goods items. |
| `parcel.items[].name` | string | See description | Item name. |
| `parcel.items[].type` | string | See description | Item type shown in the example. |
| `parcel.items[].value` | number | See description | Declared item value. |
| `parcel.items[].weight` | number | See description | Item weight; must be greater than zero. |
| `parcel.items[].quantity` | number | See description | Item quantity. |
| `cod` | number | See description | Persisted COD; compare with request.moneyCollection. |
| `totalFees` | number | See description | Total fees after discounts including VAT. |
| `totalTax` | number | See description | Total VAT. |
| `originalPrice` | number | See description | Original price shown in the source example; calculation not specified. |
| `detailedFees` | object | See description | Recorded detailed fees. |
| `detailedFees.currency` | string | See description | Example uses USD; do not assume every pricing response uses this currency. |
| `detailedFees.serviceFee` | array | See description | Recorded fees. |
| `detailedFees.serviceFee[].service` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `detailedFees.serviceFee[].fee` | number | See description | Pre-VAT fee. |
| `detailedFees.serviceFee[].feeAfterVat` | number | See description | Fee after VAT. |
| `detailedFees.serviceFee[].vatPrice` | number | See description | VAT amount. |
| `payerType` | string | See description | Payer. |
| `vas` | array | See description | Extra services. |
| `estDeliveryTime` | object | See description | Delivery estimate. |
| `estDeliveryTime.days` | number | See description | Estimated day count. |
| `estDeliveryTime.date` | string | See description | Estimated delivery date, DD/MM/YYYY. |
| `createdAt` | string | See description | Creation timestamp. |
| `txId` | string | See description | Transaction identifier derived from supplied txId or generated by the system; no server deduplication guarantee. |
| `invoice` | string | See description | Invoice mode. |
| `receiveType` | string | See description | Resolved receive type. |
| `partnerInfo` | object | See description | Optional discount identity; X-Client-Source normally suffices. Uses snake_case. |
| `partnerInfo.id` | number | See description | Internal partner ID. |
| `partnerInfo.partner_code` | string | See description | Partner code. |
| `partnerInfo.partner_name` | string | See description | Partner name. |
| `partnerInfo.email` | string | See description | Partner email. |
| `partnerInfo.type` | string | See description | Partner type, e.g. PARTNER. |



## Address levels



| Level | type | Order requirement |
| --- | --- | --- |
| 0 | NATIONAL | Optional; code KH, name Cambodia |
| 1 | PROVINCE | Required; id/code from provinces |
| 2 | DISTRICT | Required; id/code from level 2 |
| 3 | VILLAGE | Required; id/code from level 3 |
| 999 | OTHER | Optional; house number, street, building |



## COD persistence diagram


```mermaid
flowchart TD
  A["product.moneyCollection in pricing"] --> B["Select COD service branch only"]
  B --> C["Create a separate order request"]
  C --> D{"Top-level moneyCollection supplied?"}
  D -->|Yes| E["Persist and compare response.cod"]
  D -->|Missing or null| F["Order records cod = 0"]
```


## Error handling

See [HTTP codes and source limitations](reference). HTTP success does not prove COD, fees, or cancellation are correct; inspect the documented business fields. Do not assume create-order retries are safe.

