Skip to content

Extracting Freight and Handling Charges Separately From Goods on an Invoice

9 min read · updated August 11, 2026

A freight line looks exactly like a goods line: a description, a quantity of one, a unit price, a line total. Nothing about its appearance distinguishes it, and three downstream systems care very much about the difference.

Why freight cannot live in the goods lines

If freight is coded as goods, four things go wrong quietly.

  • Inventory valuation. Landed cost is goods plus freight plus duty, and it is allocated across units. A freight amount sitting in a goods line with a quantity of one gets valued as a single unit of an unknown product, so unit costs are wrong for everything else on the order.
  • Tax. Whether delivery charges are taxable varies by US state and, in some regimes, by whether the charge is separately stated on the invoice. Merging freight into goods removes the separately-stated condition and changes the answer.
  • Customs value. For imports, whether freight forms part of the declared value depends on the delivery term. A pipeline that cannot see freight as freight cannot compute either answer.
  • Three-way matching. A purchase order lists goods. A freight line will never match a PO line, so it produces a permanent unmatched quantity that a human resolves manually on every single delivery.

In EN 16931 terms, freight is a charge rather than a goods line: BT-141 at line level or the document-level charge total, BT-108. Charges add to the total where allowances subtract, and both sit outside the sum of line nets, BT-106.

Where it hides, and what it is called

There is no standard wording, so a keyword list is a starting point rather than a solution. Terms that appear as separate charges include freight, carriage, delivery, shipping, postage, handling, packing, crating, pallet charge, fuel surcharge, residential delivery surcharge, liftgate, demurrage, customs clearance fee, and insurance. Several of those are freight-adjacent but not freight, and some businesses need them separated further.

Two harder cases defeat keyword matching entirely. First, a supplier may charge freight as a product code from its own catalogue — “9999-DEL” with a description that is a product name. Second, under a delivered term the freight may be genuinely absent because it is included in the unit prices, and the invoice will not say so. Neither is recoverable from the line text alone; the first is solved by a per-supplier mapping in your own item master, the second by reading the delivery term.

So classify rather than keyword-match, and keep the evidence:

"lines": [
  { "line_no": 1, "type": "goods",   "description": "Bearing housing, 40mm",
    "quantity": 120, "unit_price_minor": 1450, "line_net_minor": 174000 },
  { "line_no": 2, "type": "charge",  "charge_kind": "freight",
    "description": "Carriage - pallet x2", "line_net_minor": 8500,
    "classification_evidence": "no product code; qty 1; appears after subtotal rule" }
],
"charges_total_minor": 8500,
"lines_net_total_minor": 174000

The check that finds a miscoded freight line

The invoice usually prints a goods subtotal before it prints freight. That gives you a second, independent statement of the same quantity, so the difference between the two is diagnostic — a cross-field amount validation rule with a very specific payoff. Take an invoice with the following printed figures:

Line 1  Bearing housing 40mm   120 @ 14.50   1,740.00
Line 2  Seal kit                40 @ 10.50     420.00
Line 3  Carriage                 1 @ 85.00      85.00
                       Goods subtotal        2,160.00
                       Carriage                 85.00
                       Net total             2,245.00
                       VAT 21%                 471.45
                       Total due             2,716.45

Now run two sums over the extraction. The sum of all lines classified as goods should equal the printed goods subtotal. If line 3 was classified as goods, that sum is 2,245.00 against a printed subtotal of 2,160.00 — a difference of exactly 85.00, which is exactly the amount of the line you misclassified. The check does not merely say something is wrong; it names the amount, and a single-line lookup for a line net equal to the discrepancy identifies the culprit outright.

The net total check still passes in both cases, which is why a totals-only reconciliation misses this entirely. 2,160.00 plus 85.00 and 2,245.00 plus 0.00 both reach 2,245.00. You need the intermediate subtotal to catch it, and that is an argument for extracting every printed subtotal rather than only the fields your schema requires.

A second check catches the reverse error. Freight is almost never quantity-priced: a charge line with a quantity above one and a unit price that multiplies cleanly is more likely to be goods. A goods line with a quantity of one, no product code and no unit of measure is more likely to be a charge. Neither is conclusive; both are useful priors to hand a reviewer.

The Incoterm decides whether it belongs here

Whether a supplier invoice should carry freight at all is not a formatting question. It is determined by the delivery term agreed on the purchase order. Under EXW or FCA the buyer arranges and pays carriage, so freight arrives on a separate carrier invoice and a freight line on the supplier invoice is an anomaly worth querying. Under CIF, CIP, DAP, DPU or DDP the seller bears carriage to the named place, so it is either a stated line or already inside the unit prices.

That makes the delivery term a validation input, not trivia: extract it from the PO, and treat “freight billed under EXW” as a flag. The eleven codes, the revision that governs them, and how to extract them are in extracting delivery terms from a purchase order.

Allocated, prepaid and credited freight

  • Allocated freight. Some suppliers spread carriage across the goods lines rather than stating it. The invoice then has no freight line and the unit prices do not match the PO prices. The tell is a small, consistent uplift on every line; the fix is a query to the supplier, not a parser.
  • Prepaid and add. The supplier paid the carrier and is passing the cost through, sometimes with the carrier’s own invoice attached as a second page. Extract it as a charge with the carrier named, and expect the amount to reconcile to the attachment rather than to any price list.
  • Credited freight. A goodwill reversal of a delivery charge is an allowance, not a negative charge, and putting it in the wrong bucket makes the total off by twice the amount — the sign problem described in extracting line-item discounts and rebates.
  • Fuel surcharges as a percentage. Printed as “18.5% fuel” against the carriage line, so its base is another charge rather than the goods. Store the base explicitly or the recomputation will never agree.