← All Articles
April 28, 2026
9 min read
AI · Healthcare · Compliance
AI for Healthcare Admin: Automating Prior Authorizations and Intake Forms
Prior authorizations stall care, frustrate doctors, and bury staff in paperwork. AI can’t fix insurance regulation, but it can eliminate the administrative friction — extracting structured data from forms, validating fields, checking coverage rules, and routing decisions to the right team. Here’s how to build it inside HIPAA constraints.
The problem: manual prior authorization processing
The current workflow looks like this:
- Patient needs a procedure.
- Doctor’s office calls insurance or fills a form.
- Insurance manually reviews the request.
- It takes 7–14 days to get an approval (or denial).
- Patient can’t schedule; the procedure is delayed.
Where time is wasted on the provider side:
- Document extraction (5 min): Someone reads the request and pulls out diagnosis, procedure code, and dates.
- Insurance plan lookup (10 min): Finding coverage rules for this patient and procedure.
- Compliance check (15 min): Verifying every required field is present.
- Routing (5 min): Sending to the right department — oncology, orthopedics, cardiology.
Total: 35 minutes per request × hundreds of requests per week = massive overhead.
The automation: an AI document pipeline
The shape of the workflow:
Prior Auth Form (PDF or web form)
↓
Document Upload (encrypted S3)
↓
Claude: Extract structured data
↓
Validation Layer: Check required fields
↓
Plan Lookup: Query coverage rules (DynamoDB)
↓
Decision Logic: Auto-approve if routine, flag if complex
↓
Route to appropriate team
↓
Patient/Doctor notification
Step 1: Encrypted document storage
All patient data is PHI (Protected Health Information). It must be encrypted at rest and in transit.
resource "aws_s3_bucket" "prior_auth_forms" {
bucket = "healthcare-prior-auth-forms-prod"
tags = {
HIPAA = "true"
PHI = "true"
}
}
# Enforce encryption at rest
resource "aws_s3_bucket_server_side_encryption_configuration" "prior_auth_forms" {
bucket = aws_s3_bucket.prior_auth_forms.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.prior_auth.arn
}
bucket_key_enabled = true
}
}
# Block public access
resource "aws_s3_bucket_public_access_block" "prior_auth_forms" {
bucket = aws_s3_bucket.prior_auth_forms.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# Enable versioning for audit trail
resource "aws_s3_bucket_versioning" "prior_auth_forms" {
bucket = aws_s3_bucket.prior_auth_forms.id
versioning_configuration {
status = "Enabled"
}
}
Every document is encrypted, versioned, and auditable.
Step 2: Extract structured data with Claude
Use Claude to parse forms and extract the fields you need:
import base64
import boto3
import json
from anthropic import Anthropic
from datetime import datetime
s3 = boto3.client('s3')
dynamodb = boto3.resource('dynamodb')
client = Anthropic()
def extract_prior_auth_data(bucket: str, key: str):
"""Extract structured data from a prior auth form. Logs every step for audit."""
audit_table = dynamodb.Table('prior_auth_audit_log')
request_id = f"{datetime.now().isoformat()}-{key}"
audit_table.put_item(Item={
'request_id': request_id,
'timestamp': datetime.now().isoformat(),
'document_key': key,
'action': 'extraction_started',
'status': 'in_progress',
})
try:
doc = s3.get_object(Bucket=bucket, Key=key)
content = doc['Body'].read()
prompt = """Extract the following from this prior authorization form:
- Patient name, ID, DOB
- Insurance plan
- Procedure code (CPT) and description
- Diagnosis codes (ICD-10)
- Requesting provider
- Date of service requested
- Medical necessity justification
- Current medications (if applicable)
Return as JSON with these exact field names.
If a field is not present, return null."""
response = client.messages.create(
model='claude-opus-4-1-20250805',
max_tokens=1500,
messages=[{
'role': 'user',
'content': [
{'type': 'text', 'text': prompt},
{'type': 'document', 'source': {
'type': 'base64',
'media_type': 'application/pdf',
'data': base64.b64encode(content).decode(),
}},
],
}],
)
extracted = json.loads(response.content[0].text)
audit_table.put_item(Item={
'request_id': request_id,
'timestamp': datetime.now().isoformat(),
'document_key': key,
'action': 'extraction_completed',
'status': 'success',
'fields_extracted': list(extracted.keys()),
})
return extracted
except Exception as e:
audit_table.put_item(Item={
'request_id': request_id,
'timestamp': datetime.now().isoformat(),
'document_key': key,
'action': 'extraction_failed',
'status': 'error',
'error': str(e),
})
raise
Every extraction is logged for compliance audits. If there’s ever a question about how a decision was made, the audit log shows what data was extracted and when.
Step 3: Validation layer
Check that all required fields are present and correctly formatted:
def validate_prior_auth(data: dict) -> dict:
"""Returns {valid: bool, errors: [...], warnings: [...]}."""
errors, warnings = [], []
required = ['patient_id', 'insurance_plan', 'procedure_code', 'diagnosis_codes']
for field in required:
if not data.get(field):
errors.append(f"Missing required field: {field}")
if data.get('patient_id') and len(str(data['patient_id'])) < 5:
errors.append("Patient ID appears invalid")
if data.get('procedure_code') and not is_valid_cpt_code(data['procedure_code']):
errors.append("Invalid CPT code")
if data.get('diagnosis_codes'):
for code in data['diagnosis_codes']:
if not is_valid_icd10(code):
errors.append(f"Invalid ICD-10 code: {code}")
if data.get('medical_necessity') is None:
warnings.append("No medical necessity justification provided")
if data.get('date_of_service') and is_emergency_timeframe(data['date_of_service']):
warnings.append("Urgent/emergency request - expedited review needed")
return {
'valid': len(errors) == 0,
'errors': errors,
'warnings': warnings,
}
Invalid requests are flagged. Warnings are noted but don’t block processing.
Step 4: Coverage rules and auto-decision
For routine procedures with standard coverage, make automatic decisions; for everything else, route for review:
def check_coverage(data: dict) -> dict:
coverage_table = dynamodb.Table('insurance_coverage_rules')
plan = data.get('insurance_plan')
procedure = data.get('procedure_code')
try:
response = coverage_table.get_item(Key={
'plan_id': plan,
'procedure_code': procedure,
})
if 'Item' in response:
rule = response['Item']
return {
'covered': rule.get('covered', False),
'requires_auth': rule.get('requires_auth', False),
'reason': rule.get('description', 'Standard coverage'),
}
# Not in rules -- safe default: require manual auth.
return {'covered': None, 'requires_auth': True,
'reason': 'Procedure not in standard coverage rules'}
except Exception as e:
return {'covered': None, 'requires_auth': True,
'reason': f'Coverage check failed: {e}'}
def make_decision(data: dict, validation: dict, coverage: dict) -> dict:
if not validation['valid']:
return {'decision': 'denied',
'reason': 'Incomplete/invalid submission',
'issues': validation['errors'],
'route_to': 'manual_review'}
if coverage['covered'] is False:
return {'decision': 'denied',
'reason': 'Procedure not covered under plan',
'route_to': 'patient_notification'}
if coverage['requires_auth'] is False:
return {'decision': 'approved',
'reason': 'Routine procedure, pre-authorized',
'route_to': 'patient_notification'}
return {'decision': 'pending_review',
'reason': 'Requires clinical review',
'route_to': 'clinical_team',
'priority': 'high' if validation['warnings'] else 'normal'}
Real outcome: Roughly 40% of requests auto-approve (routine procedures, standard coverage). The remaining 60% are flagged for human review with the data already extracted, validated, and pre-categorized. Clinical staff stop reviewing 100% of requests — they review the 60% that actually need judgment.
Step 5: Notifications and routing
Decisions get routed to the right team via SNS and DynamoDB queues:
def route_and_notify(request: dict, decision: dict):
sns = boto3.client('sns')
if decision['route_to'] == 'patient_notification':
sns.publish(
TopicArn='arn:aws:sns:us-east-1:ACCOUNT:prior-auth-approvals',
Message=f"""
Prior Authorization: {decision['decision'].upper()}
Request ID: {request['request_id']}
Patient: {request['patient_name']}
Procedure: {request['procedure_description']}
Reason: {decision['reason']}
""")
elif decision['route_to'] == 'clinical_team':
review_table = dynamodb.Table('prior_auth_clinical_review')
review_table.put_item(Item={
'request_id': request['request_id'],
'created_at': datetime.now().isoformat(),
'priority': decision.get('priority', 'normal'),
'assigned_to': None,
'status': 'pending',
'data': request,
})
sns.publish(
TopicArn='arn:aws:sns:us-east-1:ACCOUNT:prior-auth-clinical-review',
Message=f"New prior auth for clinical review: {request['request_id']}",
)
elif decision['route_to'] == 'manual_review':
error_queue = dynamodb.Table('prior_auth_error_queue')
error_queue.put_item(Item={
'request_id': request['request_id'],
'created_at': datetime.now().isoformat(),
'reason': decision['reason'],
'issues': decision['issues'],
'status': 'pending_correction',
})
HIPAA considerations
What you need on the operations side:
- Business Associate Agreement (BAA) with Anthropic — they’ll provide one.
- Encryption at rest and in transit via S3 KMS and HTTPS.
- Access controls using IAM roles and least privilege.
- Audit logging — every action logged, immutable.
- Data retention policy — how long documents are kept and when they’re purged.
What Claude’s API gives you:
- No data retention — API calls aren’t stored by Anthropic.
- HIPAA-eligible (with a BAA in place).
- Enterprise SLA available.
Real numbers
Manual processing: 35 min per form × 100 forms per week = 58 hours per week = $2,900 per week = roughly $150k per year.
With automation:
- 40% auto-approved (saves 100% of manual time on those forms): 14 hours per week.
- 60% routed for review (saves 80% of data extraction and validation): 34 hours per week.
- Total saved: 40 hours per week = $2,000 per week = roughly $104k per year.
Build cost: $12–15k. Payback period: 3–4 months. The system pays for itself before the next quarterly review.
Drowning in prior auth? Three Moons Network builds HIPAA-compliant AI systems for healthcare. Email charles@threemoonsnetwork.net and let’s automate the paperwork.
Get the free AI Readiness Checklist
15 questions to diagnose your team’s AI readiness, where you’ll see ROI fastest, and what to tackle first.
✓ Takes 5 minutes
✓ Actionable next steps
✓ No sales pitch
No spam. Unsubscribe anytime.
or
Ready to build AI that actually works?
Let’s talk about how SRE discipline transforms AI from a risky experiment into a reliable business system.
Book Your Free Discovery Call