Tracking Status Normalisation Across Carriers
If you work with more than one carrier, you have this problem whether or not you have named it. Each partner invented its own vocabulary for describing where a parcel is, and none of them agree.
Passing those raw statuses through to your customers produces a tracking page that contradicts itself depending on who carried the parcel. Normalisation is the work of preventing that.
What the problem actually looks like
Consider a parcel that has arrived at a local facility and is waiting to go out for delivery. One carrier may describe this as a single "In Transit". Another may split the same physical situation into "Arrived at Facility", "Processed at Facility" and "Out for Delivery". A third might call it "Shipment Received at Destination Hub".
All three are accurate. None of them are comparable. And a customer who ships with you twice, through different carriers, sees two different levels of detail for the same journey — which reads as inconsistency in your service, not the carrier's.
The solution: own your status model
The fix is to define your own set of statuses first, based on what your business and your customers care about, and treat every carrier's vocabulary as a foreign language to be translated into it.
A workable internal model is usually smaller than people expect. Something like:
Resist the temptation to add a state for every nuance a carrier reports. Each additional status is something your staff, your customers and your reports all have to understand. If two states would always lead to the same action, they should be one state.
Keep the original alongside the mapped one
Store both: the carrier's raw status exactly as received, and your normalised equivalent. Show the normalised status to customers and the raw one to your operations team.
This matters when something goes wrong. If a customer disputes a status, you need to be able to show exactly what the carrier told you and when, not a value you derived from it. It also means a mapping error is recoverable — you can re-map historical events, which is impossible if you discarded the original.
Unknown statuses must be loud
Carriers add statuses without telling you. The single most important design decision in a normalisation layer is what happens when one arrives that you have never seen.
The wrong answers are to drop it silently, or to default it to something plausible like "In Transit". Both look fine and both hide a growing gap between what the carrier is reporting and what you are showing.
The right answer is to store the event, map it to a safe holding state, and raise it for review. An unmapped status should be a small piece of work in somebody's queue within a day, not a discovery made three months later when a customer complains.
Events arrive out of order
Especially over webhooks. A "Delivered" event can arrive before the "Out for Delivery" that preceded it, because they travelled through different queues.
Two rules handle almost all of this. First, order the timeline by the carrier's event timestamp, not by when you received it. Second, do not allow a terminal state to be overwritten by an earlier one — a delivered shipment should not revert to "In Transit" because a late event turned up.
Duplicates are equally routine. Deduplicate on carrier, AWB, status and event time, and processing the same event twice becomes harmless.
Treat the mapping as an asset, not a task
The mapping table is not something you build once at integration time. Carriers change their vocabulary, add services with new status flows, and occasionally rename things without notice.
Keep it as configuration rather than code, so a new mapping can be added without a deployment. Keep it reviewed — a periodic report of raw statuses seen versus statuses mapped will show drift before customers do.
Why this is worth the effort
Normalisation is invisible when it works, which is why it gets cut from scope. What it actually buys you:
That third point is worth dwelling on. Without normalisation you cannot honestly compare carrier performance, because you are comparing different measurements. Which means you cannot make evidence-based decisions about which partner to use where — and that decision is usually worth considerably more than the integration cost.
Where we come in
Status normalisation is a core part of the shipment tracking software and courier aggregator platforms we build, and it is scoped explicitly rather than absorbed quietly into integration work.
More reading
How Courier API Integration Works
What actually happens when your software talks to a courier's API — the endpoints involved, the order they are called in, and the parts that are harder than they look.
Webhooks vs Polling for Shipment Tracking
Two ways to find out that a parcel moved. One is more efficient, one is more reliable, and most real systems end up using both — for good reasons.
Courier API Failure Handling: Retries, Backoff and Idempotency
The difference between an integration that works in testing and one that survives production is entirely in how it behaves when the other side misbehaves.