Generate X12 EDI from Java
The EDI Parser for Java can generate X12 EDI directly from Java business objects. The generation API provides the same functionality as the EDI Generation API, but runs inside your Java application without an HTTP request or JSON serialization.
EDI generation is currently supported for:
835healthcare payment and remittance advice transactions837Pprofessional claim transactions837Iinstitutional claim transactions
Generation uses the same Claim, Payment, ServiceLine, PatientSubscriber, OrgOrPerson, and related objects returned by the parser. See the Java parser object model and Javadoc API for field details.
Before using the examples, add the parser library to your project and configure a license key.
Generation Flow
Use EdiWriter to write the EDI envelope, transaction, and business objects in order:
- Create an
EdiWriteraround a JavaWriter. - Write the
ISAinterchange andGSfunctional group. - Write an
EdiTransactionfor theSTtransaction. - Write one or more
Claimobjects for an837, orPaymentobjects for an835. - Review the validation issues returned while writing.
- Close
EdiWriter; it writes the required closing segments automatically.
File ediFile = new File("837p.edi");
try (var fileWriter = new FileWriter(ediFile);
var ediWriter = new EdiWriter(fileWriter)) {
var isa = new InterchangeControl("ZZ", "123", "ZZ", "456");
var gs = new FunctionalGroup(TransactionType.PROF, "1", "2");
ediWriter.writeIsa(isa);
ediWriter.writeFunctionalGroup(gs);
EdiTransaction transaction = create837Transaction(TransactionType.PROF);
ediWriter.writeTransaction(transaction);
Claim claim = createProfessionalClaim();
var validationIssues = ediWriter.writeClaim(claim);
validationIssues.forEach(System.out::println);
}
EdiWriter assigns unique interchange and group control numbers when they are not provided. It can also assign the transaction’s originator application ID. Closing the writer completes the transaction, functional group, and interchange envelopes.
The shared envelope setup is available in GenerateEdiExampleHelper.java.
Generate an 837P Professional Claim
Use TransactionType.PROF for both the functional group and transaction. Create the claim with Claim.createProfClaim, then populate its providers, subscriber, diagnoses, and professional service lines.
var transaction = new EdiTransaction(TransactionType.PROF);
transaction.sender(createSubmitter());
transaction.receiver(createReceiver());
ediWriter.writeTransaction(transaction);
var claim = Claim.createProfClaim("1234567890", "11");
claim.billingProvider(createBillingProvider());
claim.subscriber(createSubscriber());
claim.addDiagCodes(List.of("J0300", "Z1159"));
var line = ServiceLine.createProfLine(
"99213",
new BigDecimal("100.00"),
BigDecimal.ONE,
LocalDate.of(2025, 1, 1),
List.of(1, 2));
line.procedure().addModifier("25");
claim.addLine(line);
var validationIssues = ediWriter.writeClaim(claim);
The submitter and receiver are required at the transaction level. The example also shows required billing-provider and subscriber data, including the payer associated with the subscriber.
View the complete 837P and 837I generation example in GitHub.
Generate an 837I Institutional Claim
Use TransactionType.INST and create the claim with Claim.createInstClaim. Institutional claims use revenue-code service lines and can include occurrence, value, and other institutional codes.
var claim = Claim.createInstClaim(
"1234567890",
"11",
"1",
"01",
LocalDate.of(2025, 1, 1),
LocalDate.of(2025, 1, 31));
claim.addDiagCodes(List.of("M24562", "E8359", "Z1159"));
claim.diags().get(0).isPresentOnAdmission(true);
claim.addCodeEntity(new CodeEntity(UbCodeType.OCCURRENCE, "01")
.occurrenceDate(LocalDate.of(2025, 1, 1)));
var line = ServiceLine.createInstLine(
"300", new BigDecimal("100"), new BigDecimal("5"));
line.unitType(UnitType.DAYS);
line.serviceDateFrom(LocalDate.of(2025, 1, 1));
line.serviceDateTo(LocalDate.of(2025, 1, 6));
claim.addLine(line);
var validationIssues = ediWriter.writeClaim(claim);
The complete Generate837EdiExample contains runnable methods for both professional and institutional claims.
Generate an 835 Payment
Use TransactionType.PAYMENT for the functional group and transaction. The transaction contains payment-level data and payer/payee information. Each Payment represents an adjudicated claim and contains its service lines and adjustments.
var transaction = new EdiTransaction(TransactionType.PAYMENT);
transaction.transactionHandlingType(TransactionHandlingType.PAYMENT_AND_ADVICE);
transaction.totalPaymentAmount(new BigDecimal("1000.00"));
transaction.creditOrDebitFlagCode("C");
transaction.paymentMethodType(PaymentMethodType.CHECK);
transaction.paymentDate(LocalDate.of(2026, 6, 1));
transaction.checkOrEftTraceNumber("12345");
transaction.sender(createPayer());
transaction.receiver(createPayee());
ediWriter.writeTransaction(transaction);
var payment = Payment.createPayment(
"5554555444",
"94060555410000",
AdjudicatedClaimStatus.PRIMARY,
InsurancePlanType.PPO);
payment.patient(createPatient());
payment.patientResponsibilityAmount(new BigDecimal("300.00"));
payment.addLine(createServiceLine());
var validationIssues = ediWriter.writePayment(payment);
The full example builds the payer and payee, a patient, a service line, supplemental amounts, and a claim adjustment.
View the complete 835 generation example in GitHub.
Validation
EdiWriter validates transactions, claims, and payments while writing them. Capture and review the validation issues returned by writeTransaction, writeClaim, and writePayment rather than assuming that generated EDI is valid.
var transactionIssues = ediWriter.writeTransaction(transaction);
transactionIssues.forEach(System.out::println);
var claimIssues = ediWriter.writeClaim(claim);
claimIssues.forEach(System.out::println);
Validation checks required data, transaction structure, balancing, data types, and supported healthcare code sets. Correct reported issues before sending generated EDI to a trading partner.
Parse, Modify, and Generate EDI
Because parsing and generation use the same object model, you can parse an existing transaction, update its objects, and write a new EDI file. This example increases each 837P service-line charge by 10 percent and recalculates the claim total:
try (var parser = new EdiParser(inputFile);
var fileWriter = new FileWriter(outputFile);
var ediWriter = new EdiWriter(fileWriter)) {
EdiParsingResults results = parser.parse(100);
writeIsaAndGs(ediWriter, TransactionType.PROF);
for (Claim claim : results.claims()) {
EdiTransaction transaction = claim.transaction();
transaction.creationDate(LocalDate.now());
transaction.creationTime(LocalTime.now());
ediWriter.writeTransaction(transaction);
BigDecimal total = BigDecimal.ZERO;
for (ServiceLine line : claim.lines()) {
line.chargeAmount(line.chargeAmount().multiply(BigDecimal.valueOf(1.1)));
total = total.add(line.chargeAmount());
}
claim.chargeAmount(total);
var validationIssues = ediWriter.writeClaim(claim);
validationIssues.forEach(System.out::println);
}
}
For files with multiple parsing chunks or transactions, follow the complete example’s loop and preserve the correct envelope and transaction boundaries.
View the complete parse-modify-generate example in GitHub.
Run the Examples
The complete examples are JUnit tests in the hdi.edi.gen package. Clone the repository and run the Java parser test suite from the java-parser directory:
./gradlew test
The suite writes generated files to the repository’s out_edi_files directory. TransformClaimExample is an opt-in example and can be run directly from an IDE.