REST · MCP · GPT · OpenAPI 3.1.0

The reference layer, documented

23 REST endpoints · 24 MCP tools — every response carries its _source: the authority, the dataset edition, and where it came from.

> tools/call adr_lookup { "un_number": "1203" } { "count": 1, "results": [ { "un_number": "1203", "proper_shipping_name": "MOTOR SPIRIT or GASOLINE or PETROL", "class": "3", "classification_code": "F1", "packing_group": "II", "labels": "3", "special_provisions": "243 534 664", "limited_quantity": "1 L", "excepted_quantity": "E2", "transport_category": "2", "tunnel_restriction_code": "(D/E)", "hazard_identification_number": "33", "variant_index": 0, "variant_count": 1 } ], "meta": { "source": "ADR 2025 (UNECE, ECE/TRANS/352, applicable 1 Jan 2025); given legal effect by EU Directive 2008/68/EC (consolidated). Factual compilation, best-effort — not legal advice, not a regulatory authority.", "edition": "ADR 2025", "entries": 2939 }, "_source": { "type": "reference", "authority": "UNECE", "dataset": "ADR 2025", "source_url": "https://unece.org/adr-2025-files", "data_vintage": "ADR 2025", "licence": "factual compilation, no named open licence", "retrieved_via": "freightutils.com" } }
npx freightutils-mcp
Claude DesktopCursorChatGPTn8nZapierMake
Open Playground →📥 Download OpenAPI 3.1.0 Spec (JSON)📥 Download Postman Collection

Compatible with Swagger and Postman import

Overview

The FreightUtils API is the neutral freight reference layer for AI agents — authoritative dangerous-goods, customs, location and freight-calculation data an agent can call and cite, from primary sources (ADR 2025 / UNECE, HS 2022 / WCO, IATA-regulated airline prefixes). Neutral by design: no freight to sell and no carrier to push, so an agent can trust it as ground truth. It is a stateless REST API; every calculator on this site has a corresponding endpoint. No authentication is required. Responses are JSON. CORS is enabled for all origins.

Base URL: https://www.freightutils.com/api
Download OpenAPI 3.1.0 Spec (JSON)

Reliability & Support

FreightUtils APIs are hosted on Vercel's global edge network with automatic SSL and CDN caching.

Status
APIs are actively maintained and monitored.
Support
contact@freightutils.com — corrections and API issues typically addressed within 2 business days.
Versioning
Reference endpoints (ADR, HS, airlines) include a meta object with data source and edition information. Breaking changes will be announced via the API docs page.
Open Access Tier
No authentication required for casual use. Rate limit: 25 requests per day per IP. Free API keys available for 100/day.
Commercial Access
For production integrations with higher limits, see Pro pricing or contact us directly.
Free API Key
Get 100 requests/day — no credit card required
Enter your email and we'll send you an API key instantly.
Anonymous: 25/day · Free key: 100/day · Pro: 50,000/month
Need higher limits? See our plans →

MCP Server — AI Agent Integration

The full MCP server reference — all 24 tools, the response envelope, rate limits and directory listings — lives on its own page.

MCP server docs →

FreightUtils is the neutral freight reference layer for AI agents, available as a Model Context Protocol (MCP) server — direct, citable access to all 24 MCP tools (23 REST-backed + get_subscribe_link) from authoritative sources, with no freight to sell and no carrier to push.

Install via npm
npx freightutils-mcp
Or connect via URL
https://www.freightutils.com/api/mcp
Claude Desktop Configuration
Add to your claude_desktop_config.json:
{ "mcpServers": { "freightutils": { "command": "npx", "args": ["freightutils-mcp"] } } }
First-time setup verification

After saving the config, fully quit and relaunch your MCP client (Claude Desktop, Cursor, Cline). MCP servers are only loaded at client startup — editing the config in a running session does nothing until restart.

Confirm the FreightUtils MCP surface is reachable before asking your agent any freight question:

curl https://www.freightutils.com/api/mcp/health

A 200 response with "status":"ok" and "tools_registered":24 means the remote MCP surface is live. The endpoint is callable by your agent too — Claude/Cursor/Cline can hit it for a self-diagnostic without you having to open a terminal.

Cursor Configuration
Cursor uses an mcp.json file (Settings → MCP). Same shape as Claude Desktop:
{ "mcpServers": { "freightutils": { "command": "npx", "args": ["-y", "freightutils-mcp"] } } }
Cline Configuration
Cline (VS Code extension): open the MCP server settings panel, click "Edit MCP Settings", add:
{ "mcpServers": { "freightutils": { "command": "npx", "args": ["-y", "freightutils-mcp"], "disabled": false, "autoApprove": [] } } }
Troubleshooting
SymptomLikely causeFix
Tools not appearing in the clientMCP client wasn’t restarted after the config editFully quit (Cmd+Q on macOS / right-click → Quit on Windows tray) and relaunch. Don’t just close the window.
"Server failed to start" / spawn error in client logsnpx not on PATH, or node version older than 18Install Node.js 18+ from nodejs.org. On macOS, an absolute path in the config (e.g. "/opt/homebrew/bin/npx") avoids PATH issues for GUI-launched clients.
Tool calls return HTTP 429 / "rate_limited"Anonymous IP cap of 25 requests/day exceededGet a free API key from the signup form below (100/day) or upgrade to Pro (50,000/month). The freightutils-mcp npm package passes the key through on every call (since v2.3.0) — set the FREIGHTUTILS_API_KEY env var in your MCP client config. On the remote URL (https://www.freightutils.com/api/mcp), send it as an X-API-Key header.
Specific tool returns "isError": trueBad input shape (snake_case vs camelCase, missing required field) or unknown lookup key (UN number / HS code / AWB prefix not in the dataset)The error message in the tool response names the field. Verify against the schema at /api-docs or call the corresponding playground endpoint directly to confirm the input shape.
Want to verify the surface from inside an agentNo CLI access during a conversationAsk the agent to fetch /api/mcp/health. The endpoint is public, returns the server version + registered tool count + transport URLs in a single JSON, and is rate-limit exempt so the diagnostic always works.
What AI agents can do
Calculate loading metres for 20 Euro pallets on an artic trailer
Look up UN 1203 and check if 200 litres qualifies for ADR exemption
What's the chargeable weight for 2 boxes 120×80×100cm at 500kg?
Find the airline with AWB prefix 176
How many boxes 40×30×25cm fit on a Euro pallet?

Get Started in 2 Minutes

// FreightUtils API — JavaScript example
// Calculate loading metres for 10 Euro pallets

const response = await fetch(
  'https://www.freightutils.com/api/ldm?pallet=euro&qty=10'
);
const data = await response.json();

console.log(`LDM: ${data.ldm}`);
console.log(`Utilisation: ${data.utilisation_percent}%`);
console.log(`Fits: ${data.fits}`);

All endpoints work the same way. No auth, no signup. Full reference below ↓

POST/api/shipment/summaryShipment Summary (Composite)Try it →
Flagship Endpoint

Composite endpoint that chains CBM, chargeable weight, LDM, ADR compliance, and UK duty/VAT estimation into a single call. Accepts a unified Shipment object and returns comprehensive results based on transport mode.

Mode Parameter

ModeCalculations Included
roadCBM, LDM, pallet spaces, trailer utilisation, road chargeable weight (1 LDM = 1,750 kg), vehicle suggestion
airCBM, volumetric weight (1 CBM = 167 kg), air chargeable weight
seaCBM, revenue tonnes (W/M at 1 CBM = 1,000 kg), container suggestion
multimodalAll of the above — road, air, and sea calculations combined

Example Request

Mixed 3-item road shipment with a DG item and HS code:

curl -X POST "https://www.freightutils.com/api/shipment/summary" \ -H "Content-Type: application/json" \ -d '{ "mode": "road", "origin": { "country": "DE", "locode": "DEHAM" }, "destination": { "country": "GB", "locode": "GBFXT" }, "incoterm": "CIF", "freight_cost": 850, "insurance_cost": 120, "items": [ { "description": "Machine parts on Euro pallets", "length": 120, "width": 80, "height": 110, "weight": 480, "quantity": 6, "stackable": false, "pallet_type": "euro", "hsCode": "847989", "customs_value": 12000 }, { "description": "Cleaning solvent (DG)", "length": 60, "width": 40, "height": 50, "weight": 25, "quantity": 4, "unNumber": "1993" }, { "description": "Spare filters", "length": 40, "width": 30, "height": 20, "weight": 8, "quantity": 10, "stackable": true } ] }'

Example Response

{ "mode": "road", "item_count": 3, "totals": { "pieces": 20, "grossWeight": 3060, "volumeCBM": 7.28, "chargeableWeight": 3060, "billing_basis": "weight" }, "modeSpecific": { "loadingMetres": 4.0, "pallet_spaces": 10, "trailerUtilisation": 29.41, "suggested_vehicle": "13.6m Artic Trailer", "chargeable_weight_road": 7000 }, "compliance": { "hasDangerousGoods": true, "adrFlags": { "unNumbers": ["1993"], "totalPoints": 300, "exemptionApplicable": true } }, "customs": { "hsCodesPresent": true, "canEstimateUkDuty": true, "dutyEstimate": { "cif_value": 12970, "duty_rate": "1.7%", "duty_amount": 220.49, "vat_rate": "20%", "vat_amount": 2638.1, "totalTaxes": 2858.59 } }, "warnings": [], "disclaimer": "Estimates only — verify with carrier and customs broker", "dataVersion": { "adr": "UNECE ADR 2025", "hs": "WCO HS 2022", "duty": "GOV.UK Trade Tariff API" } }

Pro-tier endpoint. Free access: 25 requests/day anonymous, 100/day with a free API key. Subscribe for higher limits.

GET/api/ldmLoading Metres CalculatorTry it →

Calculate the loading metres (LDM) required for a consignment on a UK/EU road freight trailer.

Parameters

ParameterTypeRequiredDescriptionDefault
lengthnumberYes*Pallet length in millimetres
widthnumberYes*Pallet width in millimetres
palletstringNo*Preset: euro, uk, half, quarter. Replaces length/width.
qtyintegerNoNumber of pallets1
stackablebooleanNoWhether pallets can be stackedfalse
stack2 or 3NoMax stack height (used when stackable=true)2
weightnumberNoWeight per pallet in kgnull
vehiclestringNoartic, rigid10, rigid75, luton, us53 (53ft US/Canada), us48 (48ft US), customartic
vehicle_lengthnumberNoCustom vehicle length in metres (required when vehicle=custom)

* Either pallet (preset ID) or both length and width must be provided.

Example Requests

12 Euro pallets on an artic:

GET /api/ldm?pallet=euro&qty=12&vehicle=artic

Custom dimensions, stackable, with weight check:

GET /api/ldm?length=1200&width=1000&qty=5&stackable=true&stack=2&weight=300&vehicle=rigid10

cURL example:

curl "https://www.freightutils.com/api/ldm?pallet=euro&qty=12&vehicle=artic"

US 53ft trailer:

curl "https://www.freightutils.com/api/ldm?pallet=euro&qty=20&vehicle=us53"

Response

{ "ldm": 4.8, "vehicle": { "name": "13.6m Artic Trailer", "length_m": 13.6, "max_payload_kg": 24000 }, "utilisation_percent": 35.29, "pallet_spaces": { "used": 12, "available": 33 }, "total_weight_kg": null, "fits": true, "warnings": [], "meta": { "inputs": { "length_mm": 1200, "width_mm": 800, "qty": 12, "stackable": false, "stack_factor": 2, "weight_per_pallet_kg": null, "vehicle": "artic" } } }
GET/api/cbmCubic Metres CalculatorTry it →

Calculate the cubic metre (CBM) volume of a shipment. Returns total CBM plus equivalents in cubic feet, litres, and cubic inches.

Parameters

ParameterTypeRequiredDescriptionDefault
lnumberYesLength of one piece in centimetres
wnumberYesWidth of one piece in centimetres
hnumberYesHeight of one piece in centimetres
pcsintegerNoNumber of identical pieces1

Example Request

5 boxes, 120×80×100 cm each:

curl "https://www.freightutils.com/api/cbm?l=120&w=80&h=100&pcs=5"
{ "cbm_per_piece": 0.96, "total_cbm": 4.8, "total_volume_m3": 4.8, "cubic_feet": 169.5106, "litres": 4800, "cubic_inches": 292913.8, "pieces": 5, "meta": { "inputs": { "length_cm": 120, "width_cm": 80, "height_cm": 100, "pieces": 5 } } }
GET/api/emissionsFreight Emissions (ISO 14083 / GLEC)Try it →

Estimate freight transport CO2e using the ISO 14083 / GLEC distance-based method: emissions = mass × distance × an open emission-intensity factor (kgCO2e/tonne-km). Provide actual gross mass, not chargeable/volumetric weight (a common air-freight mistake — see mass_basis). Returns well-to-wheel and tank-to-wheel emissions, the exact factor used, and a _source citing both the method and the specific open factor (DEFRA / EPA / ADEME). Each result also carries empty_running (the fleet-average factor already includes average empty running — don't double-count an empty return), representativeness (sea/air = low, high real-world variance), a human-readable summary, and _source.factor.last_verified. You provide the distance — this endpoint does not route. Best-effort estimate, not a verified carbon report; an unknown mode/sub_mode/region returns available:false with the covered options.

Parameters

ParameterTypeRequiredDescriptionDefault
massnumberYesShipment mass (in mass_unit)
mass_unitkg | tonnesNoUnit for masskg
distance_kmnumberYesTransport distance in km (caller-provided; not routed)
modeenumYesroad | rail | sea | air | inland_waterway
sub_modestringNoVehicle class (e.g. articulated, container ship)representative
regionuk | us | frNoFactor source: uk=DEFRA, us=EPA, fr=ADEMEper-mode
basiswtw | ttwNoWell-to-wheel or tank-to-wheelwtw

Example Request

10 tonnes by road, 500 km, UK (DEFRA), well-to-wheel:

curl "https://www.freightutils.com/api/emissions?mass=10&mass_unit=tonnes&distance_km=500&mode=road&region=uk&basis=wtw"
{ "available": true, "tonne_km": 5000, "factor": { "authority": "UK DEFRA / DESNZ — Greenhouse gas reporting: conversion factors", "edition": "2026", "region": "uk", "unit": "kgCO2e/tonne-km", "wtw": 0.12715, "ttw": 0.10356 }, "emissions": { "wtw_kgco2e": 635.75, "ttw_kgco2e": 517.8, "primary_kgco2e": 635.75, "basis_used": "wtw" }, "mass_basis": "actual_gross_mass", "empty_running": "sector_average_included", "representativeness": "medium", "confidence": "medium — fleet-average factor representative for the mode", "summary": "635.75 kgCO2e WTW for 10 t × 500 km by road (UK DEFRA 2026 fleet-average factor). Uses ACTUAL GROSS MASS, not chargeable/volumetric weight. Fleet-average empty running is already included — do not add a separate empty-return leg.", "methodology": "ISO 14083: 2023 / GLEC Framework v3.2", "_source": { "type": "methodology", "standard": "ISO 14083: 2023 / GLEC Framework v3.2", "source_url": "https://www.freightutils.com/methodology", "computed_by": "freightutils.com", "factor": { "authority": "UK DEFRA / DESNZ — Greenhouse gas reporting: conversion factors", "edition": "2026", "value": 0.12715, "unit": "kgCO2e/tonne-km", "basis": "wtw", "last_verified": "2026-06-26", "licence": "Open Government Licence v3.0" } } }
GET/api/validateIdentifier Validator (ISO 6346 / AWB / IMO)Try it →

Parse an arbitrary string (e.g. a booking line or email) to find and validate every freight identifier in it — shipping container (ISO 6346), air waybill (IATA modulus-7) and IMO ship number — or validate a single identifier by type. Returns per identifier: type, normalised form, valid (pass/fail), expected vs actual check digit, details (container owner/category; AWB airline; IMO number) and a _source. Structural only — a valid check digit means well-formed, not that the entity exists.

Parameters

ParameterTypeRequiredDescriptionDefault
textstringNo*Arbitrary string to scan for container / AWB / IMO identifiers (parse mode)
valuestringNo*A single identifier to validate (typed mode); requires type
typecontainer | awb | imoNo*Identifier type for value

*Provide text (parse mode) OR value+type (typed mode).

Example Request

Parse a mixed string:

curl "https://www.freightutils.com/api/validate?text=Box%20CSQU3054383%20on%20IMO9074729"
{ "found": [ { "type": "container", "raw": "CSQU3054383", "normalised": "CSQU3054383", "valid": true, "check_digit": { "expected": 3, "actual": 3 }, "details": { "owner_prefix": "CSQ", "equipment_category": "U", "equipment_category_label": "Freight container", "serial": "305438" }, "_source": { "type": "methodology", "standard": "ISO 6346", "authority": "ISO", "computed_by": "freightutils.com" } }, { "type": "imo", "raw": "IMO9074729", "normalised": "IMO9074729", "valid": true, "check_digit": { "expected": 9, "actual": 9 }, "details": { "number": "9074729" }, "_source": { "type": "methodology", "standard": "IMO Ship Identification Number Scheme", "authority": "IMO", "computed_by": "freightutils.com" } } ], "disclaimer": "Structural validation only — a valid check digit means the identifier is well-formed, not that the container/shipment/vessel exists or is active." }
GET/api/ics2-checkICS2 Stop-Words Checker (EU goods descriptions)Try it →

Check a goods description against the official EU ICS2 stop-words list (unacceptable/vague terms for entry summary declarations). Returns the flagged terms — each with a note on whether it is the standalone description (automatic ENS rejection) or embedded (make the description more specific) — a clean boolean, a caveat, and a _source citing the EU list + legal basis. Reference only: not an ENS filing, not a compliance determination; the list is non-exhaustive and clean does not guarantee acceptance. No accepted/rejected verdict. The submitted description is not persisted or logged (response is no-store).

Parameters

ParameterTypeRequiredDescriptionDefault
descriptionstringYesThe goods description to check against the EU ICS2 stop-words list

Example Request

A vague standalone description:

curl "https://www.freightutils.com/api/ics2-check?description=general%20cargo"
{ "description": "general cargo", "flagged": [ { "term": "General cargo", "note": "Used as the entire goods description — a listed stop-word on its own is an automatic ENS rejection. Replace it with a specific product description..." } ], "clean": false, "caveat": "The EU ICS2 stop-words list is non-exhaustive ... a \"clean\" result does NOT mean the declaration will be accepted ...", "_source": { "type": "reference", "authority": "European Commission DG TAXUD — EU ICS2 (Advance Cargo Information System)", "legal_basis": "Commission Delegated Regulation (EU) 2015/2446, Annex B, data element 18 05 000 000 (Description of goods)", "list_in_force": "2026-05-04", "non_exhaustive": true, "retrieved_via": "freightutils.com" }, "disclaimer": "Reference check only. ... not an ENS filing, not a customs-compliance determination, and not legal advice ..." }
GET/api/airportsAirport Code Lookup (IATA / ICAO / name)Try it →

Look up an airport by IATA code (3 letters), ICAO code (4 chars), or free-text name / city search. Provide one of iata, icao or q. Returns the full record (both codes, name, type, municipality, region, country, coordinates, elevation); ambiguous name searches return ranked candidates. Optional type filter. Data: OurAirports (public domain), cross-checked vs OpenFlights + Wikidata. Reference only — not for navigation; verify current codes with IATA/ICAO.

Parameters

ParameterTypeRequiredDescriptionDefault
iatastringOne ofExact 3-letter IATA code (e.g. LHR)
icaostringOne ofExact 4-character ICAO code (e.g. EGLL)
qstringOne ofName / city / municipality search (min 2 chars)
typestringNoFilter: large_airport, medium_airport, small_airport, heliport, closed, seaplane_base

Example Request

curl "https://www.freightutils.com/api/airports?q=heathrow"
{ "count": 1, "results": [ { "ident": "EGLL", "iata_code": "LHR", "name": "London Heathrow Airport", "type": "large_airport", "municipality": "London", "region": "England", "country": "GB", "country_name": "United Kingdom", "latitude": 51.470748, "longitude": -0.459909, "elevation_ft": 83 } ], "disclaimer": "Airport reference data from OurAirports (public domain) ... not for navigation; verify current IATA / ICAO codes with the airport authority.", "_source": { "type": "reference", "authority": "OurAirports (community-maintained open data)", "dataset": "OurAirports 2026-06-24", "source_url": "https://ourairports.com/data/", "licence": "Public Domain (OurAirports — dedicated to the public domain)", "retrieved_via": "freightutils.com" } }
GET/api/nearest-airportNearest airports to a coordinateTry it →

Find the airports nearest to a caller-provided latitude/longitude, sorted by great-circle (haversine) distance with distance_km on each result. Coordinates are input only — never stored or logged. Optional radius_km, max_results (1–50, default 10) and type filter. Does NOT geocode place names or compute routes — pass coordinates you already hold.

Parameters

ParameterTypeRequiredDescriptionDefault
latnumberYesLatitude in decimal degrees (-90 to 90)
lonnumberYesLongitude in decimal degrees (-180 to 180)
radius_kmnumberNoMaximum distance in kilometres
max_resultsintegerNoResults to return (1–50)10
typestringNoFilter by airport type (e.g. large_airport)

Example Request

curl "https://www.freightutils.com/api/nearest-airport?lat=51.47&lon=-0.46&max_results=3&type=large_airport"
{ "count": 3, "results": [ { "ident": "EGLL", "iata_code": "LHR", "name": "London Heathrow Airport", "type": "large_airport", "country": "GB", "latitude": 51.470748, "longitude": -0.459909, "distance_km": 0.1 }, { "ident": "EGKK", "iata_code": "LGW", "name": "London Gatwick Airport", "type": "large_airport", "country": "GB", "latitude": 51.148102, "longitude": -0.190278, "distance_km": 40.6 }, { "ident": "EGGW", "iata_code": "LTN", "name": "London Luton Airport", "type": "large_airport", "country": "GB", "latitude": 51.874699, "longitude": -0.368333, "distance_km": 45.4 } ], "disclaimer": "Airport reference data from OurAirports (public domain) ... coordinates are the airport reference point, not for navigation.", "_source": { "type": "reference", "authority": "OurAirports (community-maintained open data)", "dataset": "OurAirports 2026-06-24", "licence": "Public Domain (OurAirports — dedicated to the public domain)", "retrieved_via": "freightutils.com" } }
GET/api/chargeable-weightAir Freight Chargeable WeightTry it →

Calculate air freight chargeable weight — whichever is higher between actual gross weight and volumetric (dimensional) weight. Supports custom volumetric factors for all carriers.

Parameters

ParameterTypeRequiredDescriptionDefault
lnumberYesLength of one piece in centimetres
wnumberYesWidth of one piece in centimetres
hnumberYesHeight of one piece in centimetres
gwnumberYesTotal gross weight of all pieces in kg
pcsintegerNoNumber of identical pieces1
factorintegerNoVolumetric divisor: 6000 (IATA standard), 5000 (express carriers)6000

Example Request

2 pieces, 120×80×100 cm, 500 kg total, IATA factor:

curl "https://www.freightutils.com/api/chargeable-weight?l=120&w=80&h=100&gw=500&pcs=2&factor=6000"
{ "chargeable_weight_kg": 500, "basis": "actual", "gross_weight_kg": 500, "volumetric_weight_kg": 320, "volumetric_weight_per_piece_kg": 160, "cbm": 1.92, "ratio": 3.84, "factor": 6000, "pieces": 2, "meta": { "inputs": { "length_cm": 120, "width_cm": 80, "height_cm": 100, "gross_weight_kg": 500, "pieces": 2, "factor": 6000 } } }
GET/api/palletPallet Box Fitting CalculatorTry it →

Calculate how many boxes fit on a pallet using a layer-based algorithm. Returns boxes per layer, number of layers, total boxes, orientation used, and volume/weight analysis. Optional weight constraint caps the result at the pallet's maximum payload.

Parameters

ParameterTypeRequiredDescriptionDefault
plnumberYesPallet length in centimetres
pwnumberYesPallet width in centimetres
pmhnumberYesMaximum total stack height in centimetres (floor to top of cargo)
blnumberYesBox length in centimetres
bwnumberYesBox width in centimetres
bhnumberYesBox height in centimetres
phnumberNoPallet board/deck height in cm — deducted from usable height15
bwtnumberNoWeight per box in kg — enables weight constraint calculation
mpwnumberNoMaximum pallet payload weight in kg — caps result if weight exceeded
rotatebooleanNoAllow 90° rotation of boxes for best fit. Pass false to disable.true

Example Request

curl "https://www.freightutils.com/api/pallet?pl=120&pw=80&pmh=220&bl=40&bw=30&bh=25&bwt=5&mpw=1500"
{ "boxes_per_layer": 8, "layers": 8, "total_boxes": 64, "orientation": "original", "boxes_per_row": 3, "boxes_per_col": 2, "usable_height_cm": 205, "utilisation_percent": 62.5, "total_box_volume_cbm": 0.192, "pallet_volume_cbm": 1.968, "wasted_space_cbm": 1.776, "weight_limited": false, "total_weight_kg": 320, "remaining_weight_capacity_kg": 1180, "meta": { "inputs": { "pallet_length_cm": 120, "pallet_width_cm": 80, "pallet_max_height_cm": 220, "pallet_height_cm": 15, "box_length_cm": 40, "box_width_cm": 30, "box_height_cm": 25, "box_weight_kg": 5, "max_payload_weight_kg": 1500, "allow_rotation": true } } }
GET/api/adrADR 2025 Dangerous Goods LookupTry it →

Look up ADR 2025 dangerous goods by UN number, search by substance name, or filter by hazard class. The dataset contains 2,939 entries from the ADR 2025 Dangerous Goods List (Table A). Responses are cached for 1 hour (s-maxage=3600).

Query Modes

ParameterTypeDescriptionMax results
unstringExact UN number lookup. Accepts 1203, UN1203, or 01203.1
searchstringCase-insensitive partial match on the proper shipping name. Min 2 characters. Also accepts q as an alias.50
classstringFilter by ADR hazard class (e.g. 3, 6.1, 1.1).100

Provide exactly one parameter per request. Omitting all parameters returns a 400 with usage hints.

Example Requests

Exact UN number lookup:

curl "https://www.freightutils.com/api/adr?un=1203"
{ "count": 1, "results": [ { "un_number": "1203", "proper_shipping_name": "MOTOR SPIRIT or GASOLINE or PETROL", "class": "3", "classification_code": "F1", "packing_group": "II", "labels": "3", "special_provisions": "243 534 664", "limited_quantity": "1 L", "excepted_quantity": "E2", "transport_category": "2", "tunnel_restriction_code": "(D/E)", "hazard_identification_number": "33", "variant_index": 0, "variant_count": 1 } ], "meta": { "source": "ADR 2025 (UNECE, ECE/TRANS/352); given legal effect by EU Directive 2008/68/EC (consolidated)", "edition": "ADR 2025", "entries": 2939 } }

Search by substance name:

curl "https://www.freightutils.com/api/adr?search=acetone"
{ "count": 3, "results": [ ... ] }

Filter by hazard class:

curl "https://www.freightutils.com/api/adr?class=3"
{ "count": 50, "results": [ ... ] }
GETPOST/api/adr-calculatorADR 1.1.3.6 Exemption CalculatorTry it →

Calculate whether the ADR 1.1.3.6 small load exemption applies to a dangerous goods consignment. Supports single-substance GET queries and multi-substance POST requests. Checks both total points threshold (1,000) and per-substance quantity limits per ADR 1.1.3.6.3.

GET — Single Substance

ParameterTypeRequiredDescription
unstringYesUN number (e.g. 1203)
qtynumberYesQuantity in kg or litres

Example — 200 litres of petrol:

curl "https://www.freightutils.com/api/adr-calculator?un=1203&qty=200"
{ "items": [ { "un_number": "1203", "proper_shipping_name": "MOTOR SPIRIT or GASOLINE or PETROL", "class": "3", "transport_category": "2", "quantity": 200, "multiplier": 3, "points": 600 } ], "total_points": 600, "threshold": 1000, "exempt": true, "has_category_zero": false, "has_quantity_exceedance": false, "warnings": [], "message": "1.1.3.6 exemption applies" }

POST — Multi-Substance Load

Request body:

POST /api/adr-calculator Content-Type: application/json { "items": [ { "un_number": "1203", "quantity": 200 }, { "un_number": "1090", "quantity": 50 } ] }

Response structure is identical to the GET endpoint, with multiple items in the array.

Multi-variant UN numbers: some UN numbers have more than one ADR Table A row (different packing groups / concentration bands with different transport categories — e.g. UN 1789 PG II vs PG III). Pass an optional packing_group(I/II/III, GET query or per item) or variant_index(from /api/adr) to pin one row. Without one, the response is HTTP 200 with human_review_required: true and a candidates[] list (no verdict) rather than a silently-guessed row.

Response Fields

FieldTypeDescription
packing_groupstring | nullResolved ADR packing group for the row (echoed for traceability)
variant_indexnumberResolved ADR Table A variant index for the row
transport_categorystringADR transport category (0–4)
multipliernumber | nullPoints multiplier for the category (null for cat 0)
pointsnumber | nullquantity × multiplier
total_pointsnumberSum of all substance points
exemptbooleantrue if total ≤ 1,000 AND no cat 0 AND no quantity exceedance
has_category_zerobooleantrue if any substance is transport category 0
has_quantity_exceedancebooleantrue if any substance exceeds its per-category max quantity
warningsstring[]Human-readable warning messages for limit violations
POST/api/adr/lq-checkADR Limited & Excepted Quantity CheckerTry it →

Check whether dangerous goods qualify for ADR Limited Quantity (Chapter 3.4) or Excepted Quantity (Chapter 3.5) concessions. Accepts up to 20 items per request and returns per-item pass/fail status against ADR Table A limits.

Request Body

FieldTypeRequiredDescription
modestringNolq (default) or eq
itemsarrayYes1–20 items to check
items[].un_numberstringYesUN number (e.g. 1203)
items[].quantitynumberYesQuantity per inner packaging
items[].unitstringNoml, L (default), g, or kg
items[].inner_packaging_qtynumberNoNumber of inner packagings per outer (EQ mode only)
items[].packing_groupstringNoI/II/III — disambiguates a UN number with more than one ADR Table A row (e.g. UN 1789). Ignored for single-row UN numbers.
items[].variant_indexnumberNoADR Table A variant index (from /api/adr) — pins one row when variants share a packing group (concentration bands).

A UN number that resolves to more than one ADR Table A row without a packing_group/variant_index returns HTTP 200 with human_review_required: true and a candidates[] list (no verdict) rather than checking a silently-guessed packing group.

Example — check LQ for 0.5 L of petrol:

curl -X POST https://www.freightutils.com/api/adr/lq-check \ -H "Content-Type: application/json" \ -d '{"mode":"lq","items":[{"un_number":"1203","quantity":0.5,"unit":"L"}]}'
{ "mode": "lq", "overall_status": "qualifies", "items": [ { "un_number": "1203", "substance": "MOTOR SPIRIT or GASOLINE or PETROL", "class": "3", "packing_group": "II", "lq_limit": "1 L", "lq_limit_value": 1, "lq_limit_unit": "L", "eq_code": "E2", "quantity_entered": 0.5, "unit_entered": "L", "status": "within_limit", "reason": "0.5 L is within the LQ limit of 1 L per inner packaging" } ], "summary": { "total_items": 1, "qualifying": 1, "exceeding": 0, "not_permitted": 0 }, "references": { "adr_chapter": "3.4", "table": "3.2 Column 7a" } }

Response Fields

FieldTypeDescription
modestringlq or eq
overall_statusstringqualifies, does_not_qualify, or partial
items[]arrayPer-item results with substance info, limits, and pass/fail
items[].statusstringwithin_limit, exceeds_limit, or not_permitted
summaryobjectCounts of qualifying, exceeding, and not-permitted items
referencesobjectADR chapter and table references
GET/api/airlinesAirline Codes & AWB Prefix LookupTry it →

Search airlines by name, IATA code, ICAO code, AWB prefix, or country. The dataset contains6,357 airlines including 391 cargo airlines with AWB prefixes.

Query Modes

ParameterTypeDescriptionMatch
qstringGeneral search — matches name, codes, prefix, country. Smart: 2–3 digits match prefix only, 2–3 letters match IATA/ICAO only, 4+ chars search all fields.Smart
iatastringIATA 2-letter code (e.g. EK)Exact
icaostringICAO 3-letter code (e.g. UAE)Exact
prefixstringAWB 3-digit prefix (e.g. 176)Exact
countrystringCountry name (e.g. Germany)Partial

Example Requests

AWB prefix lookup:

curl "https://www.freightutils.com/api/airlines?prefix=176"
{ "count": 1, "results": [ { "slug": "emirates", "airline_name": "Emirates", "iata_code": "EK", "icao_code": "UAE", "awb_prefix": ["176"], "callsign": "EMIRATES", "country": "United Arab Emirates", "has_cargo": true, "aliases": ["Emirates SkyCargo"], "verified": true, "sources": [ { "url": "https://en.wikipedia.org/wiki/Emirates_(airline)", "accessed_at": "2026-05-13" }, { "url": "https://airhex.com/airlines/emirates/", "accessed_at": "2026-05-13" }, { "url": "https://airlinecodes.info/EK", "accessed_at": "2026-05-13" }, { "url": "https://www.skycargo.com/", "accessed_at": "2026-05-13" } ], "audited_at": "2026-05-13", "decision_rationale": "Rule 1 (rounding noise / most-published value). Anchor IATA=\"EK\", ICAO=\"UAE\", AWB prefix=[\"176\"]. All 4 cited sources (Wikipedia, airhex, airlinecodes.info, carrier's own cargo page) concur on these values. Record verified as part of the airline-data-integrity-A LHR-weighted anchor set." } ], "meta": { "source": "IATA / ICAO airline code registries", "airlines": 6357, "last_verified": "2026-05-13" }, "_source": { "type": "reference", "authority": "IATA / ICAO airline code registries", "provenance_status": "pending-verification" } }

IATA code lookup:

curl "https://www.freightutils.com/api/airlines?iata=EK"

Name search:

curl "https://www.freightutils.com/api/airlines?q=emirates"

Response Fields

FieldTypeDescription
slugstringURL-friendly identifier
airline_namestringOfficial airline name
iata_codestring | null2-character IATA designator
icao_codestring | null3-character ICAO designator
awb_prefixstring[] | null3-digit AWB prefix(es) — array, some airlines have multiple
callsignstring | nullRadio callsign for ATC communication
countrystring | nullCountry of registration
has_cargobooleantrue if airline has AWB prefix(es)
aliasesstring[] | nullAlternative names (e.g. cargo division name)
verifiedbooleantrue if prefix confirmed from multiple independent sources
sourcesobject[]Audited records only — the independent source URLs (with access dates) behind the record
audited_atstringAudited records only — date of the multi-source audit
decision_rationalestringAudited records only — why the published values were accepted

Responses also carry a top-level _source citability envelope and a meta block whose airlines count is derived from the dataset at build time — never hand-typed.

GET/api/incotermsINCOTERMS 2020 LookupTry it →

Look up INCOTERMS 2020 trade terms. Returns all 11 terms by default, or filter by code or transport category. Each term includes seller/buyer responsibilities, risk and cost transfer points, insurance obligations, and practical guidance.

Parameters

ParameterTypeDescription
codestringINCOTERM code (e.g. FOB, CIF, DDP)
categorystringFilter by transport mode: any_mode or sea_only

Omit all parameters to return all 11 INCOTERMS 2020 terms.

Example Requests

Single term lookup:

curl "https://www.freightutils.com/api/incoterms?code=FOB"
{ "code": "FOB", "name": "Free on Board", "slug": "fob-free-on-board", "category": "sea_only", "summary": "Seller delivers goods on board the vessel at port of shipment. One of the most commonly used terms.", "seller_responsibility": "Deliver goods on board the vessel at named port. Export clearance. Loading costs.", "buyer_responsibility": "Main sea freight, insurance, import clearance, duties.", "risk_transfer": "When goods are on board the vessel at port of shipment.", "cost_transfer": "At port of shipment, once loaded on board.", "insurance": "No obligation on either party.", "export_clearance": "Seller.", "import_clearance": "Buyer.", "best_for": "Sea freight where buyer wants to arrange their own shipping and insurance. Very commonly used in international trade.", "watch_out": "Sea and inland waterway ONLY. Despite being widely used, FOB is technically incorrect for containerised cargo..." }

Filter by transport category:

curl "https://www.freightutils.com/api/incoterms?category=sea_only"

All terms:

curl "https://www.freightutils.com/api/incoterms"
GET/api/containersContainer Capacity ReferenceTry it →

Shipping container specifications — internal/external dimensions, weights, door openings, and pallet capacity for all 10 standard ISO container types. Optionally calculate how many items fit in a specific container.

Query Modes

ParameterTypeRequiredDescription
typestringNoContainer slug (e.g. 20ft-standard, 40ft-high-cube). Omit to list all.
lnumberNoItem length in cm (requires type + w + h)
wnumberNoItem width in cm
hnumberNoItem height in cm
wtnumberNoItem weight in kg
qtyintegerNoNumber of items

Example Requests

List all containers:

curl "https://www.freightutils.com/api/containers"

Single container specs:

curl "https://www.freightutils.com/api/containers?type=40ft-high-cube"

Loading calculation — how many 60×40×40cm boxes fit in a 40ft HC:

curl "https://www.freightutils.com/api/containers?type=40ft-high-cube&l=60&w=40&h=40&wt=15&qty=500"
{ "container": { "name": "40ft High Cube", "slug": "40ft-high-cube", ... }, "loading": { "fits_lengthwise": 20, "fits_widthwise": 5, "fits_height": 6, "max_items": 600, "requested_qty": 500, "fits": true, "total_weight_kg": 7500, "within_payload": true, "utilisation_percent": 63.2 } }
GET/api/convertUnit ConverterTry it →

Convert between freight-relevant units — weights, volumes, lengths, and freight-specific conversions (CBM to chargeable weight, CBM to freight tonnes).

Parameters

ParameterTypeRequiredDescription
valuenumberYesThe number to convert
fromstringYesSource unit code
tostringYesTarget unit code

Supported Unit Codes

GroupCodes
Weightkg, lbs, oz, tonnes, short_tons, long_tons
Volumecbm, cuft, cuin, litres, gal_us, gal_uk
Lengthcm, inches, m, feet, mm
Freightchargeable_kg (target only, from=cbm), freight_tonnes (target only, from=cbm)

Example Requests

Standard conversion:

curl "https://www.freightutils.com/api/convert?value=100&from=kg&to=lbs"
{ "input": { "value": 100, "unit": "kg", "name": "Kilograms" }, "result": { "value": 220.462442, "unit": "lbs", "name": "Pounds" }, "formula": "Kilograms × 2.204624 = Pounds" }

CBM to chargeable weight (IATA 6000 divisor):

curl "https://www.freightutils.com/api/convert?value=10&from=cbm&to=chargeable_kg"
{ "input": { "value": 10, "unit": "cbm", "name": "Cubic Metres" }, "result": { "value": 1666.7, "unit": "chargeable_kg", "name": "Chargeable Weight (kg)" }, "formula": "Cubic Metres × 166.67 = Chargeable Weight (kg)", "note": "IATA volumetric weight: 1 CBM = 166.67 kg (divisor 6000)..." }

CBM to freight tonnes (W/M rule):

curl "https://www.freightutils.com/api/convert?value=5&from=cbm&to=freight_tonnes"
GET/api/hsHS Code LookupTry it →

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 all 6,937 codes across 21 sections and 97 chapters.

Query Modes

ParameterTypeDescriptionMax results
qstringCase-insensitive search on descriptions and codes. Min 2 characters.50
codestringExact HS code lookup (2, 4, or 6 digit). Returns full details with ancestor chain and children.1
sectionstringBrowse by section (Roman numeral, e.g. II). Returns all chapters in that section.All

Provide exactly one parameter per request. Omitting all parameters returns a 400 with usage hints.

Example Requests

Search by description:

curl "https://www.freightutils.com/api/hs?q=coffee"
{ "query": "coffee", "results": [ { "hscode": "0901", "description": "Coffee, whether or not roasted...", "level": 4, "section": "II", "parent": "09" } ], "count": 12 }

Code lookup with ancestors:

curl "https://www.freightutils.com/api/hs?code=090111"
{ "hscode": "090111", "description": "Coffee; not roasted, not decaffeinated", "level": 6, "section": "II", "parent": "0901", "ancestors": [ { "hscode": "09", "description": "Coffee, tea, mate and spices", "level": 2 }, { "hscode": "0901", "description": "Coffee, whether or not roasted...", "level": 4 } ], "children": [], "sectionName": "Vegetable products" }

Browse section:

curl "https://www.freightutils.com/api/hs?section=II"
POST/api/consignmentMulti-Item Consignment CalculatorTry it →

Calculate total CBM, loading metres (LDM), volumetric and mode-specific chargeable weight across a multi-item mixed consignment — per-line and grand totals, plus objective advisory flags (implausible density, mode/option mismatch, dangerous-goods presence by UN number against the ADR 2025 reference, and ISO 6346 container / IATA AWB check-digit validity). Supports sea, air, and road modes. Canonical request/response schema: consignment.v1.json.

Best-effort deterministic calculation and reference data only. Verify all inputs. Not regulatory, customs, or dangerous-goods compliance advice — you remain responsible for classification, documentation and carrier acceptance.

Request Body (JSON)

FieldTypeRequiredDescription
modestringNoroad (default), air, or sea
linesarrayYes*1–50 canonical line objects (see below). Preferred.
itemsarrayYes*Legacy flat alias (dimensions in cm, weight in kg). *Provide lines or items.
optionsobjectNoair_volumetric_divisor (default 6000), container_number, awb_number

Canonical Line Object (lines[])

FieldTypeRequiredDescription
quantityintegerYesNumber of identical pieces
dimsobjectYes{ l, w, h, unit } — unit one of mm, cm, m, in
weightobjectYes{ value, unit } — unit one of kg, g, t, lb
stackablebooleanNoStack two-high (halves loading-metre footprint)
hs_codestringNoHS commodity code (6–10 digits)
un_numberstringNoUN number — triggers the dangerous-goods reference flag
descriptionstringNoItem label

Example Request

curl -X POST "https://www.freightutils.com/api/consignment" \ -H "Content-Type: application/json" \ -d '{ "mode": "air", "lines": [ { "quantity": 4, "dims": { "l": 120, "w": 80, "h": 100, "unit": "cm" }, "weight": { "value": 300, "unit": "kg" } }, { "quantity": 10, "dims": { "l": 60, "w": 40, "h": 50, "unit": "cm" }, "weight": { "value": 15, "unit": "kg" } } ]}'
{ "schema_version": "consignment.v1", "mode": "air", "air_volumetric_divisor": 6000, "per_line": [ /* cbm, gross_weight_kg, volumetric_weight_kg, ldm, chargeable_weight_kg, ... per line */ ], "totals": { "cbm": 5.04, "gross_weight_kg": 1350, "volumetric_weight_kg": 840, "chargeable_weight_kg": 1350, "billing_basis": "weight", "line_count": 2, "piece_count": 14 }, "flags": [], "disclaimer": "Best-effort deterministic calculation and reference data only. ..." }
POST/api/dutyUK Import Duty & VAT EstimatorTry it →

Estimate UK import duty and VAT for a commodity code using live GOV.UK Trade Tariff data. Accepts customs value, origin country, freight/insurance costs, and INCOTERM for CIF adjustment.

Request Body (JSON)

FieldTypeRequiredDescription
commodity_codestringYesHS/tariff code (min 6 digits)
origin_countrystringYesISO 2-letter country code (e.g. CN, DE)
customs_valuenumberYesGoods value in GBP
freight_costnumberNoFreight cost in GBP (added to CIF value)
insurance_costnumberNoInsurance cost in GBP (added to CIF value)
incotermstringNoINCOTERM (e.g. FOB, CIF, EXW)

Example Request

curl -X POST "https://www.freightutils.com/api/duty" \ -H "Content-Type: application/json" \ -d '{ "commodity_code": "847989", "origin_country": "CN", "customs_value": 10000, "freight_cost": 500, "insurance_cost": 50, "incoterm": "FOB" }'
{ "commodity_code": "847989", "origin_country": "CN", "cif_value": 10550, "duty_rate": "1.7%", "duty_amount": 179.35, "vat_rate": "20%", "vat_amount": 2145.87, "totalTaxes": 2325.22, "preferentialRate": false, "meta": { "source": "GOV.UK Trade Tariff API", "licence": "Open Government Licence v3" } }
GET/api/unlocodeUN/LOCODE LookupTry it →

Search and look up UN/LOCODE transport locations — 116,129+ seaports, airports, rail terminals, inland depots, and border crossings worldwide. Responses are cached for 24 hours.

Query Modes

ParameterTypeDescription
codestringExact UN/LOCODE lookup (e.g. GBLHR, NLRTM)
qstringSearch by name (e.g. rotterdam, heathrow)
countrystringFilter by country code (e.g. GB, NL)
functionstringFilter by function: port, airport, rail, road, icd, border
limitintegerMax results (1–100, default: 20)

Example Requests

Search by name:

curl "https://www.freightutils.com/api/unlocode?q=rotterdam"
{ "query": "rotterdam", "count": 3, "results": [ { "locode": "NLRTM", "name": "Rotterdam", "country": "NL", "subdivision": "ZH", "functions": ["port", "rail", "road"], "coordinates": { "lat": 51.92, "lon": 4.48 } } ], "meta": { "source": "UNECE UN/LOCODE 2024-2 (PDDL)", "total_entries": 116129 } }

Exact code lookup:

curl "https://www.freightutils.com/api/unlocode?code=GBLHR"

Filter by country and function:

curl "https://www.freightutils.com/api/unlocode?country=GB&function=port&limit=10"
GET/api/uldAir Freight ULD TypesTry it →

Look up air freight Unit Load Device (ULD) specifications. 16 types including LD3 (AKE), PMC main deck pallet, temperature-controlled containers, and more. Returns dimensions, weights, volume, and aircraft compatibility.

Parameters

ParameterTypeDescription
typestringULD code or slug (e.g. AKE, PMC). Omit to list all.
categorystringFilter: container, pallet, or special
deckstringFilter by deck: lower or main

Example Requests

Single ULD lookup:

curl "https://www.freightutils.com/api/uld?type=AKE"

Filter by category:

curl "https://www.freightutils.com/api/uld?category=pallet"

All ULD types:

curl "https://www.freightutils.com/api/uld"
GET/api/vehiclesVehicle & Trailer TypesTry it →

Look up road freight vehicle and trailer specifications. 17 types covering articulated trailers, rigid trucks, and vans. Returns internal dimensions, payload limits, pallet capacity, and features.

Parameters

ParameterTypeDescription
slugstringVehicle slug (e.g. standard-curtainsider). Omit to list all.
categorystringFilter: articulated, rigid, or van
regionstringFilter: EU or US

Example Requests

Single vehicle lookup:

curl "https://www.freightutils.com/api/vehicles?slug=standard-curtainsider"

Filter by category:

curl "https://www.freightutils.com/api/vehicles?category=articulated"

Filter by region:

curl "https://www.freightutils.com/api/vehicles?region=EU"

HTTP Status Codes

CodeMeaning
200Success — calculation result returned as JSON
400Bad Request — missing or invalid parameters. Check the error message in the response.
404Not Found — no results for the given query (airlines and ADR endpoints)
405Method Not Allowed — only GET (or POST for /api/adr-calculator, /api/adr/lq-check, /api/shipment/summary) is supported
500Internal Server Error — unexpected error, please report via GitHub

Field Naming

All endpoints use snake_case field names in responses (e.g. internal_length_cm, max_gross_kg). POST request bodies on /api/duty and /api/consignment accept either casing for backwards compatibility — snake_case is the documented form.

Rate Limiting

The API is free to use. Anonymous rate limit: 25 requests per day per IP. Free API key: 100 requests per day. Pro: 50,000 requests per month.

Error Responses

All endpoints return standard HTTP error codes with a descriptive JSON error message:

400Bad RequestMissing or invalid parameters
{"error": "Missing required parameter: l (length in cm)"}
404Not FoundResource does not exist
{"error": "No ADR entry found for UN number 9999"}
500Server ErrorUnexpected error
{"error": "Internal server error"}

Response Envelope (agent-facing, opt-in)

Every tool can also return a v1 response envelope — a thin, agent-facing wrapper that keeps the answer under result and adds the four things an autonomous agent needs to use and cite it safely: how much to trust it (confidence), where it came from(_source), a ready-to-quote line (citation), and — when relevant —what was corrected (normalized_input), advisories (warnings),blocking errors with a recovery hint (blocking_errors), and time-boxed validity(validity). It is fully described by the JSON Schema at /schemas/response-envelope.v1.json.

The envelope is opt-in. The flat legacy body (the answer at the top level) stays the default and is byte-unchanged, so existing REST consumers and the freightutils-mcp npm package are unaffected. Request the envelope explicitly with either ?envelope=1 or an Accept header:

curl "https://www.freightutils.com/api/airports?q=heathrow&envelope=1"
curl -H "Accept: application/vnd.freightutils.v1+json" "https://www.freightutils.com/api/airports?q=heathrow"

On the hosted MCP server (/api/mcp) the envelope is returned as structuredContent (validating against each tool’s output schema), while content[0].text keeps the flat legacy JSON so text-parsing clients are unaffected. envelope_version ("1") lets any consumer detect the shape.

Confidence model

confidence.level is high / medium / low, and confidence.basissays why. A numeric score (0–1) is present only when the basis ismatch_quality.

basisMeaningTypical level
deterministicPure computation (CBM, chargeable weight, LDM, conversions).high
provenanceReference-data lookup with an audit status.high (verified) / medium (provenance pending)
match_qualityFuzzy / ranked search — carries a score.from the score
freshnessComputed over live, time-sensitive data (e.g. UK duty rates).high

Warnings & blocking errors

warnings are non-blocking advisories; blocking_errors mean no answer was produced (ok: false) and each carries a recovery hint (an action, and often atool + params to retry with). Both use a stable UPPER_SNAKE code taxonomy; the keys are omitted entirely when empty (never []).

codeMeaning
RATE_LIMITEDQuota exceeded (maps to the 429 + Retry-After).
MISSING_INPUTA required parameter was absent.
INVALID_INPUTA parameter was present but malformed.
NOT_FOUNDAn exact lookup (code / id) matched nothing.
NO_MATCHA search / ranked query returned nothing.
FUZZY_BEST_MATCHAdvisory: the top result is a best-effort fuzzy match, not an exact hit.
PROVENANCE_PENDINGAdvisory: this dataset’s provenance is pending independent verification.
METHOD_NOT_ALLOWEDWrong HTTP method for the endpoint (e.g. GET on a POST-only tool).

Provenance, citation & validity

_source is the canonical provenance (name, checked date orrequest-time, and provenance_status: verified / pending-verification /computed / live). citation.text is a ready-to-quote line, with an optionalqualifier hedge for fuzzy or not-legal-advice answers. validity appears only on time-boxed tools (regulatory editions, live rates) and carries effective_from / effective_to /as_of.

Fuzzy best-match (GET /api/airports?q=heathrow&envelope=1):

{ "envelope_version": "1", "ok": true, "result": { "count": 2, "results": [ { "name": "Heathrow Airport", "iata_code": "LHR" } ] }, "confidence": { "level": "medium", "basis": "match_quality", "score": 0.66 }, "normalized_input": { "query": "heathrow", "normalized_query": "heathrow", "matched_field": "name" }, "warnings": [ { "code": "FUZZY_BEST_MATCH", "message": "Best of 2 ranked match(es) — matched on name." } ], "_source": { "name": "OurAirports (public domain)", "checked": "2026-06-24", "provenance_status": "verified", "source_url": "https://ourairports.com/data/" }, "citation": { "text": "Heathrow Airport (LHR) — OurAirports.", "qualifier": "Fuzzy best match for \"heathrow\"; verify the code." } }

Blocking error with a recovery hint (GET /api/adr?un=9999&envelope=1 → 404):

{ "envelope_version": "1", "ok": false, "result": {}, "confidence": { "level": "high", "basis": "provenance" }, "blocking_errors": [ { "code": "NOT_FOUND", "message": "UN number 9999 not found in the ADR 2025 dataset.", "recovery": { "action": "Check the UN number and retry, or search by name.", "tool": "adr_lookup", "params": { "un": "1203" } } } ], "_source": { "name": "UNECE (ADR 2025)", "checked": "2026-05-13", "provenance_status": "verified" }, "citation": { "text": "UN 9999 is not listed in UNECE ADR 2025." } }

Platform Commitments

Five pages that spell out what you can rely on:

Changelog
Every release, with an RSS feed.
Status
Current health plus 24h and 7d uptime.
Roadmap
Shipped, in progress, and what’s next.
Versioning Policy
Breaking-change contract and semver.
Deprecation Policy
3-month minimum notice with migration guides.

Source Code & Issue Reporting

The FreightUtils MCP server is open source. Report bugs, request features, or contribute on GitHub: github.com/SoapyRED/freightutils-mcp. For data corrections or API support, email contact@freightutils.com.