Python port of the CMS Integrated Outpatient Code Editor (I/OCE)
Project description
PyOCE
PyOCE is a production-grade Python port of the CMS Integrated Outpatient Code Editor (I/OCE) — the official rules engine used by the Centers for Medicare & Medicaid Services to edit, group, and price hospital outpatient claims under the OPPS (Outpatient Prospective Payment System).
What Does the I/OCE Do?
The I/OCE applies 150+ clinical and administrative edit rules to each outpatient claim, including:
- Validity checks — bill type, dates, diagnosis codes, HCPCS/CPT codes, modifiers, revenue codes
- NCCI edits — procedure-to-procedure code pairs that should not be billed together
- APC assignment — grouping services into Ambulatory Payment Classifications for pricing
- Status indicator assignment — determining whether each line is payable, packaged, or denied
- Discounting and packaging — applying OPPS payment logic (multiple procedure discounting, composite APCs, etc.)
- Specialty handling — FQHC visits, biosimilars, telehealth, mental health, non-opioid therapies, Section 603, and more
PyOCE replicates this logic in pure Python, verified against the CMS Java reference implementation.
Features
- Parity-tested — Cross-validated against official CMS Java TESTDB outputs across thousands of claims
- High throughput — Optimized LMDB-backed reference data with zero-copy memory mapping; processes 1,000+ claims per second
- Zero-config data — Reference database is bundled as a compressed archive and auto-extracted on first use
- Version-aware — Full support for IOCE version ranges; lookups respect historical data boundaries
- Thread-safe — LMDB supports concurrent reads from multiple processes/threads
- Simple API — Plain
dictin, plaindictout; no ORM, no protobuf, no ceremony - Self-contained — Single package with bundled reference data; no external services needed
- Reusable engine —
IoceComponentgives access to edit descriptions, APC descriptions, and other lookup utilities
Installation
pip install pyoce
Requirements: Python 3.12+, no system dependencies beyond the Python standard library.
On first use, the bundled reference database (~2.7 MB compressed, ~10 MB uncompressed LMDB) is automatically inflated to ~/.cache/pyoce/.
Quick Start
import pyoce
claim = {
"claimId": "DEMO-001",
"billType": "131",
"dateStarted": "20240101",
"dateEnded": "20240101",
"principalDiagnosisCode": {"diagnosis": "J449"},
"lineItemList": [
{
"serviceDate": "20240101",
"hcpcs": "99213",
"revenueCode": "0510",
"unitsInput": "1",
"charge": "15000",
}
],
}
result = pyoce.process_claim(claim)
# Inspect results
print(f"Return code: {result['processingInformation']['returnCode']}")
for li in result["lineItemList"]:
print(f" {li['hcpcs']} → APC {li['paymentApc']}, SI {li['statusIndicator']}")
# Look up edit descriptions (human-readable)
engine = pyoce.IoceComponent()
assert result is engine.process(claim) # same API, reusable
print(engine.get_edit_description("001"))
print(engine.get_apc_description("5021"))
Input Fields
| Field | Type | Notes |
|---|---|---|
claimId |
str |
Unique claim identifier |
billType |
str |
3-char bill type (e.g. "131" for hospital outpatient) |
dateStarted / dateEnded |
str |
YYYYMMDD format |
receiptDate |
str |
YYYYMMDD, used for version range lookups |
principalDiagnosisCode |
dict |
{"diagnosis": "J449", "presentOnAdmission": "Y"} |
secondaryDiagnosisCodeList |
list[dict] |
Additional diagnosis codes |
lineItemList |
list[dict] |
Per-line: hcpcs, revenueCode, serviceDate, unitsInput, charge, optional modifiers |
See the src/pyoce/model/external/ package for the full external model.
Output Fields
The output dict mirrors the input structure with additions:
- Claim-level:
claimDisposition,claimRejectionEditList,claimDenialEditList, etc. - Line-level:
paymentApc,statusIndicator,paymentIndicator,discountingFormula,rejectionDenialFlag, edit lists per buffer type - Processing metadata:
returnCode,version, timing information
How It Works
Claims flow through a 5-phase sequential pipeline:
INITIALIZATION → PREPROCESSING → PROCESSING → POSTPROCESSING → FINALIZATION
| Phase | Responsibility |
|---|---|
| Initialization | Load and validate reference data tables (cached after first claim) |
| Preprocessing | Copy input to internal model, validate bill type/dates, load table data per claim, validate contractor overrides |
| Processing | Execute 150+ edit rules, routed by bill type (see below) |
| Postprocessing | Calculate disposition, payment flags, discounting, composite APCs, units |
| Finalization | Copy internal processing state back to external output model |
Bill Type Routing
The processing phase dispatches to one of 24 bill-type-specific logic paths based on the claim's bill type, OPPS/non-OPPS flag, and condition codes. The most common path — 13x (Hospital Outpatient) — applies approximately 150 sequential rule checks including NCCI edits, status/payment indicator assignment, add-on code pairing, modifier validation, and specialty payment logic.
For a complete bill-type routing table, see the internal architecture documentation.
Reference Data
PyOCE ships with a pre-built LMDB database containing 39 CMS reference tables (213,277 records) covering APC assignments, HCPCS code attributes, ICD-10 diagnoses, NCCI edit pairs, offset tables, status/payment indicators, composite APCs, and all add-on code mappings — versioned across the full IOCE version range.
Overriding the Database Location
from pyoce.dao.provider import LmdbDataProvider
# Point to a custom LMDB database
LmdbDataProvider.reset_instance()
provider = LmdbDataProvider(env_path="/path/to/pyoce.mdb")
Rebuilding the Database
To rebuild the LMDB database from CMS flat files:
uv run python scripts/build_db.py
This reads Report-Tables/ (not included in the repository) and writes src/pyoce/data/pyoce.mdb.xz.
Development
# Clone and install in editable mode with dev dependencies
git clone https://github.com/cms-gov/pyoce.git
cd pyoce
uv pip install -e ".[dev]"
CI Verification
Run the exact checks used in CI:
uv run ruff format --check . # code formatting
uv run ruff check . # linting
uv run mypy src # strict type checking
uv run pytest # full test suite
Testing
| Suite | Command | Requires |
|---|---|---|
| Unit tests | uv run pytest tests/unit |
Nothing |
| Integration (parity) | uv run pytest tests/integration |
cms_mf/claims.json (CMS TESTDB) |
| Full suite | uv run pytest |
cms_mf/claims.json |
Unit tests cover flag enums, data providers, DAOs, external models, converters, utilities, and individual logic rules. Integration tests feed real CMS TESTDB claims through the engine and compare output field-by-field against the Java reference implementation.
Parity Report
Generate a detailed mismatch report for all claims with expected outputs:
PYTHONPATH=. uv run python tests/integration/test_parity_report.py
Or test a single claim by ID:
PYTHONPATH=. uv run python tests/integration/test_parity_report.py --claim <id>
Project Structure
src/pyoce/
├── __init__.py # Public API: process_claim(), IoceComponent
├── api/ # Entry points, claim execution engine
├── model/
│ ├── external/ # Public claim/line models (dataclasses)
│ └── internal/ # Processing state models (~50 fields per claim)
├── logic/
│ ├── initialization/ # Phase 1: load & validate tables
│ ├── preprocessing/ # Phase 2: validate inputs, load per-claim data
│ ├── processing/ # Phase 3: 150+ edit rules, bill-type paths
│ │ ├── addon/ # Add-on code pairing logic
│ │ └── specialty/ # FQHC, biosimilar, telehealth, S603, etc.
│ ├── postprocessing/ # Phase 4: disposition, flags, composites
│ └── finalization/ # Phase 5: output marshaling
├── dao/ # Data access layer (42 table DAOs, description provider)
├── rsc/ # Flag enums, edit registry, constants
├── util/ # FlagSet, Navigator, range maps, utilities
└── data/ # Bundled LMDB database (compressed)
License
Apache License, Version 2.0 — see LICENSE.
Contributing
See CONTRIBUTING.md for development setup, coding standards, and pull request guidelines.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyoce-0.1.0.tar.gz.
File metadata
- Download URL: pyoce-0.1.0.tar.gz
- Upload date:
- Size: 3.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
00b82ae43d44c5fed7825c46c953c5119722300d55e2e4346ac391af790e0dea
|
|
| MD5 |
daa2a8fd7946c5288f15ab089bb1f0d3
|
|
| BLAKE2b-256 |
3f692a42b73ffc427d829decff4a387e7bf2391ad05aa89b95c7a62dc80d34ce
|
Provenance
The following attestation bundles were made for pyoce-0.1.0.tar.gz:
Publisher:
publish.yml on Bedrock-Billing/pyoce
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyoce-0.1.0.tar.gz -
Subject digest:
00b82ae43d44c5fed7825c46c953c5119722300d55e2e4346ac391af790e0dea - Sigstore transparency entry: 1465410308
- Sigstore integration time:
-
Permalink:
Bedrock-Billing/pyoce@04dc5ab9d4c69cd764b7743e8f0b7df0d0b226f2 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Bedrock-Billing
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@04dc5ab9d4c69cd764b7743e8f0b7df0d0b226f2 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyoce-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pyoce-0.1.0-py3-none-any.whl
- Upload date:
- Size: 3.3 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f55810c1d036b6cd7cf9ba4ba8c2f1d67f997f19c9695976fb557cdb2c45e7be
|
|
| MD5 |
8cc74ed12a89f5b4f13efcd81c511756
|
|
| BLAKE2b-256 |
18653bf115ff1724555b647762041f62eba83aa468f593a5644d9fe37a9428b2
|
Provenance
The following attestation bundles were made for pyoce-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on Bedrock-Billing/pyoce
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyoce-0.1.0-py3-none-any.whl -
Subject digest:
f55810c1d036b6cd7cf9ba4ba8c2f1d67f997f19c9695976fb557cdb2c45e7be - Sigstore transparency entry: 1465410382
- Sigstore integration time:
-
Permalink:
Bedrock-Billing/pyoce@04dc5ab9d4c69cd764b7743e8f0b7df0d0b226f2 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Bedrock-Billing
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@04dc5ab9d4c69cd764b7743e8f0b7df0d0b226f2 -
Trigger Event:
release
-
Statement type: