Skip to content

Extracting Line Items From a Freight Rate Confirmation

10 min read · updated August 11, 2026

A rate confirmation is not a small invoice. It is the agreement a broker and a carrier make before the freight moves, and roughly half the money on it is conditional — payable only if something happens during the load. An extraction that returns a list of charges and a total has thrown away the half that matters.

What a rate con is, and what its total means

The document is issued by a broker to a carrier, usually as a one or two page PDF, and it is signed and returned before dispatch. It sets out who is hauling what, from where to where, in what equipment, by when, and for how much. The carrier later issues an invoice against it, and a freight-audit process compares the two.

The total on the rate con is the agreed linehaul plus any charges already known at booking. It is a floor, not a prediction. If the driver waits four hours at the receiver, detention is owed and the invoice will legitimately exceed the rate con’s total. Any validation rule of the form “invoice total must equal rate confirmation total” will produce a permanent stream of false exceptions, and the people running the audit will start ignoring the queue. This is the single most useful thing to know about the document.

So the extraction output is two structures: the agreed charges, which foot to the stated total, and the entitlement rules, which do not have amounts yet. The second structure is what makes the invoice check possible later.

Parties and the identifiers that resolve them

There are at least four parties on the page and their names are the least reliable way to tell them apart. Carrier names are near- duplicates across the industry, DBA names differ from legal names, and the shipper on the rate con is often the broker’s customer rather than the physical origin.

  • Broker, with an MC number issued by the US Federal Motor Carrier Safety Administration.
  • Carrier, with its own MC number and a USDOT number. Both are printed on most rate cons; the USDOT number is the more durable identifier because MC numbers are being phased toward USDOT-only identification.
  • Shipper and consignee, each with an address, a contact and an appointment window.
  • Load number, PRO number and BOL number, which are three different identifiers assigned by three different parties for the same shipment. Store all three. Matching an invoice to a rate con on the wrong one of them is the commonest cause of an unmatched document, in the same way that matching a credit memo to its invoice fails on identifier choice rather than on extraction quality.

Extract identifiers as labelled strings with their issuing authority, never as a single reference_number. A DOT number is digits; an MC number is often printed as MC-000000 and sometimes as MC 000000 or bare digits, so normalise by stripping the prefix and keeping the numeral, and keep the raw form.

Accessorials are rules, not amounts

This is the section that defines the document. A typical accessorial block reads like this:

Linehaul                                  2,450.00
Fuel surcharge (included in linehaul)          0.00
--------------------------------------------------
TOTAL                                     2,450.00

Detention: 2 hours free at each stop, then $45/hr,
           max $360 per stop. Must be documented on
           the BOL and reported before departure.
Layover:   $250 per 24 hours, pre-approval required.
TONU:      $200 if cancelled after dispatch.
Lumper:    reimbursed at cost with receipt.
Driver assist / unload: not authorised.

Every line under the total is a conditional entitlement with up to five components: a trigger, a free allowance, a rate, a unit, and a cap. An extractor that produces [detention, 0.00] has technically read the page and produced nothing usable. The shape you want is nested rather than flat:

{
  "type": "detention",
  "free_allowance": { "value": 2, "unit": "hour", "per": "stop" },
  "rate": { "amount": 45.00, "currency": "USD", "unit": "hour" },
  "cap": { "amount": 360.00, "per": "stop" },
  "preconditions": [
    "documented on BOL",
    "reported before departure"
  ],
  "source_text": "Detention: 2 hours free at each stop, then $45/hr, max $360 per stop."
}

Keep source_text. The preconditions are the part a model will paraphrase, and a paraphrased precondition is the difference between a payable claim and a denied one. When the invoice arrives claiming four hours of detention, the audit needs the original sentence, not a summary of it.

Note the negatives too. “Driver assist: not authorised” and “No pallet exchange” are extractable rules with a rate of zero and an explicit prohibition, and dropping them because they carry no number means the audit has no basis to deny the charge. Model entitlement as a tri-state — permitted with a rate, permitted subject to approval, prohibited — rather than as presence or absence of an amount.

Stops, equipment and the fields that are free text

Stops are ordered and there can be more than two. A multi-stop load lists pickups and drops in sequence, each with an appointment window, a reference number and sometimes its own stop charge. The sequence is meaningful, so the schema is an ordered array with a stop_type of pickup or delivery, not a pair of origin and destination fields. Rate cons that lay stops out in two columns invite exactly the reading-order failure that layout-aware document parsing exists to solve.

Appointment windows are not timestamps. 04/14 0800-1500 is a window, in the local time of the facility, on a date with no year. FCFS means first come first served with no appointment at all. Store a start, an end, an is_appointment flag and the facility’s timezone if you can resolve it from the address; storing a single datetime forces a choice the document did not make.

Equipment type is free text with a temperature attached. You will see 53' Van, 53 dry, Reefer -10F, R/F continuous 34F, Flatbed w/ tarps. Two things need extracting separately: the trailer class, normalised to an enum, and the temperature requirement including whether it is continuous or cycle run. The temperature is a claim-critical field on refrigerated freight and it is buried in a string that looks decorative.

Where it breaks

Two rate cons for one load. Rates get amended and the broker reissues. Both PDFs have the same load number and different totals, and often the only distinguishing mark is a revision date in a footer or the word “REVISED” in a header. Extract every date on the page and treat the most recent document for a load number as authoritative, but keep the earlier one — the delta is frequently what a dispute is about.

The terms are on page two and nobody sent page two. Carrier requirements — insurance minimums, tracking consent, invoice submission deadlines, quick-pay discount terms — usually sit on a second page of dense small print. A one-page scan is not an incomplete-looking document; it looks fine. Record the page count and whether the terms block was found, so that its absence is a fact rather than a silence.

Currency and unit ambiguity on cross-border loads. A load moving into Canada may quote CAD without saying so, and weights may be in pounds or kilograms depending on the broker. Neither is reliably marked. Where the document does not state a currency, record the absence explicitly rather than defaulting, and let the reconciliation step apply a rule based on the broker.

The signature block is the acceptance. The carrier’s countersignature and date is what makes the rate con binding, and it is frequently missing on the copy that reaches accounting. Extract it as a nullable object and treat “present but undated” as a third state, for the same reasons set out for signatories on a signed PDF.