VerityVerity API

Python SDK

Official Verity SDK for Python with type hints and modern async support

The Verity Python SDK gives you clean, typed access to Medicare coverage intelligence. Built for data science workflows and backend services.

Installation

pip install verity-python

Requires Python 3.8+. Works with any HTTP client under the hood (uses httpx).

Quick start

from verity import VerityClient

client = VerityClient(api_key="vrt_live_YOUR_API_KEY")

# Make your first request
health = client.health()
print(health["data"]["status"])  # "healthy"

Get your API key from the Developer Console.

Authentication

from verity import VerityClient
import os

# Pass directly
client = VerityClient(api_key="vrt_live_YOUR_API_KEY")

# Or from environment
client = VerityClient(api_key=os.getenv("VERITY_API_KEY"))

# Custom base URL for testing
client = VerityClient(
    api_key="vrt_live_YOUR_API_KEY",
    base_url="https://staging.verity.backworkai.com/api/v1"
)

Common scenarios

Check if a procedure needs prior auth

Most prior auth checks fail because you don't know what documentation to include. The API tells you exactly what's required.

result = client.check_prior_auth(
    procedure_codes=["27447"],  # Total knee replacement
    diagnosis_codes=["M17.11"],  # Unilateral primary osteoarthritis, right knee
    state="TX"
)

if result["data"]["pa_required"]:
    print(f"Warning: Prior authorization required")
    print(f"Confidence: {result['data']['confidence']}")
    print(f"Reason: {result['data']['reason']}")
    
    # Show exact documentation requirements
    print("\nYou need:")
    for item in result["data"]["documentation_checklist"]:
        print(f"  • {item}")
    
    # Show which policies triggered this
    print(f"\nBased on {len(result['data']['matched_policies'])} policies:")
    for policy in result["data"]["matched_policies"][:3]:
        print(f"  • {policy['policy_id']}: {policy['title']}")

Output:

Warning: Prior authorization required
Confidence: high
Reason: Procedure requires review of medical necessity

You need:
  • X-ray documentation showing degenerative joint disease
  • Conservative treatment history (6+ weeks)
  • Functional assessment scores
  • BMI documentation

Based on 8 policies:
  • L33822: Total Knee Replacement
  • A57305: Billing and Coding: Joint Replacement

The confidence field tells you how reliable this is. high means multiple policies agree. low means it's ambiguous or jurisdiction-dependent.

Look up codes with reimbursement data

result = client.lookup_code(
    code="76942",
    include=["rvu", "policies"]
)

code_data = result["data"]
print(f"{code_data['code']}: {code_data['description']}")

# RVU data is current year (2026)
if code_data.get("rvu"):
    rvu = code_data["rvu"]
    print(f"\nReimbursement:")
    print(f"  Work RVU: {rvu['work_rvu']}")
    print(f"  Facility: ${rvu['facility_price']}")
    print(f"  Non-facility: ${rvu['non_facility_price']}")

# Coverage policies show disposition by jurisdiction
if code_data.get("policies"):
    print(f"\nCoverage: {len(code_data['policies'])} policies found")
    
    covered = sum(1 for p in code_data["policies"] if p["disposition"] == "covered")
    not_covered = sum(1 for p in code_data["policies"] if p["disposition"] == "not_covered")
    
    print(f"  Covered: {covered}")
    print(f"  Not covered: {not_covered}")
    print(f"  Conditional: {len(code_data['policies']) - covered - not_covered}")

Search policies by keyword or semantically

# Keyword search (fast, exact matches)
result = client.list_policies(
    q="continuous glucose monitoring",
    policy_type="LCD",
    status="active",
    limit=10
)

print(f"Found {len(result['data'])} active LCDs\n")

for policy in result["data"]:
    print(f"{policy['policy_id']}: {policy['title']}")
    print(f"  Jurisdiction: {policy.get('jurisdiction', 'National')}")
    print(f"  Effective: {policy.get('effective_date', 'N/A')}")

Semantic search (slower but finds related concepts):

result = client.list_policies(
    q="devices that monitor blood sugar levels",
    mode="semantic",  # Uses embedding similarity
    limit=10
)

Semantic search finds policies about CGM devices even though you didn't use the exact term. It's slower (~2-3x) but more flexible.

Compare coverage across MACs

Medicare coverage isn't national. A procedure covered in Texas (JM) might not be covered in Pennsylvania (J05).

result = client.compare_policies(
    procedure_codes=["76942"],
    jurisdictions=["J05", "J06", "J12", "JM"]
)

for juris in result["data"]["comparison"]:
    print(f"\n{juris['jurisdiction']} - {juris['mac_name']}")
    print(f"States: {', '.join(juris['states'])}")
    print(f"Policies: {len(juris['policies'])}")
    
    for policy in juris["policies"]:
        print(f"  • {policy['policy_id']}: {policy['disposition']}")

This shows you exactly where coverage differs. Useful for multi-state practices or national payers.

Monitor policy changes

Policies change constantly. New LCDs get published, existing ones get retired, criteria get updated.

from datetime import datetime, timedelta

# Get changes from the last 7 days
seven_days_ago = (datetime.now() - timedelta(days=7)).isoformat() + "Z"

result = client.get_policy_changes(
    since=seven_days_ago,
    change_type="updated",
    limit=20
)

print(f"Policy updates in the last 7 days: {len(result['data'])}\n")

for change in result["data"]:
    print(f"{change['policy_id']}: {change['change_type']}")
    print(f"  {change.get('change_summary', 'No summary available')}")
    print(f"  {change['timestamp']}\n")

Use this to stay current without manually checking payer portals.

Get full policy details with criteria

result = client.get_policy(
    policy_id="L33831",
    include=["criteria", "codes", "attachments"]
)

policy = result["data"]

print(f"{policy['title']}")
print(f"Type: {policy['policy_type']} | Status: {policy['status']}")
print(f"Effective: {policy.get('effective_date', 'N/A')}\n")

# Coverage criteria are AI-extracted from the PDF
if policy.get("criteria"):
    print("Coverage Criteria:")
    for section, blocks in policy["criteria"].items():
        print(f"\n{section.upper()}:")
        for block in blocks[:3]:
            print(f"  • {block.get('text', '')[:100]}...")

# Show which codes this policy covers
if policy.get("codes"):
    print(f"\nCovers {len(policy['codes'])} codes:")
    for code in policy["codes"][:10]:
        print(f"  • {code['code']} ({code['code_system']}): {code['disposition']}")

The criteria field contains structured text blocks extracted from the policy PDF. They're tagged by section (indications, limitations, documentation, etc.) and searchable via the /coverage/criteria endpoint.

Search specific coverage criteria

Sometimes you need to find policies with specific requirements (e.g., BMI cutoffs, frequency limits).

result = client.search_criteria(
    q="BMI greater than 40",
    section="indications",
    policy_type="LCD",
    limit=10
)

print("Policies with BMI > 40 requirement:\n")

for criteria in result["data"]:
    print(f"{criteria['policy_id']} ({criteria['section']})")
    print(f"  {criteria['text'][:150]}...")
    print(f"  Tags: {', '.join(criteria.get('tags', []))}\n")

This is useful for finding policies with specific clinical criteria without reading every LCD.

List MAC jurisdictions

result = client.list_jurisdictions()

print("Medicare Administrative Contractors:\n")

for juris in result["data"]:
    print(f"{juris['jurisdiction_code']}: {juris['mac_name']}")
    print(f"  States: {', '.join(juris.get('states', []))}")
    print(f"  Type: {juris.get('mac_type', 'N/A')}\n")

Error handling

The SDK raises structured exceptions. Catch them specifically, not just generic Exception.

from verity import (
    VerityClient,
    VerityError,
    AuthenticationError,
    ValidationError,
    NotFoundError,
    RateLimitError
)

client = VerityClient(api_key="vrt_live_YOUR_API_KEY")

try:
    result = client.lookup_code(code="INVALID")
except AuthenticationError:
    print("Invalid API key")
except ValidationError as e:
    print(f"Bad request: {e.message}")
    if e.details:
        print(f"Details: {e.details}")
except NotFoundError:
    print("Code not found")
except RateLimitError as e:
    print(f"Rate limited. Resets in {e.reset - time.time():.0f}s")
except VerityError as e:
    print(f"API error: {e.message} (code: {e.code})")

Don't catch VerityError at the top level unless you're doing generic error handling. Catch specific exceptions first.

Response format

All methods return dictionaries matching this structure:

{
    "success": True,
    "data": { ... },  # The actual response
    "meta": {
        "request_id": "req_...",
        "timestamp": "2026-01-25T12:00:00Z"
    }
}

Error responses:

{
    "success": False,
    "error": {
        "code": "VALIDATION_ERROR",
        "message": "Invalid parameter: code",
        "hint": "Code must be a valid CPT, HCPCS, or ICD-10 code"
    }
}

Type hints

The SDK includes type hints for IDE autocomplete. Use them.

from verity import VerityClient
from typing import Dict, Any

client = VerityClient(api_key="vrt_live_YOUR_API_KEY")

# Type checker knows what parameters are valid
result: Dict[str, Any] = client.lookup_code(
    code="76942",
    include=["rvu", "policies"],  # IDE suggests valid values
    jurisdiction="JM",
    fuzzy=True
)

# Access with confidence
if result["success"]:
    description: str = result["data"]["description"]
    found: bool = result["data"]["found"]

Advanced configuration

Custom timeout

client = VerityClient(
    api_key="vrt_live_YOUR_API_KEY",
    timeout=60  # seconds
)

Automatic retries

The SDK retries transient failures (rate limits, timeouts) with exponential backoff. Max 3 retries by default. This is automatic—you don't need to configure it.

What the SDK doesn't do

The SDK wraps the REST API. It doesn't:

  • Cache responses (build your own cache if needed)
  • Batch requests (send them concurrently if you need parallelism)
  • Make coverage decisions (it returns what's in the policies, you interpret them)

These are intentional design choices. The SDK is low-level and unopinionated.

Resources

Next steps

On this page