EDI X12 #
EDI is dense and infrequent — you set up a trading partner once, then touch it
quarterly and have forgotten everything. This page is reference-grade: what
Bizuno actually supports, how a document moves, and where to look when one
doesn’t.
What’s supported #
Bizuno implements five X12 transaction sets, all real and operational:
| Set | Name | Direction | In Bizuno |
|---|---|---|---|
| 850 | Purchase Order | Inbound | Parsed and posted as a Sales Order (pending review) |
| 997 | Functional Acknowledgment | Both | Emitted for every inbound 850; accepted inbound |
| 810 | Invoice | Outbound | Built from a posted invoice |
| 855 | PO Acknowledgment | Outbound | Line-level accept/reject of a PO |
| 856 | Advance Ship Notice (ASN) | Outbound | Shipment confirmation with HL loops + tracking |
Transport is SFTP (via phpseclib) — Bizuno pulls inbound files from the
partner’s “get” directory and writes outbound files to a “put” directory.
Configuring a trading partner #
Trading partners are configured under Settings → EDI Configuration (the
adminEdi controller); each partner is stored as metadata against a contact.
The fields that matter:
| Field | Meaning |
|---|---|
cID |
The customer/vendor contact this partner is |
ediID |
Your sender ID (goes in the ISA/GS of replies) |
rcvrID |
Their receiver ID (verified against inbound ISA) |
sepTag / sepSec |
Segment terminator (~) and element separator (*) |
hostName / userName / userPass |
SFTP connection |
pathGet / pathPut |
Inbound and outbound directories on the SFTP server |
Multiple partners are supported — each is its own metadata row, and a poll runs
through all of them. File names are auto-generated as
{rcvrID}_{soNum}_{controlNum}_{spec}.edi; there’s no name-pattern to configure.
Inbound 850 lifecycle #
SFTP poll (ediGet)
→ pull files from the partner's pathGet
→ parse: split on sepTag (~) into segments, sepSec (*) into elements
→ verify ISA receiver ID matches rcvrID
→ dispatch each segment to its handler (x12_850_rcv)
→ map to a Sales Order (journal_id = 10), status "pending review"
→ post the order
→ build and send a 997 back to pathPut (AK5 = A accepted / E errors)
The order lands as pending review, not silently final — a human approves it
before it becomes a live commitment. Duplicate POs (same partner + PO number) are
detected and skipped.
Outbound 810 lifecycle #
Trigger: ediTransmit(invoiceID, '810')
→ build the envelope + segments from the posted invoice
→ write {rcvrID}_{soNum}_{ctl}_810.edi to pathPut over SFTP
→ verify the file landed
→ log the transmission (expect a 997 back from the partner)
855 (PO ack) and 856 (ASN) follow the same outbound shape, built by their
respective x12_855_rsp / x12_856_rsp builders.
Segment reference #
A document is an envelope wrapping content segments:
ISA ── interchange envelope (sender/receiver IDs, control number)
GS ── functional group
ST ── transaction set (850 / 810 / …)
BEG PO header (inbound 850) | BIG invoice header (outbound 810)
N1/N3/N4 name + address (bill-to / ship-to / …)
PO1 line item (inbound) | IT1 line item (outbound)
PID product description (paired with the line)
N9 + MSG reference text → captured as a $0 description line (see below)
CTT transaction totals
SE ── transaction-set trailer
GE ── functional group trailer
IEA ── interchange trailer
The dispatcher routes each segment to a handler by name. Unknown segments are
not fatal — they’re logged to the trace
(as a trap entry) and skipped, so an unexpected segment annotates the diagnostics
rather than failing the whole document.
The N9 + MSG pattern #
Some partners send reference text (e.g. “PO POLICIES” plus a URL) in N9/MSG
segments. Rather than ignore them or trap on them, Bizuno captures the N9 label +
MSG text as a $0 description line on the resulting Sales Order — visible to
the reviewer, zero effect on totals. MSG is handled as an explicit no-op so the
segment dispatcher doesn’t log it as unexpected. (since v7.4.0.)
Errors, acknowledgments, and reconciliation #
- Inbound errors (bad ST, receiver-ID mismatch, unknown SKU, price variance)
accumulate during processing. A 997 is still returned for every inbound 850,
withAK5 = Awhen clean orEwhen errors were found, so the partner learns
the outcome. - Logging: each EDI exchange is recorded as transaction metadata (spec,
status, control number, the raw payload, the ack payload and date), and
success/error emails go to the addresses configured in the EDI settings. - Reconciliation: match your outbound documents to the partner’s returning
997s; an outbound 810 with no 997 back, or an inbound 850 whose 997 you sent
withAK5 = E, is what to chase.
When something goes wrong: read the trace #
EDI problems surface in the trace file.
Unexpected segments, parse failures, SFTP connection errors, and SKU/price
mismatches all leave entries there (with credentials scrubbed). Reproduce the
poll or transmit, then read the trace for that run — it’s the fastest path from
“the partner says it failed” to the actual segment that broke.
Related #
- Trap and trace files — where EDI parse/segment errors land
- Quote → SO → Invoice → Payment → Deposit — the Sales Order an inbound 850 becomes
- REST API surface —
ediCronand the token-authenticated portal API
