> ## Documentation Index
> Fetch the complete documentation index at: https://traddal.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Calculate duty

> Landed-cost calculation for a single HS code and shipment.

Requires the `calculate:read` scope.

<ParamField body="hs_code" type="string" required>
  4–10 digit HS code (dots allowed), e.g. `4202.92.3120`.
</ParamField>

<ParamField body="origin_country" type="string" required>
  ISO 3166-1 alpha-2 country of origin.
</ParamField>

<ParamField body="destination_country" type="string" required>
  ISO alpha-2 destination country (case-insensitive).
</ParamField>

<ParamField body="declared_value" type="number" required>
  **Per-unit** customs value of the goods — the line total is
  `declared_value × quantity`.
</ParamField>

<ParamField body="quantity" type="number" default="1">
  Number of units.
</ParamField>

<ParamField body="currency" type="string">
  ISO 4217 currency of `declared_value` (3 letters). The response converts
  to the destination's currency and reports the rate used.
</ParamField>

<ParamField body="weight" type="number">
  Shipment weight (≥ 0), in `weight_unit`.
</ParamField>

<ParamField body="weight_unit" type="string" default="kg">
  `kg` or `lb`.
</ParamField>

<ParamField body="shipping_cost" type="number" default="0">
  Freight — added to the customs value for CIF-basis destinations.
</ParamField>

<ParamField body="insurance_cost" type="number" default="0">
  Insurance — added to the customs value for CIF-basis destinations.
</ParamField>

<ParamField body="transport_mode" type="string" default="sea">
  `sea`, `air`, `road`, or `rail`. Mode-scoped fees (e.g. US Harbor
  Maintenance Fee) only apply on a positive match.
</ParamField>

<ParamField body="shipping_terms" type="string" default="FOB">
  `FOB`, `CIF`, `EXW`, or `DDP`.
</ParamField>

<ParamField body="shipment_channel" type="string">
  `postal` or `courier` — affects de minimis and channel-specific regimes.
</ParamField>

<ParamField body="entry_date" type="string">
  `YYYY-MM-DD`. Rates are resolved as of this date (defaults to today).
</ParamField>

<ParamField body="components" type="array">
  Up to 10 `{ material, value }` pairs for content-based measures (e.g.
  steel/aluminum content under Section 232).
</ParamField>

<ParamField body="metal_weight_percentage" type="number">
  Metal content by weight (0–100), for weight-conditioned measures.
</ParamField>

<ParamField body="manual_claims" type="array">
  Up to 20 exemption/claim codes (e.g. Chapter 99 exclusion codes) to apply
  explicitly. Claim-type exemptions are never auto-applied — they surface in
  `exemptions.available_exemptions` until claimed here.
</ParamField>

<ParamField body="destination_region" type="string">
  Sub-national region code (e.g. a Canadian province) for regional taxes.
</ParamField>

<ParamField body="volume" type="number">
  Volume for excise-style per-volume rates, in `volume_unit`.
</ParamField>

<ParamField body="volume_unit" type="string">
  `l`, `hl`, or `ml`.
</ParamField>

## Response

<ResponseField name="rate_found" type="boolean">
  Whether a duty rate exists for this code/origin.
</ResponseField>

<ResponseField name="currencies" type="object">
  `{ declared, destination, exchange_rate, source, rate_date }` — how your
  declared currency was converted.
</ResponseField>

<ResponseField name="values" type="object">
  `{ declared_value_per_unit, declared_value_total, customs_value,
      shipping_cost, insurance_cost }`, in the destination currency.
</ResponseField>

<ResponseField name="exemptions" type="object">
  De minimis outcome (`de_minimis_threshold`, `de_minimis_exempt`, plus
  `tax_de_minimis_threshold`/`tax_de_minimis_exempt` where the destination
  has a separate tax threshold). `tariff_exemptions` lists exclusion codes
  that fired; `available_exemptions` lists claim codes you *could* file
  (pass them in `manual_claims` to apply).
</ResponseField>

<ResponseField name="estimated_duties" type="object">
  `tariffs` — the applied duty lines, each
  `{ name, rate, amount, type, code?, estimated? }`; one of
  `normal_tariff` / `preferential_tariff` / `punitive_tariff` says which
  tier applied; `total_duty` is the sum.
</ResponseField>

<ResponseField name="fees" type="object">
  Present when import fees apply (e.g. US MPF/HMF): keyed by fee code, each
  `{ code, name, amount }`, plus `total_fees`.
</ResponseField>

<ResponseField name="vat" type="object">
  Present when the destination levies VAT/GST: `{ rate, amount }` (plus
  `code`/`name` for named regional taxes).
</ResponseField>

<ResponseField name="additional_tariff_measures" type="array">
  Conditional measures (metal content, weight conditions, manual claims)
  that matched but are **not** included in totals — each with a `note`
  explaining the condition.
</ResponseField>

<ResponseField name="totals" type="object">
  `{ duty, fees, vat, total }` in the destination currency.
</ResponseField>

<ResponseField name="data_source" type="object | null">
  Which tariff publication answered: `{ version, source, imported_at }`.
</ResponseField>

<ResponseField name="request_id" type="string | null">
  Log id — appears in `GET /usage-history/calculate`.
</ResponseField>

### Validation errors

If your workspace enforces country validation rules for the destination and
the request violates one, the API responds `400` with an `errors` array
instead of a quote:

```json theme={null}
{ "errors": [ { "code": "US_MAX_VALUE", "description": "Line value exceeds the configured limit" } ] }
```

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://{partner}.mytraddal.com/admin/api/v1/calculate \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer {access_token}' \
    -d '{
      "hs_code": "4202.92.3120",
      "origin_country": "VN",
      "destination_country": "US",
      "declared_value": 45.00,
      "quantity": 2,
      "currency": "USD",
      "transport_mode": "air"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "success": true,
    "message": "",
    "hs_code": "4202923120",
    "origin_country": "VN",
    "destination_country": "US",
    "entry_date": "2026-07-30",
    "transport_mode": "air",
    "shipping_terms": "FOB",
    "quantity": 2,
    "currencies": {
      "declared": "USD",
      "destination": "USD",
      "exchange_rate": 1,
      "source": "same_currency",
      "rate_date": null
    },
    "values": {
      "declared_value_per_unit": 45.0,
      "declared_value_total": 90.0,
      "customs_value": 90.0,
      "shipping_cost": 0,
      "insurance_cost": 0
    },
    "exemptions": {
      "de_minimis_threshold": 0,
      "de_minimis_exempt": false
    },
    "estimated_duties": {
      "tariffs": [
        { "name": "Customs duty (general)", "rate": "17.6%", "amount": 15.84, "type": "general" }
      ],
      "normal_tariff": {
        "tariffs": [
          { "name": "Customs duty (general)", "rate": "17.6%", "amount": 15.84, "type": "general" }
        ],
        "total_duty": 15.84
      },
      "total_duty": 15.84
    },
    "fees": {
      "mpf": { "code": "MPF", "name": "Merchandise Processing Fee", "amount": 2.62 },
      "total_fees": 2.62
    },
    "totals": {
      "duty": 15.84,
      "fees": 2.62,
      "vat": 0,
      "total": 18.46
    },
    "rate_found": true,
    "data_source": {
      "version": "2026 Rev 7",
      "source": "hts_rates_2026_rev7.csv",
      "imported_at": "2026-06-30T08:11:02.000Z"
    },
    "request_id": "9f0f4b7c-1f3a-4d0e-9c5a-6c1f2a7b8d90"
  }
  ```
</ResponseExample>
