Coverage payer_plan_period documented primary

FHIR Coverage captures a patient's insurance enrollment (payer, plan, coverage period, subscriber relationship). It maps to OMOP payer_plan_period, which records continuous enrollment under a specific health benefit plan from a given payer. Unlike clinical event tables, payer_plan_period carries no _type_concept_id; it is purely administrative. One active Coverage resource produces one payer_plan_period row. Overlapping or adjacent periods for the same person/payer may be collapsed.

Conversion profile omop-coverage-payer-plan-period
A FHIR instance converts to payer_plan_period iff it validates against this profile.
Path Card Type Binding / Fixed Comment
Coverage.status 1..* fixed: active Only active coverage produces a payer_plan_period row.
Coverage.beneficiary 1..* Reference Required for payer_plan_period.person_id.
Coverage.period 1..*MS
Coverage.period.start 1..*MS Required for payer_plan_period.payer_plan_period_start_date.
Coverage.payor 1..*MS Required for payer_concept_id / payer_source_value.
ViewDefinition (Stage 1 flattener) omop-coverage-payer-plan-period
11 columns · resource Coverage
column name FHIRPath type
id Coverage.id id
subject_id Coverage.beneficiary Reference(Patient)
payer_plan_period_start_date Coverage.period.start dateTime
payer_plan_period_end_date Coverage.period.end dateTime
payer Coverage.payor[0] Reference(Organization|Patient|RelatedPerson)
payer_text Coverage.payor[0] Reference(Organization|Patient|RelatedPerson)
plan Coverage.type.coding[0].code code
plan_text Coverage.type.text string
sponsor Coverage.policyHolder Reference(Organization|Patient|RelatedPerson)
sponsor_text Coverage.policyHolder Reference(Organization|Patient|RelatedPerson)
family_text Coverage.subscriberId string
Condition: Coverage.status = 'active'

Fields (17)

  • payer_plan_period_id Coverage.id integer · id
    PKrequired
    Surrogate key. Generated via hash/sequence/lookup of Coverage.id.
  • person_id Coverage.beneficiary integer · Reference(Patient)
    FK→PERSONrequired
    Resolve Patient reference to integer person_id via the same ID mapping used by the Patient mapper.
  • payer_plan_period_start_date Coverage.period.start date · dateTime
    required
    Coverage start date. If absent, use ETL epoch or earliest known date. NOT NULL in OMOP.
    2 sources ▾
  • payer_plan_period_end_date Coverage.period.end date · dateTime
    required
    Coverage end date. If absent or open-ended, use 9999-12-31 or ETL end date. NOT NULL in OMOP.
    2 sources ▾
  • payer_concept_id Coverage.payor[0] integer · Reference(Organization|Patient|RelatedPerson)
    FK→CONCEPTmap:payer
    transform:resolve payor[0] -> Organization.name -> OMOP Payer vocabulary lookup
    OMOP Payer vocabulary concept (vocabulary_id='Payer', domain_id='Payer'). Resolve Organization reference, map name to payer concept. Default: 0. If payor references Patient (self-pay), use concept_id 436.
    2 sources ▾
  • payer_source_value Coverage.payor[0] varchar(50) · Reference(Organization|Patient|RelatedPerson)
    transform:resolve payor[0] -> Organization.name or Reference.display
    Verbatim payer name or identifier. Resolve Organization reference and extract Organization.name. Fallback to Reference.display. Truncate to 50 chars.
    2 sources ▾
  • payer_source_concept_id constant integer · integer
    FK→CONCEPT=0
    Source concept for the payer if a non-standard vocabulary is used. Default: 0.
  • plan_concept_id Coverage.type.coding[0].code integer · code
    FK→CONCEPTmap:plan_type
    transform:map Coverage.type (v3-ActCode) to OMOP Plan vocabulary
    Map Coverage.type to OMOP Plan vocabulary. No standard OMOP vocabulary maps directly to Coverage.type. Default: 0.
  • plan_source_value Coverage.type.text | Coverage.class.where(type.coding.code='plan').name | Coverage.class.where(type.coding.code='plan').value varchar(50) · string
    transform:Use Coverage.type.text, or class entry where type.coding.code='plan'. Concatenate group+plan if both present.
    Plan name as it appears in source. Truncate to 50 chars.
  • plan_source_concept_id constant integer · integer
    FK→CONCEPT=0
    Source concept for the plan. Default: 0.
  • sponsor_concept_id Coverage.policyHolder integer · Reference(Organization|Patient|RelatedPerson)
    FK→CONCEPT
    transform:resolve policyHolder -> Organization.name -> OMOP Sponsor vocabulary lookup
    OMOP Sponsor vocabulary concept. The policyHolder (often the employer) is the sponsor. Default: 0.
  • sponsor_source_value Coverage.policyHolder varchar(50) · Reference(Organization|Patient|RelatedPerson)
    transform:resolve policyHolder -> Organization.name or identifier
    Sponsor name from policyHolder reference. Truncate to 50 chars.
  • sponsor_source_concept_id constant integer · integer
    FK→CONCEPT=0
    Source concept for the sponsor. Default: 0.
  • family_source_value Coverage.subscriberId varchar(50) · string
    The subscriber ID links all family members under the same policy. Truncate to 50 chars.
  • stop_reason_concept_id constant integer · integer
    FK→CONCEPT=0
    FHIR Coverage has no stop reason field. If Coverage.status='cancelled', could use a concept for cancellation. Default: 0.
  • stop_reason_source_value varchar(50) · string
    Not directly available from FHIR Coverage. Could store Coverage.status if not 'active'.
  • stop_reason_source_concept_id constant integer · integer
    FK→CONCEPT=0
    Default: 0.

Vocabularies

payer

Source Display Concept ID Concept Name
Medicare Organization name containing 'Medicare' 280 Medicare
Medicare Managed Care Medicare HMO/PPO payor 281 Medicare Managed Care
Medicaid State Medicaid organization 289 Medicaid
Medicaid Managed Care Medicaid MCO 290 Medicaid Managed Care
TRICARE Military insurance 296 DoD TRICARE
VA VA coverage 302 Veteran Care
Private Generic commercial insurer 327 Private Health Insurance
HMO HMO commercial plan 329 Commercial Managed Care - HMO
PPO PPO commercial plan 330 Commercial Managed Care - PPO
Managed Care Generic managed care 340 Managed Care, Unspecified
Self-pay Coverage.type = 'pay' (self-pay) or payor references Patient 436 Self-pay
Charity Charity coverage 438 Charity
Workers Comp Workers compensation 447 Worker's Compensation
(unmapped) Payor cannot be mapped to OMOP vocabulary 0 No matching concept

plan_type

Source Display Concept ID Concept Name
EHCPOL Extended healthcare 327 Private Health Insurance
HIP Health insurance plan policy 327 Private Health Insurance
MCPOL Managed care policy 340 Managed Care, Unspecified
SUBSIDMC Subsidized managed care program - Medicare/Medicaid Managed Care
SUBSUPP Subsidized supplemental health program - Medicare/Medicaid
MILITARY Military health program 296 DoD TRICARE
VET Veteran health program 302 Veteran Care
WCBPOL Workers compensation 447 Worker's Compensation
CHAR Charity program 438 Charity
pay Self-pay 436 Self-pay
SAFNET Safety net clinic program - HRSA Program

Edge Cases

Missing Coverage.period
Both payer_plan_period_start_date and payer_plan_period_end_date are NOT NULL. Use ETL epoch date for start, 9999-12-31 or current date for end. Log warning.
Open-ended period (period.end absent)
Coverage is still active. Use 9999-12-31 or the ETL run date as payer_plan_period_end_date.
period.end < period.start
Data quality error. Skip the record or swap dates with a warning.
Coverage.status != 'active'
Skip Coverage resources with status cancelled, draft, or entered-in-error. Do not create a payer_plan_period row.
Multiple payor[] entries
OMOP has a single payer_source_value per row. Options: (a) take the first payor, (b) create one row per payor with the same period, (c) concatenate payor names (truncated to 50 chars).
payor references Patient (self-pay)
Set payer_source_value = 'Self-pay' or patient name, payer_concept_id = 436.
No Organization resource for payor
Use Reference.display as fallback for payer_source_value. If no display, use the reference string itself.
Overlapping Coverage periods (same person, same payer)
Collapse into a single payer_plan_period row with MIN(start), MAX(end). FhirToCdm does this via CanPayerPlanPeriodBeCombined() -- combines when payer+plan source values match.
Coverage.class[] absent
No plan details available. plan_source_value = null. Use Coverage.type.text if available.
Multiple Coverage resources for same person
Create one payer_plan_period row per Coverage (per payer/plan/period combination). May collapse adjacent/overlapping periods.
subscriberId too long for varchar(50)
Truncate to 50 characters.
Coverage from EOB (no discrete Coverage resource)
Derive payer_plan_period from ExplanationOfBenefit.billablePeriod + insurer. Group by patient+insurer, MIN/MAX dates.

Reference Implementations