Validate EDI Last updated: 2026-09-30
ediFabric .NET and ediFabric Native validate an EDI file against its model. The model says which segments and elements are allowed. The validator checks that the file follows that model, and how far it checks is a HIPAA SNIP level. A higher level includes every check from the levels below it. The default for both products is level 2.
The rules below are the same checks in both products. .NET reads them from the C# template attributes. Native reads them from the model you pass to set_map. EDI models is how those two forms are written.
How validation runs
ediFabric .NET validates in two steps. Reading the file checks the structure of the transaction (SNIP level 1). HasErrors on the message is false when that read succeeded. IsValid() then runs the level you set in ValidationSettings.ValidationLevel. The default is LimitsAndCodes_SNIP2. The result is a MessageErrorContext of segment and data-element errors.
MessageErrorContext errors;
bool ok = message.IsValid(out errors, new ValidationSettings
{
ValidationLevel = ValidationLevel.InterSegment_SNIP4
});ediFabric Native validates while it parses, when the parse mode is 2 or 3. Mode 2 returns the transaction JSON and a validation report. Mode 3 also returns the acknowledgment. The level is validate.snip_level in the parse configuration. Values are 1 to 4. 0, or leaving it out, keeps the default of 2. Validation stops after max_errors (100 by default).
{
"validate": {
"snip_level": 4,
"skip_hl_seq": false,
"skip_seq_count": false,
"date_format": null,
"time_format": null,
"regex": null,
"max_errors": 100
}
}Parse modes and the rest of this JSON are in the Native introduction. The 837P parse call is in Convert between EDI and JSON for ediFabric Native.
HIPAA SNIP levels
Each level includes the levels before it. Setting level 4 runs levels 1, 2, 3, and 4. Setting level 2 stops before balancing and syntax rules.
| Level | What it adds | .NET | Native |
|---|---|---|---|
| 1 | Syntactical integrity of the EDI structure. | While the reader translates the file. HasErrors reports it. Set SyntaxOnly_SNIP1 to stop here. | snip_level 1. Element, code, length, HL, syntax, and balancing checks are not run. |
| 2 | Required items, repetitions, length, data types, EDI codes, HL, sequence counters, and envelope control numbers. | Default. LimitsAndCodes_SNIP2. | Default. snip_level 2. |
| 3 | Balancing. Claim and payment amounts must add up. | Balancing_SNIP3. Built into the 820, 835, 837D, 837I, and 837P templates. | snip_level 3. Runs the balancing rules on the model. |
| 4 | Syntax rules and situational rules inside a segment or composite. | InterSegment_SNIP4. Conditional attributes cover the syntax notes. Situational rules are added on the template. | snip_level 4. Runs every syntax and situational rule on the model. |
There is no level 5, 6, or 7 switch. Those HIPAA types are partner and product rules, described at the end of this page. How to validate HIPAA SNIP levels is the .NET walkthrough. Common EDI validation settings is every ValidationSettings property.
What is validated
Level 2 is this list. The .NET attribute is what you put on the template. Native reads the same fact from the OpenEDI model.
| Check | .NET | Native |
|---|---|---|
| A mandatory segment or loop is missing, or an item is in the wrong position. | The template structure and [Required] on the segment or loop. | A term marked mandatory that is absent where the model expects it. An element past the end of the segment is too many data elements. An extra component is too many components. |
| A mandatory data element is missing. | [Required]. | Usage M on an empty element. |
| A repeating segment, loop, or element repeats too many times, or too few. | List<> and [ListCount]. | The repeat count on the term. Over the maximum is too many repetitions. |
| The value is shorter or longer than the guide allows. | [StringLength]. | minLength and maxLength. A leading minus on numeric and decimal values, and one decimal point, do not count toward the length. |
| The EDI code is not in the allowed set. | [DataElement] pointing at a class with [EdiCodes]. An empty code list is treated as alphanumeric. | The code set on the element. An empty code list is treated as alphanumeric. The error is invalid EDI code. |
| The data type is wrong. | [DataElement] and the type class, such as X12_N0, X12_R, X12_AN, X12_DT, or X12_TM. | The element type: X12_N, X12_R, X12_AN, X12_DT, X12_TM, or X12_ID for a code. The types are listed below. |
| Characters in an alphanumeric value are outside the syntax set. | SyntaxSet on ValidationSettings. Off until you set Basic, Extended, CustomSyntax, or RegexSyntax. | validate.regex. Off until you set it. The same check as a .NET syntax set. |
| A DTP date does not match its format qualifier. | Element 1251 is checked when the previous element is 1250 with value D8 or RD8. | The same rule. D8 is one yyyyMMdd date. RD8 is a range of two dates separated by a hyphen. |
| An HL hierarchy is broken, or an LX or ENT counter is not 1, 2, 3. | HL validation, and [SeqCount]. Turn them off with DisableHLSegmentValidation and SkipSeqCountValidation. | Collected while the transaction is read and checked at SE. Turn them off with skip_hl_seq and skip_seq_count. |
| ISA, GS, or ST does not match its trailer, or a control number is repeated. | IsValid(). Trailer checks can be skipped with SkipTrailerValidation while you are still building a message. | ISA, GS, and ST are checked against IEA, GE, and SE: control numbers match, the segment count matches, and a control number is not reused inside its envelope. A missing trailer is an improper end of file. |
Validate EDI with templates is each .NET attribute, the order they run, and the shape of the error. X12 data elements is the type list, syntax sets, and ISA and GS.
Data types
Type checks run at level 2. Alphanumeric character checks run only when a syntax set or regex is set.
| Type | What a valid value is |
|---|---|
X12_N, X12_N0 through X12_N6 | Digits only. An optional leading minus is allowed and does not count toward the length. The digit after N is the implied decimal places. N and N0 are the same. |
X12_R | Digits and one decimal point. The point character is . unless you change it. A leading minus is allowed. The sign and the decimal point do not count toward the length. |
X12_AN | Any character, until a syntax set or regex limits the set. Basic is uppercase letters, digits, and the X12 basic specials. Extended adds lowercase and a wider set of symbols. |
X12_DT | Length 6 (yyMMdd) or 8 (yyyyMMdd), and a real calendar date. DateFormat or date_format replaces that pattern. |
X12_TM | Length 4 (hhmm), 6 (hhmmss), 7 (hhmmssf), or 8 (hhmmssff). TimeFormat or time_format replaces that pattern. |
X12_ID | A code. Checked against the code set, not against a character class. |
Syntax rules
Syntax rules run at level 4, inside one segment or one composite. They are the HIPAA syntax notes. On a .NET template they are conditional attributes. On a Native model they are the rules stored with the segment or composite.
| Rule | .NET attribute | What fails |
|---|---|---|
| Paired | [Paired] | One of the elements is present and another of the paired elements is empty. |
| Conditional | [Conditional] | The first element is present and a later element in the condition is empty. |
| List conditional | [ConditionalAny] | The first element is present and every other element in the condition is empty. |
| Exclusion | [Exclusion] | More than one of the elements is present. |
| Required | [RequiredAny] | Every element in the condition is empty. |
Situational rules are the other half of level 4. They depend on whether another element is present and on its value.
| Rule | .NET | What fails |
|---|---|---|
| Required if | A custom attribute, or the situational rule on the template. IsSituational on the error marks it for a 999 CTX segment. | The second element has one of the listed values and the first element is empty. |
| Exclusion if | The same. | The second element has one of the listed values and the first element is present. |
| Not used | [NotUsed], or the situational rule. | The element is present. It must never be sent. |
.NET does not run situational rules until they are on the template. How to validate HIPAA situational rules shows a custom attribute and the rules shipped for 270, 271, 276, and 277. Native runs the situational rules that are already in the model when snip_level is 4.
HL levels and sequence counters
Both run at level 2, at the end of the transaction, and both can be turned off.
An HL segment is checked for a single parent, a parent id only on a child, a blank parent id on the root, a parent that exists, matching parent and child ids, a child code of 1 only when a child HL follows, a numeric id, and ids in sequence. For HIPAA the root id is 1. skip_hl_seq on Native, and DisableHLSegmentValidation on .NET, skip the sequential-id part of that check.
A repeating loop that carries a sequence counter, such as LX, must number its items 1, 2, 3 in order. [SeqCount] marks that element on a .NET template. Native reads the same marker from the model. SkipSeqCountValidation and skip_seq_count turn it off.
Balancing
Level 3 checks that amounts in the transaction add up. The rules live on the HIPAA templates. Native runs the same rules from the model when snip_level is 3 or 4.
| Transaction | Rule |
|---|---|
| 820 | BPR02 equals the sum of RMR04 in loops 2300A and 2300B. |
| 820 | RMR04 equals RMR05 plus ADX01. |
| 835 | SVC02 minus the sum of the CAS amounts in loop 2110 equals SVC03. |
| 835 | CLP03 minus the CAS amounts in loops 2100 and 2110 equals CLP04. |
| 835 | The sum of CLP04 in loop 2100, minus the PLB adjustments, equals BPR02. |
| 837D | CLM02 in loop 2300 equals the sum of SV302 in loop 2400. |
| 837I | CLM02 in loop 2300 equals the sum of SV202 in loop 2400. |
| 837P | CLM02 in loop 2300 equals the sum of SV102 in loop 2400. |
Levels 5, 6, and 7
SNIP types 5, 6, and 7 are not extra engine levels. They are changes to the model.
- Type 5, external code sets. .NET loads partner codes with a code-set map, an external list, or a copy of the template. Native uses the code sets in the OpenEDI model. Edit them in the EDI spec builder and download the Native file again. A failed code is still "invalid EDI code".
- Type 6, product or type of service. The segments that apply only to one kind of service have to sit in the right place in the template or the OpenEDI schema. Extra conditions are the same syntax and situational rules as level 4.
- Type 7, a trading partner. Build a partner model: a derived or copied C# template for .NET, or an edited OpenEDI schema for Native. ISA and GS can be part of that partner model. How to modify EDI templates is the .NET copy. EDI models is the OpenEDI edit.
Where to read on
- Validate EDI with templates, How to validate HIPAA SNIP levels, How to validate HIPAA situational rules, and X12 data elements.
- Common EDI validation settings for
ValidationSettings. - Native parse configuration for
snip_level,skip_hl_seq,skip_seq_count, andregex. - X12 999 acknowledgment error codes for the codes those failures become.
