Why Bond and Insurance Verification Is Not Optional

When a contractor causes property damage, injures a worker, or abandons a job mid-project, the first question a homeowner or platform operator asks is: who pays? If the contractor has adequate general liability insurance, their policy pays for property damage caused during the job. If they have workers' compensation coverage, an injured worker's medical costs and lost wages run through that policy rather than as a direct liability claim against your platform or the property owner.

A surety bond serves a different function. It is not insurance for accidents - it is a financial guarantee that the contractor will fulfill the terms of their contract. If a licensed, bonded contractor takes a deposit and disappears, the homeowner can file a claim against the bond to recover their losses. The surety company pays the claim and then pursues the contractor for reimbursement. For the homeowner, this is the difference between a recoverable bad outcome and a total loss.

From a platform liability perspective, the risk profile of a contractor with a $15,000 bond and $1M general liability policy is dramatically different from one who has a license but let their bond lapse and dropped to a minimum-limit policy to cut costs. Both will pass a basic license status check. Only bond and insurance verification surfaces that difference.

Regulatory Requirements Add Complexity

Many state licensing boards mandate both a surety bond and proof of general liability insurance as conditions of license issuance and renewal. But the requirements are not uniform. Some states set minimum bond amounts that have not been updated in decades and are effectively symbolic. Others tie bond requirements to the contractor's license class - a Class A general contractor in California faces very different requirements than a specialty sub-contractor. And some trades in some states face no bond requirement at all.

For platforms operating across multiple states, tracking what each state requires for each trade classification is a material operational burden. The ContractorVerify API addresses this by embedding the applicable state requirement into the verification response alongside the contractor's actual coverage data, so your compliance logic can evaluate the gap between what is required and what the contractor actually holds - rather than just checking whether they answered "yes" to a bond question in their profile.

What the ContractorVerify API Returns for Bond and Insurance

The verification response includes a dedicated coverage object with the following fields:

{
  "license": {
    "number": "1088432",
    "type": "General Building Contractor",
    "state": "CA",
    "status": "active",
    "expiration_date": "2027-05-31",
    "bond_required": true,
    "insurance_required": true
  },
  "coverage": {
    "bond": {
      "required": true,
      "status": "active",
      "amount": 25000,
      "state_minimum": 25000,
      "meets_minimum": true,
      "surety_company": "Merchants Bonding Company",
      "bond_number": "MBC-TX-884421",
      "effective_date": "2025-06-01",
      "expiration_date": "2026-06-01",
      "days_until_expiration": 68
    },
    "general_liability": {
      "required": true,
      "status": "verified",
      "per_occurrence_limit": 1000000,
      "aggregate_limit": 2000000,
      "policy_number": "GL-2025-44821-A",
      "carrier": "Travelers Insurance",
      "effective_date": "2025-08-15",
      "expiration_date": "2026-08-15",
      "certificate_on_file": true,
      "last_verified": "2026-03-20T09:00:00Z"
    },
    "workers_compensation": {
      "required": true,
      "status": "active",
      "carrier": "State Compensation Insurance Fund",
      "policy_number": "WC-9984421",
      "expiration_date": "2026-09-30"
    }
  }
}

The key fields for platform compliance decisions are:

State-by-State Contractor Bond Requirements

Bond requirements vary widely by state and trade classification. The following table shows current general contractor bond minimums for the ten largest contractor markets in the US:

State GC Bond Minimum Class/Tier Notes Governing Body
California $25,000 Flat minimum for all CSLB licensees. Unchanged since 2023 legislative update (up from $15,000). CSLB
Texas $10,000 Applies to HVAC and electrical contractor license classes. GCs are not state-licensed; no state bond requirement. TDLR
Florida $10,000 - $300,000 Tiered by license class. Certified General Contractor requires $300K. Registered (county-level) contractors have lower minimums set by jurisdiction. DBPR / County boards
New York $15,000 (NYC: $100,000+) State minimum is $15K but NYC Home Improvement Contractor license requires $100K bond. Commercial work adds additional bonding layers. NYC DCA / State DOS
Illinois Varies by municipality Illinois does not license GCs at the state level. Chicago requires a $10,000 bond for roofing contractors; other trades vary by city. Local licensing boards
Pennsylvania No state minimum Pennsylvania has no statewide GC licensing or bonding requirement. Home improvement contractors must register (not bond) under HICPA. Philadelphia and Pittsburgh have local requirements. OAGC (registration only)
Ohio $25,000 (HVAC/plumbing) Ohio Construction Industry Licensing Board sets trade-specific minimums. GC licensing is at the county level with varying bond requirements. OCILB / County boards
Georgia $25,000 (Class I) GCOC (Georgia Construction Industry Licensing Board) licenses GCs in Class I (unlimited) and Class II (residential under $1M) categories with different bond tiers. GCOC
North Carolina $10,000 - $75,000 Tiered by license class. Limited (projects under $500K) requires $10K; Unlimited requires $75K. Separate specialty trade licensing boards set their own bond requirements. NCLBGC
Arizona $2,500 - $15,000 ROC (Registrar of Contractors) sets bond amounts by license category. Residential Contractor (CR-39) requires $4,000; Commercial General Engineering (A) requires $15,000. Arizona ROC
Important: Bond minimums set by state agencies are legal floors, not platform standards. A $2,500 Arizona bond covers almost nothing on a $50,000 remodel. Platforms should establish their own minimum bond thresholds based on the job values they facilitate - and use the API's bond.amount field to enforce them, not just the meets_minimum flag.

Bond Verification vs. Insurance Certificate Verification - The Difference

These two coverage types are often mentioned together, but they work differently and require different verification approaches.

Surety Bonds: State-Verifiable

In states where the licensing board requires a bond as a condition of licensure, the bond status is typically embedded directly in the license record. When you query CSLB for a California contractor's license, the response includes bond information because CSLB requires bond filing as part of the licensing process and tracks bond status as part of their records. This is the most reliable bond verification path - the data comes from the same authoritative source as the license itself.

For trades where bond status is tracked by the licensing board, the ContractorVerify API pulls bond data from the same database query as the license data. The data_source field in the response specifies this - you will see values like "cslb_live" for California or "tdlr_live" for Texas HVAC, indicating the bond data is as fresh as the license data itself.

General Liability Insurance: Certificate-Based

Unlike bonds, general liability insurance is not typically filed with or tracked by state licensing boards. A contractor proves their insurance coverage by providing an ACORD 25 certificate - a standardized one-page document issued by their insurance carrier listing the policyholder, carrier, policy number, coverage types, per-occurrence and aggregate limits, and expiration date.

The limitation of certificate-based verification is that certificates can become stale. An ACORD 25 issued in August 2025 might accurately reflect the contractor's coverage on that date, but if the contractor let the policy lapse in January 2026 (or reduced their limits at renewal), the certificate your platform collected at onboarding no longer reflects reality.

More rigorous insurance verification involves contacting the carrier or broker directly to confirm active policy status - a process called "certificate verification" or "COI verification." The ContractorVerify API supports this through carrier integrations for major commercial insurers, allowing the general_liability.status field to return "verified" (confirmed with carrier) rather than just "certificate_on_file" (unconfirmed document submitted).

> Automate Your License Verification_

ContractorVerify returns bond amount, bond status, and insurance requirements in a single API call - normalized across all 50 states. Stop chasing ACORD certificates and manual bond lookups. One API call handles the entire compliance stack.

Join the Waitlist

Code Example: Pulling Bond and Insurance Data via API

The simplest call that returns complete bond and insurance data for a California contractor looks like this:

POST https://api.contractorverify.io/v1/verify
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

{
  "license_number": "1088432",
  "state": "CA",
  "trade": "general",
  "include_coverage": true
}

The include_coverage: true flag activates the full coverage object in the response. For high-volume use cases where you only need license status (not bond/insurance), omitting this flag reduces response latency and API credit consumption.

To build a coverage adequacy check that enforces your platform's own minimums rather than just the state minimum, evaluate the response fields directly:

// Platform compliance logic example (Node.js)
async function assessContractorCompliance(licenseNumber, state, trade) {
  const response = await fetch('https://api.contractorverify.io/v1/verify', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.CONTRACTORVERIFY_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      license_number: licenseNumber,
      state: state,
      trade: trade,
      include_coverage: true
    })
  });

  if (!response.ok) {
    const err = await response.json().catch(() => ({}));
    throw new Error(err.message || `Verification failed (${response.status})`);
  }

  const data = await response.json();
  const { license, coverage } = data;

  const PLATFORM_MINIMUMS = {
    bond_amount: 25000,                  // Platform minimum regardless of state floor
    gl_per_occurrence: 500000,           // $500K per occurrence minimum
    gl_aggregate: 1000000,               // $1M aggregate minimum
    expiration_warning_days: 45          // Flag coverage expiring within 45 days
  };

  const issues = [];

  // License status check
  if (license.status !== 'active') {
    issues.push({ severity: 'BLOCK', code: 'LICENSE_INACTIVE', detail: `License status: ${license.status}` });
  }

  // Bond checks
  if (coverage.bond.required) {
    if (coverage.bond.status !== 'active') {
      issues.push({ severity: 'BLOCK', code: 'BOND_INACTIVE', detail: `Bond status: ${coverage.bond.status}` });
    }
    if (coverage.bond.amount < PLATFORM_MINIMUMS.bond_amount) {
      issues.push({
        severity: 'BLOCK',
        code: 'BOND_INSUFFICIENT',
        detail: `Bond amount $${coverage.bond.amount} is below platform minimum $${PLATFORM_MINIMUMS.bond_amount}`
      });
    }
    if (coverage.bond.days_until_expiration < PLATFORM_MINIMUMS.expiration_warning_days) {
      issues.push({
        severity: 'WARN',
        code: 'BOND_EXPIRING_SOON',
        detail: `Bond expires in ${coverage.bond.days_until_expiration} days`
      });
    }
  }

  // General liability checks
  if (coverage.general_liability.required) {
    if (coverage.general_liability.status === 'not_provided') {
      issues.push({ severity: 'BLOCK', code: 'GL_MISSING', detail: 'No general liability certificate on file' });
    }
    if (coverage.general_liability.per_occurrence_limit < PLATFORM_MINIMUMS.gl_per_occurrence) {
      issues.push({
        severity: 'BLOCK',
        code: 'GL_LIMIT_LOW',
        detail: `GL per-occurrence $${coverage.general_liability.per_occurrence_limit} below platform minimum`
      });
    }
  }

  const blockingIssues = issues.filter(i => i.severity === 'BLOCK');

  return {
    approved: blockingIssues.length === 0,
    issues,
    verified_at: data.verification_timestamp
  };
}

This pattern separates the API call (getting the data) from the compliance decision (applying your platform's rules to the data). That separation is important because the same API response data supports multiple policy configurations - a residential-only platform and a commercial platform might apply very different minimums to the same contractor record without needing separate API integrations.

Building an Automated Compliance Check: License + Bond + Insurance Combined

Effective contractor compliance programs treat license, bond, and insurance as three independent expiration timelines that all need monitoring - not a one-time check at onboarding. The compliance state of a contractor can change at any point after they join your platform:

The recommended architecture for ongoing compliance monitoring uses a scheduled re-verification job rather than relying on contractors to self-report changes. Here is the general pattern:

  1. Onboarding verification: Full /v1/verify call with include_coverage: true. Store license.expiration_date, coverage.bond.expiration_date, and coverage.general_liability.expiration_date in your database. Record the verification_timestamp.
  2. Next verification date calculation: Set re-verification to the earliest of: 45 days before any expiration date, or 90 days from the last verification - whichever comes first.
  3. Scheduled job: Daily cron queries your database for contractors whose next_verification_date <= today. Run a batch verification call for all of them via /v1/batch.
  4. Status change detection: Compare the new verification result against the stored state. If any field has changed - particularly license.status, coverage.bond.status, or coverage.general_liability.status - trigger a status change event in your system.
  5. Automated response: Status change events drive platform actions - email notifications to the contractor, suspension of new job assignments, flags in the admin dashboard.

Edge Cases: Trades That Don't Require Bonds, and States With Unusual Rules

Not every trade in every state requires a bond. Several important edge cases affect how you interpret the API's bond_required field:

Sole Proprietor Exemptions

A handful of states exempt sole proprietor contractors from bond requirements that apply to business entities. This is most common in states like Pennsylvania and Illinois, where licensing is municipal rather than state-level. If your platform serves a mix of sole proprietors and incorporated contractor businesses, the bond_required field already accounts for the entity type - it reflects whether this specific contractor, given their license class and entity structure, is legally required to hold a bond.

States Where Bond Status Is Not Publicly Accessible

Florida's DBPR and New York's Department of State do not expose real-time bond status through their public license lookup portals. For these states, the API's coverage.bond.status field may return "state_not_available", meaning the bond requirement exists but the current status cannot be confirmed from public sources. For Florida and New York contractors, the recommended approach is to require contractors to submit their current bond certificate directly, and use the API's certificate ingestion endpoint to store and track it.

Workers' Compensation Opt-Outs

Texas is the most prominent example of a state with a workers' compensation opt-out system. Texas employers can legally choose to be "non-subscribers" to the workers' compensation system. Non-subscriber status is legal but significantly increases the platform's risk profile for any injuries on jobs those contractors perform, since injury claims go directly through civil litigation rather than the WC system. The API returns "workers_compensation.status": "non_subscriber_tx" for Texas contractors who have formally opted out, so your compliance logic can flag them for additional review rather than treating them as non-compliant.

Specialty Trades With No Bond Requirement

Some specialty trades - such as landscape maintenance (not installation), handyman services, and certain cleaning trades - do not require state bonds because the licensing framework that would mandate them simply does not exist. For these contractors, the API returns "bond_required": false and "bond.status": "not_applicable". This is not a compliance deficiency - it accurately reflects the regulatory environment for that trade. Platform insurance requirements still apply, but the bond check should be skipped in your compliance logic to avoid false positives.

> Automate Your License Verification_

Bond amounts, insurance requirements, and expiration dates for every contractor on your platform - checked automatically and stored in a normalized format. Stop managing spreadsheets of certificate expiration dates. ContractorVerify handles the full compliance stack in one API call.

Join the Waitlist

Why Inadequate Bonding Is a Platform Risk, Not Just a Contractor Risk

Home services platforms, property management software, and contractor marketplaces occupy an increasingly uncomfortable middle position in contractor liability. Courts in several states have found platform operators liable for contractor actions when the platform was found to have exercised sufficient control over the contractor relationship to constitute employment - a doctrinal shift driven by the gig economy litigation wave of the 2020s.

Even short of employment classification, platforms face reputational and litigation risk when they place a consumer with an inadequately bonded or uninsured contractor and that contractor causes a serious loss. The consumer's first call is to the platform. If the platform's compliance checks were insufficient or outdated, that conversation starts from a very weak position.

Building a verifiable compliance record - timestamped API verification results stored for every contractor, re-verification on a documented schedule, and clear policy thresholds applied consistently - is not just operationally sound. It is the documentation that demonstrates due diligence when a claim or lawsuit arises. The ContractorVerify API makes this record-keeping automatic: every verification call returns a request_id and verification_timestamp that can be stored in your database as an immutable compliance audit trail.

The platforms that build this infrastructure properly are also the ones that can truthfully tell their customers: "We verify every contractor's license, bond, and insurance before they work on your home, and we re-verify automatically every 90 days." That is a differentiator worth having.