Troubleshooting | 1099Policy

Troubleshooting

This guide covers common issues you may encounter when integrating COI Review, along with recommended solutions.

Error status

When a certificate ends up in error status, processing failed before evaluation could complete. There are three common causes:

Cause Description
AI parsing failure The AI couldn't extract any meaningful data from the PDF (blank, corrupted, or unreadable)
Processing exception An unexpected error occurred during processing
Retries exhausted Transient errors (rate limits, timeouts) persisted after multiple retry attempts

What to do

def handle_certificate_status(certificate):
    if certificate['status'] == 'error':
        # Log for investigation
        log_error(f"Certificate {certificate['id']} failed processing")

# Notify contractor to re-upload
        request_new_certificate(certificate['contractor'])

There is no automatic retry mechanism you can trigger. The recommended approach is to request a new certificate from the contractor.

Processing timeouts

Certificate processing typically completes within 1-2 minutes. However, under certain conditions it can take longer:

Timeout Duration
AI processing 5 minutes per attempt
Overall job 10 minutes per attempt
Maximum with retries ~2 hours (worst case)

Transient failures (rate limits, server errors, timeouts) are retried up to 3 times with exponential backoff (30s, 60s, 120s delays).

Recommended handling

def check_stuck_certificates():
    """Run periodically to catch certificates that may be stuck"""
    two_hours_ago = time.time() - (2 * 60 * 60)

# Find certificates still processing after 2 hours
    stuck = Certificate.query.filter(
        Certificate.status.in_(['pending', 'processing']),
        Certificate.created < two_hours_ago
    ).all()

for cert in stuck:
        # Alert your team or request re-upload
        handle_stuck_certificate(cert)

File issues

Rejected uploads

Issue Error Solution
Wrong format File must be PDF Only PDF files are accepted. Convert images, Word docs, or scanned TIFFs to PDF first.
Too large File exceeds 15 MB limit Compress the PDF or request a smaller file from the contractor.
Invalid PDF File is not a valid PDF The file may be corrupted or have an incorrect extension. Request a new copy.

Processing failures due to file quality

Issue Result Solution
Blank or corrupted PDF error status Request a valid PDF from the contractor
Poor scan quality Rules fail due to unparseable data Request a clearer scan or a digitally-generated certificate
Important data on page 3+ Rules fail (data not extracted) Request a certificate with all coverage details on pages 1-2

Page limit Only the first 2 pages of each PDF are analyzed. Most standard ACORD forms include all relevant information on page 1, but custom certificates may vary.

Date parsing issues

The AI recognizes only three date formats:

Format Example
MM/DD/YYYY 01/15/2025
MM/DD/YY 01/15/25
YYYY-MM-DD 2025-01-15

Certificates using other formats (e.g., 15 Jan 2025, January 15, 2025, DD/MM/YYYY) will have dates parsed as null, causing expiration-related rules to fail.

Symptoms

Solution

Request a certificate with dates in a supported format, or have your compliance team manually review and approve the expiration rules.

Missing or unparseable fields

When the AI cannot extract a field that a rule depends on, the rule fails. This is by design—certificates are flagged for human review rather than auto-approved when data is uncertain.

Scenario Behavior
Amount field missing or unparseable Treated as $0, rule fails
Required field is null or empty is_not_none check fails
Date field missing or unparseable Treated as null, rule fails
Boolean field missing Treated as false, rule fails

Debugging

Fetch the full review results to see what was extracted:

curl "https://api.1099policy.com/api/v1/files/certificates/{id}?expand[]=review_results.full" \
  -u YOUR_SECRET_KEY:

Compare parsed_certificate_json with the original PDF to identify parsing issues.

Multiple certificates per contractor

Each certificate upload creates an independent record. The system does not deduplicate or lock based on contractor.

Scenario Behavior
New certificate uploaded while one is processing Both process independently, both produce results
Multiple approved certificates exist Both remain valid; your application decides which to use
Contractor uploads corrected certificate Original certificate remains (with its status); new one evaluated separately

Determining the current certificate

def get_current_certificate(contractor_id):
    response = requests.get(
        'https://api.1099policy.com/api/v1/files/certificates',
        auth=('YOUR_SECRET_KEY', ''),
        params={'contractor': contractor_id}
    )
    certificates = response.json()['data']

# Option 1: Most recent approved certificate
    approved = [c for c in certificates if c['status'] == 'approved']
    if approved:
        return max(approved, key=lambda x: x['created'])

# Option 2: Most recent non-error certificate
    valid = [c for c in certificates if c['status'] != 'error']
    if valid:
        return max(valid, key=lambda x: x['created'])

return None

Expired certificates

Certificates are evaluated at upload time. A certificate that was approved may later have an expired policy.

Proactive expiration tracking

from datetime import datetime, timedelta

def check_expiring_certificates():
    """Run daily to identify certificates expiring soon"""

response = requests.get(
        'https://api.1099policy.com/api/v1/files/certificates',
        auth=('YOUR_SECRET_KEY', ''),
        params={'status': 'approved', 'limit': 100}
    )

for cert in response.json()['data']:
        # Fetch full details to get expiration date
        details = fetch_full_results(cert['id'])

if details['review_results']:
            parsed = details['review_results'].get('parsed_certificate_json', {})

# Check GL expiration (adjust path for other coverage types)
            gl = parsed.get('coverages', {}).get('commercial_general_liability', {})
            expiration = gl.get('policy_expiration_date')

if expiration and is_expiring_soon(expiration, days=30):
                notify_contractor_to_renew(cert['contractor'])

def is_expiring_soon(date_string, days=30):
    """Check if date is within the specified number of days"""
    for fmt in ['%m/%d/%Y', '%m/%d/%y', '%Y-%m-%d']:
        try:
            expiration = datetime.strptime(date_string, fmt)
            return expiration <= datetime.now() + timedelta(days=days)
        except ValueError:
            continue
    return False  # Couldn't parse date

Split limits vs. Combined Single Limit (Auto Liability)

For automobile liability, if you require split limits (e.g., Bodily Injury per Person ≥ $100K) but the certificate only shows a Combined Single Limit (CSL), the system automatically checks whether the CSL meets the required amount.

Your rule Certificate shows Result
BI per Person ≥ $100,000 CSL of $500,000 Pass (CSL meets requirement)
BI per Person ≥ $100,000 CSL of $50,000 Fail (CSL below requirement)
BI per Person ≥ $100,000 BI per Person of $250,000 Pass (exact field matches)

This prevents false failures for certificates that use CSL formatting.

Workers' Compensation only requirements

When your insurance requirement only includes Workers' Compensation coverage (no GL, Auto, etc.), the system automatically skips validation of additional insured names in the description of operations. This is because additional insured endorsements are not applicable to WC-only policies.

No action needed—this is handled automatically.

Voided audit results

In rare cases, audit results may be voided by your compliance team (e.g., if a certificate was evaluated against an incorrect requirement). Voided results:

You don't need to handle voided results in your integration—they're filtered out before the response reaches you.

Troubleshooting checklist

When investigating certificate issues:

Check How
Certificate status GET /api/v1/files/certificates/{id} — check status field
What was extracted Add ?expand[]=review_results.full — examine parsed_certificate_json
Which rules failed Look at audit_results where result: "fail"
Original file Download from pdf_url and compare with parsed data
File requirements Confirm PDF format, under 15 MB, coverage info on pages 1-2
Date formats Check certificate uses MM/DD/YYYY, MM/DD/YY, or YYYY-MM-DD

Getting help

If you've investigated an issue and need assistance: