Accessorial Charges, Demurrage and Detention: Why Your AP System Can't Validate Them (And How to Fix It) | Peakflo Blog
Accessorial Charges, Demurrage and Detention: Why Your AP System Can't Validate Them (And How to Fix It)
Chirashree Dan
TL;DR: Accessorial charges such as fuel surcharge, demurrage, detention, waiting time and re-delivery have no purchase order line to match against, so every one becomes a manual AP exception. Flat dollar tolerances make it worse: a 300 dollar auto-pass rule waves through unauthorized charges while burying teams in warnings on legitimate ones. The fix is a charge-code taxonomy of 30 to 60 normalized codes, each mapped to the contract clause that authorizes it, with free-time clocks computed from operational event data and split lines consolidated before matching. Teams that implement it in 8 to 12 weeks typically move most accessorial lines to straight-through processing.
Ask a logistics finance team where their accounts payable time goes and the answer is rarely the base freight charge. That part is easy: it was ordered, it has a purchase order line, it has a rate card, and it matches. The time goes to everything else on the invoice.
Fuel surcharge. Demurrage. Detention. Waiting time. Re-delivery. Packing. Cargo insurance. Local transport. Handling. Storage. Customs clearance. Chassis usage. Congestion fee. These are accessorial charges, and on a typical forwarder invoice they often outnumber the base freight lines several times over.
They share one structural property that breaks conventional accounts payable automation: none of them exist on the purchase order. They cannot, because the events that triggered them had not happened when the PO was raised. Nobody orders three days of demurrage in advance.
So the matching engine behaves exactly as designed and still produces an unusable outcome. Every accessorial line is an unmatched line. Every unmatched line is an exception. The exception queue becomes the job.
What Are Accessorial Charges on a Logistics Invoice?
Accessorial charges are ancillary fees billed for services and events beyond the base transport move. Three characteristics drive the validation problem:
- They are triggered at execution, not at ordering. A container sat at the terminal five days. A driver waited ninety minutes at a dock. A delivery attempt failed and was repeated. None of this was foreseeable at booking.
- They are authorized by contract clauses, not purchase orders. The right to bill detention lives in the carrier service agreement, along with the rate, the free time and the escalation tiers. That document, not the PO, is the source of truth.
- They are described inconsistently. The same charge appears as “detention”, “equipment detention”, “truck waiting”, “standby time” and “driver waiting charge” across five carriers, and sometimes across five invoices from one carrier.
That third point is why teams who try to fix this with rules alone stall. You cannot write a rule against a charge you cannot reliably identify.
Why Can’t Your AP System Validate Accessorial Charges?
Three-way matching compares invoice line to PO line to goods receipt line. Remove the PO line and the structure loses its anchor.
Most ERPs respond by dumping the line into an exception queue with a generic reason code such as “no matching PO line” or “unplanned delivery cost”. A human then opens the carrier contract as a PDF, finds the clause, reads the free-time allowance, checks the transport system for when the container was actually returned, does the arithmetic, and approves or disputes. Five to fifteen minutes, on a line worth perhaps 180 dollars.
The economics are plainly wrong, which is why many teams quietly stop checking. Research on logistics cost, including work published by UNCTAD on transport and trade logistics and trade cost data from the World Bank, consistently identifies ancillary and terminal-related charges as a material and poorly controlled share of landed cost. When validation costs more than the charge, unauthorized billing becomes permanent.
Fixing it starts with a taxonomy. Each charge type needs a definition, a trigger, a governing clause and a validation method before automation can touch it.
| Charge code | What triggers it | Governing contract clause | How to validate it |
|---|---|---|---|
| Fuel surcharge | Base freight move, indexed to fuel price period | Fuel adjustment clause with index and percentage basis | Recompute as stated percentage of base freight only, using index for service date |
| Demurrage | Cargo or container held inside terminal past free time | Terminal free-time clause, days plus tiered daily rate | Chargeable days from gate-in and gate-out events, less free days, apply tier |
| Detention | Carrier equipment held outside terminal past free time | Equipment free-time and detention clause | Compute pickup to empty-return, less free days, apply daily rate |
| Waiting time | Driver idle at pickup or delivery beyond grace period | Waiting time clause, grace minutes plus hourly rate | Validate against arrival and departure timestamps, apply contract rounding |
| Re-delivery | Failed first delivery attempt requiring a repeat trip | Failed delivery clause, flat fee per attempt | Confirm a failed-attempt event exists and count attempts; reject if none |
| Packing and repacking | Cargo requires palletising, crating or repacking | Value-added services schedule, per unit or per job | Unit count against handling record, unit rate against schedule |
| Cargo insurance | Declared value cover requested for the shipment | Insurance clause, percentage of declared value | Recompute against declared value on the shipping document |
| Local transport or drayage | First or last mile leg outside the main haul | Local haulage rate card by lane or zone | Match origin and destination zone to rate card lane |
| Handling, lift-on lift-off | Container or cargo movement at terminal or depot | Terminal handling schedule, per move | Count moves against terminal record, apply per-move rate |
| Storage and warehousing | Cargo held beyond agreed period at depot or warehouse | Storage clause, free days plus rate per pallet or CBM per day | Chargeable days and volume from warehouse records |
| Customs clearance and documentation | Declaration filed, permit issued, document amended | Customs services schedule, per declaration or document | Count declarations and amendments against the customs record |
| Congestion or peak season surcharge | Port congestion or seasonal capacity event declared | Surcharge clause with effective date window | Confirm the service date falls inside the declared window |
Twelve rows is illustrative. Most logistics AP functions end up with 30 to 60 normalized codes.
Why Do Demurrage and Detention Get Confused, and Why Does It Matter?
These two are the highest-value accessorials and the most frequently mis-billed, and teams routinely lump them into one bucket.
The distinction is simple once stated. Demurrage is a clock on your cargo sitting in their terminal. Detention is a clock on their equipment sitting in your yard. Different clocks, different free-time allowances, different rate tiers, usually different clauses.
Treating them as one code means validating both against whichever free-time number you happened to configure, which produces confident, automated, wrong answers. That is worse than a manual exception.
| Dimension | Demurrage | Detention |
|---|---|---|
| What it charges for | Cargo or container remaining inside the terminal or port | Carrier equipment remaining in your possession |
| Who typically charges it | Terminal operator, port authority or shipping line | Shipping line, carrier or equipment owner |
| Clock starts | Discharge or gate-in at terminal | Equipment pickup or gate-out |
| Clock stops | Cargo gated out of terminal | Empty equipment returned to nominated depot |
| Free time basis | Terminal free days, often calendar days including weekends | Equipment free days, sometimes working days only |
| Rate behavior | Commonly tiered and escalating after the first days | Often flat per day, sometimes tiered on long holds |
| Typical dispute cause | Free-time start date disputed, or closure days counted as chargeable | Empty return timestamp disputed, or depot refusal not credited |
| Evidence needed to dispute | Terminal gate records and free-time clause | Interchange receipt or empty-return proof and equipment clause |
The last row is the operationally important one. A dispute you cannot evidence is a dispute you will lose, so the validation layer must capture the evidence at the moment it computes the variance, not three weeks later.
Why Do Flat Dollar Tolerances Fail on Accessorial Charges?
The instinctive fix is a tolerance rule: auto-approve anything under 300 dollars, review the rest. Easy to configure, feels proportionate, and wrong for this problem.
A flat threshold asks “is this charge big?” when the question that determines whether you owe it is “is this charge authorized?“. The two have no correlation. A 280 dollar detention charge on a container returned inside free time is entirely unauthorized. A 4,000 dollar demurrage charge on a container stuck behind a customs hold for nine days may be entirely contractual. No threshold value resolves this, because the variable being thresholded is not the variable that matters.
Tolerance rules are still the right mechanism for price and quantity variance on goods you actually ordered, and those design patterns are covered in our guide to invoice exception management and tolerance rules. Accessorials need a second evaluation axis on top, closer to the logic in multi-condition invoice validation rules, where the decision depends on several contract parameters at once.
| Aspect | Flat dollar tolerance | Contract-clause validation |
|---|---|---|
| Question it answers | Is the charge small enough to ignore? | Does a clause authorize this charge at this amount? |
| Data required | Invoice amount only | Charge code, clause parameters, operational event data |
| Unauthorized small charges | Auto-approved and paid, permanently | Auto-disputed with computed variance and evidence |
| Legitimate large charges | Routed to a human every time | Auto-approved when recomputation matches |
| Exception volume | High and constant | Falls as taxonomy and clause coverage improve |
| Audit trail quality | Approved under threshold policy | Clause reference, computed value, variance, evidence |
| Effect on carrier behavior | None; overbilling goes unchallenged | Disputes become systematic, so billing accuracy improves |
| Maintenance burden | Trivial to configure, impossible to improve | Higher setup, compounding accuracy returns |
The last row is the honest trade-off. Clause validation costs more to stand up, and it is the only approach that improves rather than staying flat, which is the same reasoning behind effective invoice overpayment prevention.
How Do Split Charge Lines Break Line-Level Matching?
One failure mode catches even teams with a good taxonomy.
A carrier agrees additional charges of 1,000 for a job. The invoice arrives showing packing 500 and freight 500. The header total is correct, but every individual line fails, because no single line equals the agreed 1,000 and the 500 packing line corresponds to no 500 packing agreement. Sometimes this is administrative habit; sometimes it is deliberate, because splitting a charge across two codes moves each piece under a tolerance threshold.
The fix is charge-group consolidation before matching:
FOR each shipment_reference ON the invoice:
Classify every line into a normalised charge_code
Assign each charge_code to a charge_family
base_freight | accessorial_agreed | accessorial_event_driven | duty_and_tax
For family = accessorial_agreed:
consolidated_total = SUM(line_amount) across all lines in family
agreed_total = contract.additional_charges_agreed
IF consolidated_total == agreed_total
-> PASS the whole group, allocate to GL by line
ELSE IF consolidated_total < agreed_total
-> PASS with under-billing note
ELSE
-> EXCEPTION: group over-billing, variance = difference
For family = accessorial_event_driven:
validate each line individually against its clause and event data
(free-time clocks cannot be consolidated - each carries its own evidence)
Two rules make this work. Consolidation applies only to charge families where a single agreed figure exists; event-driven charges such as demurrage stay line-level because each carries its own evidence. And the consolidated group still needs correct GL allocation per line, so consolidation governs the validation decision, not the posting.
How Should Free Time Be Validated Automatically?
Free time is where the real money sits, and it is the one category that cannot be validated from the invoice alone. You need independent event data.
- Clock start: the contractually defined start event, taken from your own operational record rather than the carrier’s assertion. Discharge or terminal gate-in for demurrage; equipment gate-out for detention.
- Clock stop: terminal gate-out for demurrage, empty return acceptance for detention.
- Elapsed days: computed on the contractual calendar basis, the parameter most often configured wrongly. Calendar days including weekends is common for demurrage; working days only appears frequently in detention clauses.
- Chargeable days: elapsed days less the clause free-time allowance.
- Amount: chargeable days run through the tier structure, which is rarely a single flat rate.
- Cap check: some clauses cap total demurrage per container or shipment.
Two adjustments matter in practice. Force majeure and terminal closure days are often excluded by clause, so the calendar needs a suspension list. And where a depot refuses an empty return, the refusal record should stop the detention clock at the attempted return, not the accepted one.
With all six parameters digitized, the engine produces a computed amount and a variance with the underlying events attached. That is a dispute pack, not just a flag, and it is what makes an AI-powered validation layer worth the setup. The same reasoning applies on the sell side, where uncaptured accessorials become 3PL revenue leakage rather than overpayment.
How Do You Build a Charge-Code Taxonomy That AP Can Actually Use?
The taxonomy is built from your own data, not a template.
Start with historical lines. Pull twelve months of accessorial invoice lines with descriptions, carrier, amount and shipment reference. Most teams find several thousand distinct description strings collapsing into a few dozen genuine charge types.
Cluster and normalize. Define one canonical code per group, recording the observed variants as aliases. That alias list is what lets a classifier handle the next invoice without human help.
Attach five attributes per code: definition, aliases, authorizing clause type, validation method, default GL account. Correct coding is half the value, and the same challenge appears in any non-PO invoice validation programme.
Rank by volume times value. Ten codes usually cover most accessorial lines. Automate those first; treat the long tail as a later phase.
Digitize the clauses for your top carriers. Extract free days, rate, tiers, calendar basis, cap and the base the charge applies to into structured fields. Teams underestimate this step, and it is the one that makes everything downstream possible. Where commercial terms are set by international trade rules, the ICC Incoterms rules determine which party bears which charge, so the taxonomy should record that allocation. Airfreight operators should align codes to the standard charge descriptions published by IATA so ocean and air accessorials sit in one register.
Accessorial validation sits on top of base rate validation, not instead of it; that layer is covered in our guide to freight invoice audit and rate card validation.
How Does This Work With On-Premise SAP ECC or S/4HANA?
Most established logistics operators run SAP on-premise, and the reasonable objection to any new validation capability is that it must not become an ERP project.
It does not have to be. Accessorial validation works as a layer in front of SAP. It captures the invoice, classifies lines against the taxonomy, validates against clause parameters and event data, resolves split-line groups, then posts a single clean, coded document into SAP. Vendor master, posted document, payment run and audit trail are unchanged, and SAP stays the system of record.
Three integration paths cover essentially all on-premise estates:
- File over SFTP. The lowest-friction option and the one Basis teams approve fastest. Structured files land in a monitored directory, and master data extracts come back the same way. No new inbound ports, no new SAP components.
- IDoc. The native document interface, using INVOIC for the vendor invoice and the corresponding master data IDocs inbound. Suits estates already running IDoc traffic through a governed channel.
- RFC and BAPI. Direct calls where near-real-time posting or lookup is needed, such as validating a vendor or cost centre during classification.
None of these depend on an S/4HANA migration. A team on ECC with a migration two years out gets the benefit now and re-points the same interfaces later. The architecture is set out in our guide to adding an AI layer to SAP accounts payable, and the same connectivity model covers other ERPs through standard integrations.
What Does Implementation Actually Look Like?
Successful teams treat this as a data and contract exercise with a software component, not a software rollout. Operations transformation research from McKinsey and Deloitte consistently finds the constraint in this kind of programme is reference-data quality rather than tooling.
| Phase | Duration | Main activity | Output | Success signal |
|---|---|---|---|---|
| 1. Taxonomy build | 2-3 weeks | Cluster 12 months of accessorial lines into normalized codes | Charge-code register with GL mapping | Over 90 percent of historical lines classify |
| 2. Clause digitization | 2-3 weeks | Extract free time, rates, tiers, caps, calendar basis | Structured clause parameters per carrier and code | Top 10 carriers by spend fully parameterised |
| 3. Event data connection | 2 weeks | Feed gate-in, gate-out, pickup, empty-return timestamps | Independent free-time clock computation | Demurrage recomputable without carrier input |
| 4. Split-line consolidation | 1 week | Configure charge families and agreed-total grouping | Group-level validation before line matching | False exceptions on split lines eliminated |
| 5. Shadow mode | 2-4 weeks | Run the engine alongside humans, compare decisions | Tuned taxonomy and clause parameters | Engine agrees with reviewers at an acceptable rate |
| 6. Straight-through processing | Ongoing | Enable auto-approve, auto-dispute and ERP posting | Validated documents posting without touch | Majority of accessorial lines processed untouched |
Set budget expectations from market ranges rather than assumptions. Mid-market logistics AP automation with contract-clause validation generally lands in the tens of thousands of dollars annually for platform and implementation combined, with payback driven by recovered overbilling and redeployed AP hours. Singapore operators should check current support under the IMDA SMEs Go Digital programme before scoping, and can see local context in our guide to logistics procurement automation in Singapore.
One sequencing note. If a meaningful share of carriers still send PDFs rather than structured EDI, solve capture in parallel, because a taxonomy cannot classify a line that was never extracted correctly; see straight-through processing for non-EDI supplier invoices. 3PLs running subcontracted carrier networks should also review self-billing validation for subcontracted carriers.
Our Verdict: This Is a Taxonomy Problem Before It Is an Automation Problem
The instinct when accessorial exceptions pile up is to buy better matching software. That is the wrong first move, and it is why many logistics AP automation projects underdeliver.
The binding constraint is not matching capability. It is that the business has never written down what its accessorial charges are, which clause authorizes each one, and what parameters govern them. Until that exists, any engine you deploy is matching against nothing.
- Build the taxonomy first, even manually. A spreadsheet of 40 normalized codes with aliases and clause references creates value before any software is configured, because it makes disputes possible.
- Digitize clauses for the top ten carriers only. The long tail is real but it is not where the money is, and chasing it early stalls the project.
- Treat free-time clocks as an event-data problem. If you cannot compute the clock from your own records, you are not validating demurrage. You are accepting it.
- Consolidate before you match. Split-line handling is a small piece of logic that removes a large share of false exceptions.
- Keep flat tolerances for what they are good at: price and quantity variance on ordered goods, not accessorials.
- Do not wait for the ERP roadmap. The validation layer works against ECC today, with no migration dependency.
The failure mode to avoid is the middle path: automating classification without digitising clauses. That produces a system that confidently tells you a charge is detention, and still cannot tell you whether you owe it.
Conclusion
Accessorial charges break AP validation for a structural reason, not a technology reason. They are event-driven charges being tested by an order-driven control, and the purchase order they are supposed to match against was never going to contain them.
Replacing the missing PO line with the contract clause resolves it. Classify each accessorial into a normalized code, map the code to the clause that authorizes it, compute free time from your own operational events, consolidate split lines before matching, and route on the reason for a variance rather than its dollar size.
The payoff shows up in three places: an exception queue that shrinks instead of growing with volume, disputes that arrive with evidence so carriers settle them, and an audit trail naming the clause behind every approval. Pair it with well-designed approval threshold and escalation rules for the residual exceptions, and build the wider programme from our complete guide to accounts payable automation or agentic spend management for the layer above it.