Files
cyclone/docs/reference/co-medicaid.md
T
Tyler c62826daea feat(sp9): multi-payer, multi-NPI, SFTP stub for dzinesco/TOC
- providers table seeded with 3 NPIs (Montrose, Delta, Salida)
- payers + payer_configs (per-tx config) join table
- clearhouse singleton (dzinesco identity, SFTP block, filename block)
- config/payers.yaml loader with Pydantic schema validation
- cyclone/edi/filenames.py: HCPF X12 File Naming Standards helpers
- cyclone/clearhouse/sftp.py: stub that copies to ./var/sftp/staging/...
- cyclone/secrets.py: macOS Keychain wrapper via keyring
- 11 new validation rules R200-R210 (CO MAP + HCPF naming)
- 6 new API endpoints (/api/clearhouse/*, /api/config/*, /api/admin/reload-config)
- migration 0007
- 72 new tests (646 total passing, was 574)

See spec: docs/superpowers/specs/2026-06-20-cyclone-multi-payer-npi-sftp-design.md
2026-06-20 23:07:31 -06:00

5.8 KiB
Raw Blame History

Colorado Medicaid — payer specifics

Cyclone's CO Medicaid (PayerConfig.co_medicaid() and PayerConfig835.co_medicaid_835()) factories encode the trading-partner and code-set rules that the Colorado Department of Health Care Policy & Financing (HCPF) requires.

Trading Partner IDs (TPID)

Role 837P 835
Sender SKCO0 (varies; usually the clearinghouse)
Receiver COHCPF (varies)

These appear in the NM1*PR (payer) and NM1*40 (receiver) segments of the 837P file.

dzinesco's TPID (clearinghouse identity)

Field Value
Clearinghouse name dzinesco
dzinesco TPID 11525703
Submitter name (NM1*41) Dzinesco
Submitter contact Tyler Martinez tyler@dzinesco.com
SFTP host mft.gainwelltechnologies.com
SFTP username colorado-fts\coxix_prod_11525703
SFTP outbound dir /CO XIX/PROD/coxix_prod_11525703/FromHPE
SFTP inbound dir /CO XIX/PROD/coxix_prod_11525703/ToHPE

dzinesco's 3 billing-provider NPIs

All 3 NPIs are registered to the same Montrose corporate office. They share tax ID 721587149 and taxonomy 251E00000X (Home Health).

NPI Label Legal name Address
1881068062 Montrose TOC, Inc. 1100 East Main St, Suite A, Montrose, CO 814014063
1851446637 Delta TOC, Inc. 1100 East Main St, Suite A, Montrose, CO 814014063
1467507269 Salida TOC, Inc. 1100 East Main St, Suite A, Montrose, CO 814014063

Production data (June 2026) confirms all 3 NPIs submit through the same Montrose address block. See SP9 spec docs/superpowers/specs/2026-06-20-cyclone-multi-payer-npi-sftp-design.md.

SFTP submission to Gainwell

dzinesco submits 837P files to Gainwell's MFT (Managed File Transfer) at mft.gainwelltechnologies.com. The full SFTP path layout is specified by the user (2026-06-20):

  • Outbound (we send): /CO XIX/PROD/coxix_prod_11525703/FromHPE
  • Inbound (HPE/Gainwell sends to us): /CO XIX/PROD/coxix_prod_11525703/ToHPE

File naming

Per the HCPF X12 File Naming Standards Quick Guide (https://hcpf.colorado.gov/tp-x12-filenaming):

  • Outbound (we send): TPID-TransactionType-yyyymmddhhmmssSSS-1of1.X12
    • Example: 11525703-837P-20260620132243505-1of1.x12
    • 17-digit millisecond precision, Mountain Time (NOT UTC)
    • "1of1" is the only accepted sequence value
  • Inbound (HPE sends): TP<TPID>-<OrigTx>_M<Tracking>-<ts>-1of1_<FileType>.x12
    • Example: TP11525703-837P_M019048402-20260520231513488-1of1_999.x12
    • FileType is one of: 999, TA1, 270, 271, 276, 277, 277CA, 278, 820, 834, 835, ENCR
    • 277CA is distinguished by ST*277CA content (filename uses 277)

SP9 stub vs SP13 wire-up

The SP9 SFTP client is a stub that writes generated 837 files to ./var/sftp/staging/{outbound_path}/{filename} instead of opening a real SFTP connection. The structural interface matches the future paramiko-backed implementation, so SP13 is a one-file swap.

clearhouse.sftp_block.stub is true by default. Set to false (and create the Keychain entry, see below) to enable real SFTP.

Keychain setup (one-time, by operator)

security add-generic-password -s cyclone -a sftp.gainwell.password -w '<password>'
security find-generic-password -s cyclone -a sftp.gainwell.password -w

The cyclone/secrets.py module fetches the secret by name. When the entry is missing or keyring is not installed, the SFTP stub falls back to <stub-secret> so the local flow still works.

Verification

# List providers (3 NPIs)
curl http://localhost:8000/api/config/providers

# List payers (1 = CO_TXIX)
curl http://localhost:8000/api/config/payers

# List CO_TXIX configs
curl http://localhost:8000/api/config/payers/CO_TXIX/configs

# Clearhouse identity
curl http://localhost:8000/api/clearhouse

# Submit 2 claims to the SFTP stub
curl -X POST http://localhost:8000/api/clearhouse/submit \
  -H 'Content-Type: application/json' \
  -d '{"claim_ids": ["CLM-1", "CLM-2"], "payer_id": "CO_TXIX"}'

# Files appear at ./var/sftp/staging/CO XIX/PROD/coxix_prod_11525703/FromHPE/
ls -la "./var/sftp/staging/CO XIX/PROD/coxix_prod_11525703/FromHPE/"

Payer IDs

837P (claims)

  • NM1*PR N104 = "SKCO0" (COHCPF)

835 (remittance)

  • BPR10 = "81-1725341" — TXIX (Medicaid) account
  • BPR10 = "84-0644739" — BHA (behavioral health) account
  • N1*PR N104 = "7912900843" — payer ID
  • N1*PR N102 is one of "CO_TXIX" or "CO_BHA"

Allowed codes

837P CLM05-3 (frequency code)

Code Meaning
1 Original claim
7 Replacement claim
8 Void / cancel

Cyclone raises R030_frequency_allowed if any other value appears.

835 CLP02 (claim status code)

Allowed: {1, 2, 3, 4, 19, 20, 21, 22, 23, 25}. See the 835 reference note for the meaning of each.

Place of service (POS)

All CMS POS codes 0199 are accepted. The canonical list lives in cyclone/parsers/payer.py as CMS_PLACE_OF_SERVICE_CODES and is the source of truth for validation and any UI dropdowns.

Validation rules Cyclone enforces

See 837p.md and the cyclone.parsers.validator / cyclone.parsers.validator_835 modules.

Adding a new payer

The pattern is:

  1. Add a PayerConfig (837P) and PayerConfig835 (835) factory in cyclone/parsers/payer.py — usually thin wrappers that override only the differing fields (allowed codes, payer IDs).
  2. Register the factory in the PAYER_FACTORIES / PAYER_FACTORIES_835 dicts in cyclone/api.py and cyclone/cli.py.
  3. Add a smoke fixture under backend/tests/fixtures/ (a real or synthetic file matching the new payer's rules) and a parser test that loads it.
  4. Update this note + the 837p/835 notes with the new payer's specifics.