Skip to main content
fi-fhir docs

Installation

Getting Started with fi-fhir

This guide walks you through parsing your first healthcare message, understanding the output, and running a basic workflow.

Installation

Option 1: Build from Source

# Clone the repository
git clone https://gitlab.flexinfer.ai/libs/fi-fhir.git
cd fi-fhir

# Build the CLI
make build

# Verify installation
./bin/fi-fhir --version

Option 2: Go Install

go install gitlab.flexinfer.ai/libs/fi-fhir/cmd/fi-fhir@latest

Option 3: Docker

docker pull registry.gitlab.flexinfer.ai/libs/fi-fhir:latest
docker run registry.gitlab.flexinfer.ai/libs/fi-fhir:latest --version

Option 4: TypeScript SDK

npm install @fi-fhir/sdk

Parse Your First Message

Let's parse a sample HL7v2 ADT (Admit/Discharge/Transfer) message.

1. Create a Sample Message

Save this as sample.hl7:

MSH|^~\&|EPIC|HOSPITAL|FHIRSERVER|DEST|20240115120000||ADT^A01|12345|P|2.5
EVN|A01|20240115120000
PID|1||MRN12345^^^EPIC^MR||Smith^John^A||19800115|M|||123 Main St^^Springfield^IL^62701||555-123-4567|||||SSN123456789
PV1|1|I|ICU^101^A^HOSPITAL||||1234567890^Jones^Sarah^M^^^MD|||MED||||||||VN98765|||||||||||||||||||||||||20240115100000

2. Parse the Message

fi-fhir parse --format hl7v2 --pretty sample.hl7

3. Understand the Output

You'll see a JSON event like this:

{
  "meta": {
    "id": "evt_abc123",
    "type": "patient_admit",
    "source": "default",
    "format": "HL7v2",
    "timestamp": "2024-01-15T12:00:00Z",
    "source_message_id": "12345"
  },
  "patient": {
    "mrn": "MRN12345",
    "name": {
      "family": "Smith",
      "given": ["John", "A"]
    },
    "birthDate": "1980-01-15",
    "gender": "M",
    "address": {
      "line": ["123 Main St"],
      "city": "Springfield",
      "state": "IL",
      "postalCode": "62701"
    }
  },
  "encounter": {
    "identifier": "VN98765",
    "class": "inpatient",
    "location": "ICU-101-A"
  }
}

Key observations:

  • The message type ADT^A01 became the semantic event patient_admit
  • HL7 field paths like PID.5 are now structured JSON (patient.name)
  • Healthcare-specific encoding (like ^ delimiters) is handled automatically

The Three-Phase Pipeline

fi-fhir processes messages through three distinct phases:

Phase 1: Byte Normalization

  • Character encoding detection (UTF-8, ISO-8859-1, etc.)
  • Line ending normalization (CR, LF, CRLF)
  • BOM marker handling

Phase 2: Syntactic Parsing

  • Delimiter extraction from MSH segment
  • Segment and field splitting
  • Escape sequence handling

Phase 3: Semantic Extraction

  • Event type classification (A01 → patient_admit)
  • Identifier extraction and validation
  • Field mapping to canonical model

This pipeline is visualized interactively in the Playground.

Run a Basic Workflow

Workflows route events to destinations based on filters.

1. Create a Workflow Configuration

Save this as workflow.yaml:

workflow:
  name: basic_routing
  version: "1.0"

  routes:
    - name: log_admits
      filter:
        event_type: patient_admit
      actions:
        - type: log
          level: info
          message: "Patient admitted: {{.Patient.Name.Family}}, {{.Patient.Name.Given}}"

2. Run the Workflow

# Parse and pipe to workflow
fi-fhir parse --format hl7v2 sample.hl7 | fi-fhir workflow run --config workflow.yaml

# Or use dry-run to see what would happen without side effects
fi-fhir parse --format hl7v2 sample.hl7 | fi-fhir workflow run --dry-run --config workflow.yaml

3. Expected Output

INFO  Patient admitted: Smith, [John A]

Parse Different Formats

CSV Patient Data

# Create sample CSV
cat > patients.csv << 'EOF'
mrn,first_name,last_name,dob,gender
12345,John,Smith,1980-01-15,M
67890,Jane,Doe,1990-06-20,F
EOF

# Parse
fi-fhir parse --format csv --pretty patients.csv

EDI 837P Claim

# Parse an EDI claim file
fi-fhir parse --format edi --pretty claim.edi

CDA/CCDA Document

# Parse a clinical document
fi-fhir parse --format cda --pretty document.xml

Validate Configuration

Before running in production, validate your configurations:

# Validate workflow configuration
fi-fhir workflow validate workflow.yaml

# Validate source profile
fi-fhir validate profile epic_adt.yaml

# Show current configuration
fi-fhir config show

Quick Start with Persistence

By default, fi-fhir serve uses in-memory stores — events vanish on restart. To enable persistent storage, start PostgreSQL and set environment variables.

1. Start PostgreSQL

# Using docker-compose (includes PostgreSQL, Qdrant, Temporal)
docker-compose up -d

# Or use an existing PostgreSQL instance

2. Configure Environment

export FI_FHIR_DATABASE_DRIVER=postgres
export FI_FHIR_DATABASE_HOST=localhost
export FI_FHIR_DATABASE_PORT=5432
export FI_FHIR_DATABASE_NAME=fi_fhir
export FI_FHIR_DATABASE_USERNAME=fi_fhir
export FI_FHIR_DATABASE_PASSWORD=fi_fhir_dev
export FI_FHIR_DATABASE_SSL_MODE=disable

3. Start the Server

fi-fhir serve --workflow configs/adt-workflow.yaml

You should see:

Profile store: PostgreSQL
Event store: PostgreSQL
Workflow lifecycle store: PostgreSQL

Or use the make dev shortcut which handles all of the above:

make dev

4. Verify Persistence

Submit a message via GraphQL at http://localhost:8081, restart the server, and query events — they persist across restarts.

Graceful Degradation

When database env vars are absent, fi-fhir falls back to in-memory stores with a warning. No crash, no configuration required for basic usage.

Next Steps

To learn about...Read...
Source Profile configurationSource Profiles
Workflow filters and actionsWorkflows
FHIR resource generationFHIR Output
Interactive learningPlayground Tutorial
Full development setupDevelopment Setup

Common Issues

"Unknown format"

Ensure you specify --format correctly: hl7v2, csv, edi, cda, or fhir.

"Failed to parse message"

Check that your message is well-formed. Use --verbose flag for detailed error messages:

fi-fhir parse --format hl7v2 --verbose sample.hl7

"Warning: Missing segment"

This is often expected behavior. Healthcare data is messy, and fi-fhir records warnings while continuing to parse. See Source Profiles for tolerance configuration.