X12 EDI
The @openinsure/x12 package provides a pure TypeScript parser and builder for X12 EDI transaction sets used in healthcare, insurance, and transportation. No external EDI libraries or services are required — all processing runs in-process on Cloudflare Workers.
Supported Transaction Sets
Section titled “Supported Transaction Sets”| Set | Name | Direction | Use case |
|---|---|---|---|
| 834 | Benefit Enrollment & Maintenance | Inbound | Group health member enrollment from employer |
| 835 | Healthcare Claim Payment/Advice | Inbound | EOB from carrier to provider / plan |
| 837P | Healthcare Claim — Professional | Outbound | Stop-loss claim submission to reinsurer |
| 210 | Motor Carrier Freight Invoice | Inbound | Freight billing for transportation lines |
| 211 | Motor Carrier Bill of Lading | Inbound | Shipment manifest for cargo insurance |
Parsing
Section titled “Parsing”import { parseX12 } from '@openinsure/x12';
const raw = `ISA*00* *00* *ZZ*SENDER *ZZ*RECEIVER *230601*1200*^*00501*000000001*0*P*:~GS*BE*SENDER*RECEIVER*20230601*1200*1*X*005010X220A1~ST*834*0001~...`;
const result = parseX12(raw);// result.transactionSets[0].type → '834'// result.transactionSets[0].loops → parsed loop structure// result.valid → true | false// result.errors → validation error detailsMember Enrollment (834)
Section titled “Member Enrollment (834)”import { parse834, type MemberEnrollment } from '@openinsure/x12';
const enrollments: MemberEnrollment[] = parse834(raw834String);
enrollments.forEach((member) => { console.log(member.memberId); // '12345' console.log(member.firstName); // 'Jane' console.log(member.lastName); // 'Smith' console.log(member.birthDate); // '1985-03-15' console.log(member.coverageType); // 'HMO' | 'PPO' | 'HDHP' console.log(member.effectiveDate); // '2025-01-01' console.log(member.terminationDate); // null (active)});Claim Payment (835)
Section titled “Claim Payment (835)”import { parse835, type ClaimPayment } from '@openinsure/x12';import { toDollars } from '@openinsure/rating';
const payments: ClaimPayment[] = parse835(raw835String);
payments.forEach((payment) => { console.log(payment.claimNumber); // carrier's claim control number console.log(payment.paymentAmount); // { cents: 2750000, currency: 'USD' } console.log(toDollars(payment.paymentAmount)); // 27500 console.log(payment.checkNumber); // '00198734' console.log(payment.payerName); // 'Acme Health Plan' payment.serviceLines.forEach((line) => { console.log(line.procedure); // '99213' console.log(line.submitted); // Money — submitted charge console.log(line.paid); // Money — paid amount });});Building
Section titled “Building”import { build837P, type ProfessionalClaim } from '@openinsure/x12';import { money } from '@openinsure/rating';
const claim: ProfessionalClaim = { claimNumber: 'CLM-2025-001', patientName: 'Jane Smith', patientDob: '19850315', patientGender: 'F', subscriberId: 'SUB-00123', payerName: 'Acme Health Plan', diagnosisCodes: ['J06.9'], // Upper respiratory infection totalCharge: money(185.0), // { cents: 18500, currency: 'USD' } serviceLines: [ { procedure: '99213', // Office visit, established patient serviceDate: '20250615', units: 1, charge: money(185.0), placeOfService: '11', // Office diagnosis: '1', }, ],};
const edi = build837P([claim], { senderId: 'OPENINSURE', receiverId: 'REINSURER',});
// edi → valid X12 837P EDI string ready for transmissionTransportation (210 / 211)
Section titled “Transportation (210 / 211)”For commercial transportation insurance programs:
import { parse210, parse211 } from '@openinsure/x12';
// 210 — Freight Invoice (auto-generate invoice from carrier's EDI)const invoice = parse210(raw210);// invoice.proNumber, invoice.shipDate, invoice.weight, invoice.charges[]
// 211 — Bill of Lading (manifest for cargo insurance underwriting)const bol = parse211(raw211);// bol.shipmentId, bol.origin, bol.destination, bol.commodities[]Validation
Section titled “Validation”The parser validates each transaction set against the relevant HIPAA or X12 implementation guide:
| Check | Example |
|---|---|
| ISA/GS/GE/IEA envelope | Segment counts must match |
| Required elements | Missing NM1 segment → error |
| Element format | Date must be YYYYMMDD |
| Code values | Only valid X12 qualifier codes accepted |
const result = parseX12(rawEdi);if (!result.valid) { result.errors.forEach((err) => { console.error(`${err.segmentId}/${err.elementPosition}: ${err.message}`); });}Production Considerations
Section titled “Production Considerations”- Money type: All monetary fields (
paymentAmount,submitted,paid,charge,totalCharge, etc.) returnMoneyobjects from@openinsure/ratingwith integer-cent precision. UsetoDollars(m)for display formatting. - Character encoding: X12 uses ASCII. Characters outside the basic ASCII set in insured names or addresses must be transliterated before building.
- Segment terminator: The package defaults to
~. Some trading partners use\nor\r\n. Configurable inbuild*()functions. - Acknowledgment (999): The package can parse 999 functional acknowledgments to confirm your 837P was accepted.
Integration Points
Section titled “Integration Points”- Member enrollment (834) → populates the
memberstable for group health captives - Claim payment (835) → auto-reconciles claim payments against open reserves in the TigerBeetle ledger
- Professional claim (837P) → submits stop-loss claims to the reinsurer
- BOL (211) → pre-populates cargo submission fields for transportation risks