I'm Chris, founder of SignalEDI. Yesterday we took apart the 850 purchase order; as promised, today we follow the order out the warehouse door. Meet the 856 — the Advance Ship Notice (ASN) — the document your customers require you to send before the truck shows up.
The ASN is where EDI stops feeling like paperwork and starts feeling like engineering: it models a physical shipment as a nested hierarchy of shipment → orders → pallets → items. Get the hierarchy wrong and you get chargebacks. It's the most structurally demanding document in retail EDI, and the one that breaks the most mappings.
The sample
Here's a sanitized ASN for a single shipment covering one purchase order, one pallet, one line item. Same delimiters as yesterday: ~ segments, * elements.
ISA*00* *00* *ZZ*RECEIVERID *ZZ*SENDERID *260930*0930*^*00501*000000007*0*P*>~
GS*SH*SENDERID*RECEIVERID*20260930*0930*7*X*005010~
ST*856*0007~
BSN*00*ASN-98765*20260930*093015~
HL*1**S~
TD5*O*2*UPSN*M*UPS GROUND~
TD3*TL*1*1000*G*48*L*36*W~
REF*CN*CNTR-55431~
HL*2*1*O~
LIN**UP*012345678905~
SN1*1*100*EA~
PRF*PO-12345***20260929~
HL*3*2*P~
MAN*GM*PAL-001122~
HL*4*3*I~
LIN**UP*012345678905~
SN1*4*48*EA~
CTT*4~
SE*21*0007~
GE*1*7~
IEA*1*000000007~
The header: BSN
BSN*00*ASN-98765*20260930*093015 — the Beginning Segment for Ship Notice:
-
00— original (not a07replacement or01cancel; ASN replacements are common because reality changes) -
ASN-98765— the shipment ID. This string will be referenced by the carrier, the receiving dock, and the retailer's chargeback engine. Treat it like a primary key. - The date and time (
093015= 09:30:15) matter more than on an 850: this ASN documents when the shipment was created, and retailers enforce "ASN before arrival" windows measured in hours.
The hierarchy: HL loops (the whole game)
Everything after BSN is built from HL (Hierarchical Level) segments, and this is where ASN mappings live or die:
HL*1**S~ -> level 1, parent = none, type = S (Shipment)
HL*2*1*O~ -> level 2, parent = 1, type = O (Order)
HL*3*2*P~ -> level 3, parent = 2, type = P (Pack/pallet)
HL*4*3*I~ -> level 4, parent = 3, type = I (Item)
Each HL carries its own ID (first element), its parent's ID (second), and the level type (third: S, O, P, I). The structure is a tree: shipment contains orders, orders contain packs, packs contain items.
The nasty part: trading partners disagree about which levels they want. Some retailers want only S → O → I (ship, order, item — no pallet detail). Others require the full S → O → P → I, or even tare levels below the pallet. Big-box retailers will fine you if the item is nested under the wrong parent. This is why yesterday's EDI-L notes mentioned the "crazy hierarchy" thread — a shipper wanting shipment+item+pallet data without item-to-pallet assignment is exactly the kind of request that makes ASN mapping a discipline.
A common newcomer bug: hard-coding the HL structure for one partner. Every new trading partner will have a different hierarchy requirement, so the mapping has to generate the tree, not paste it.
Transport detail: TD5 / TD3
TD5*O*2*UPSN*M*UPS GROUND — carrier details: 2 = standard carrier alpha code list, UPSN = UPS's code, M = motor carrier. TD3*TL*1*1000*G*48*L*36*W describes the equipment: trailer (TL), gross weight 1000 pounds, 48 inches long, 36 inches wide.
These segments feed the receiving dock's planning system. If your TD3 weights are wrong or missing, the warehouse schedules the wrong unloading crew and the invoice discrepancy flags fire downstream.
REF*CN*CNTR-55431 — CN = carrier reference (the tracking/pro number). This one segment is how the ASN gets matched to the physical shipment at the dock door.
Order and pack levels: LIN / SN1 / PRF / MAN
At the order level (HL*2, parent HL*1):
-
LIN**UP*012345678905— line item identification:UP= UPC. Same product from the 850's PO1, now shipping. -
SN1*1*100*EA— item detail: line 1, 100 each. Note this is the shipment quantity for this line — the source of many "short shipment" chargeback disputes. -
PRF*PO-12345***20260929— references the original purchase order number (PO-12345from yesterday's 850). This is the field that ties the whole cycle together: 850 creates the PO number, the 856 references it, the 810 invoice will reference it again. If your PRF number doesn't match the retailer's PO number exactly — including leading zeros — the invoice auto-matching fails and payment stalls.
At the pack level (HL*3):
-
MAN*GM*PAL-001122— marks and numbers:GM= SSCC-18 bar-coded pallet serial number.PAL-001122is the license plate of that pallet. Retailers scan it at receiving; it must match the ASN's pack level, or the receiving system rejects the pallet.
At the item level (HL*4): LIN identifies the product again and SN1*4*48*EA says 48 units of line item 4 on this pallet. Pallet math — items per pack — gets validated on arrival.
The trailer: CTT / SE
CTT*4 — four HL loops in this transaction. SE*21*0007 — 21 segments, matching ST control 0007. Then GS/IEA close as usual.
The 856 trailer check matters operationally: a receiving system will reject an ASN whose CTT count doesn't match the actual HL segments, and a rejected ASN often means the shipment gets treated as an unscheduled arrival — with the associated fees.
Why this matters to API people
- It's a serialized tree. The HL mechanism is EDI's answer to nested data: flat segments reconstructing a tree via parent pointers. If you've ever written a parser that turns adjacency-list rows into a JSON tree, you've already implemented HL processing — the difference is the tree is the payload and the parent pointers are inside the payload.
- Hierarchy is a partner-specific configuration, not a constant. Your "856 generator" needs to be parameterized by partner: which levels, which qualifiers, which reference IDs. Retailers fine you for getting this wrong, which is why ASN onboarding is measured in weeks, not hours — unless the tooling generates the structure from a partner profile instead of a template.
- The three-document chain is the real system. 850 (order) → 856 (ship notice) → 810 (invoice) is a distributed workflow with no central coordinator, correlated by PO numbers and shipment IDs across companies. It's eventual consistency in the supply chain, circa 1980. Sound familiar?
If your company ships to retailers and the onboarding packet says "ASN required," the 856 is the document you'll spend the most time on — and the one where getting the hierarchy right on the first pass saves you the chargeback conversation nobody enjoys.
I run SignalEDI — AI-assisted EDI mapping and testing for SMBs, flat monthly pricing, no per-document fees. This is my daily EDI deep-dive series for developers: AS2 on the 28th, the 850 yesterday, the 856 today. Tomorrow we're into retailer compliance — what chargebacks actually are and how EDI documents trigger them.
Top comments (0)