Build a Prior Auth Readiness Check
Your EHR needs to tell coordinators whether a prior auth submission is ready before they submit it. This guide walks through the full integration -- from fetching payer rules to parsing a readiness verdict.
Estimated integration time: 30 minutes. Works with sandbox keys (tln_test_) so you can build and test for free.
Fetch payer rules
Start by understanding what the payer actually requires. The GET /api/v1/rules endpoint returns documentation requirements, blocking rules, approval rates, and common denial reasons for a specific payer + procedure combination.
curl -H "X-API-Key: tln_test_YOUR_KEY" \
"https://talonapi.dev/api/v1/rules?payer=aetna&cpt=27447"The response includes blocking_requirements (must-haves that will cause a denial if missing) and soft_requirements (nice-to-haves that improve approval odds). You will use both in step 3.
{
"blocking_requirements": [
"6+ weeks documented conservative treatment",
"BMI documented",
"Functional limitation score"
],
"soft_requirements": [
"Physical therapy notes",
"Failed medication list"
],
"approval_rate": 0.84,
"common_denial_reasons": [
{ "reason": "Insufficient conservative treatment" }
]
}Map your EHR documentation to the check format
The readiness check accepts an available_documentation object that describes what your system currently has on file. Map your EHR's internal data model to these boolean/numeric fields:
// Map your EHR fields to the Talon format
const availableDocs = {
has_clinical_notes: Boolean(patient.latestNote),
has_imaging: patient.imagingReports.length > 0,
has_conservative_treatment_docs: Boolean(patient.ptRecords),
conservative_treatment_weeks: patient.ptWeeksCompleted ?? 0,
has_bmi: Boolean(patient.vitals?.bmi),
has_functional_score: Boolean(patient.functionalScore),
has_failed_medication_list: patient.failedMeds.length > 0,
};false / 0 and will flag them as gaps.Submit the readiness check
Post your documentation map to POST /api/v1/rules/check. The API evaluates it against the payer's requirements and returns a verdict.
curl -X POST "https://talonapi.dev/api/v1/rules/check" \
-H "X-API-Key: tln_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"payer": "Aetna",
"cpt_code": "27447",
"available_documentation": {
"has_clinical_notes": true,
"has_imaging": true,
"has_conservative_treatment_docs": true,
"conservative_treatment_weeks": 8,
"has_bmi": false,
"has_functional_score": false,
"has_failed_medication_list": true
}
}'Parse the readiness response
The response tells you everything your coordinator needs to make a decision:
{
"ready_to_submit": true,
"readiness_score": 0.75,
"blocking_gaps": [],
"satisfied_requirements": [
"Clinical notes included",
"Imaging documentation included",
"Conservative treatment documented (8 weeks)",
"Failed medication list included"
],
"recommended_additions": [
"Include BMI documentation",
"Include functional limitation score"
],
"approval_probability": {
"if_submitted_now": 0.84,
"if_gaps_resolved": 0.89
},
"estimated_turnaround_days": 5,
"common_denial_reasons": [
{ "reason": "Insufficient conservative treatment" }
]
}ready_to_submit -- Boolean. If false, there are blocking gaps that will almost certainly cause a denial.
blocking_gaps -- Array of strings describing requirements that are not met. Empty means no blockers.
recommended_additions -- Non-blocking items that would improve approval odds.
approval_probability -- Two numbers: the chance of approval if submitted now vs. if you resolve the recommended additions first.
Complete TypeScript integration
Here is a production-ready function that performs the full readiness check flow. It fetches rules first (for context), then submits the check.
const TALON_BASE = "https://talonapi.dev";
interface AvailableDocs {
has_clinical_notes: boolean;
has_imaging: boolean;
has_conservative_treatment_docs: boolean;
conservative_treatment_weeks: number;
has_bmi: boolean;
has_functional_score: boolean;
has_failed_medication_list: boolean;
}
interface ReadinessResult {
ready_to_submit: boolean;
readiness_score: number;
blocking_gaps: string[];
recommended_additions: string[];
approval_probability: { if_submitted_now: number; if_gaps_resolved: number };
estimated_turnaround_days: number;
}
export async function checkPAReadiness(
apiKey: string,
payer: string,
cptCode: string,
docs: AvailableDocs
): Promise<ReadinessResult> {
const headers = {
"X-API-Key": apiKey,
"Content-Type": "application/json",
};
// 1. Fetch payer rules (cache this — it changes infrequently)
const rulesRes = await fetch(
`${TALON_BASE}/api/v1/rules?payer=${encodeURIComponent(payer)}&cpt=${cptCode}`,
{ headers }
);
if (!rulesRes.ok) {
const err = await rulesRes.json();
throw new Error(`Rules lookup failed: ${err.error?.message ?? rulesRes.statusText}`);
}
// 2. Submit readiness check
const checkRes = await fetch(`${TALON_BASE}/api/v1/rules/check`, {
method: "POST",
headers,
body: JSON.stringify({
payer,
cpt_code: cptCode,
available_documentation: docs,
}),
});
if (!checkRes.ok) {
const err = await checkRes.json();
throw new Error(`Readiness check failed: ${err.error?.message ?? checkRes.statusText}`);
}
return checkRes.json();
}
// Usage
const result = await checkPAReadiness(
"tln_test_abc123",
"Aetna",
"27447",
{
has_clinical_notes: true,
has_imaging: true,
has_conservative_treatment_docs: true,
conservative_treatment_weeks: 8,
has_bmi: false,
has_functional_score: false,
has_failed_medication_list: true,
}
);
if (!result.ready_to_submit) {
console.log("BLOCKED:", result.blocking_gaps);
} else if (result.recommended_additions.length > 0) {
console.log("Ready but could be stronger:", result.recommended_additions);
console.log(`Approval now: ${result.approval_probability.if_submitted_now}`);
console.log(`With additions: ${result.approval_probability.if_gaps_resolved}`);
} else {
console.log("Fully ready to submit.");
}Python equivalent
import requests
from dataclasses import dataclass
TALON_BASE = "https://talonapi.dev"
@dataclass
class ReadinessResult:
ready_to_submit: bool
readiness_score: float
blocking_gaps: list[str]
recommended_additions: list[str]
approval_now: float
approval_with_additions: float
turnaround_days: int
def check_pa_readiness(
api_key: str,
payer: str,
cpt_code: str,
docs: dict,
) -> ReadinessResult:
headers = {"X-API-Key": api_key}
# 1. Fetch payer rules (cache this result)
rules_res = requests.get(
f"{TALON_BASE}/api/v1/rules",
params={"payer": payer, "cpt": cpt_code},
headers=headers,
)
rules_res.raise_for_status()
# 2. Submit readiness check
check_res = requests.post(
f"{TALON_BASE}/api/v1/rules/check",
headers={**headers, "Content-Type": "application/json"},
json={
"payer": payer,
"cpt_code": cpt_code,
"available_documentation": docs,
},
)
check_res.raise_for_status()
data = check_res.json()
return ReadinessResult(
ready_to_submit=data["ready_to_submit"],
readiness_score=data["readiness_score"],
blocking_gaps=data["blocking_gaps"],
recommended_additions=data["recommended_additions"],
approval_now=data["approval_probability"]["if_submitted_now"],
approval_with_additions=data["approval_probability"]["if_gaps_resolved"],
turnaround_days=data["estimated_turnaround_days"],
)
# Usage
result = check_pa_readiness(
api_key="tln_test_abc123",
payer="Aetna",
cpt_code="27447",
docs={
"has_clinical_notes": True,
"has_imaging": True,
"has_conservative_treatment_docs": True,
"conservative_treatment_weeks": 8,
"has_bmi": False,
"has_functional_score": False,
"has_failed_medication_list": True,
},
)
if not result.ready_to_submit:
print("BLOCKED:", result.blocking_gaps)
elif result.recommended_additions:
print("Ready but could be stronger:", result.recommended_additions)
print(f"Approval now: {result.approval_now}")
print(f"With additions: {result.approval_with_additions}")
else:
print("Fully ready to submit.")Tips for production
GET /api/v1/rules response for 24 hours to reduce latency.404 for a payer/CPT combination, it means Talon does not have rules for that pair yet. Show a "manual review required" message instead of failing.tln_test_ return realistic fake data and are never rate-limited. Switch to tln_live_ only when you go to production. approval_probability.if_submitted_now and if_gaps_resolved tells your coordinator how much improvement they can get by gathering the recommended additions. If the delta is small, it may not be worth the delay.