Skip to content

Integra Output Format Schemas

Complete guide for integrating with Integra AL3 parser outputs.


Quick Reference

Format Schema File When to Use
JSON json-output.schema.json REST APIs, web applications, single-file processing
NDJSON json-output.schema.json Streaming, batch processing, line-by-line ingestion
CSV csv-output.schema.json Excel, SQL databases, flat file systems

Optional Reference: - al3-groups-dictionary.schema.json - Complete AL3 group catalog with all 278 groups and their data elements


Output Formats Explained

JSON Format (Array with Metadata)

Structure:

{
  "policies": [
    {
      "code": "2TRG",
      "level": 2,
      "iteration": 1,
      "dataElements": {
        "Transaction Type": "01"
      },
      "children": [...]
    }
  ],
  "metadata": {
    "parseTime": "2026-01-31T17:20:00Z",
    "groupCount": 2
  }
}

Note: Validation results are provided via HTTP headers (X-Integra-Validation-Status, etc.) and the /v1/validate endpoint. They are not included in the parsed JSON body.

Use Cases: - REST API responses - Single-file processing - When you need metadata (parse time, counts)

Schema: json-output.schema.json


NDJSON Format (Newline-Delimited JSON)

Structure:

{"code":"2TRG","level":2,"dataElements":{...},"children":[...]}
{"code":"5BPI","level":5,"dataElements":{...}}

Each line is a complete JSON object (same as items in the JSON policies array).

Use Cases: - Streaming data pipelines - Batch processing (process line-by-line) - BigQuery, Snowflake, Kafka - Large files (memory-efficient)

Schema: Same json-output.schema.json - each line is one Group object


CSV Format (Flattened)

Structure: The CSV output follows RFC 4180 standards. - Forced Quotes: All fields are enclosed in double quotes "". - Escaping: Double quotes within data are escaped as "". - Flattened: Hierarchical data is flattened into rows, with ParentID and NodeID columns to reconstruct relationships.

"ID","RefID","Key","Name","FormattedValue","ActualValue","RawValue","GroupCode","Level","NodeID","ParentID"
"1","1","5BPI","Premium Amount","$1234.56","1234.56","0000123456F","5BPI","5","12","4"
"2","1","5BPI","Effective Date","2024-01-15","2024-01-15","20240115","5BPI","5","12","4"

Columns Explained:

Column Description
ID Unique ID for the data element row
RefID Reference ID (internal use)
Key Data Element Name (e.g. "Premium Amount")
Name Same as Key (for backwards compatibility)
FormattedValue Value formatted for display (e.g. "$1234.56")
ActualValue Unformatted string representation of the typed value (e.g. "1234.56")
RawValue Original fixed-width raw value from AL3 file
GroupCode AL3 Group Code (e.g. "5BPI")
Level Group Level (e.g. "5")
NodeID Unique ID of the Group this element belongs to
ParentID ID of the parent Group (allows reconstructing the tree)

Understanding Hierarchy in CSV: Since CSV is flat, we use NodeID and ParentID to represent the AL3 tree structure. - Every Group is assigned a unique NodeID. - Every Group (except roots) refers to its parent via ParentID. - You can join rows on NodeID = ParentID to find children.

Field Logic Patterns (JSON/NDJSON)

In JSON output (and NDJSON), the primary key contains the Actual Value. Additional keys with suffixes are provided when representations differ.

1. Actual Value (Primary Key)

The standard field name contains the processed, typed value (as number, string, boolean, or date string).

{
  "Premium Amount": 1234.56,      // Numeric
  "Effective Date": "2025-01-17", // String (ISO Date)
  "Active": true                  // Boolean
}

2. Formatted Value (- Formatted)

Present only if the human-readable description differs from the Actual Value. Common for Coded fields where Actual is the code (e.g. "01") and Formatted is the description (e.g. "Basic Coverage").

{
  "Coverage Type": "01",
  "Coverage Type - Formatted": "Basic Coverage"
}

3. Raw Value (- Raw)

Present only if the original raw bytes differ from the Actual/Formatted representations. Useful for debugging or exact reproduction.

{
  "Premium Amount": 1234.56,
  "Premium Amount - Raw": "0000123456F"
}

If the raw value is effectively same as actual (e.g. text fields), this key is omitted to save space.


Personal Name Expansion

Names with format code P (Personal) are expanded into separate components:

Input (AL3):

PSMITH    JANE            ANN       JR              MS   

Output (JSON):

{
  "Insured Name - Prefix": "MS",
  "Insured Name - FirstName": "JANE",
  "Insured Name - MiddleName": "ANN",
  "Insured Name - LastName": "SMITH",
  "Insured Name - Suffix": "JR",
  "Insured Name - Raw": "PSMITH    JANE            ANN       JR              MS   "
}

Format Codes:

  • P (Personal): Expanded into components (shown above)
  • C (Commercial): Single consolidated string
  • F (Family): Single consolidated string
  • G (Generic): Single consolidated string
  • Blank: Single consolidated string

Non-Personal Names:

{
  "Agent Name": "ABC INSURANCE AGENCY INC",
  "Agent Name - Raw": "CABC INSURANCE AGENCY INC"
}

Integration Examples

Python

JSON Format

import json

# Load JSON file
with open('output.json') as f:
    data = json.load(f)

# Iterate through policies
for policy in data['policies']:
    print(f"Group: {policy['code']} (Level {policy['level']})")

    # Access data elements
    elements = policy.get('dataElements', {})
    if 'Premium Amount' in elements:
        print(f"  Premium: {elements['Premium Amount']}")
        print(f"  Premium (Raw): {elements.get('Premium Amount - Raw')}")

    # Process children recursively
    for child in policy.get('children', []):
        print(f"  Child: {child['code']}")

NDJSON Format (Memory-Efficient)

import json

# Process line-by-line (no memory issues with large files)
with open('output.ndjson') as f:
    for line in f:
        policy = json.loads(line)

        # Same structure as JSON array items
        print(f"Group: {policy['code']}")
        print(f"Data: {policy['dataElements']}")

        # Can process millions of records efficiently

JavaScript/Node.js

JSON Format

const fs = require('fs');

// Load JSON file
const data = JSON.parse(fs.readFileSync('output.json', 'utf8'));

// Iterate through policies
data.policies.forEach(policy => {
  console.log(`Group: ${policy.code} (Level ${policy.level})`);

  // Access data elements
  const elements = policy.dataElements || {};
  if (elements['Premium Amount']) {
    console.log(`  Premium: ${elements['Premium Amount']}`);
  }

  // Process children
  (policy.children || []).forEach(child => {
    console.log(`  Child: ${child.code}`);
  });
});

NDJSON Format (Stream Processing)

const fs = require('fs');
const readline = require('readline');

// Stream-based processing (memory-efficient)
const rl = readline.createInterface({
  input: fs.createReadStream('output.ndjson'),
  crlfDelay: Infinity
});

rl.on('line', (line) => {
  const policy = JSON.parse(line);

  console.log(`Group: ${policy.code}`);
  console.log(`Data: ${JSON.stringify(policy.dataElements)}`);
});

rl.on('close', () => {
  console.log('Processing complete');
});

SQL (PostgreSQL with JSONB)

Import JSON Data

-- Create table
CREATE TABLE al3_policies (
  id SERIAL PRIMARY KEY,
  data JSONB NOT NULL
);

-- Import JSON (flattened from policies array)
-- Use a script to split the array into individual rows
COPY al3_policies (data) FROM '/path/to/policies.ndjson';

Query Examples

-- Get all premium amounts
SELECT 
  data->>'code' as group_code,
  data->'dataElements'->>'Premium Amount' as premium,
  data->'dataElements'->>'Effective Date' as effective_date
FROM al3_policies
WHERE data->>'level' = '5';

-- Search for specific names
SELECT 
  data->>'code',
  data->'dataElements'->>'Insured Name - LastName' as last_name,
  data->'dataElements'->>'Insured Name - FirstName' as first_name
FROM al3_policies
WHERE data->'dataElements'->>'Insured Name - LastName' = 'SMITH';

-- Aggregate by group code
SELECT 
  data->>'code' as group_type,
  COUNT(*) as count,
  AVG((data->'dataElements'->>'Premium Amount')::numeric) as avg_premium
FROM al3_policies
GROUP BY data->>'code';

Apache Spark (PySpark)

from pyspark.sql import SparkSession

# Initialize Spark
spark = SparkSession.builder.appName("AL3Parser").getOrCreate()

# Read NDJSON (most efficient for Spark)
df = spark.read.json("output.ndjson")

# Show schema
df.printSchema()

# Query data
df.select(
    "code",
    "level",
    "dataElements.Premium Amount"
).show()

# Filter and transform
premiums = df.filter(df.code == "5BPI") \
    .select("dataElements.Premium Amount") \
    .collect()

Pandas (Python)

import pandas as pd
import json

# Load NDJSON into DataFrame
with open('output.ndjson') as f:
    data = [json.loads(line) for line in f]

df = pd.DataFrame(data)

# Expand dataElements into columns
elements_df = pd.json_normalize(df['dataElements'])
result = pd.concat([df[['code', 'level', 'iteration']], elements_df], axis=1)

# Analyze
print(result['Premium Amount'].describe())
print(result.groupby('code').size())

Schema Validation

Using ajv-cli (Node.js)

# Install
npm install -g ajv-cli ajv-formats

# Validate JSON output
ajv validate \
  -s json-output.schema.json \
  -d output.json \
  --spec=draft2020

# Validate NDJSON (validate each line)
cat output.ndjson | while read line; do
  echo "$line" | ajv validate -s json-output.schema.json -d - --spec=draft2020
done

Using Python jsonschema

import json
import jsonschema

# Load schema
with open('json-output.schema.json') as f:
    schema = json.load(f)

# Validate JSON
with open('output.json') as f:
    data = json.load(f)
    jsonschema.validate(data, schema)

# Validate NDJSON
with open('output.ndjson') as f:
    for line in f:
        policy = json.loads(line)
        # Validate against Group definition
        jsonschema.validate(policy, schema['$defs']['Group'])

Complete Examples

Example 1: Policy with Coverage

Input AL3: Policy with basic information and coverage details

Output JSON:

{
  "policies": [
    {
      "code": "2TRG",
      "level": 2,
      "iteration": 1,
      "dataElements": {
        "Transaction Type": "01"
      },
      "children": [
        {
          "code": "5BPI",
          "level": 5,
          "iteration": 1,
          "dataElements": {
            "Policy Number": "POL123456",
            "Effective Date": "2025-01-17",
            "Effective Date - Raw": "20250117",
            "Premium Amount": "1234.56",
            "Premium Amount - Raw": "0000123456F",
            "Insured Name - Prefix": "MS",
            "Insured Name - FirstName": "JANE",
            "Insured Name - LastName": "SMITH",
            "Insured Name - Raw": "PSMITH    JANE            ..."
          },
          "children": [
            {
              "code": "7COV",
              "level": 7,
              "iteration": 1,
              "dataElements": {
                "Coverage Type": "01",
                "Coverage Type - Formatted": "Baseboard | Basic",
                "Coverage Limit": "500000.00",
                "Coverage Limit - Raw": "0050000000{"
              },
              "children": []
            }
          ]
        }
      ]
    }
  ],
  "metadata": {
    "parseTime": "2026-01-31T20:30:00Z",
    "groupCount": 3
  }
}

Same as NDJSON:

{"code":"2TRG","level":2,"iteration":1,"dataElements":{"Transaction Type":"01"},"children":[...]}
{"code":"5BPI","level":5,"iteration":1,"dataElements":{...},"children":[...]}
{"code":"7COV","level":7,"iteration":1,"dataElements":{...},"children":[]}

FAQ

Q: Do I need both json-output.schema.json and al3-groups-dictionary.schema.json?

A: No. You only need json-output.schema.json for integration. The dictionary is an optional reference to see all possible AL3 groups and their fields.

Q: How do I handle NDJSON vs JSON?

A: Use the same schema (json-output.schema.json). For NDJSON, validate each line against the Group definition at $defs/Group.

Q: Why are some fields missing "-Raw" suffix?

A: Only fields with different formatted vs raw values include the "-Raw" suffix. If the value is already in final form (like text fields), no "-Raw" suffix is added.

Q: How do I know which groups will appear in my output?

A: It depends on your AL3 input file. Use the al3-groups-dictionary.schema.json to see all possible groups and their fields.

Q: What if a personal name doesn't have all components?

A: Missing components are omitted. For example, if there's no middle name, the "MiddleName" field won't appear.

Q: How do I handle hierarchical data?

A: Use the children array. Each Group can contain child Groups, forming a tree structure that mirrors the AL3 hierarchy.

Integra Schema Definitions

This directory contains the public JSON schemas for Integra output formats.

API Documentation (Swagger/OpenAPI)

Integra provides an interactive API documentation and testing interface.

  • Swagger UI: Visit /swagger/index.html (e.g., http://localhost:8080/swagger/index.html) to explore endpoints and test requests interactively.
  • OpenAPI Spec: The raw OpenAPI 3.0 specification is available at /openapi.yaml.

You can import openapi.yaml into tools like Postman or Insomnia to automatically configure the API collection.

API Validation Headers

All API responses (JSON, CSV, Parquet, NDJSON) include the following headers to provide immediate validation feedback:

  • X-Integra-Validation-Status: true if valid, false if errors exist.
  • X-Integra-Error-Count: Number of validation errors.
  • X-Integra-Warning-Count: Number of validation warnings.
  • X-Processing-Time: Total processing duration.

If X-Integra-Validation-Status is false, you can request the full validation report by sending the same file to the /v1/validate endpoint.


Support

For questions or issues with schema integration: - Review the schema files in this directory - Check the examples above - Validate your output against the schemas - Contact support with specific validation errors


AL3 Data Types Reference

Understanding AL3 data types is crucial for interpreting values and generating valid input.

Numeric Types

Type Description Example Input Parsed Value
N0 Numeric (integer) 00123 123
N2 Numeric (2 implied decimals) 12345 123.45
S0 Signed Numeric (integer) 0012K (-122) -122
S2 Signed Numeric (2 decimals) 1234K -123.42
WD Whole Dollars (Signed) 00100 100
PCT Percentage (3 integer + 1 decimal) 123 12.3
MOD Modification Factor 12345 1.2345

Note: Signed fields in AL3 often use "overpunch" characters (last digit + sign combined). Integra automatically decodes these into standard negative numbers.

Date & Time

Type Format Example Description
DT8 YYYYMMDD 20250117 Standard date format
DT6 YYMMDD 250117 Legacy 2-digit year (avoid in generation)
D4Y MMYYYY 012025 Month and Year only
TI HHMM 1430 24-hour time
TM6 HHMMSS 143000 Time with seconds

Text & Coded

Type Description Notes
AN Alphanumeric Uppercase A-Z, 0-9, special chars
CD ACORD Code Value is a code (e.g., "01"). See schema for descriptions.
IC Industry Code Use defined industry standard codes.
Y/N Boolean "Y" = true, "N" = false, "?"/Blank = null

Validation Rules

When generating or validating AL3 files, Integra enforces the following strict rules:

1. Structural Integrity

  • Header (1MHG): Every transaction must start with a 1MHG (Message Header) group.
  • Trailer (1MTG): Every transaction must end with a 1MTG (Message Trailer) group.
  • Hierarchy: Groups must follow the parent-child relationship defined in the ACORD AL3 standard. A child group cannot appear without its parent.

2. Field Validation

  • Required Fields: Fields marked as Mandatory (M) in the schema must be present and non-empty.
  • Type Safety:
    • Numeric fields must contain valid digits (or sign characters).
    • Date fields must form valid calendar dates (e.g. 20250230 is invalid).
  • Length: Values must fit within the defined fixed width.
    • Generation: Values exceeding the length will cause a validation error.
    • Formatting: Short values are automatically padded (zeros for numeric/dates, spaces for text).

3. Logic & Totals

  • 1MTG Validation: The Message Trailer contains the total character count (Length) of the transaction. Integra validates that the parsed message length matches this value to ensure no data was truncated.

Version: 1.0.0
Last Updated: 2026-02-01