{
  "openapi": "3.1.0",
  "info": {
    "title": "Contractor License Verification API",
    "version": "1.0.0",
    "summary": "Verify any US contractor license against the official state record.",
    "description": "A clean, normalized REST API that verifies US contractor licenses across states \u2014 status, expiry, classification, bond/insurance \u2014 aggregated from official public-records sources. Coverage: 299,112 records (WA 160,823 as of 2026-06-19; OR 56,041 as of 2026-06-18; CA 82,248 (partial) as of 2026-06-18). Every record carries an official `source_url` and an `as_of` date; an unknown license returns `found:false` (never a fabricated record); partial state coverage is flagged via `/v1/states` and the `partial` field, never hidden. The same data is available to AI agents over MCP at `/v1/mcp` (see /server.json). Pre-launch (Stage 0): free, no API key required yet.",
    "license": {
      "name": "Public records, redistributed for verification (not for sale)."
    },
    "contact": {
      "url": "https://license-verify.pages.dev/"
    },
    "x-integrity": "Facts copied verbatim from the official source with source_url + as_of on every record; partial coverage is flagged (see California); answers are never editorialized and never for sale."
  },
  "externalDocs": {
    "description": "Human + machine docs (REST index, MCP, coverage, professions).",
    "url": "https://license-verify.pages.dev/v1"
  },
  "servers": [
    {
      "url": "https://license-verify.pages.dev",
      "description": "Production"
    }
  ],
  "paths": {
    "/v1": {
      "get": {
        "operationId": "getIndex",
        "summary": "Machine-readable API index / docs.",
        "description": "Lists endpoints, parameters, examples, the integrity statement, and live coverage.",
        "responses": {
          "200": {
            "description": "API index.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiIndex"
                }
              }
            }
          }
        }
      }
    },
    "/v1/lookup": {
      "get": {
        "operationId": "lookupLicense",
        "summary": "Verify a single license by number (the core call).",
        "description": "Returns every record matching that license number in the given state. A no-match is a valid 200 with `found:false` \u2014 the API never fabricates a record.",
        "parameters": [
          {
            "name": "state",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "WA",
                "OR",
                "CA"
              ]
            },
            "description": "State to look in."
          },
          {
            "name": "license",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "License number (non-alphanumerics are ignored when matching). `license_number` is accepted as an alias."
          }
        ],
        "responses": {
          "200": {
            "description": "Verification result (found:true|false).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LookupResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing/invalid state or license.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Dataset temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/search": {
      "get": {
        "operationId": "searchLicenses",
        "summary": "Search by business / principal name.",
        "description": "Name search within a state (or across all states). Scoped to records whose name begins with the query's first character; `q` must be at least 2 characters.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 2
            },
            "description": "Name query (>= 2 chars, matched from the first character)."
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "WA",
                "OR",
                "CA"
              ]
            },
            "description": "Restrict to one state. Omit to search all covered states."
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "suspended",
                "expired"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paged search results.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              }
            }
          },
          "400": {
            "description": "`q` too short / invalid state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Dataset temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/licenses": {
      "get": {
        "operationId": "listLicenses",
        "summary": "Paged by-state list (license#-sorted compact records).",
        "description": "Returns one fixed-size page of a state's licenses. `status`/`city` filter WITHIN the returned page; use /v1/search for cross-page filtered queries.",
        "parameters": [
          {
            "name": "state",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "WA",
                "OR",
                "CA"
              ]
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "0-based page index."
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Filter within the returned page only."
          },
          {
            "name": "city",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Filter within the returned page only."
          }
        ],
        "responses": {
          "200": {
            "description": "One page of compact records + pagination + coverage.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing/invalid state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Page out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Dataset temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/states": {
      "get": {
        "operationId": "getCoverage",
        "summary": "Coverage & freshness table.",
        "description": "Per-state record counts, as_of dates, source attribution, and honest `partial` flags.",
        "responses": {
          "200": {
            "description": "Coverage table.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatesResponse"
                }
              }
            }
          },
          "502": {
            "description": "Dataset temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/mcp": {
      "post": {
        "operationId": "mcpEndpoint",
        "summary": "MCP server (JSON-RPC 2.0 over Streamable HTTP) for AI agents.",
        "description": "Same data, four tools: lookup_license, search_licenses, list_licenses, get_coverage. Send JSON-RPC `initialize` / `tools/list` / `tools/call`. GET this URL for a capability summary. The standardized MCP descriptor is at /server.json.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "A JSON-RPC 2.0 request (or batch).",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC 2.0 response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "LicenseRecord": {
        "type": "object",
        "description": "A cite-stamped license record, read verbatim from the official source. Field sets vary by state, so additional source fields (bond/insurance/county/zip/etc.) may appear.",
        "additionalProperties": true,
        "required": [
          "license_number",
          "status",
          "state",
          "source_url",
          "as_of"
        ],
        "properties": {
          "license_number": {
            "type": "string",
            "description": "Official license number (as published by the source)."
          },
          "business_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Business / entity name on the license."
          },
          "principal_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Principal / individual name, where the source provides it."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "expired",
              "unknown"
            ],
            "description": "Normalized status. status_raw + status_basis document how it was derived from the official column."
          },
          "status_raw": {
            "type": [
              "string",
              "null"
            ],
            "description": "The raw status string published by the source, verbatim."
          },
          "license_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "License type / classification label where the source labels it."
          },
          "license_type_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Classification code(s), e.g. CSLB 'B| C36'."
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "WA",
              "OR",
              "CA"
            ]
          },
          "expiration_date": {
            "type": [
              "string",
              "null"
            ],
            "description": "ISO date, where published."
          },
          "source_url": {
            "type": "string",
            "description": "Official public-records URL this record was read from (cite stamp)."
          },
          "as_of": {
            "type": "string",
            "description": "ISO date the record was last read from the source (freshness stamp)."
          }
        }
      },
      "CompactRecord": {
        "type": "object",
        "description": "Compact record returned by /v1/search and /v1/licenses. Call /v1/lookup for the full cite-stamped record.",
        "additionalProperties": true,
        "properties": {
          "license_number": {
            "type": "string",
            "description": "Official license number (as published by the source)."
          },
          "business_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Business / entity name on the license."
          },
          "principal_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Principal / individual name, where the source provides it."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "expired",
              "unknown"
            ],
            "description": "Normalized status. status_raw + status_basis document how it was derived from the official column."
          },
          "license_type_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Classification code(s), e.g. CSLB 'B| C36'."
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "WA",
              "OR",
              "CA"
            ]
          },
          "expiration_date": {
            "type": [
              "string",
              "null"
            ],
            "description": "ISO date, where published."
          }
        }
      },
      "StateCoverage": {
        "type": "object",
        "required": [
          "state",
          "records",
          "partial",
          "as_of"
        ],
        "properties": {
          "state": {
            "type": "string",
            "enum": [
              "WA",
              "OR",
              "CA"
            ]
          },
          "records": {
            "type": "integer"
          },
          "partial": {
            "type": "boolean",
            "description": "true = a disclosed bootstrap slice, not full coverage."
          },
          "as_of": {
            "type": "string"
          },
          "source": {
            "type": [
              "string",
              "null"
            ]
          },
          "source_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "coverage_note": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ApiIndex": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "product": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "integrity": {
            "type": "string",
            "description": "The standing integrity statement returned on every response."
          },
          "description": {
            "type": "string"
          },
          "states_covered": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "total_records": {
            "type": [
              "integer",
              "null"
            ]
          },
          "endpoints": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        }
      },
      "LookupResponse": {
        "type": "object",
        "required": [
          "found",
          "count",
          "records"
        ],
        "properties": {
          "product": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "integrity": {
            "type": "string",
            "description": "The standing integrity statement returned on every response."
          },
          "query": {
            "type": "object",
            "additionalProperties": true
          },
          "found": {
            "type": "boolean"
          },
          "count": {
            "type": "integer"
          },
          "records": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LicenseRecord"
            }
          }
        }
      },
      "SearchResponse": {
        "type": "object",
        "required": [
          "total_matches",
          "count",
          "records"
        ],
        "properties": {
          "product": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "integrity": {
            "type": "string",
            "description": "The standing integrity statement returned on every response."
          },
          "query": {
            "type": "object",
            "additionalProperties": true
          },
          "total_matches": {
            "type": "integer"
          },
          "count": {
            "type": "integer"
          },
          "note": {
            "type": "string"
          },
          "records": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CompactRecord"
            }
          }
        }
      },
      "ListResponse": {
        "type": "object",
        "required": [
          "state",
          "pagination",
          "records"
        ],
        "properties": {
          "product": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "integrity": {
            "type": "string",
            "description": "The standing integrity statement returned on every response."
          },
          "state": {
            "type": "string",
            "enum": [
              "WA",
              "OR",
              "CA"
            ]
          },
          "coverage": {
            "$ref": "#/components/schemas/StateCoverage"
          },
          "pagination": {
            "type": "object",
            "properties": {
              "page": {
                "type": "integer"
              },
              "page_size": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "total_pages": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "total_records": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "filter_applied": {
            "type": "object",
            "additionalProperties": true
          },
          "count": {
            "type": "integer"
          },
          "note": {
            "type": "string"
          },
          "records": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CompactRecord"
            }
          }
        }
      },
      "StatesResponse": {
        "type": "object",
        "required": [
          "states_covered",
          "total_records",
          "states"
        ],
        "properties": {
          "product": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "integrity": {
            "type": "string",
            "description": "The standing integrity statement returned on every response."
          },
          "states_covered": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "total_records": {
            "type": "integer"
          },
          "states": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StateCoverage"
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      }
    }
  }
}
