Contractor trust-check API and MCP server

Vet every contractor in one call.

Better Vetters tells an AI agent whether a contractor is real, licensed, and pulling permits. It checks official state license boards and city permit portals, then returns a verdict, a score, and the records behind them.

20 free checks, then $0.15 per check. Coverage today: WA, TX (Austin permits), and NYC.

POST /v1/contractor/check
curl -s -X POST \
  https://api.bettervetters.com/v1/contractor/check \
  -H "Authorization: Bearer $BV_API_KEY" \
  -d '{"name":"Example Roofing LLC","state":"WA"}'

{
  "verdict": "trusted",
  "trust_score": 96,
  "match": { "confidence": 0.99 },
  "license": { "status": "active", "expires": "2027-03-01" },
  "permits": { "last_12_months": 14 },
  "data_freshness": { … }
}

Illustrative response. Names, numbers, and dates are made up.

What a check returns

A verdict, a score, and the evidence behind them.

Every response carries the records it was built from, the limits of those records, and when each source was last refreshed.

Verdict, score, and reasons

One of seven verdicts, a 0 to 100 trust score, and a list of reason codes that show how the score was built.

License record

License type, class, status, expiry date, days until expiry, suspension date, and a link to verify it on the licensing board’s own site.

Insurance and bond (WA)

Whether general-liability insurance and a surety bond are on file, with amounts, providers, and expiry dates.

Permit activity

Permit counts overall and for the last 12 months, the most recent permit date, and sample permits with links to the city record.

Discipline where published

Washington license suspension dates and NYC DCWP charges and outcomes. Not available for Texas.

Match confidence

A 0 to 1 name-match confidence, the signals it used, and alternate candidates, so your agent knows when to confirm.

Seven verdicts

Built for an agent to branch on.

Verdict names are the exact values of the verdict field. Color is never the only signal: every badge has its own icon.

VerdictWhat it means
trustedConfident match (confidence 0.8+) with a score of 80 or more. License in good standing in the covered sources.
likely_okMostly clean, score 60 to 79. Worth a glance, not a blocker.
cautionNeeds a human look, score 35 to 59. For example an expired license or enforcement findings.
high_riskLicense suspended or revoked, or a score under 35 in the covered sources.
unknownNo reliable match to score, so no judgment either way.
not_foundNo matching record in the covered sources. A missing record is not proof of a problem.
out_of_coverageThe contractor’s state is outside current coverage (WA, TX, NY). Not charged.

The score is a weighted sum of the components that can speak to the contractor: license status and expiry (50), insurance and bond in WA (12), discipline (13), and permit activity (25). Zero permits is neutral, because permit coverage is one city per state.

Sample response

The real response shape, abridged.

A matched Washington contractor. The structure is the live API’s; the business, numbers, and dates here are illustrative.

200 OK · application/json
{
  "status": "matched",
  "verdict": "trusted",
  "trust_score": 96,
  "match": {
    "confidence": 0.99,
    "name_score": 100.0,
    "basis": [
      "name",
      "phone"
    ],
    "ambiguous": false,
    "matched_business_name": "EXAMPLE ROOFING LLC",
    "alternates": []
  },
  "license": {
    "license_number": "EXAMPRL000XX",
    "state": "WA",
    "type": "CONSTRUCTION CONTRACTOR",
    "class": "GENERAL",
    "status": "active",
    "business_name": "EXAMPLE ROOFING LLC",
    "city": "SEATTLE",
    "issued_or_effective": "2023-03-01",
    "expires": "2027-03-01",
    "days_until_expiry": 111,
    "suspended_on": null,
    "source_id": "wa_lni_contractors",
    "verify_url": "https://secure.lni.wa.gov/verify/Detail.aspx?UBI=000000000&LIC=EXAMPRL000XX&SAW="
  },
  "insurance_bond": {
    "insurance": {
      "on_file": true,
      "amount_usd": 1000000.0,
      "provider": "Example Insurance Co",
      "expires": "2027-01-15"
    },
    "bond": {
      "on_file": false,
      "amount_usd": null,
      "provider": null
    }
  },
  "permits": {
    "total": 48,
    "last_12_months": 14,
    "last_24_months": 29,
    "last_permit_date": "2026-10-21",
    "jurisdictions": [
      "Seattle"
    ],
    "match_basis": [
      "name"
    ],
    "samples": [
      {
        "permit_number": "0000000-RR",
        "issue_date": "2026-10-21",
        "type": "Roof",
        "jurisdiction": "Seattle",
        "status": "Completed",
        "url": "https://services.seattle.gov/portal/customize/LinkToRecord.aspx?altId=0000000-RR"
      }
    ]
  },
  "discipline": {
    "available": true,
    "scope": "License suspension date only (no infraction feed on open data).",
    "summary": {
      "suspended_on": null
    },
    "actions": []
  },
  "reasons": [
    {
      "code": "LICENSE_ACTIVE",
      "effect": "positive",
      "points": "50/50",
      "detail": "Licence active through 2027-03-01"
    },
    {
      "code": "INSURANCE_BOND",
      "effect": "positive",
      "points": "8/12",
      "detail": "insurance on file ($1,000,000); no active bond on file"
    },
    {
      "code": "NO_SUSPENSION",
      "effect": "positive",
      "points": "13/13",
      "detail": "No suspension recorded in L&I licence data (infractions are not published as open data)"
    },
    {
      "code": "PERMIT_ACTIVITY",
      "effect": "positive",
      "points": "25/25",
      "detail": "48 permit(s) in the covered window (Seattle, see /v1/coverage); 14 in the last 12 months; most recent 2026-10-21"
    }
  ],
  "data_freshness": {
    "wa_lni_contractors": {
      "name": "WA L&I Contractor License Data - General",
      "last_refreshed_at": "2026-11-10T02:12:12Z",
      "publisher_updated_at": "2026-11-10T01:36:16Z",
      "refresh_cadence": "Daily (observed nightly updates)",
      "url": "https://data.wa.gov/d/m8qx-ubtq"
    }
  },
  "billing": {
    "charged_usd": 0.15,
    "balance_usd": 2.85,
    "checks_remaining": 19,
    "idempotent_replay": false
  }
}

Abridged: other_licenses, additional permit samples, and the other sources in data_freshness are omitted. The full field list is in the docs and in openapi.json.

Coverage

Three places today, and we say so.

License data comes from the state or city that issues it. Permit data is one city per state.

WA

Washington

L&I contractor licenses with insurance and bond, plus Seattle building permits.

TX

Texas

TDLR electrical, A/C, sign, appliance-install, elevator, and well-driller licenses, plus Austin permits. Texas has no statewide general-contractor license.

NYC

New York City

DCWP Home Improvement Contractor and Construction Labor Provider licenses, DCWP enforcement charges, and DOB permits.

See the exact sources, record counts, and refresh cadence.

Pricing

$0.15 per check.
Your first 20 are free.

Pay per call. No subscription, no minimum, and no card to create a key.

See pricing details

$0.15per check20 free checks to start

Agent-friendly

Machine first, human readable second.

Structured output, named fields, and the files agents look for.

MCP server

A stdio MCP server exposes check_contractor and get_coverage, calling the HTTP API with your key. Setup.

OpenAPI and llms.txt

A 3.1 OpenAPI spec at openapi.json and a plain-text summary at llms.txt.

Safe retries

Send an Idempotency-Key and a retried request returns the stored result without a second charge.

Machine-readable 402

Out of credits? You get HTTP 402 with the price, your balance, and that credit packs are coming soon, instead of a dead end.

Reason codes

Each score comes with codes such as LICENSE_ACTIVE and PERMIT_ACTIVITY, each with an effect and points.

Source freshness

Each response lists, for every source it used, when we last refreshed and when the publisher last updated.

Honest about limits

What a check can and cannot tell you.

It tells you

  • Whether a license record matches, and its status and expiry.
  • Whether insurance and a bond are on file (WA).
  • Whether permits name the contractor in Seattle, Austin, or NYC.
  • Suspension dates (WA) and DCWP charges (NYC) where they are published.

It does not tell you

  • Anything outside WA, TX, and NYC.
  • That a missing record means a problem. A missing record is not an accusation.
  • Anything about permits outside Seattle, Austin, and NYC.
  • Anything a consumer report would cover. This is public records, not a consumer report.

FAQ

Questions agent builders ask.

What does Better Vetters check?

One call returns whether a US contractor matches a license record, the license’s status and expiry, insurance and bond on file (WA), permit activity in the covered city, discipline where it is published, a match confidence, a 0 to 100 trust score, the reasons behind the score, and when each source was last refreshed.

Is this a background check or a consumer report?

No. Better Vetters reports public records. It is not a consumer reporting agency, and its output is not a consumer report under the Fair Credit Reporting Act. Do not use it for employment, credit, insurance, or tenant-screening decisions. See the Terms of Service.

Which places are covered?

Washington State, Texas (with Austin permits), and New York City. Permit data is one city per state: Seattle, Austin, and NYC. A request for any other state returns out_of_coverage and is not charged. See Coverage for the exact sources.

What does a check cost?

$0.15 per check. Every new API key starts with 20 free checks, and you do not need a card to create one.

How should my agent act on a verdict?

Treat trusted and likely_ok as a positive signal and caution and high_risk as a reason for a human to look. Treat match.confidence below 0.8 as a possible match and confirm the returned license number or address. not_found means no record in the covered sources, which is not proof of a problem.

How do I use it from an MCP client?

Run the stdio MCP server with your API key. It exposes two tools, check_contractor and get_coverage. Setup steps are in the docs.

How fresh is the data?

It depends on the source. Most publishers update daily or nightly; the NYC license feed is weekly and the NYC charges feed is monthly. Responses include a data_freshness block with the last refresh and the publisher’s own update time for each source used.

What happens when my credits run out?

The API returns HTTP 402 with a machine-readable body that includes the price, your balance, and that credit packs are coming soon. Nothing is charged for that request. Your free starter credits work now.

Are unused credits refundable?

No. All credit purchases are final and non-refundable, except where applicable law requires a refund, or to correct a duplicate or erroneous charge. Unused credits are not refundable. Credits do not expire while the account is active. Free starter credits have no cash value.

Is it safe to retry a request?

Yes. Send an Idempotency-Key header and a retried request returns the original result without a second charge.

Run your first 20 checks free.

Create a key, send one request, and read the verdict.

create a key
# Get a key (20 free checks, no card). The key is shown once.
curl -s -X POST https://api.bettervetters.com/v1/keys \
  -H 'content-type: application/json' \
  -d '{"label":"my-agent"}'