{
  "openapi": "3.0.3",
  "info": {
    "title": "FreightUtils API",
    "description": "Free freight calculation and reference data APIs. No authentication required. JSON responses. CORS enabled for all origins.",
    "version": "1.0.0",
    "contact": {
      "name": "FreightUtils",
      "url": "https://www.freightutils.com",
      "email": "contact@freightutils.com"
    },
    "license": {
      "name": "Free to use",
      "url": "https://www.freightutils.com/api-docs"
    }
  },
  "servers": [
    {
      "url": "https://www.freightutils.com",
      "description": "Production"
    }
  ],
  "paths": {
    "/api/ldm": {
      "get": {
        "operationId": "calculateLdm",
        "summary": "Loading Metres Calculator",
        "description": "Calculate loading metres (LDM) for pallets on a vehicle. Supports preset pallet sizes or custom dimensions. Returns utilisation percentage, pallet spaces, and fit warnings.",
        "tags": [
          "Calculators"
        ],
        "parameters": [
          {
            "name": "pallet",
            "in": "query",
            "description": "Preset pallet type. If omitted, length and width are required.",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "euro",
                "uk",
                "half",
                "quarter"
              ]
            },
            "example": "euro"
          },
          {
            "name": "length",
            "in": "query",
            "description": "Pallet length in millimetres. Required if no pallet preset is specified.",
            "required": false,
            "schema": {
              "type": "number"
            },
            "example": 1200
          },
          {
            "name": "width",
            "in": "query",
            "description": "Pallet width in millimetres. Required if no pallet preset is specified.",
            "required": false,
            "schema": {
              "type": "number"
            },
            "example": 800
          },
          {
            "name": "qty",
            "in": "query",
            "description": "Number of pallets.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            },
            "example": 2
          },
          {
            "name": "stackable",
            "in": "query",
            "description": "Whether the pallets are stackable.",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "example": false
          },
          {
            "name": "stack",
            "in": "query",
            "description": "Stack factor (number of pallets that can be stacked). Only relevant when stackable is true.",
            "required": false,
            "schema": {
              "type": "integer",
              "enum": [
                2,
                3
              ],
              "default": 2
            },
            "example": 2
          },
          {
            "name": "weight",
            "in": "query",
            "description": "Weight per pallet in kilograms.",
            "required": false,
            "schema": {
              "type": "number"
            },
            "example": 500
          },
          {
            "name": "vehicle",
            "in": "query",
            "description": "Vehicle type for utilisation calculation.",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "artic",
                "rigid10",
                "rigid75",
                "luton",
                "us53",
                "us48",
                "custom"
              ],
              "default": "artic"
            },
            "example": "artic"
          },
          {
            "name": "vehicle_length",
            "in": "query",
            "description": "Custom vehicle length in metres. Only used when vehicle is 'custom'.",
            "required": false,
            "schema": {
              "type": "number"
            },
            "example": 13.6
          }
        ],
        "responses": {
          "200": {
            "description": "Successful LDM calculation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LdmResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or missing parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/cbm": {
      "get": {
        "operationId": "calculateCbm",
        "summary": "CBM Calculator",
        "description": "Calculate cubic metres (CBM), cubic feet, litres, and cubic inches from box dimensions.",
        "tags": [
          "Calculators"
        ],
        "parameters": [
          {
            "name": "l",
            "in": "query",
            "description": "Length in centimetres.",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 120
          },
          {
            "name": "w",
            "in": "query",
            "description": "Width in centimetres.",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 80
          },
          {
            "name": "h",
            "in": "query",
            "description": "Height in centimetres.",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 100
          },
          {
            "name": "pcs",
            "in": "query",
            "description": "Number of pieces.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            },
            "example": 2
          }
        ],
        "responses": {
          "200": {
            "description": "Successful CBM calculation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CbmResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or missing parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/chargeable-weight": {
      "get": {
        "operationId": "calculateChargeableWeight",
        "summary": "Chargeable Weight Calculator",
        "description": "Calculate the chargeable weight for air freight shipments by comparing actual gross weight against volumetric weight.",
        "tags": [
          "Calculators"
        ],
        "parameters": [
          {
            "name": "l",
            "in": "query",
            "description": "Length in centimetres.",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 120
          },
          {
            "name": "w",
            "in": "query",
            "description": "Width in centimetres.",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 80
          },
          {
            "name": "h",
            "in": "query",
            "description": "Height in centimetres.",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 100
          },
          {
            "name": "gw",
            "in": "query",
            "description": "Gross weight in kilograms.",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 500
          },
          {
            "name": "pcs",
            "in": "query",
            "description": "Number of pieces.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            },
            "example": 2
          },
          {
            "name": "factor",
            "in": "query",
            "description": "Volumetric divisor factor. Standard air freight is 6000.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 6000
            },
            "example": 6000
          },
          {
            "name": "mode",
            "in": "query",
            "description": "Calculation mode: air (default) or sea (W/M at 1 CBM = 1 revenue tonne)",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "air",
                "sea"
              ],
              "default": "air"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful chargeable weight calculation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChargeableWeightResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or missing parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/pallet": {
      "get": {
        "operationId": "calculatePalletFitting",
        "summary": "Pallet Fitting Calculator",
        "description": "Calculate how many boxes fit on a pallet, including layers, orientation, volume utilisation, and weight limits.",
        "tags": [
          "Calculators"
        ],
        "parameters": [
          {
            "name": "pl",
            "in": "query",
            "description": "Pallet length in centimetres.",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 120
          },
          {
            "name": "pw",
            "in": "query",
            "description": "Pallet width in centimetres.",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 80
          },
          {
            "name": "pmh",
            "in": "query",
            "description": "Pallet maximum height in centimetres (total including deck).",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 220
          },
          {
            "name": "bl",
            "in": "query",
            "description": "Box length in centimetres.",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 40
          },
          {
            "name": "bw",
            "in": "query",
            "description": "Box width in centimetres.",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 30
          },
          {
            "name": "bh",
            "in": "query",
            "description": "Box height in centimetres.",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 25
          },
          {
            "name": "ph",
            "in": "query",
            "description": "Pallet deck height in centimetres.",
            "required": false,
            "schema": {
              "type": "number",
              "default": 15
            },
            "example": 15
          },
          {
            "name": "bwt",
            "in": "query",
            "description": "Weight per box in kilograms.",
            "required": false,
            "schema": {
              "type": "number"
            },
            "example": 5
          },
          {
            "name": "mpw",
            "in": "query",
            "description": "Maximum payload weight in kilograms.",
            "required": false,
            "schema": {
              "type": "number"
            },
            "example": 1000
          },
          {
            "name": "rotate",
            "in": "query",
            "description": "Allow box rotation to find best fit.",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": true
            },
            "example": true
          }
        ],
        "responses": {
          "200": {
            "description": "Successful pallet fitting calculation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PalletFittingResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or missing parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/adr": {
      "get": {
        "operationId": "lookupAdr",
        "summary": "ADR / UN Number Lookup",
        "description": "Look up ADR dangerous goods data by UN number, name search, or hazard class filter. Provide exactly one search parameter.",
        "tags": [
          "Reference Data",
          "ADR"
        ],
        "parameters": [
          {
            "name": "un",
            "in": "query",
            "description": "UN number to look up (e.g. 1203).",
            "required": false,
            "schema": {
              "type": "string"
            },
            "example": "1203"
          },
          {
            "name": "search",
            "in": "query",
            "description": "Search term to find substances by name.",
            "required": false,
            "schema": {
              "type": "string"
            },
            "example": "petrol"
          },
          {
            "name": "q",
            "in": "query",
            "description": "Alias for search. Search term to find substances by name.",
            "required": false,
            "schema": {
              "type": "string"
            },
            "example": "diesel"
          },
          {
            "name": "class",
            "in": "query",
            "description": "Filter by ADR hazard class.",
            "required": false,
            "schema": {
              "type": "string"
            },
            "example": "3"
          }
        ],
        "responses": {
          "200": {
            "description": "Matching ADR substance records.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdrLookupResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or missing parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/adr-calculator": {
      "get": {
        "operationId": "calculateAdrExemptionGet",
        "summary": "ADR 1.1.3.6 Exemption Calculator (single item)",
        "description": "Calculate whether a single dangerous goods item qualifies for ADR 1.1.3.6 transport exemption based on transport category points.",
        "tags": [
          "Reference Data",
          "ADR"
        ],
        "parameters": [
          {
            "name": "un",
            "in": "query",
            "description": "UN number of the substance.",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "1203"
          },
          {
            "name": "qty",
            "in": "query",
            "description": "Quantity being transported (kg for solids, litres for liquids).",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 200
          }
        ],
        "responses": {
          "200": {
            "description": "ADR exemption calculation result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdrCalculatorResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or missing parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "calculateAdrExemption",
        "summary": "ADR 1.1.3.6 Exemption Calculator (multiple items)",
        "description": "Calculate whether multiple dangerous goods items together qualify for ADR 1.1.3.6 transport exemption. Points are summed across all items.",
        "tags": [
          "Reference Data",
          "ADR"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdrCalculatorRequest"
              },
              "example": {
                "items": [
                  {
                    "un_number": "1203",
                    "quantity": 200
                  },
                  {
                    "un_number": "1950",
                    "quantity": 50
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "ADR exemption calculation result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdrCalculatorResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or missing parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/airlines": {
      "get": {
        "operationId": "searchAirlines",
        "summary": "Airline Lookup",
        "description": "Search for cargo airlines by name, IATA code, ICAO code, AWB prefix, or country. Provide one search parameter.",
        "tags": [
          "Reference Data"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "General search term (matches airline name, codes, and country).",
            "required": false,
            "schema": {
              "type": "string"
            },
            "example": "emirates"
          },
          {
            "name": "iata",
            "in": "query",
            "description": "2-character IATA airline code.",
            "required": false,
            "schema": {
              "type": "string"
            },
            "example": "EK"
          },
          {
            "name": "icao",
            "in": "query",
            "description": "3-character ICAO airline code.",
            "required": false,
            "schema": {
              "type": "string"
            },
            "example": "UAE"
          },
          {
            "name": "prefix",
            "in": "query",
            "description": "3-digit AWB prefix number.",
            "required": false,
            "schema": {
              "type": "string"
            },
            "example": "176"
          },
          {
            "name": "country",
            "in": "query",
            "description": "Country name to filter airlines by.",
            "required": false,
            "schema": {
              "type": "string"
            },
            "example": "United Arab Emirates"
          }
        ],
        "responses": {
          "200": {
            "description": "Matching airline records.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AirlinesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or missing parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/incoterms": {
      "get": {
        "operationId": "lookupIncoterms",
        "summary": "INCOTERMS 2020 Lookup",
        "description": "Look up INCOTERMS 2020 rules by code or filter by category. Returns detailed responsibility breakdowns for each term. When called with a specific code, returns a single detailed object. When called without a code, returns all terms.",
        "tags": [
          "Reference Data"
        ],
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "description": "INCOTERMS code (e.g. FOB, CIF, EXW).",
            "required": false,
            "schema": {
              "type": "string"
            },
            "example": "FOB"
          },
          {
            "name": "category",
            "in": "query",
            "description": "Filter by transport mode category.",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "any_mode",
                "sea_only"
              ]
            },
            "example": "sea_only"
          }
        ],
        "responses": {
          "200": {
            "description": "INCOTERMS data. Returns a single Incoterm object when queried by code, or a list when browsing.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/IncotermDetail"
                    },
                    {
                      "$ref": "#/components/schemas/IncotermsListResponse"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid or missing parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/hs": {
      "get": {
        "operationId": "lookupHsCodes",
        "summary": "HS Code Lookup",
        "description": "Search and browse Harmonized System (HS 2022) commodity codes. Supports text search by product description, exact code lookup with ancestor chain, and section browsing. Covers 6,940 codes across 21 sections and 97 chapters.",
        "tags": [
          "Reference Data"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "Case-insensitive search on descriptions and HS codes. Min 2 characters.",
            "required": false,
            "schema": {
              "type": "string"
            },
            "example": "coffee"
          },
          {
            "name": "code",
            "in": "query",
            "description": "Exact HS code lookup (2, 4, or 6 digit). Returns full details with ancestor chain.",
            "required": false,
            "schema": {
              "type": "string"
            },
            "example": "0901"
          },
          {
            "name": "section",
            "in": "query",
            "description": "Browse by section Roman numeral. Returns all chapters in that section.",
            "required": false,
            "schema": {
              "type": "string"
            },
            "example": "II"
          }
        ],
        "responses": {
          "200": {
            "description": "HS code data. Response shape varies by query mode.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/HsSearchResponse"
                    },
                    {
                      "$ref": "#/components/schemas/HsCodeDetail"
                    },
                    {
                      "$ref": "#/components/schemas/HsSectionResponse"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Code or section not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/containers": {
      "get": {
        "operationId": "getContainers",
        "summary": "Container Capacity Reference",
        "description": "Shipping container specifications for all 10 standard ISO container types. Returns dimensions, weights, door openings, and pallet capacity. Optionally calculate how many items of given dimensions fit in a specific container.",
        "tags": [
          "Reference Data"
        ],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "description": "Container type slug. Omit to list all containers.",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "20ft-standard",
                "40ft-standard",
                "20ft-high-cube",
                "40ft-high-cube",
                "20ft-open-top",
                "40ft-open-top",
                "20ft-flat-rack",
                "40ft-flat-rack",
                "20ft-reefer",
                "40ft-reefer"
              ]
            },
            "example": "40ft-high-cube"
          },
          {
            "name": "l",
            "in": "query",
            "description": "Item length in centimetres. Requires type, w, and h for loading calculation.",
            "required": false,
            "schema": {
              "type": "number"
            },
            "example": 60
          },
          {
            "name": "w",
            "in": "query",
            "description": "Item width in centimetres.",
            "required": false,
            "schema": {
              "type": "number"
            },
            "example": 40
          },
          {
            "name": "h",
            "in": "query",
            "description": "Item height in centimetres.",
            "required": false,
            "schema": {
              "type": "number"
            },
            "example": 40
          },
          {
            "name": "wt",
            "in": "query",
            "description": "Item weight in kilograms.",
            "required": false,
            "schema": {
              "type": "number"
            },
            "example": 15
          },
          {
            "name": "qty",
            "in": "query",
            "description": "Number of items.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            },
            "example": 100
          }
        ],
        "responses": {
          "200": {
            "description": "Container specifications or loading calculation result.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ContainerListResponse"
                    },
                    {
                      "$ref": "#/components/schemas/ContainerSpec"
                    },
                    {
                      "$ref": "#/components/schemas/ContainerLoadingResponse"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Container type not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/convert": {
      "get": {
        "operationId": "convertUnits",
        "summary": "Unit Converter",
        "description": "Convert between freight-relevant units — weights, volumes, lengths, and freight-specific conversions (CBM to chargeable weight using IATA 6000 divisor, CBM to freight tonnes using W/M rule).",
        "tags": [
          "Calculators"
        ],
        "parameters": [
          {
            "name": "value",
            "in": "query",
            "description": "The number to convert.",
            "required": true,
            "schema": {
              "type": "number"
            },
            "example": 100
          },
          {
            "name": "from",
            "in": "query",
            "description": "Source unit code.",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "kg",
                "lbs",
                "oz",
                "tonnes",
                "short_tons",
                "long_tons",
                "cbm",
                "cuft",
                "cuin",
                "litres",
                "gal_us",
                "gal_uk",
                "cm",
                "inches",
                "m",
                "feet",
                "mm"
              ]
            },
            "example": "kg"
          },
          {
            "name": "to",
            "in": "query",
            "description": "Target unit code. Includes freight-specific targets: chargeable_kg (from cbm only) and freight_tonnes (from cbm only).",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "kg",
                "lbs",
                "oz",
                "tonnes",
                "short_tons",
                "long_tons",
                "cbm",
                "cuft",
                "cuin",
                "litres",
                "gal_us",
                "gal_uk",
                "cm",
                "inches",
                "m",
                "feet",
                "mm",
                "chargeable_kg",
                "freight_tonnes"
              ]
            },
            "example": "lbs"
          }
        ],
        "responses": {
          "200": {
            "description": "Conversion result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversionResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or missing parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/consignment": {
      "post": {
        "summary": "Multi-item consignment calculator",
        "description": "Calculate total CBM, weight, LDM, and chargeable weight for mixed consignments. Supports road, air, and sea modes.",
        "operationId": "calculateConsignment",
        "tags": [
          "Consignment"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "items"
                ],
                "properties": {
                  "mode": {
                    "type": "string",
                    "enum": [
                      "road",
                      "air",
                      "sea"
                    ],
                    "default": "road"
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "length",
                        "width",
                        "height"
                      ],
                      "properties": {
                        "description": {
                          "type": "string"
                        },
                        "length": {
                          "type": "number"
                        },
                        "width": {
                          "type": "number"
                        },
                        "height": {
                          "type": "number"
                        },
                        "quantity": {
                          "type": "integer",
                          "default": 1
                        },
                        "grossWeight": {
                          "type": "number"
                        },
                        "stackable": {
                          "type": "boolean"
                        },
                        "palletType": {
                          "type": "string",
                          "enum": [
                            "none",
                            "euro",
                            "uk",
                            "us"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Consignment calculation result"
          },
          "400": {
            "description": "Validation error"
          }
        }
      }
    },
    "/api/duty": {
      "post": {
        "summary": "UK import duty and VAT estimator",
        "description": "Estimate UK import duty and VAT using live GOV.UK Trade Tariff data.",
        "operationId": "estimateDuty",
        "tags": [
          "Customs"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "commodityCode",
                  "originCountry",
                  "customsValue"
                ],
                "properties": {
                  "commodityCode": {
                    "type": "string",
                    "example": "6204430000"
                  },
                  "originCountry": {
                    "type": "string",
                    "example": "CN"
                  },
                  "customsValue": {
                    "type": "number",
                    "example": 10000
                  },
                  "freightCost": {
                    "type": "number",
                    "example": 500
                  },
                  "insuranceCost": {
                    "type": "number",
                    "example": 50
                  },
                  "incoterm": {
                    "type": "string",
                    "example": "FOB"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Duty and VAT estimate"
          },
          "400": {
            "description": "Invalid parameters"
          }
        }
      }
    },
    "/api/unlocode": {
      "get": {
        "summary": "UN/LOCODE transport location lookup",
        "description": "Search 116,000+ UN/LOCODE entries by name, code, country, or function type.",
        "operationId": "searchUnlocode",
        "tags": [
          "Reference"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "Search by name or code",
            "schema": {
              "type": "string"
            },
            "example": "rotterdam"
          },
          {
            "name": "code",
            "in": "query",
            "description": "Exact UN/LOCODE",
            "schema": {
              "type": "string"
            },
            "example": "NLRTM"
          },
          {
            "name": "country",
            "in": "query",
            "description": "ISO 2-letter country",
            "schema": {
              "type": "string"
            },
            "example": "GB"
          },
          {
            "name": "function",
            "in": "query",
            "description": "Function type",
            "schema": {
              "type": "string",
              "enum": [
                "port",
                "airport",
                "rail",
                "road",
                "icd",
                "border"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Max results",
            "schema": {
              "type": "integer",
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search results"
          },
          "404": {
            "description": "Code not found"
          }
        }
      }
    },
    "/api/uld": {
      "get": {
        "operationId": "getULDs",
        "summary": "Air Freight ULD Types",
        "description": "Look up air freight ULD specifications. 15 types including AKE (LD3), PMC, temperature-controlled containers. Returns dimensions, weights, volume, aircraft compatibility.",
        "tags": ["Reference Data"],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "description": "ULD code or slug (e.g. AKE, PMC). Omit to list all.",
            "required": false,
            "schema": { "type": "string" },
            "example": "AKE"
          },
          {
            "name": "category",
            "in": "query",
            "description": "Filter by category: container, pallet, or special.",
            "required": false,
            "schema": { "type": "string", "enum": ["container", "pallet", "special"] }
          },
          {
            "name": "deck",
            "in": "query",
            "description": "Filter by deck position: lower or main.",
            "required": false,
            "schema": { "type": "string", "enum": ["lower", "main"] }
          }
        ],
        "responses": {
          "200": { "description": "ULD specification(s)." },
          "404": { "description": "ULD type not found." }
        }
      }
    },
    "/api/vehicles": {
      "get": {
        "operationId": "getVehicles",
        "summary": "Vehicle & Trailer Types",
        "description": "Look up road freight vehicle and trailer specifications. 17 types covering articulated trailers, rigid trucks, and vans. Returns dimensions, payload limits, pallet capacity.",
        "tags": ["Reference Data"],
        "parameters": [
          {
            "name": "slug",
            "in": "query",
            "description": "Vehicle slug (e.g. standard-curtainsider). Omit to list all.",
            "required": false,
            "schema": { "type": "string" },
            "example": "standard-curtainsider"
          },
          {
            "name": "category",
            "in": "query",
            "description": "Filter by category: articulated, rigid, or van.",
            "required": false,
            "schema": { "type": "string", "enum": ["articulated", "rigid", "van"] }
          },
          {
            "name": "region",
            "in": "query",
            "description": "Filter by region: EU or US.",
            "required": false,
            "schema": { "type": "string", "enum": ["EU", "US"] }
          }
        ],
        "responses": {
          "200": { "description": "Vehicle specification(s)." },
          "404": { "description": "Vehicle type not found." }
        }
      }
    },
    "/api/adr/lq-check": {
      "post": {
        "operationId": "checkLqEq",
        "summary": "ADR Limited & Excepted Quantity Checker",
        "description": "Check whether dangerous goods items qualify for ADR Limited Quantity (Chapter 3.4) or Excepted Quantity (Chapter 3.5) concessions. Returns per-item pass/fail against ADR Table A limits.",
        "tags": [
          "Reference Data",
          "ADR"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["items"],
                "properties": {
                  "mode": {
                    "type": "string",
                    "enum": ["lq", "eq"],
                    "default": "lq",
                    "description": "Check mode — 'lq' for Limited Quantity (Ch 3.4) or 'eq' for Excepted Quantity (Ch 3.5)"
                  },
                  "items": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 20,
                    "items": {
                      "type": "object",
                      "required": ["un_number", "quantity"],
                      "properties": {
                        "un_number": {
                          "type": "string",
                          "description": "UN number (1-4 digits)",
                          "example": "1203"
                        },
                        "quantity": {
                          "type": "number",
                          "description": "Quantity per inner packaging",
                          "example": 0.5
                        },
                        "unit": {
                          "type": "string",
                          "enum": ["ml", "L", "g", "kg"],
                          "default": "L",
                          "description": "Unit of measure"
                        },
                        "inner_packaging_qty": {
                          "type": "number",
                          "description": "Number of inner packagings per outer (EQ mode only)"
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "mode": "lq",
                "items": [
                  { "un_number": "1203", "quantity": 0.5, "unit": "L" }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "LQ/EQ check result with per-item status.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "mode": { "type": "string", "enum": ["lq", "eq"] },
                    "overall_status": { "type": "string", "enum": ["qualifies", "does_not_qualify", "partial"] },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "un_number": { "type": "string" },
                          "substance": { "type": "string" },
                          "class": { "type": "string" },
                          "packing_group": { "type": "string" },
                          "lq_limit": { "type": "string" },
                          "lq_limit_value": { "type": "number", "nullable": true },
                          "lq_limit_unit": { "type": "string", "nullable": true },
                          "eq_code": { "type": "string" },
                          "quantity_entered": { "type": "number" },
                          "unit_entered": { "type": "string" },
                          "status": { "type": "string", "enum": ["within_limit", "exceeds_limit", "not_permitted"] },
                          "reason": { "type": "string" }
                        }
                      }
                    },
                    "summary": {
                      "type": "object",
                      "properties": {
                        "total_items": { "type": "integer" },
                        "qualifying": { "type": "integer" },
                        "exceeding": { "type": "integer" },
                        "not_permitted": { "type": "integer" }
                      }
                    },
                    "references": {
                      "type": "object",
                      "properties": {
                        "adr_chapter": { "type": "string" },
                        "table": { "type": "string" }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid or missing parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "405": {
            "description": "Use POST with a JSON body."
          }
        }
      }
    },
    "/api/shipment/summary": {
      "post": {
        "summary": "Composite shipment summary",
        "description": "Chains CBM, chargeable weight, LDM, ADR compliance, and UK duty estimation into one response. The flagship composite endpoint.",
        "operationId": "shipmentSummary",
        "tags": [
          "Composite"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "mode",
                  "items"
                ],
                "properties": {
                  "mode": {
                    "type": "string",
                    "enum": [
                      "road",
                      "air",
                      "sea",
                      "multimodal"
                    ]
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "length",
                        "width",
                        "height",
                        "weight",
                        "quantity"
                      ],
                      "properties": {
                        "description": {
                          "type": "string"
                        },
                        "length": {
                          "type": "number"
                        },
                        "width": {
                          "type": "number"
                        },
                        "height": {
                          "type": "number"
                        },
                        "weight": {
                          "type": "number"
                        },
                        "quantity": {
                          "type": "integer"
                        },
                        "stackable": {
                          "type": "boolean"
                        },
                        "hsCode": {
                          "type": "string"
                        },
                        "unNumber": {
                          "type": "string"
                        },
                        "customsValue": {
                          "type": "number"
                        }
                      }
                    }
                  },
                  "origin": {
                    "type": "object",
                    "properties": {
                      "country": {
                        "type": "string"
                      },
                      "locode": {
                        "type": "string"
                      }
                    }
                  },
                  "destination": {
                    "type": "object",
                    "properties": {
                      "country": {
                        "type": "string"
                      },
                      "locode": {
                        "type": "string"
                      }
                    }
                  },
                  "incoterm": {
                    "type": "string"
                  },
                  "freightCost": {
                    "type": "number"
                  },
                  "insuranceCost": {
                    "type": "number"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Complete shipment summary"
          },
          "400": {
            "description": "Validation error"
          },
          "405": {
            "description": "Use POST"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message.",
            "example": "Missing required parameter: length"
          }
        },
        "required": [
          "error"
        ]
      },
      "LdmVehicle": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Human-readable vehicle name.",
            "example": "13.6m Artic Trailer"
          },
          "length_m": {
            "type": "number",
            "description": "Vehicle loading length in metres.",
            "example": 13.6
          },
          "max_payload_kg": {
            "type": "number",
            "description": "Maximum payload capacity in kilograms.",
            "example": 24000
          }
        },
        "required": [
          "name",
          "length_m",
          "max_payload_kg"
        ]
      },
      "LdmPalletSpaces": {
        "type": "object",
        "properties": {
          "used": {
            "type": "integer",
            "description": "Number of pallet spaces used.",
            "example": 2
          },
          "available": {
            "type": "integer",
            "description": "Total pallet spaces available on the vehicle.",
            "example": 33
          }
        },
        "required": [
          "used",
          "available"
        ]
      },
      "LdmMetaInputs": {
        "type": "object",
        "properties": {
          "length_mm": {
            "type": "number",
            "description": "Pallet length in mm as interpreted.",
            "example": 1200
          },
          "width_mm": {
            "type": "number",
            "description": "Pallet width in mm as interpreted.",
            "example": 800
          },
          "qty": {
            "type": "integer",
            "description": "Number of pallets.",
            "example": 2
          },
          "stackable": {
            "type": "boolean",
            "example": false
          },
          "stack_factor": {
            "type": "integer",
            "example": 2
          },
          "weight_per_pallet_kg": {
            "type": "number",
            "nullable": true,
            "example": null
          },
          "vehicle": {
            "type": "string",
            "example": "artic"
          }
        }
      },
      "LdmResponse": {
        "type": "object",
        "properties": {
          "ldm": {
            "type": "number",
            "description": "Calculated loading metres.",
            "example": 0.8
          },
          "vehicle": {
            "$ref": "#/components/schemas/LdmVehicle"
          },
          "utilisation_percent": {
            "type": "number",
            "description": "Percentage of vehicle length used.",
            "example": 5.88
          },
          "pallet_spaces": {
            "$ref": "#/components/schemas/LdmPalletSpaces"
          },
          "total_weight_kg": {
            "type": "number",
            "nullable": true,
            "description": "Total weight of all pallets in kg, or null if weight not provided.",
            "example": null
          },
          "fits": {
            "type": "boolean",
            "description": "Whether the load fits on the selected vehicle.",
            "example": true
          },
          "warnings": {
            "type": "array",
            "description": "Any warnings about the load (e.g. overweight, overhang).",
            "items": {
              "type": "string"
            },
            "example": []
          },
          "meta": {
            "type": "object",
            "properties": {
              "inputs": {
                "$ref": "#/components/schemas/LdmMetaInputs"
              }
            }
          }
        },
        "required": [
          "ldm",
          "vehicle",
          "utilisation_percent",
          "pallet_spaces",
          "total_weight_kg",
          "fits",
          "warnings",
          "meta"
        ]
      },
      "CbmMetaInputs": {
        "type": "object",
        "properties": {
          "length_cm": {
            "type": "number",
            "example": 120
          },
          "width_cm": {
            "type": "number",
            "example": 80
          },
          "height_cm": {
            "type": "number",
            "example": 100
          },
          "pieces": {
            "type": "integer",
            "example": 2
          }
        }
      },
      "CbmResponse": {
        "type": "object",
        "properties": {
          "cbm_per_piece": {
            "type": "number",
            "description": "Cubic metres per single piece.",
            "example": 0.96
          },
          "total_cbm": {
            "type": "number",
            "description": "Total cubic metres for all pieces.",
            "example": 1.92
          },
          "total_volume_m3": {
            "type": "number",
            "description": "Total volume in cubic metres (same as total_cbm).",
            "example": 1.92
          },
          "cubic_feet": {
            "type": "number",
            "description": "Total volume in cubic feet.",
            "example": 67.8042
          },
          "litres": {
            "type": "number",
            "description": "Total volume in litres.",
            "example": 1920
          },
          "cubic_inches": {
            "type": "number",
            "description": "Total volume in cubic inches.",
            "example": 117165.5
          },
          "pieces": {
            "type": "integer",
            "description": "Number of pieces.",
            "example": 2
          },
          "meta": {
            "type": "object",
            "properties": {
              "inputs": {
                "$ref": "#/components/schemas/CbmMetaInputs"
              }
            }
          }
        },
        "required": [
          "cbm_per_piece",
          "total_cbm",
          "total_volume_m3",
          "cubic_feet",
          "litres",
          "cubic_inches",
          "pieces",
          "meta"
        ]
      },
      "ChargeableWeightMetaInputs": {
        "type": "object",
        "properties": {
          "length_cm": {
            "type": "number",
            "example": 120
          },
          "width_cm": {
            "type": "number",
            "example": 80
          },
          "height_cm": {
            "type": "number",
            "example": 100
          },
          "gross_weight_kg": {
            "type": "number",
            "example": 500
          },
          "pieces": {
            "type": "integer",
            "example": 2
          },
          "factor": {
            "type": "integer",
            "example": 6000
          }
        }
      },
      "ChargeableWeightResponse": {
        "type": "object",
        "properties": {
          "chargeable_weight_kg": {
            "type": "number",
            "description": "The chargeable weight (higher of actual vs volumetric).",
            "example": 500
          },
          "basis": {
            "type": "string",
            "description": "Whether the chargeable weight is based on 'actual' gross weight or 'volumetric' weight.",
            "enum": [
              "actual",
              "volumetric"
            ],
            "example": "actual"
          },
          "gross_weight_kg": {
            "type": "number",
            "description": "Actual gross weight in kg.",
            "example": 500
          },
          "volumetric_weight_kg": {
            "type": "number",
            "description": "Total volumetric weight in kg.",
            "example": 320
          },
          "volumetric_weight_per_piece_kg": {
            "type": "number",
            "description": "Volumetric weight per piece in kg.",
            "example": 160
          },
          "cbm": {
            "type": "number",
            "description": "Total cubic metres.",
            "example": 1.92
          },
          "ratio": {
            "type": "number",
            "description": "Weight-to-volume ratio (kg per CBM).",
            "example": 3.84
          },
          "factor": {
            "type": "integer",
            "description": "Volumetric divisor factor used.",
            "example": 6000
          },
          "pieces": {
            "type": "integer",
            "description": "Number of pieces.",
            "example": 2
          },
          "meta": {
            "type": "object",
            "properties": {
              "inputs": {
                "$ref": "#/components/schemas/ChargeableWeightMetaInputs"
              }
            }
          }
        },
        "required": [
          "chargeable_weight_kg",
          "basis",
          "gross_weight_kg",
          "volumetric_weight_kg",
          "volumetric_weight_per_piece_kg",
          "cbm",
          "ratio",
          "factor",
          "pieces",
          "meta"
        ]
      },
      "PalletFittingMetaInputs": {
        "type": "object",
        "properties": {
          "pallet_length_cm": {
            "type": "number",
            "example": 120
          },
          "pallet_width_cm": {
            "type": "number",
            "example": 80
          },
          "pallet_max_height_cm": {
            "type": "number",
            "example": 220
          },
          "pallet_height_cm": {
            "type": "number",
            "example": 15
          },
          "box_length_cm": {
            "type": "number",
            "example": 40
          },
          "box_width_cm": {
            "type": "number",
            "example": 30
          },
          "box_height_cm": {
            "type": "number",
            "example": 25
          },
          "box_weight_kg": {
            "type": "number",
            "nullable": true,
            "example": null
          },
          "max_payload_weight_kg": {
            "type": "number",
            "nullable": true,
            "example": null
          },
          "allow_rotation": {
            "type": "boolean",
            "example": true
          }
        }
      },
      "PalletFittingResponse": {
        "type": "object",
        "properties": {
          "boxes_per_layer": {
            "type": "integer",
            "description": "Number of boxes fitting in a single layer.",
            "example": 8
          },
          "layers": {
            "type": "integer",
            "description": "Number of layers that fit within the height constraint.",
            "example": 8
          },
          "total_boxes": {
            "type": "integer",
            "description": "Total number of boxes fitting on the pallet.",
            "example": 64
          },
          "orientation": {
            "type": "string",
            "description": "Whether boxes were rotated for best fit.",
            "enum": [
              "standard",
              "rotated"
            ],
            "example": "rotated"
          },
          "boxes_per_row": {
            "type": "integer",
            "description": "Number of boxes per row along the pallet length.",
            "example": 4
          },
          "boxes_per_col": {
            "type": "integer",
            "description": "Number of boxes per column along the pallet width.",
            "example": 2
          },
          "usable_height_cm": {
            "type": "number",
            "description": "Usable stacking height after subtracting deck height.",
            "example": 205
          },
          "utilisation_percent": {
            "type": "number",
            "description": "Volume utilisation percentage.",
            "example": 100
          },
          "total_box_volume_cbm": {
            "type": "number",
            "description": "Total volume of all boxes in CBM.",
            "example": 1.92
          },
          "pallet_volume_cbm": {
            "type": "number",
            "description": "Usable pallet volume in CBM.",
            "example": 1.968
          },
          "wasted_space_cbm": {
            "type": "number",
            "description": "Wasted space in CBM.",
            "example": 0.048
          },
          "weight_limited": {
            "type": "boolean",
            "description": "Whether the result was limited by weight rather than space.",
            "example": false
          },
          "total_weight_kg": {
            "type": "number",
            "nullable": true,
            "description": "Total weight of all boxes, or null if box weight not provided.",
            "example": null
          },
          "remaining_weight_capacity_kg": {
            "type": "number",
            "nullable": true,
            "description": "Remaining weight capacity, or null if not applicable.",
            "example": null
          },
          "meta": {
            "type": "object",
            "properties": {
              "inputs": {
                "$ref": "#/components/schemas/PalletFittingMetaInputs"
              }
            }
          }
        },
        "required": [
          "boxes_per_layer",
          "layers",
          "total_boxes",
          "orientation",
          "boxes_per_row",
          "boxes_per_col",
          "usable_height_cm",
          "utilisation_percent",
          "total_box_volume_cbm",
          "pallet_volume_cbm",
          "wasted_space_cbm",
          "weight_limited",
          "total_weight_kg",
          "remaining_weight_capacity_kg",
          "meta"
        ]
      },
      "AdrSubstance": {
        "type": "object",
        "properties": {
          "un_number": {
            "type": "string",
            "description": "UN number identifying the dangerous goods.",
            "example": "1203"
          },
          "proper_shipping_name": {
            "type": "string",
            "description": "Official ADR proper shipping name.",
            "example": "MOTOR SPIRIT or GASOLINE or PETROL"
          },
          "class": {
            "type": "string",
            "description": "ADR hazard class.",
            "example": "3"
          },
          "classification_code": {
            "type": "string",
            "description": "ADR classification code.",
            "example": "F1"
          },
          "packing_group": {
            "type": "string",
            "description": "Packing group (I, II, or III).",
            "example": "II"
          },
          "labels": {
            "type": "string",
            "description": "Required hazard labels.",
            "example": "3"
          },
          "special_provisions": {
            "type": "string",
            "description": "Applicable special provisions.",
            "example": "243 534 664"
          },
          "limited_quantity": {
            "type": "string",
            "description": "Limited quantity allowance.",
            "example": "1 L"
          },
          "excepted_quantity": {
            "type": "string",
            "description": "Excepted quantity code.",
            "example": "E2"
          },
          "transport_category": {
            "type": "string",
            "description": "Transport category for 1.1.3.6 exemption (0-4).",
            "example": "2"
          },
          "tunnel_restriction_code": {
            "type": "string",
            "description": "Tunnel restriction code.",
            "example": "(D/E)"
          },
          "hazard_identification_number": {
            "type": "string",
            "description": "Kemler/HIN code for orange plates.",
            "example": "33"
          },
          "variant_index": {
            "type": "integer",
            "description": "Index of this variant (0-based) when a UN number has multiple entries.",
            "example": 0
          },
          "variant_count": {
            "type": "integer",
            "description": "Total number of variants for this UN number.",
            "example": 1
          }
        },
        "required": [
          "un_number",
          "proper_shipping_name",
          "class",
          "classification_code",
          "packing_group",
          "labels",
          "special_provisions",
          "limited_quantity",
          "excepted_quantity",
          "transport_category",
          "tunnel_restriction_code",
          "hazard_identification_number",
          "variant_index",
          "variant_count"
        ]
      },
      "AdrLookupResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Number of matching results.",
            "example": 1
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdrSubstance"
            }
          }
        },
        "required": [
          "count",
          "results"
        ]
      },
      "AdrCalculatorRequest": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "description": "Array of dangerous goods items to calculate.",
            "items": {
              "type": "object",
              "properties": {
                "un_number": {
                  "type": "string",
                  "description": "UN number of the substance.",
                  "example": "1203"
                },
                "quantity": {
                  "type": "number",
                  "description": "Quantity being transported (kg or litres).",
                  "example": 200
                }
              },
              "required": [
                "un_number",
                "quantity"
              ]
            }
          }
        },
        "required": [
          "items"
        ]
      },
      "AdrCalculatorItem": {
        "type": "object",
        "properties": {
          "un_number": {
            "type": "string",
            "description": "UN number of the substance.",
            "example": "1203"
          },
          "proper_shipping_name": {
            "type": "string",
            "description": "Official ADR proper shipping name.",
            "example": "MOTOR SPIRIT or GASOLINE or PETROL"
          },
          "class": {
            "type": "string",
            "description": "ADR hazard class.",
            "example": "3"
          },
          "transport_category": {
            "type": "string",
            "description": "Transport category (0-4).",
            "example": "2"
          },
          "quantity": {
            "type": "number",
            "description": "Quantity being transported.",
            "example": 200
          },
          "multiplier": {
            "type": "integer",
            "description": "Points multiplier for this transport category.",
            "example": 3
          },
          "points": {
            "type": "number",
            "description": "Calculated points (quantity x multiplier).",
            "example": 600
          }
        },
        "required": [
          "un_number",
          "proper_shipping_name",
          "class",
          "transport_category",
          "quantity",
          "multiplier",
          "points"
        ]
      },
      "AdrCalculatorResponse": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdrCalculatorItem"
            }
          },
          "total_points": {
            "type": "number",
            "description": "Sum of all item points.",
            "example": 600
          },
          "threshold": {
            "type": "integer",
            "description": "1.1.3.6 threshold (always 1000).",
            "example": 1000
          },
          "exempt": {
            "type": "boolean",
            "description": "Whether the shipment qualifies for 1.1.3.6 exemption.",
            "example": true
          },
          "has_category_zero": {
            "type": "boolean",
            "description": "Whether any item is transport category 0 (never exempt).",
            "example": false
          },
          "has_quantity_exceedance": {
            "type": "boolean",
            "description": "Whether any single item exceeds its maximum quantity per transport unit.",
            "example": false
          },
          "warnings": {
            "type": "array",
            "description": "Any warnings about the calculation.",
            "items": {
              "type": "string"
            },
            "example": []
          },
          "message": {
            "type": "string",
            "description": "Human-readable exemption status message.",
            "example": "1.1.3.6 exemption applies"
          }
        },
        "required": [
          "items",
          "total_points",
          "threshold",
          "exempt",
          "has_category_zero",
          "has_quantity_exceedance",
          "warnings",
          "message"
        ]
      },
      "Airline": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "description": "URL-friendly airline identifier.",
            "example": "emirates"
          },
          "airline_name": {
            "type": "string",
            "description": "Full airline name.",
            "example": "Emirates"
          },
          "iata_code": {
            "type": "string",
            "description": "2-character IATA airline designator.",
            "example": "EK"
          },
          "icao_code": {
            "type": "string",
            "description": "3-character ICAO airline designator.",
            "example": "UAE"
          },
          "awb_prefix": {
            "type": "array",
            "description": "3-digit Air Waybill prefix number(s).",
            "items": {
              "type": "string"
            },
            "example": [
              "176"
            ]
          },
          "callsign": {
            "type": "string",
            "description": "Radio telephony callsign.",
            "example": "EMIRATES"
          },
          "country": {
            "type": "string",
            "description": "Country of registration.",
            "example": "United Arab Emirates"
          },
          "has_cargo": {
            "type": "boolean",
            "description": "Whether the airline operates cargo services.",
            "example": true
          },
          "aliases": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true,
            "description": "Alternative names (e.g. cargo division name).",
            "example": [
              "Emirates SkyCargo"
            ]
          },
          "verified": {
            "type": "boolean",
            "description": "Whether the airline data has been verified.",
            "example": true
          }
        },
        "required": [
          "slug",
          "airline_name",
          "iata_code",
          "icao_code",
          "awb_prefix",
          "callsign",
          "country",
          "has_cargo",
          "verified"
        ]
      },
      "AirlinesResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Number of matching results.",
            "example": 1
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Airline"
            }
          }
        },
        "required": [
          "count",
          "results"
        ]
      },
      "IncotermDetail": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "INCOTERM code.",
            "example": "FOB"
          },
          "name": {
            "type": "string",
            "description": "Full INCOTERM name.",
            "example": "Free on Board"
          },
          "slug": {
            "type": "string",
            "description": "URL-friendly identifier.",
            "example": "fob-free-on-board"
          },
          "category": {
            "type": "string",
            "description": "Transport mode category.",
            "enum": [
              "any_mode",
              "sea_only"
            ],
            "example": "sea_only"
          },
          "summary": {
            "type": "string",
            "description": "Brief summary of the term."
          },
          "seller_responsibility": {
            "type": "string",
            "description": "What the seller is responsible for."
          },
          "buyer_responsibility": {
            "type": "string",
            "description": "What the buyer is responsible for."
          },
          "risk_transfer": {
            "type": "string",
            "description": "Point at which risk transfers from seller to buyer."
          },
          "cost_transfer": {
            "type": "string",
            "description": "Point at which cost responsibility transfers."
          },
          "insurance": {
            "type": "string",
            "description": "Insurance obligations."
          },
          "export_clearance": {
            "type": "string",
            "description": "Who handles export customs clearance."
          },
          "import_clearance": {
            "type": "string",
            "description": "Who handles import customs clearance."
          },
          "best_for": {
            "type": "string",
            "description": "Scenarios this term is best suited for."
          },
          "watch_out": {
            "type": "string",
            "description": "Common pitfalls or things to be aware of."
          }
        },
        "required": [
          "code",
          "name",
          "slug",
          "category",
          "summary",
          "seller_responsibility",
          "buyer_responsibility",
          "risk_transfer",
          "cost_transfer",
          "insurance",
          "export_clearance",
          "import_clearance",
          "best_for",
          "watch_out"
        ]
      },
      "IncotermsListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Number of INCOTERMS returned.",
            "example": 11
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IncotermDetail"
            }
          }
        },
        "required": [
          "count",
          "results"
        ]
      },
      "ContainerSpec": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Container type name.",
            "example": "40ft High Cube"
          },
          "slug": {
            "type": "string",
            "description": "URL-friendly identifier.",
            "example": "40ft-high-cube"
          },
          "internalLengthCm": {
            "type": "number",
            "description": "Internal length in cm.",
            "example": 1203
          },
          "internalWidthCm": {
            "type": "number",
            "description": "Internal width in cm.",
            "example": 235
          },
          "internalHeightCm": {
            "type": "number",
            "description": "Internal height in cm.",
            "example": 269
          },
          "externalLengthCm": {
            "type": "number",
            "description": "External length in cm.",
            "example": 1219
          },
          "externalWidthCm": {
            "type": "number",
            "description": "External width in cm.",
            "example": 244
          },
          "externalHeightCm": {
            "type": "number",
            "description": "External height in cm.",
            "example": 290
          },
          "doorWidthCm": {
            "type": "number",
            "nullable": true,
            "description": "Door opening width in cm.",
            "example": 234
          },
          "doorHeightCm": {
            "type": "number",
            "nullable": true,
            "description": "Door opening height in cm.",
            "example": 263
          },
          "capacityCbm": {
            "type": "number",
            "description": "Internal volume in CBM.",
            "example": 76.2
          },
          "tareWeightKg": {
            "type": "number",
            "description": "Empty container weight in kg.",
            "example": 3900
          },
          "maxGrossKg": {
            "type": "number",
            "description": "Maximum gross weight in kg.",
            "example": 30480
          },
          "maxPayloadKg": {
            "type": "number",
            "description": "Maximum cargo weight in kg.",
            "example": 26580
          },
          "euroPallets": {
            "type": "string",
            "description": "Number of EUR pallets (1200x800mm) that fit.",
            "example": "25"
          },
          "gmaPallets": {
            "type": "string",
            "description": "Number of GMA pallets (48x40in) that fit.",
            "example": "20"
          },
          "description": {
            "type": "string",
            "description": "Container description."
          },
          "notes": {
            "type": "string",
            "description": "Usage notes."
          }
        },
        "required": [
          "name",
          "slug",
          "internalLengthCm",
          "internalWidthCm",
          "internalHeightCm",
          "capacityCbm",
          "tareWeightKg",
          "maxGrossKg",
          "maxPayloadKg",
          "euroPallets",
          "gmaPallets"
        ]
      },
      "ContainerListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Number of containers.",
            "example": 10
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContainerSpec"
            }
          }
        },
        "required": [
          "count",
          "results"
        ]
      },
      "ContainerLoadingResponse": {
        "type": "object",
        "properties": {
          "container": {
            "$ref": "#/components/schemas/ContainerSpec"
          },
          "loading": {
            "type": "object",
            "properties": {
              "fits_lengthwise": {
                "type": "integer",
                "description": "Items fitting along the length."
              },
              "fits_widthwise": {
                "type": "integer",
                "description": "Items fitting along the width."
              },
              "fits_height": {
                "type": "integer",
                "description": "Items fitting in height."
              },
              "max_items": {
                "type": "integer",
                "description": "Maximum items that physically fit."
              },
              "requested_qty": {
                "type": "integer",
                "description": "Quantity requested."
              },
              "fits": {
                "type": "boolean",
                "description": "Whether all requested items fit."
              },
              "total_weight_kg": {
                "type": "number",
                "description": "Total weight of loaded items."
              },
              "within_payload": {
                "type": "boolean",
                "description": "Whether total weight is within payload limit."
              },
              "utilisation_percent": {
                "type": "number",
                "description": "Volume utilisation percentage."
              }
            }
          }
        },
        "required": [
          "container",
          "loading"
        ]
      },
      "ConversionResult": {
        "type": "object",
        "properties": {
          "input": {
            "type": "object",
            "properties": {
              "value": {
                "type": "number",
                "description": "Input value.",
                "example": 100
              },
              "unit": {
                "type": "string",
                "description": "Input unit code.",
                "example": "kg"
              },
              "name": {
                "type": "string",
                "description": "Input unit name.",
                "example": "Kilograms"
              }
            },
            "required": [
              "value",
              "unit",
              "name"
            ]
          },
          "result": {
            "type": "object",
            "properties": {
              "value": {
                "type": "number",
                "description": "Converted value.",
                "example": 220.462
              },
              "unit": {
                "type": "string",
                "description": "Output unit code.",
                "example": "lbs"
              },
              "name": {
                "type": "string",
                "description": "Output unit name.",
                "example": "Pounds"
              }
            },
            "required": [
              "value",
              "unit",
              "name"
            ]
          },
          "formula": {
            "type": "string",
            "description": "Human-readable conversion formula.",
            "example": "Kilograms × 2.20462 = Pounds"
          },
          "note": {
            "type": "string",
            "description": "Additional context for freight-specific conversions."
          }
        },
        "required": [
          "input",
          "result",
          "formula"
        ]
      },
      "HsCode": {
        "type": "object",
        "properties": {
          "hscode": {
            "type": "string",
            "description": "HS code (2, 4, or 6 digits).",
            "example": "0901"
          },
          "description": {
            "type": "string",
            "description": "Product description.",
            "example": "Coffee, whether or not roasted or decaffeinated"
          },
          "level": {
            "type": "integer",
            "description": "Hierarchy level: 2=chapter, 4=heading, 6=subheading.",
            "example": 4
          },
          "parent": {
            "type": "string",
            "description": "Parent code or TOTAL for chapters.",
            "example": "09"
          },
          "section": {
            "type": "string",
            "description": "Section Roman numeral.",
            "example": "II"
          }
        },
        "required": [
          "hscode",
          "description",
          "level",
          "parent",
          "section"
        ]
      },
      "HsCodeDetail": {
        "type": "object",
        "properties": {
          "hscode": {
            "type": "string",
            "example": "090111"
          },
          "description": {
            "type": "string",
            "example": "Coffee; not roasted, not decaffeinated"
          },
          "level": {
            "type": "integer",
            "example": 6
          },
          "parent": {
            "type": "string",
            "example": "0901"
          },
          "section": {
            "type": "string",
            "example": "II"
          },
          "ancestors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HsCode"
            }
          },
          "children": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HsCode"
            }
          },
          "sectionName": {
            "type": "string",
            "example": "Vegetable products"
          }
        },
        "required": [
          "hscode",
          "description",
          "level",
          "parent",
          "section",
          "ancestors",
          "children",
          "sectionName"
        ]
      },
      "HsSearchResponse": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "example": "coffee"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HsCode"
            }
          },
          "count": {
            "type": "integer",
            "example": 12
          }
        },
        "required": [
          "query",
          "results",
          "count"
        ]
      },
      "HsSectionResponse": {
        "type": "object",
        "properties": {
          "section": {
            "type": "object",
            "properties": {
              "numeral": {
                "type": "string",
                "example": "ii"
              },
              "name": {
                "type": "string",
                "example": "Vegetable products"
              }
            }
          },
          "chapters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HsCode"
            }
          },
          "count": {
            "type": "integer",
            "example": 14
          }
        },
        "required": [
          "section",
          "chapters",
          "count"
        ]
      }
    }
  }
}