# Calculate shipping prices

Calculate the VAT and discount breakdown for a known route and service.

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

Endpoint: POST /pricing/get-all


```http
POST /tms-partner/api/v1/pricing/get-all
```

## Usage and important notes

Call get-service first to obtain appropriate `mainService`, `extraService`, and `specialService`. Send the route and product to avoid missing-input runtime failures. `manualPrice` applies only when the chosen service is not calculated automatically; `customerCode` and `partnerInfo` follow the service-discovery rules.

**COD does not change the quoted amount.** At this step and at get-service, `product.moneyCollection` only selects service rules for COD greater than zero versus zero in Drools. It does not change `totalPrice`, `mainPrice`, or `extraPrices`, and does not persist COD on an order. You must resend top-level `moneyCollection` in create-order.

`totalPrice` is the final VAT-inclusive amount after discounts. `totalPriceBeforeDiscount` is before discounts. `vat` is a percentage; `vatPrice` is the tax amount; `beforeVatPrice` excludes tax. The response exposes `round`/`roundNum`, the applied rounding rule and precision. `manualPrice` echoes the manual input or is null. `discountType=AMOUNT` means a fixed amount, `PERCENT` means a percentage.

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

Quote known services. Source table omits orderService but appendix explicitly references section 6; confirm its acceptance.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `product` | object | See description | Recommended product object. No @NotNull validation is documented for pricing. |
| `product.weight` | number | See description | Recommended weight in grams. |
| `product.type` | string | See description | Recommended goods type. Values: `GOODS`, `DOCUMENT`. |
| `product.price` | number | See description | Declared goods value; currency is not specified for this request in the source. |
| `product.moneyCollection` | number | See description | COD influences service selection only; it does not change the quoted amount or persist COD on an order. |
| `product.length` | number | See description | Length in cm. |
| `product.width` | number | See description | Width in cm. |
| `product.height` | number | See description | Height in cm. |
| `fromLocation` | array | See description | Recommended sender components, levels 0–3 and 999. |
| `fromLocation[].id` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `fromLocation[].code` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `fromLocation[].name` | string | See description | Location name or street address. |
| `fromLocation[].type` | string | See description | NATIONAL, PROVINCE, DISTRICT, VILLAGE or OTHER according to level. |
| `fromLocation[].level` | number | See description | 0 country; 1 province; 2 district; 3 village; 999 street/detail. |
| `toLocation` | array | See description | Recommended recipient components, levels 0–3. |
| `toLocation[].id` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `toLocation[].code` | string | See description | Use the identifier returned by the API, not the illustrative value. |
| `toLocation[].name` | string | See description | Location name or street address. |
| `toLocation[].type` | string | See description | NATIONAL, PROVINCE, DISTRICT, VILLAGE or OTHER according to level. |
| `toLocation[].level` | number | See description | 0 country; 1 province; 2 district; 3 village; 999 street/detail. |
| `isDomestic` | boolean | See description | Domestic=true, international=false. Defaults to true. Default: `true`. |
| `customerCode` | string | See description | Internal customer code; defaults to the account associated with X-Api-Token. |
| `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. |
| `mainService` | string | See description | Recommended main service code from get-service, e.g. CCN. |
| `extraService` | array | See description | Optional extra-service codes. |
| `specialService` | array | See description | Optional special-service codes, usually empty. |
| `manualPrice` | number | See description | Self-declared price when mainPrice.isCalculatedAutomatically=false; ignored for automatic services. |
| `orderService` | object | See description | Service preferences; UNKNOW is the source spelling. |
| `orderService.senderService` | string | See description | Changes display/default/lock flags of GTN/NTN/VTT, not price. Values: `GTCH`, `VTT`, `GTN`, `UNKNOW`. |
| `orderService.receiverService` | string | See description | Recipient preference with the same flag-only effect. Values: `NTCH`, `NTN`, `VTT`, `UNKNOW`. |



## 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
{
  "product": {
    "weight": 100,
    "type": "GOODS",
    "price": 50,
    "moneyCollection": 50,
    "length": 10,
    "width": 10,
    "height": 10
  },
  "fromLocation": [
    {
      "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
    }
  ],
  "toLocation": [
    {
      "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
    }
  ],
  "isDomestic": true,
  "mainService": "CCN",
  "extraService": [],
  "specialService": []
}
```


## 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}/pricing/get-all" \
  --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
{
  "totalPrice": 1.75,
  "totalPriceBeforeDiscount": 1.75,
  "vat": 10,
  "vatPrice": 0.16,
  "beforeVatPrice": 1.59,
  "manualPrice": null,
  "round": "NONE",
  "roundNum": 0,
  "property": {
    "calculatedWeight": 100,
    "convertedWeight": 200,
    "perimeter": 30,
    "distance": null
  },
  "mainPrice": {
    "code": "CCN",
    "name": "Express",
    "price": 1.59,
    "priceAfterDiscount": 1.59,
    "discount": 0,
    "beforeVatPrice": 1.44,
    "vatPrice": 0.14,
    "field": "KL",
    "calculatedWeight": 100,
    "extraService": [],
    "specialService": [],
    "isCalculatedAutomatically": true
  },
  "extraPrices": [],
  "specialPrices": [],
  "discount": 0,
  "totalDiscountAmount": 0,
  "discountType": "AMOUNT"
}
```


## Response fields



| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `totalPrice` | number | See description | Final total after discounts, including VAT. |
| `totalPriceBeforeDiscount` | number | See description | Total before discounts. |
| `vat` | number | See description | VAT rate, percent. |
| `vatPrice` | number | See description | Total VAT amount. |
| `beforeVatPrice` | number | See description | Total excluding VAT. |
| `manualPrice` | number / null | See description | Echoed manual price, null if omitted/not applicable. |
| `round` | string | See description | Applied rounding rule; NONE appears in the example. Full enum not supplied. |
| `roundNum` | number | See description | Rounding precision. |
| `property` | object | See description | Calculation inputs returned by pricing. |
| `property.calculatedWeight` | number | See description | Actual weight used for pricing, grams. |
| `property.convertedWeight` | number | See description | Volumetric weight, grams. |
| `property.perimeter` | number | See description | Parcel perimeter. |
| `property.distance` | number / null | See description | Distance when a distance-based service applies; otherwise null. |
| `mainPrice` | object | See description | Fields depend on whether this is mainPrice or an extra/special price. |
| `mainPrice.code` | string | See description | Service code; mainPrice.code becomes order.service; extraPrices[].code becomes order.vas[]. |
| `mainPrice.name` | string | See description | Service name. |
| `mainPrice.price` | number | See description | Listed service price; extra service list prices include VAT. |
| `mainPrice.priceAfterDiscount` | number | See description | Service amount after discount. |
| `mainPrice.discount` | number | See description | Service-specific discount amount. |
| `mainPrice.beforeVatPrice` | number | See description | Pre-VAT fee to map to detailedFees.serviceFee[].fee. |
| `mainPrice.vatPrice` | number | See description | VAT amount. |
| `mainPrice.field` | string | See description | Calculation classification: KL/TH/CC/KG/KC/CV/CV_KL. |
| `mainPrice.calculatedWeight` | number | See description | Weight used by the main service. |
| `mainPrice.extraService` | array | See description | Automatically included extra services. |
| `mainPrice.specialService` | array | See description | Automatically included special services. |
| `mainPrice.isCalculatedAutomatically` | boolean | See description | true: automatic Drools calculation; false: provide manualPrice to get-all. |
| `mainPrice.isShow` | boolean | See description | Extra service visible for selection; false means internal and need not be submitted. |
| `mainPrice.isChosen` | boolean | See description | Extra service selected by default. |
| `mainPrice.isChangeable` | boolean | See description | Whether the user may toggle the extra service; otherwise locked by orderService. |
| `mainPrice.isCalculated` | boolean | See description | Whether the extra service is priced or only displayed. |
| `extraPrices` | array | See description | Extra-service prices. |
| `extraPrices[].code` | string | See description | Service code; mainPrice.code becomes order.service; extraPrices[].code becomes order.vas[]. |
| `extraPrices[].name` | string | See description | Service name. |
| `extraPrices[].price` | number | See description | Listed service price; extra service list prices include VAT. |
| `extraPrices[].priceAfterDiscount` | number | See description | Service amount after discount. |
| `extraPrices[].discount` | number | See description | Service-specific discount amount. |
| `extraPrices[].beforeVatPrice` | number | See description | Pre-VAT fee to map to detailedFees.serviceFee[].fee. |
| `extraPrices[].vatPrice` | number | See description | VAT amount. |
| `extraPrices[].field` | string | See description | Calculation classification: KL/TH/CC/KG/KC/CV/CV_KL. |
| `extraPrices[].calculatedWeight` | number | See description | Weight used by the main service. |
| `extraPrices[].extraService` | array | See description | Automatically included extra services. |
| `extraPrices[].specialService` | array | See description | Automatically included special services. |
| `extraPrices[].isCalculatedAutomatically` | boolean | See description | true: automatic Drools calculation; false: provide manualPrice to get-all. |
| `extraPrices[].isShow` | boolean | See description | Extra service visible for selection; false means internal and need not be submitted. |
| `extraPrices[].isChosen` | boolean | See description | Extra service selected by default. |
| `extraPrices[].isChangeable` | boolean | See description | Whether the user may toggle the extra service; otherwise locked by orderService. |
| `extraPrices[].isCalculated` | boolean | See description | Whether the extra service is priced or only displayed. |
| `specialPrices` | array | See description | Special-service prices. |
| `specialPrices[].code` | string | See description | Service code; mainPrice.code becomes order.service; extraPrices[].code becomes order.vas[]. |
| `specialPrices[].name` | string | See description | Service name. |
| `specialPrices[].price` | number | See description | Listed service price; extra service list prices include VAT. |
| `specialPrices[].priceAfterDiscount` | number | See description | Service amount after discount. |
| `specialPrices[].discount` | number | See description | Service-specific discount amount. |
| `specialPrices[].beforeVatPrice` | number | See description | Pre-VAT fee to map to detailedFees.serviceFee[].fee. |
| `specialPrices[].vatPrice` | number | See description | VAT amount. |
| `specialPrices[].field` | string | See description | Calculation classification: KL/TH/CC/KG/KC/CV/CV_KL. |
| `specialPrices[].calculatedWeight` | number | See description | Weight used by the main service. |
| `specialPrices[].extraService` | array | See description | Automatically included extra services. |
| `specialPrices[].specialService` | array | See description | Automatically included special services. |
| `specialPrices[].isCalculatedAutomatically` | boolean | See description | true: automatic Drools calculation; false: provide manualPrice to get-all. |
| `specialPrices[].isShow` | boolean | See description | Extra service visible for selection; false means internal and need not be submitted. |
| `specialPrices[].isChosen` | boolean | See description | Extra service selected by default. |
| `specialPrices[].isChangeable` | boolean | See description | Whether the user may toggle the extra service; otherwise locked by orderService. |
| `specialPrices[].isCalculated` | boolean | See description | Whether the extra service is priced or only displayed. |
| `discount` | number | See description | Discount value. |
| `totalDiscountAmount` | number | See description | Total discount amount. |
| `discountType` | string | See description | AMOUNT: fixed amount; PERCENT: percentage. Values: `AMOUNT`, `PERCENT`. |



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

