Note: This document references Azure Logic Apps, which were the original orchestration runtime. CHO has since migrated to Argo Workflows on AKS — see ADR-004 for details.
Cloud Health Office - HIPAA-compliant Prior Authorization API with Da Vinci Implementation Guides
This document provides comprehensive guidance for implementing CMS-0057-F Prior Authorization workflows using FHIR R4, X12 278, and Azure Logic Apps orchestration.
- Overview
- CMS-0057-F Compliance
- Da Vinci Implementation Guides
- Architecture
- API Endpoints
- X12 278 to FHIR Mapping
- SLA Management
- Attachment Workflows
- Provider-Facing Hooks
- Consent Management
- Azure Logic Apps Orchestration
- Clearinghouse Integration
- Usage Examples
- Testing
- Security and HIPAA
The Prior Authorization API implements the CMS-0057-F Prior Authorization Rule (effective March 2023) requirements for payer systems to provide:
- Standards-based API: FHIR R4 with Da Vinci profiles
- Real-time decisions: 72-hour response for urgent, 7 days for standard
- Provider integration: CDS Hooks for coverage requirements discovery
- Documentation support: Electronic attachment submission
- X12 compatibility: Bi-directional 278 transaction mapping
✅ CMS-0057-F Compliant: Meets all regulatory requirements
✅ Da Vinci IGs: CRD, DTR, and PAS implementation guides
✅ FHIR R4 Native: Full FHIR resource support
✅ X12 278 Mapping: Seamless EDI to FHIR conversion
✅ SLA Tracking: Automated decision timeline monitoring
✅ Azure Logic Apps: Cloud-native orchestration
✅ Clearinghouse Ready: Clearinghouse integration support
✅ Comprehensive Testing: 42+ test cases with full coverage
The CMS Prior Authorization Rule (CMS-0057-F) requires impacted payers to:
- API Implementation: Build and maintain a FHIR-based API for prior authorization
- Decision Timelines:
- Urgent requests: 72 hours
- Standard requests: 7 calendar days
- Extensions: 14 additional days with justification
- Documentation Support: Accept electronic attachments
- Provider Notification: Real-time status updates
- Standards Compliance: Use Da Vinci FHIR IGs
import { calculatePriorAuthSLA, updateSLAWithDecision } from './prior-auth-api';
// Calculate SLA timeline
const sla = calculatePriorAuthSLA('urgent', new Date().toISOString());
// Result: 72-hour decision deadline
// Track compliance
const decided = updateSLAWithDecision(sla, decidedTimestamp);
console.log(`SLA Compliant: ${decided.slaCompliant}`);| Request Type | Timeline | Hours | Extension Allowed |
|---|---|---|---|
| Urgent | 72 hours | 72 | Yes (14 days) |
| Expedited | 72 hours | 72 | Yes (14 days) |
| Standard | 7 calendar days | 168 | Yes (14 days) |
Purpose: Provide real-time coverage requirements during clinical workflow
Implementation:
import { createCRDCard } from './prior-auth-api';
// Create CRD card when prior auth is required
const card = createCRDCard(
'prior-auth-required',
'Prior authorization required for MRI',
'This service requires prior authorization. Please submit request within 48 hours.'
);CDS Hooks Support:
order-select: When provider selects an orderorder-sign: Before order is signedappointment-book: When scheduling proceduresencounter-start: At encounter initiation
Purpose: Standardize documentation collection for prior authorization
Features:
- FHIR Questionnaire resources
- Adaptive questionnaires based on service type
- Pre-population from EHR data
- Structured data capture
Purpose: Submit and manage prior authorization requests via FHIR
Profiles:
Claim(PriorAuthorizationRequest): Request submissionClaimResponse(PriorAuthorizationResponse): Payer decisionBundle: Transaction bundles for complete workflows
┌────────────────┐
│ EHR/Portal │
│ (Provider) │
└────────┬───────┘
│
│ 1. CDS Hooks (CRD)
▼
┌────────────────────────────────────────────────┐
│ Prior Authorization API │
│ │
│ 2. Validate Request │
│ 3. Map X12 ↔ FHIR │
│ 4. Calculate SLA │
│ 5. Orchestrate via Logic Apps │
│ 6. Process Attachments │
│ 7. Track Decision Timeline │
└────────┬───────────────────────────────────────┘
│
│ 8. Submit to Payer
▼
┌────────────────┐ ┌──────────────────┐
│ Payer System │◄──────►│ Clearinghouse │
│ (claims backend, etc) │ │ (Clearinghouse) │
└────────────────┘ └──────────────────┘
-
TypeScript API (
src/fhir/prior-auth-api.ts)- X12 278 ↔ FHIR mapping
- SLA calculation
- CRD card generation
- Validation logic
-
Azure Logic Apps (
logicapps/workflows/)- HTTP endpoints for API
- X12 encoding/decoding
- Service Bus integration
- SFTP connectivity
-
Service Bus Topics
prior-auth-requests-{env}prior-auth-responses-{env}prior-auth-attachments-{env}
-
Data Lake Storage
- Request archival:
prior-auth/requests/yyyy/MM/dd/ - Response archival:
prior-auth/responses/yyyy/MM/dd/ - Attachments:
prior-auth/attachments/yyyy/MM/dd/
- Request archival:
POST /api/prior-auth/submit
Request Body (FHIR Claim):
{
"resourceType": "Claim",
"meta": {
"profile": ["http://hl7.org/fhir/us/davinci-pas/StructureDefinition/profile-claim"]
},
"status": "active",
"type": {
"coding": [{
"system": "http://terminology.hl7.org/CodeSystem/claim-type",
"code": "professional"
}]
},
"use": "preauthorization",
"patient": {
"reference": "Patient/MEM123456"
},
"provider": {
"identifier": {
"system": "http://hl7.org/fhir/sid/us-npi",
"value": "1234567890"
}
},
"diagnosis": [{
"sequence": 1,
"diagnosisCodeableConcept": {
"coding": [{
"system": "http://hl7.org/fhir/sid/icd-10-cm",
"code": "I50.9"
}]
}
}],
"item": [{
"sequence": 1,
"productOrService": {
"coding": [{
"system": "http://www.ama-assn.org/go/cpt",
"code": "99213"
}]
},
"servicedDate": "2024-12-15"
}]
}Response (ClaimResponse):
{
"resourceType": "ClaimResponse",
"status": "active",
"outcome": "complete",
"preAuthRef": "AUTH20241124001",
"preAuthPeriod": {
"start": "2024-12-15",
"end": "2025-03-15"
}
}GET /api/prior-auth/status/{authorizationNumber}
Response:
{
"authorizationNumber": "AUTH20241124001",
"status": "APPROVED",
"effectiveDate": "2024-12-15",
"expirationDate": "2025-03-15",
"sla": {
"submittedAt": "2024-11-24T10:00:00Z",
"decidedAt": "2024-11-26T08:30:00Z",
"slaCompliant": true,
"actualTimelineHours": 46.5
}
}POST /api/prior-auth/documentation
Request Body:
{
"authorizationNumber": "AUTH20241124001",
"attachments": [{
"type": "clinical-notes",
"contentType": "application/pdf",
"data": "base64-encoded-content",
"description": "Provider clinical notes for visit"
}]
}POST /api/prior-auth/cancel
Request Body:
{
"authorizationNumber": "AUTH20241124001",
"reason": "PROCEDURE_NOT_PERFORMED",
"notes": "Patient cancelled procedure due to scheduling conflict"
}import { mapX12278ToFHIRPriorAuth } from './prior-auth-api';
const x12Request = {
transactionSetControlNumber: 'TSC001',
requestCategory: 'HS', // Health Services
certificationType: 'I', // Initial
patient: {
memberId: 'MEM123456',
firstName: 'John',
lastName: 'Doe',
dateOfBirth: '1985-06-15',
gender: 'M'
},
requestingProvider: {
npi: '1234567890'
},
services: [{
serviceTypeCode: '48',
procedureCode: '99213',
procedureCodeType: 'CPT',
fromDate: '2024-12-15'
}],
diagnoses: [{
code: 'I50.9',
codeType: 'ABK'
}],
payerId: 'PAYER001'
};
const fhirClaim = mapX12278ToFHIRPriorAuth(x12Request);import { mapFHIRToX12278Response } from './prior-auth-api';
const claimResponse = {
resourceType: 'ClaimResponse',
outcome: 'complete',
preAuthRef: 'AUTH20241124001',
preAuthPeriod: {
start: '2024-12-15',
end: '2025-03-15'
}
};
const x12Response = mapFHIRToX12278Response(claimResponse);
// Result: { statusCode: 'A1', authorizationNumber: 'AUTH20241124001', ... }| X12 278 Field | FHIR Claim Field | Notes |
|---|---|---|
UM01 (Request Category) |
type.coding[0].code |
AR=institutional, HS/SC=professional |
UM02 (Certification Type) |
status |
I=active, 3=cancelled |
NM1*IL (Subscriber) |
patient.reference |
Patient reference |
NM1*1P (Requesting Provider) |
provider.identifier |
NPI identifier |
HI*ABK (Diagnosis) |
diagnosis[].diagnosisCodeableConcept |
ICD-10-CM codes |
SV1/SV2 (Services) |
item[].productOrService |
CPT/HCPCS codes |
DTP (Service Dates) |
item[].servicedPeriod |
Date range |
import { calculatePriorAuthSLA } from './prior-auth-api';
// Urgent request: 72-hour timeline
const urgentSLA = calculatePriorAuthSLA('urgent', submittedTimestamp);
// Standard request: 168-hour (7-day) timeline
const standardSLA = calculatePriorAuthSLA('standard', submittedTimestamp);import { updateSLAWithDecision } from './prior-auth-api';
// Update SLA when decision is made
const updatedSLA = updateSLAWithDecision(sla, decidedTimestamp);
if (updatedSLA.slaCompliant) {
console.log(`Decision made in ${updatedSLA.actualTimelineHours} hours`);
} else {
console.log(`SLA VIOLATED: Decision took ${updatedSLA.actualTimelineHours} hours`);
// Trigger alert/notification
}Key metrics to track:
- Average decision time by request type
- SLA compliance rate (target: >98%)
- Overdue requests count
- Extension rate
- Denial rate by reason
import { createAttachmentBinary, createAttachmentDocumentReference } from './prior-auth-api';
// Create Binary resource for PDF
const binary = createAttachmentBinary(
'application/pdf',
base64EncodedPDF,
'Clinical notes from visit'
);
// Create DocumentReference
const docRef = createAttachmentDocumentReference(
{ reference: `Binary/${binary.id}` },
{ reference: 'Patient/MEM123456' },
'clinical-notes'
);| Type | LOINC Code | Description |
|---|---|---|
clinical-notes |
11506-3 | Progress notes, visit summaries |
lab-results |
11502-2 | Laboratory test results |
imaging |
18748-4 | X-rays, MRI, CT scans |
other |
34133-9 | Other supporting documentation |
- During Initial Request: Include attachments in
supportingInfo - Post-Submission: Use
/api/prior-auth/documentationendpoint - Payer Request: Respond to 277 RFAI (Request for Additional Information)
import { createCDSHooksRequest } from './prior-auth-api';
// Create CDS Hooks request for order-select
const hooksRequest = createCDSHooksRequest('order-select', {
userId: 'Practitioner/123',
patientId: 'Patient/456',
encounterId: 'Encounter/789',
selections: ['ServiceRequest/MRI001']
});
// POST to payer CDS Hooks service
const response = await fetch('https://payer.com/cds-services/coverage-requirements', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(hooksRequest)
});
const cards = await response.json();
// Display cards to provider in EHR- order-select: Coverage requirements when selecting orders
- order-sign: Final check before signing order
- appointment-book: Requirements for scheduling
- encounter-start: Coverage verification at check-in
Prior Auth Required:
const card = createCRDCard(
'prior-auth-required',
'Prior authorization required',
'MRI procedures require prior authorization. Estimated approval time: 24-48 hours.'
);
// indicator: 'warning'Documentation Needed:
const card = createCRDCard(
'documentation-needed',
'Additional documentation required',
'Please provide clinical notes supporting medical necessity.'
);
// indicator: 'info'import { createPriorAuthConsent } from './prior-auth-api';
const consent = createPriorAuthConsent(
{ reference: 'Patient/MEM123456' },
{ reference: 'Patient/MEM123456' } // Patient gives own consent
);
// Store consent in FHIR server before submitting prior auth
await fhirClient.create(consent);Per HIPAA and CMS requirements:
- Explicit consent: Patient must authorize information sharing
- Purpose limitation: Consent specific to prior authorization
- Time-bound: Consent valid for specific period
- Revocable: Patient can revoke consent
import { createOrchestrationConfig } from './prior-auth-api';
const config = createOrchestrationConfig(
'https://cloudhealthoffice.azurewebsites.net',
'prod'
);
// Endpoints configured:
// - submitRequest: POST /api/prior-auth/submit
// - checkStatus: GET /api/prior-auth/status
// - submitDocumentation: POST /api/prior-auth/documentation
// - cancelAuthorization: POST /api/prior-auth/cancel{
"serviceBus": {
"requestTopic": "prior-auth-requests-prod",
"responseTopic": "prior-auth-responses-prod",
"attachmentTopic": "prior-auth-attachments-prod"
}
}HTTP Trigger → Validate → Transform → Encode X12 → Archive →
→ POST to Payer → Parse Response → Update SLA → Notify → Return
const config = createOrchestrationConfig(baseUrl, 'prod');
// Clearinghouse SFTP configuration
const clearinghouseConfig = config.clearinghouse;
// {
// tradingPartnerId: 'CLEARINGHOUSE',
// sftpEndpoint: 'sftp.clearinghouse.example.com',
// outboundFolder: '/outbound/278',
// inboundFolder: '/inbound/278'
// }- Generate X12 278 request
- Encode via Integration Account
- Upload to Clearinghouse SFTP
/outbound/278/ - Clearinghouse routes to payer
- Poll for response in
/inbound/278/
- Poll Clearinghouse SFTP
/inbound/278/ - Download 278 response file
- Decode via Integration Account
- Map to FHIR ClaimResponse
- Update SLA tracking
- Notify provider
- Archive response
# Configure trading partner in Integration Account
./configure-x12-agreements.ps1 `
-TradingPartnerName "Clearinghouse" `
-SenderId "YOURID" `
-ReceiverId "CLEARINGHOUSE"import {
mapX12278ToFHIRPriorAuth,
calculatePriorAuthSLA,
validatePriorAuthRequest
} from './prior-auth-api';
// Create X12 278 request
const request = {
transactionSetControlNumber: 'TSC001',
requestCategory: 'AR', // Inpatient
certificationType: 'I',
patient: {
memberId: 'MEM123456',
firstName: 'John',
lastName: 'Doe',
dateOfBirth: '1985-06-15',
gender: 'M'
},
requestingProvider: {
npi: '1234567890',
organizationName: 'City Hospital'
},
services: [{
serviceTypeCode: '48',
placeOfService: '21',
fromDate: '2024-12-20',
toDate: '2024-12-25',
quantity: 5,
quantityType: 'DY'
}],
diagnoses: [{
code: 'J18.9',
codeType: 'ABK'
}],
payerId: 'BCBS',
additionalInfo: {
admissionDate: '2024-12-20',
admissionType: 'Emergency'
}
};
// Validate
const validation = validatePriorAuthRequest(request);
if (!validation.valid) {
throw new Error(`Validation failed: ${validation.errors.join(', ')}`);
}
// Map to FHIR
const fhirClaim = mapX12278ToFHIRPriorAuth(request);
// Calculate SLA (urgent = 72 hours)
const sla = calculatePriorAuthSLA('urgent', new Date().toISOString());
// Submit to Logic App endpoint
const response = await fetch('https://yourapp.azurewebsites.net/api/prior-auth/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/fhir+json' },
body: JSON.stringify(fhirClaim)
});
const result = await response.json();
console.log(`Authorization Number: ${result.preAuthRef}`);
console.log(`Decision Due By: ${sla.decisionDueBy}`);import { updateSLAWithDecision } from './prior-auth-api';
// Retrieve SLA from database
const sla = await getSLAFromDatabase('AUTH20241124001');
// Check current status
const statusResponse = await fetch(
'https://yourapp.azurewebsites.net/api/prior-auth/status/AUTH20241124001'
);
const status = await statusResponse.json();
if (status.decidedAt) {
// Update SLA with decision
const updatedSLA = updateSLAWithDecision(sla, status.decidedAt);
if (!updatedSLA.slaCompliant) {
// Alert: SLA violated
await sendAlert({
severity: 'HIGH',
message: `SLA violated for AUTH20241124001`,
timeline: updatedSLA.actualTimelineHours
});
}
}import { createCDSHooksRequest, createCRDCard } from './prior-auth-api';
// EHR calls this when provider selects MRI order
app.post('/ehr/hooks/order-select', async (req, res) => {
const { patientId, selections } = req.body.context;
// Create CDS Hooks request
const hooksRequest = createCDSHooksRequest('order-select', {
userId: req.body.context.userId,
patientId,
selections
});
// Call payer CDS service
const cards = await callPayerCDSService(hooksRequest);
// Or generate card locally based on rules
if (requiresPriorAuth(selections)) {
const card = createCRDCard(
'prior-auth-required',
'Prior authorization required for MRI',
'This procedure requires prior authorization. Please submit request before scheduling.'
);
cards.push(card);
}
res.json({ cards });
});# Run all prior auth tests
npm test -- --testPathPattern=prior-auth-api
# Run with coverage
npm test -- --coverage --testPathPattern=prior-auth-api
# Run specific test suite
npm test -- -t "SLA Management"Our implementation includes 42 comprehensive test cases covering:
- ✅ X12 278 to FHIR mapping (8 tests)
- ✅ FHIR to X12 response mapping (3 tests)
- ✅ SLA calculation and tracking (6 tests)
- ✅ Da Vinci CRD integration (6 tests)
- ✅ Attachment workflows (6 tests)
- ✅ Consent management (3 tests)
- ✅ Request validation (7 tests)
- ✅ Orchestration configuration (3 tests)
- ✅ CMS-0057-F compliance (4 tests)
Test Coverage: 100% of core functions
describe('End-to-End Prior Auth Flow', () => {
it('should process complete workflow from submission to decision', async () => {
// 1. Submit request
const request = createX12Request();
const fhirClaim = mapX12278ToFHIRPriorAuth(request);
// 2. POST to endpoint
const submitResponse = await fetch('/api/prior-auth/submit', {
method: 'POST',
body: JSON.stringify(fhirClaim)
});
const { authNumber } = await submitResponse.json();
// 3. Check status
const statusResponse = await fetch(`/api/prior-auth/status/${authNumber}`);
const status = await statusResponse.json();
expect(status.authorizationNumber).toBe(authNumber);
expect(['PENDING', 'APPROVED', 'DENIED']).toContain(status.status);
});
});-
Authentication
- Azure AD OAuth 2.0
- Service principal for system-to-system
- Managed Identity for Azure resources
-
Authorization
- RBAC for API access
- Payer-specific authorization rules
- Provider NPI verification
-
Encryption
- TLS 1.2+ for all API calls
- Encryption at rest for stored data
- Key Vault for secrets management
-
Audit Logging
- All API requests logged
- PHI access tracking
- Application Insights integration
PHI Protection:
- All patient data encrypted
- Minimal necessary principle
- Secure transmission via TLS
- Access controls on all resources
BAA Requirements:
- Azure BAA in place
- Subprocessor BAAs (Clearinghouse)
- Breach notification procedures
- Regular security assessments
Audit Requirements:
// All operations logged
logger.logHIPAAEvent({
eventType: 'PRIOR_AUTH_SUBMITTED',
userId: requestingProvider.npi,
patientId: patient.memberId,
timestamp: new Date().toISOString(),
ipAddress: req.ip,
action: 'CREATE',
resourceType: 'PriorAuthorizationRequest'
});- Never log PHI: Use identifiers, not names/DOB
- Validate all inputs: Use
validatePriorAuthRequest() - Implement rate limiting: Prevent abuse
- Monitor for anomalies: Track unusual patterns
- Regular security reviews: Quarterly assessments
- CRD: http://hl7.org/fhir/us/davinci-crd/
- DTR: http://hl7.org/fhir/us/davinci-dtr/
- PAS: http://hl7.org/fhir/us/davinci-pas/
- CMS-0057-F Final Rule: https://www.cms.gov/regulations-and-guidance/guidance/interoperability/cms-0057-f
- Implementation Timeline: https://www.cms.gov/files/document/prior-authorization-implementation-timeline.pdf
- Documentation:
/docs/PRIOR-AUTHORIZATION-API.md - Issue Tracking: GitHub Issues
- Community: Cloud Health Office Discussions
✅ Initial release with full CMS-0057-F compliance
✅ Da Vinci CRD, DTR, PAS implementation
✅ X12 278 ↔ FHIR R4 mapping
✅ SLA tracking and monitoring
✅ Azure Logic Apps orchestration
✅ 42 comprehensive test cases
✅ Complete documentation
Cloud Health Office - The future of payer integration is here.