If you supply Amazon as a 1P vendor on Vendor Central, you eventually hit the limits of the web portal: manually typing shipment quantities, accidentally locking an 856 ASN before Amazon finishes reallocating the destination Fulfillment Center (N1*ST), or spending hours reconciling multi-page 820 remittance PDFs against shortage and co-op chargebacks.

Amazon Vendor Central includes a free Self-Service EDI SFTP channel (850 in → 855 / 856 / 810 out, plus 820 remittance advices) that requires zero third-party VAN fees. Yet small suppliers and integration engineers routinely get tripped up by four X12 004010 / 005010 subtleties that trigger automatic $250–$1,500+ chargebacks.

This engineering guide breaks down the exact segment structures, TypeScript parsing patterns, and pre-flight validation checks needed to run a clean Amazon 1P EDI turnaround workflow.

1. The Amazon 1P EDI Turnaround Loop (Why Portal ASN Locks Hurt)

In Vendor Central, Amazon frequently reassigns destination FCs (N1*ST 4-letter SAN codes) or issues an 860 PO Change hours after releasing an 850 Purchase Order. If you generate and submit an 856 ASN immediately on receipt, that BSN02 Shipment ID and its MAN*GM SSCC-18 carton barcodes lock to the stale FC.

With Self-Service SFTP, decouple acknowledgment from dispatch:

  1. Ingest 850 PO → validate BEG03 (PO#), PO1 item identifiers (BP / UP / IN), PO4 case-pack multiples, and N1*ST ship-to FC code.
  2. Send 855 PO Acknowledgment immediately with line-level status (ACK*IA accepted, ACK*IQ partial qty, ACK*IB backorder, ACK*IR rejected).
  3. Hold 856 ASN & 4x6" GS1-128 printing until Routing Confirmation returns your ARN (Amazon Reference Number).
  4. Emit 856 (REF*BX*<ARN>) + 810 Invoice (BIG04*<PO#>) mirrored to the exact X12 version (004010 / 005010) and ISA15 (T test vs. P production) flag from the inbound 850.

2. Threading REF*BX (ARN) & SSCC-18 Uniqueness Across 856 & 4x6" Labels

Amazon's receiving dock requires two non-negotiable links between your physical cartons, your 856 ASN, and your routing request:

  • Amazon Reference Number (REF*BX): Passed at the Shipment (HL*S) level on the 856 ASN (REF*BX*ARN123456789~) and mirrored onto the human-readable zone of your 4x6" GS1-128 shipping label.
  • Non-Colliding SSCC-18 (MAN*GM): Every physical carton (HL*P) needs a globally unique 20-digit 00 + SSCC-18 barcode with a valid GS1 Modulo-10 check digit. Reusing a serial number from a voided ASN—or having two warehouse packing stations emit the same serial simultaneously—causes an immediate receiving scan collision.
// Checking for duplicate SSCC-18 barcodes inside a single outbound 856 ASN export function findDuplicateSscc18InAsn(segments: string[][]): string[] { const seen = new Set<string>(); const duplicates = new Set<string>(); for (const seg of segments) { if (seg[0] === 'MAN' && seg[1] === 'GM' && seg[2]) { const code = seg[2].trim(); if (seen.has(code)) duplicates.add(code); seen.add(code); } } return [...duplicates]; } 

Demo-Prefix Guard: Never let a GS1 documentation example prefix like 0614141 leak into a production ISA15=P shipment or 4x6" PDF label—retailers treat it as an unmapped vendor barcode and fine per carton.

3. Parsing 820 Remittances Without Dropping Multiple ADX Deductions

A subtle bug in naive EDI 820 parsers happens inside the ENT -> RMR -> ADX remittance loop. One paid invoice (RMR*IV*INV-10482**2500.00*2500.00~) often carries multiple consecutive ADX adjustment segments—for example, a co-op marketing allowance, a shortage claim, and a late-ASN fine—plus standalone ADX segments outside an RMR loop.

If your parser assigns currentInvoice.adjustment = parseAdx(seg) instead of pushing into an array, every subsequent ADX silently overwrites the previous deduction!

export interface RemittanceAdjustment { amount: number; reasonCode: string; referenceId?: string; } export interface RemittanceInvoiceLine { invoiceNumber: string; netPaid: number; grossBilled: number; adjustments: RemittanceAdjustment[]; unexplainedVariance: number; } export function accumulateRmrAndAdx(segments: string[][]): { lines: RemittanceInvoiceLine[]; standaloneAdjustments: RemittanceAdjustment[]; } { const lines: RemittanceInvoiceLine[] = []; const standaloneAdjustments: RemittanceAdjustment[] = []; let current: RemittanceInvoiceLine | null = null; for (const seg of segments) { if (seg[0] === 'RMR') { current = { invoiceNumber: seg[2] || '', netPaid: Number(seg[4] || 0), grossBilled: Number(seg[5] || 0), adjustments: [], unexplainedVariance: 0, }; lines.push(current); } else if (seg[0] === 'ADX') { const adj: RemittanceAdjustment = { amount: Number(seg[1] || 0), reasonCode: seg[2] || '', referenceId: seg[4] || undefined, }; if (current) { current.adjustments.push(adj); } else { standaloneAdjustments.push(adj); } } else if (seg[0] === 'ENT' || seg[0] === 'SE') { current = null; } } for (const line of lines) { const adxSum = line.adjustments.reduce((acc, item) => acc + item.amount, 0); line.unexplainedVariance = Number( (line.grossBilled + adxSum - line.netPaid).toFixed(2) ); } return { lines, standaloneAdjustments }; } 

Checking unexplainedVariance to the penny immediately flags discrepancies before your 30-day Vendor Central dispute window expires.

4. Testing Without Uploading Wholesale Pricing

If you want to inspect real Amazon 850 / 824 payloads or validate your turnaround files before dropping them onto Amazon's SFTP outbox: