Search docs...

Search docs...

Search docs...

Troubleshooting

Troubleshooting

Troubleshooting

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:

CauseDescription
AI parsing failureThe AI couldn't extract any meaningful data from the PDF (blank, corrupted, or unreadable)
Processing exceptionAn unexpected error occurred during processing
Retries exhaustedTransient errors (rate limits, timeouts) persisted after multiple retry attempts

What to do

python
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.

Expand notation

No webhook is sent for error status. If you rely solely on webhooks, implement a fallback check for certificates that remain in pending or processing status for an extended period.

Processing timeouts

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

TimeoutDuration
AI processing5 minutes per attempt
Overall job10 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).

python
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

IssueErrorSolution
Wrong formatFile must be PDFOnly PDF files are accepted. Convert images, Word docs, or scanned TIFFs to PDF first.
Too largeFile exceeds 15 MB limitCompress the PDF or request a smaller file from the contractor.
Invalid PDFFile is not a valid PDFThe file may be corrupted or have an incorrect extension. Request a new copy.

Processing failures due to file quality

IssueResultSolution
Blank or corrupted PDFerror statusRequest a valid PDF from the contractor
Poor scan qualityRules fail due to unparseable dataRequest 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:

FormatExample
MM/DD/YYYY01/15/2025
MM/DD/YY01/15/25
YYYY-MM-DD2025-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

  • Policy expiration rules fail even though the certificate isn't expired
  • parsed_certificate_json shows null for date fields

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.

ScenarioBehavior
Amount field missing or unparseableTreated as $0, rule fails
Required field is null or emptyis_not_none check fails
Date field missing or unparseableTreated as null, rule fails
Boolean field missingTreated as false, rule fails

Debugging

Fetch the full review results to see what was extracted:

bash
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.

ScenarioBehavior
New certificate uploaded while one is processingBoth process independently, both produce results
Multiple approved certificates existBoth remain valid; your application decides which to use
Contractor uploads corrected certificateOriginal certificate remains (with its status); new one evaluated separately

Determining the current certificate

python
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

python
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 ruleCertificate showsResult
BI per Person ≥ $100,000CSL of $500,000Pass (CSL meets requirement)
BI per Person ≥ $100,000CSL of $50,000Fail (CSL below requirement)
BI per Person ≥ $100,000BI per Person of $250,000Pass (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:

  • Are excluded from the API response entirely
  • Don't appear in audit_results
  • Aren't counted in summary totals

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:

CheckHow
Certificate statusGET /api/v1/files/certificates/{id} — check status field
What was extractedAdd ?expand[]=review_results.full — examine parsed_certificate_json
Which rules failedLook at audit_results where result: "fail"
Original fileDownload from pdf_url and compare with parsed data
File requirementsConfirm PDF format, under 15 MB, coverage info on pages 1-2
Date formatsCheck certificate uses MM/DD/YYYY, MM/DD/YY, or YYYY-MM-DD

Getting help

If you've investigated an issue and need assistance:

  • Dashboard: Review certificates and audit results visually
  • API Reference: docs.1099policy.com
  • Support: support@1099policy.com — include the certificate ID (cert_...) in your request

Was this page helpful?

Yes

No

Was this page helpful?

Yes

No

Was this page helpful?

Yes

No

Was this page helpful?

Yes

No

Was this page helpful?

Yes

No

Was this page helpful?

Yes

No

© Copyright 2024. All rights reserved.

© Copyright 2024. All rights reserved.

© Copyright 2024. All rights reserved.

© Copyright 2024. All rights reserved.

© Copyright 2024. All rights reserved.

© Copyright 2024. All rights reserved.