Parse EDI X12 to JSON: 810 Invoice, 850 PO, 856 ASN, 855 Ack
Updated April 2026.
EDI X12 is the data format big-box retailers, distributors, and 3PLs require for B2B trading. Documents are segments of asterisk-separated elements, separated by tildes (or whatever delimiters the trading partner picked). Decoding them into JSON is mostly mechanical but the segment positions are unforgiving and the hierarchical loops in 856 ASNs trip up most ad-hoc parsers. This page is the working reference: four worked examples (810, 850, 856 with HL loops, 855), an error reference, and a structural comparison with the EDI VANs and toolkits.
New here? The full /v1/map endpoint reference (contract, sandbox scope, errors, limits, all use cases) lives at Transformation API overview →. This page is the EDI X12 deep dive.
1. 30-second quickstart
curl https://streamfix.dev/v1/map \ -H "Authorization: Bearer sk_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "payload": "ST*810*0001~BIG*20240115*INV-0042*20231201*PO-9988~REF*IA*VEND-557~IT1*1*10*EA*12.50**UP*012345678905~TDS*22500~SE*5*0001~", "target": "Parse EDI X12 810 invoice. Return invoice_number, invoice_date (YYYYMMDD to ISO), po_reference, vendor_account (REF*IA), line_items (from IT1 segments), total_amount (TDS in cents, /100)." }'
First call with a given transaction set and target text compiles a parser. Subsequent calls of the same shape hit the cache. A real EDI feed has a stable shape per transaction-set/trading-partner, so caching is highly effective.
2. Endpoint reference
POST /v1/map. Auth: Authorization: Bearer sk_YOUR_KEY.
payload- the X12 transaction-set string (fromST*throughSE*, or the full ISA envelope if you prefer).target- description of which segments to extract and how to type them.
output- the structured record.cached,fingerprint,elapsed_ms,code_length- standard.
3. Worked examples
All four outputs below are verified responses from /v1/map. EDI X12 is a standardized but trading-partner-tweaked format. The target text is where you encode your partner's specific positions. For the canonical specs, see the X12 transaction set catalog.
3.1 810 Invoice
A typical 810: BIG segment carries the invoice header (date, number, PO ref); REF with qualifier IA is the vendor account; IT1 repeats per line item; TDS is the total in implied-decimal cents.
ST*810*0001~BIG*20240115*INV-0042*20231201*PO-9988~REF*IA*VEND-557~IT1*1*10*EA*12.50**UP*012345678905~IT1*2*5*CS*100.00**UP*987654321098~TDS*22500~SE*7*0001~"Parse EDI X12 810 invoice (segments separated by ~, elements by *). Return object with: invoice_number (BIG-2), invoice_date (BIG-1, format YYYYMMDD -> ISO YYYY-MM-DD), po_reference (BIG-4), vendor_account (REF segment with REF01='IA', value at REF02), line_items (array from IT1: line_number=IT1-1, quantity=int(IT1-2), unit=IT1-3, unit_price=float(IT1-4), upc=IT1-7), total_amount (TDS-1 in cents, /100 for dollars float)."{
"invoice_number": "INV-0042",
"invoice_date": "2024-01-15",
"po_reference": "PO-9988",
"vendor_account": "VEND-557",
"line_items": [
{"line_number": "1", "quantity": 10, "unit": "EA", "unit_price": 12.5, "upc": "012345678905"},
{"line_number": "2", "quantity": 5, "unit": "CS", "unit_price": 100.0, "upc": "987654321098"}
],
"total_amount": 225.0
}3.2 850 Purchase Order
850s use BEG for the order header and PO1 for line items. The CTT segment carries the line count for validation.
ST*850*0001~BEG*00*SA*PO-12345**20240301~REF*VR*VENDOR-99~PO1*1*100*EA*9.99*CT*BP*ABC123*UP*012345678901~PO1*2*50*EA*4.50*CT*BP*XYZ789*UP*987654321098~CTT*2~SE*6*0001~"Parse EDI X12 850 Purchase Order. Return object with: purpose_code (BEG-1), order_number (BEG-3), order_date (BEG-5, YYYYMMDD -> ISO), vendor_id (REF segment with REF01='VR', value at REF02), line_items (array from PO1: line_number=PO1-1, quantity=int(PO1-2), unit=PO1-3, unit_price=float(PO1-4), buyer_part=PO1-7, upc=PO1-9), line_count (CTT-1 as int)."{
"purpose_code": "00",
"order_number": "PO-12345",
"order_date": "2024-03-01",
"vendor_id": "VENDOR-99",
"line_items": [
{"line_number": "1", "quantity": 100, "unit": "EA", "unit_price": 9.99, "buyer_part": "ABC123", "upc": "012345678901"},
{"line_number": "2", "quantity": 50, "unit": "EA", "unit_price": 4.5, "buyer_part": "XYZ789", "upc": "987654321098"}
],
"line_count": 2
}3.3 856 ASN with hierarchical loops (HL)
856 Advance Ship Notices are the hardest standard transaction set because of the hierarchical level (HL) structure: shipment loops contain order loops which contain item loops. Most homegrown parsers stop at flat segment extraction; the target text below describes the nesting.
ST*856*0001~BSN*00*ASN-2024-001*20240320*1430*0001~HL*1**S~TD5****UP*GROUND~TD1*PCT*2****G*100~REF*BM*BOL-9988~HL*2*1*O~PRF*PO456789~HL*3*2*I~LIN*1*UP*012345678901*BP*PART-A~SN1**12*EA~SE*11*0001~"Parse EDI X12 856 ASN with hierarchical levels (HL segments). Return object with: shipment_number (BSN-2), ship_date (BSN-3, YYYYMMDD -> ISO), service_level (TD5-5, lowercase), pallet_count (TD1-2, int), bol_number (REF where REF01='BM', value at REF02), orders (array; each order from HL with HL-3='O': contains po_number from PRF-1 and items array from inner HL with HL-3='I' containing LIN segments: {line_number=LIN-1, upc=LIN-3, buyer_part=LIN-5, quantity=int(SN1-2), unit=SN1-3})."{
"shipment_number": "ASN-2024-001",
"ship_date": "2024-03-20",
"service_level": "ground",
"pallet_count": 2,
"bol_number": "BOL-9988",
"orders": [
{
"po_number": "PO456789",
"items": [
{"line_number": "1", "upc": "012345678901", "buyer_part": "PART-A", "quantity": 12, "unit": "EA"}
]
}
]
}3.4 855 PO Acknowledgement
855s confirm a PO. BAK carries the acknowledgement code (e.g. AC = accepted as-is, AT = accepted with changes, RJ = rejected). Same line-item shape as 850.
"Parse EDI X12 855 Purchase Order Acknowledgement. Return object with: ack_status_code (BAK-2), buyer_po_number (BAK-3), po_date (BAK-4, YYYYMMDD -> ISO), vendor_ack_number (BAK-6), vendor_id (REF where REF01='VR', value at REF02), line_items (array from PO1: {line_number=PO1-1, quantity=int(PO1-2), unit=PO1-3, unit_price=float(PO1-4), buyer_part=PO1-7})."{
"ack_status_code": "AC",
"buyer_po_number": "PO-12345",
"po_date": "2024-03-01",
"vendor_ack_number": "ACK-0007",
"vendor_id": "VENDOR-99",
"line_items": [
{"line_number": "1", "quantity": 100, "unit": "EA", "unit_price": 9.99, "buyer_part": "ABC123"}
]
}4. Note on delimiters
All examples above use the most common delimiters: segment terminator ~, element separator *. In a real EDI feed, the ISA envelope's first 106 bytes specify the delimiters - they can be anything, and trading partners do vary. If your feed uses different separators, mention them in the target text:
"Parse EDI X12 810 invoice. Segments separated by '\\n' (newline), elements by '|'. Return object with: ..."
The cached parser handles whatever delimiters the target text declared.
5. Errors and status codes
| Status | Meaning | What to do |
|---|---|---|
200 | Parsed. | - |
400 | Body missing fields. | Check the request. |
401 | Auth. | Bearer token. |
402 | No credits. | Top up. |
422 | Parser raised. Common cause: a segment qualifier the target didn't anticipate (e.g. a REF*XX instead of REF*IA when you only described IA). | Either expand the target text to handle additional qualifiers, or branch by trading-partner spec in your handler. |
502 | Internal generation failure. | Retry. |
6. Limits and behavior
- One parser per (transaction-set + target text). 810 and 850 have different shapes; same trading partner over time will have a stable shape; the cache is highly effective for steady B2B feeds.
- What this is NOT: an EDI VAN, an AS2 client, or an envelope-handling library. Strip
ISA/GS/GE/IEAenvelopes upstream and pass just the transaction set (or the full message - the parser handles either when the target says so). - Sandbox: AST-validated Python;
re,datetime,decimalavailable. No network or filesystem.
7. Alternatives and how this differs
EDI is dominated by enterprise vendors (VANs and managed-service providers) plus a handful of open-source toolkits. Here's how /v1/map differs structurally.
| Tool | Shape | What it does | Best for |
|---|---|---|---|
| SPS Commerce | Managed-service EDI VAN | End-to-end: trading partner onboarding, AS2/SFTP transport, mapping, exception handling. Very large customer base. | Mid-market and enterprise retailers/suppliers; you want someone else to handle the whole thing. |
| TrueCommerce | Managed-service EDI VAN | Similar to SPS - full-service EDI with trading-partner network. | Same audience as SPS; pick by price, partner availability, support quality. |
| Cleo Integration Cloud | Self-managed iPaaS for EDI | Studio-style mapping editor; you run the integration but their tooling does the heavy lifting. | Companies with in-house IT who want to control the integration but not write parsers from scratch. |
| pyx12 (Python) | Open-source library | Generic X12 parser with schemas for common transaction sets; long-running project. | Engineers who want full control and don't mind maintaining segment maps. |
StreamFix /v1/map | HTTP API; one POST per document | Just the parse step. You handle transport and trading-partner setup. | You already have a pipeline (or are building one) and just want a clean way to turn segments into JSON without maintaining a segment-position map. |
Structural difference: SPS / TrueCommerce / Cleo are EDI platforms - they include the trading-partner network, AS2 transport, mapping editor, dashboards. /v1/map is just the format-conversion step. If you need the platform, those will fit better. If you have engineers and a pipeline already, the API is simpler.
8. When NOT to use this
- You don't have AS2 / SFTP / VAN transport set up. Most retailers won't even talk EDI with you without a managed partner. SPS or TrueCommerce will get you trading much faster than building it.
- You're processing thousands of documents per second. An HTTP round-trip per document is fine for normal B2B volumes (hundreds per day per trading partner) but isn't built for stream rates.
- You need certified compliance with a partner's specific implementation guide. Walmart, Target, Amazon each have detailed conformance specs.
/v1/maphandles structural parsing; conformance-checking is something you build on top, or buy. - Your trading partner uses EDIFACT (UN/EDIFACT) instead of X12. Same idea works (segments and elements), but the dictionaries are different. Just say "Parse EDIFACT INVOIC..." in the target text - generally the engine handles it, but you're outside the X12 examples shown here.
9. Get an API key
Free trial credits on signup.
Sign up