| Check | Condition | Severity | Message |
| has_narrative | narrative IS NOT NULL AND LENGTH > 0 | ERROR | Provide appeal narrative (50+ chars) |
| has_precedents | selected_precedent_ids.length > 0 | ERROR | Select at least one precedent |
| valid_precedents | All IDs exist in precedent_objects | ERROR | One or more precedents no longer exist |
| narrative_length | LENGTH(narrative) >= 50 | WARNING | Narrative seems short (50+ words) |
| precedent_relevance | Precedent payer/denial_type match appeal | WARNING | Some precedents are for different denials |
Validation Statuses
- clean — All gates pass, ready to submit
- warnings — Gates pass but recommendations to address
- errors — Gate failures, must fix before submit
POST /api/validation/validate-precedent-quality
Validate precedent quality and confidence calibration.
Authentication: Required
Authorization: Any authenticated user
Request Body
{
"precedent_ids": ["prec-uuid-1", "prec-uuid-2", "prec-uuid-3"]
}
Response (200 OK)
{
"validation_status": "clean",
"precedent_quality_report": [
{
"precedent_id": "prec-uuid-1",
"status": "valid",
"evidence_score": "Strong",
"outcome": "Won",
"confidence_level": "high",
"warnings": []
},
{
"precedent_id": "prec-uuid-2",
"status": "valid",
"evidence_score": "Moderate",
"outcome": "Won",
"confidence_level": "medium",
"warnings": []
},
{
"precedent_id": "prec-uuid-3",
"status": "stale",
"evidence_score": "Strong",
"outcome": "Won",
"confidence_level": "medium",
"warnings": [
"Precedent is 18 months old; payer policies may have changed"
]
}
]
}
Precedent Quality Checks
Evidence Score — Minimal, Moderate, Strong
Outcome — Won, Lost, Partial, Pending
Recency — Staleness warning if > 12 months old
Confidence Level — high (Strong + recent + Won), medium (other combinations), low (Lost outcomes)
POST /api/validation/appeal
Comprehensive appeal validation (combines decision + gate validation).
Authentication: Required
Authorization: Any authenticated user
Request Body
Full appeal object:
{
"denial_id": "denial-uuid",
"narrative": "...",
"evidence_elements": { ... },
"selected_precedent_ids": [ ... ]
}
Response (200 OK)
Combined validation result:
{
"validation_status": "warnings",
"decision_validation": { ... },
"quality_validation": { ... },
"recommendations": [
"Add more recent precedents from 2024",
"Expand clinical justification section",
"Consider including collateral contact documentation"
]
}
POST /api/validation/precedent
Validate precedent before submission to marketplace.
Authentication: Required
Authorization: admin, biller roles
PHI Validation: Request scanned for PHI
Request Body
{
"precedent_name": "Cigna IOP Appeal Victory",
"payer": "Cigna",
"denial_type": "Frequency Limit",
"loc": "IOP",
"narrative": "...",
"evidence_kit": { ... },
"outcome": "Won",
"status": "Complete"
}
Response (200 OK)
{
"validation_status": "clean",
"checks_passed": [
"evidence_score_set",
"outcome_set",
"policy_reference_complete",
"denial_trigger_specified",
"evidence_kit_nonempty"
],
"warnings": [],
"errors": []
}
PR-U Gates for Precedents
| Check | Condition | Severity | Message |
| evidence_score_set | evidence_score IS NOT NULL | ERROR | Rate evidence strength (Minimal/Moderate/Strong) |
| outcome_set | IF status='Complete' THEN outcome IS NOT NULL | ERROR | Set outcome (Won/Lost/Partial) |
| policy_reference_complete | policy_reference.section AND .exact_language | WARNING | Include specific policy section and quoted language |
| denial_trigger_specified | denial_trigger IS NOT NULL AND LENGTH > 0 | ERROR | Specify exact denial trigger |
| evidence_kit_nonempty | evidence_kit.required OR .recommended | WARNING | Populate evidence kit so others know what to gather |
POST /api/validation/export
Validate before export (PR-D gates, final validation).
Authentication: Required
Authorization: admin, biller roles
Request Body
{
"precedent_ids": ["prec-uuid-1", "prec-uuid-2"],
"export_format": "json",
"deidentify": true
}
Response (200 OK)
{
"validation_status": "warnings",
"errors": [],
"warnings": [
{
"precedent_id": "prec-uuid-1",
"check": "outcome_resolution",
"message": "Outcome still pending — data is incomplete",
"guidance": "This precedent will be more valuable once appeal resolves"
}
],
"export_readiness": true
}
PR-D Gates (Export Validation)
| Check | Condition | Severity | Message |
| outcome_resolution | IF status='Complete' THEN outcome != 'Pending' | WARNING | Outcome pending — data incomplete |
| sud_compliance | IF data_origin_type='SUD' THEN sharing_restrictions != 'none' | ERROR | SUD data cannot export without consent |
| traceability_complete | traceability_ledger.length >= 2 | WARNING | Traceability ledger sparse — missing decision history |
| submission_readiness | All PR-U gates pass + no urgent warnings | ERROR | Appeal not ready to submit |