{"openapi":"3.1.0","info":{"title":"licenscheck API","description":"Contractor license records as reported by state licensing boards, linked across states. Search and single-license records need no key; `/verdict` and `/graph` need `Authorization: Bearer lc_live_...` (email support@licenscheck.com). Guide, rate limits and terms: https://licenscheck.com/docs/","termsOfService":"https://licenscheck.com/terms/","contact":{"name":"licenscheck","url":"https://licenscheck.com/","email":"support@licenscheck.com"},"version":"1.0.0"},"paths":{"/licenses":{"get":{"tags":["licenses"],"summary":"Search Licenses","description":"Search licenses by contractor/business name or license number, optionally filtered by state.\n\nA search term is required: `state` only narrows a name search, so the\nendpoint can't be used to page through a whole state's licenses.\n\nArgs:\n    q: Substring to match against contractor name, business name, or\n        license number (validated by `SearchTerm`).\n    state: State to narrow the search to. Omit to search every state.\n    limit: Max results to return.\n    offset: Number of matching results to skip, for pagination. Capped\n        at the same bound as the match count, so a page past it can't\n        be requested.\n    repo: Injected `LicenseRepository`.\n\nReturns:\n    The matching page of licenses, plus the total match count.","operationId":"search_licenses_licenses_get","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":3,"maxLength":100,"description":"Name, DBA, or license number to search for (required, 3-100 characters after trimming, with at least 3 letters or digits in a row).","title":"Q"},"description":"Name, DBA, or license number to search for (required, 3-100 characters after trimming, with at least 3 letters or digits in a row)."},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/StateAbbreviation"},{"type":"null"}],"description":"Two-letter state code to narrow a search to, case-insensitive.","title":"State"},"description":"Two-letter state code to narrow a search to, case-insensitive."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Max results to return.","default":20,"title":"Limit"},"description":"Max results to return."},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":0,"description":"Number of matching results to skip.","default":0,"title":"Offset"},"description":"Number of matching results to skip."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseSearchOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/licenses/{license_id}":{"get":{"tags":["licenses"],"summary":"Get License","description":"Fetch a single license by its id.\n\nArgs:\n    license_id: The license's internal UUID.\n    repo: Injected `LicenseRepository`.\n\nReturns:\n    The matching license.\n\nRaises:\n    LicenseNotFoundError: If no license with that id exists (a 404).","operationId":"get_license_licenses__license_id__get","parameters":[{"name":"license_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"License Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseOut"}}}},"404":{"description":"No license with that id exists."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/licenses/{license_id}/graph":{"get":{"tags":["licenses"],"summary":"Get Linked Licenses","description":"Fetch every other license resolved to the same entity as this one, plus unconfirmed possible matches.\n\nArgs:\n    license_id: The queried license's internal UUID.\n    repo: Injected `LicenseRepository`.\n\nReturns:\n    The queried license's id; its linked licenses, each with its\n    cluster confidence, direct edge score and match evidence (empty if\n    the license hasn't been linked into a cluster); and its review-band\n    possible matches outside the cluster.\n\nRaises:\n    LicenseNotFoundError: If no license with that id exists (a 404).","operationId":"get_linked_entities_licenses__license_id__graph_get","parameters":[{"name":"license_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"License Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseGraphOut"}}}},"404":{"description":"No license with that id exists."},"401":{"description":"No valid API key was sent; this endpoint needs one."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/licenses/{license_id}/link-summary":{"get":{"tags":["licenses"],"summary":"Get Link Summary","description":"Count the licenses and states linked to this license's contractor, without naming them.\n\nOpen to keyless callers, as the teaser for the key-only `/graph` and\n`/verdict`: it shows a link exists, never which license or what backs it.\n\nArgs:\n    license_id: The queried license's internal UUID.\n    repo: Injected `LicenseRepository`.\n\nReturns:\n    How many other licenses and distinct states are linked.\n\nRaises:\n    LicenseNotFoundError: If no license with that id exists (a 404).","operationId":"get_link_summary_licenses__license_id__link_summary_get","parameters":[{"name":"license_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"License Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkSummaryOut"}}}},"404":{"description":"No license with that id exists."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/licenses/{license_id}/continuing-education":{"get":{"tags":["licenses"],"summary":"Get Continuing Education","description":"Fetch a license's continuing-education history.\n\nArgs:\n    license_id: The queried license's internal UUID.\n    repo: Injected `LicenseRepository`.\n\nReturns:\n    The queried license's id and its continuing-education records, most\n    recently completed first. Empty if the CE ingestion pipeline hasn't\n    populated any for it yet.\n\nRaises:\n    LicenseNotFoundError: If no license with that id exists (a 404).","operationId":"get_continuing_education_licenses__license_id__continuing_education_get","parameters":[{"name":"license_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"License Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContinuingEducationOut"}}}},"404":{"description":"No license with that id exists."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/licenses/{license_id}/classifications":{"get":{"tags":["licenses"],"summary":"Get Classifications","description":"Fetch every trade classification held under a license.\n\nArgs:\n    license_id: The queried license's internal UUID.\n    repo: Injected `LicenseRepository`.\n\nReturns:\n    The queried license's id and its classifications, primary first.\n    Empty if the ingestion pipeline hasn't populated any for it yet.\n\nRaises:\n    LicenseNotFoundError: If no license with that id exists (a 404).","operationId":"get_classifications_licenses__license_id__classifications_get","parameters":[{"name":"license_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"License Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseClassificationsOut"}}}},"404":{"description":"No license with that id exists."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/licenses/{license_id}/verdict":{"get":{"tags":["licenses"],"summary":"Get Verdict","description":"Verify a license: Clear, Review, or Risk found, with every check behind it.\n\nWeighs the license's own status, expiry and bond, every license linked\nto the same contractor, and any adverse unconfirmed possible match --\nthe same verdict the website shows, so API customers never have to\nre-derive it from `/graph`.\n\nArgs:\n    license_id: The license's internal UUID.\n    repo: Injected `LicenseRepository`.\n\nReturns:\n    The verdict, its one-sentence summary, and each check.\n\nRaises:\n    LicenseNotFoundError: If no license with that id exists (a 404).","operationId":"get_verdict_licenses__license_id__verdict_get","parameters":[{"name":"license_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"License Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerdictOut"}}}},"404":{"description":"No license with that id exists."},"401":{"description":"No valid API key was sent; this endpoint needs one."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/stats":{"get":{"tags":["stats"],"summary":"Get Stats","description":"Report how many licenses are on the covered boards' current listings.\n\nThe same exact, cached count the Coverage page sums (see\n`current_coverage`), so the two never disagree; delisted licenses are left\nout.\n\nArgs:\n    repo: Injected `LicenseRepository`.\n\nReturns:\n    The license count, always exact.","operationId":"get_stats_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatsOut"}}}}}}},"/coverage":{"get":{"tags":["coverage"],"summary":"Get Coverage","description":"List each covered state with its board, scope, publishing cadence, license count and last refresh.\n\nArgs:\n    repo: Injected `LicenseRepository`.\n\nReturns:\n    The covered states, in coverage order (see `current_coverage`).","operationId":"get_coverage_coverage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoverageOut"}}}}}}},"/key-requests":{"post":{"tags":["key requests"],"summary":"Request Key","description":"Save a \"Get an API key\" request and post it to Discord once the response is sent.\n\nA keyless visitor gets 3 per 10 minutes and 10 a day (`KEY_REQUEST_LIMIT`),\non top of the general keyless limit; a keyed caller (a customer, or the\nacceptance tests) only its key's limits. A request with the hidden\n`website` field filled in is a bot: it's acknowledged the same way, so\nthe bot learns nothing, but never saved or posted. A repeat from the same\nemail within an hour is saved but not posted again.\n\nArgs:\n    body: The form.\n    background: Runs the Discord post after responding, so the form never waits on Discord.\n    caller: Injected caller, for the form's own per-visitor limit.\n    repo: Injected `KeyRequestRepository`.\n\nReturns:\n    The acknowledgement.\n\nRaises:\n    HTTPException: 429 (with Retry-After) past the form's limit.","operationId":"request_key_key_requests_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyRequestIn"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyRequestOut"}}}},"429":{"description":"Too many requests from this visitor; retry after Retry-After seconds."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/billing":{"get":{"tags":["billing"],"summary":"Billing Status","description":"Say whether the API plan can be bought by card here, and where customers manage their subscription.\n\nReturns:\n    The status; the website shows the Subscribe button only when checkout is enabled.","operationId":"billing_status_billing_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingStatusOut"}}}}}}},"/billing/checkout":{"post":{"tags":["billing"],"summary":"Start Checkout","description":"Start buying the API plan: a Stripe Checkout Session for $99/month plus metered verifications.\n\nArgs:\n    caller: Injected caller, for the per-visitor limit.\n    gateway: Injected Stripe gateway.\n\nReturns:\n    The Checkout page to send the buyer to.","operationId":"start_checkout_billing_checkout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutOut"}}}},"503":{"description":"Self-serve checkout isn't enabled on this server."}}}},"/billing/keys":{"post":{"tags":["billing"],"summary":"Reveal Key","description":"Issue the API key for a paid Checkout Session, once.\n\nThe welcome page Stripe returns the buyer to calls this with the session\nid. The session is checked with Stripe (paid, recent, its subscription\nlive), the key is created on the `api` plan linked to that subscription,\nand returned; a second call for the same session is a 409, so a leaked\nwelcome link can't mint more keys.\n\nArgs:\n    body: The session id.\n    caller: Injected caller, for the per-visitor limit.\n    gateway: Injected Stripe gateway.\n    repo: Injected `ApiKeyRepository`.\n\nReturns:\n    The new key.\n\nRaises:\n    HTTPException: 404, 402 or 409 as described in the responses.","operationId":"reveal_key_billing_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevealIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedKeyOut"}}}},"402":{"description":"That checkout isn't paid (or is too old to reveal a key)."},"404":{"description":"No such checkout."},"409":{"description":"Its key was already shown; email support for a new one."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"BillingStatusOut":{"properties":{"checkout_enabled":{"type":"boolean","title":"Checkout Enabled","description":"True when the API plan can be bought by card; otherwise the website shows the request form."},"portal_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Portal Url","description":"Stripe's customer portal login page: cards, invoices, cancelling."}},"type":"object","required":["checkout_enabled","portal_url"],"title":"BillingStatusOut","description":"Whether self-serve checkout is on, and where customers manage billing."},"CheckOut":{"properties":{"label":{"type":"string","title":"Label","description":"The check's name, e.g. `Board status`."},"outcome":{"$ref":"#/components/schemas/CheckOutcome","description":"pass, warn, fail, or info (informational only)."},"text":{"type":"string","title":"Text","description":"The result as one plain sentence."},"segments":{"items":{"$ref":"#/components/schemas/SegmentOut"},"type":"array","title":"Segments","description":"The same result split into plain and emphasized runs, for rich rendering."}},"type":"object","required":["label","outcome","text","segments"],"title":"CheckOut","description":"One verification check and how it came out."},"CheckOutcome":{"type":"string","enum":["pass","warn","fail","info"],"title":"CheckOutcome","description":"How one verification check came out."},"CheckoutOut":{"properties":{"url":{"type":"string","title":"Url","description":"The Stripe Checkout page for the API plan."}},"type":"object","required":["url"],"title":"CheckoutOut","description":"Where to send the buyer."},"ContinuingEducationOut":{"properties":{"license_id":{"type":"string","format":"uuid","title":"License Id","description":"ID of the license whose continuing-education history was queried."},"records":{"items":{"$ref":"#/components/schemas/ContinuingEducationRecordOut"},"type":"array","title":"Records","description":"Continuing-education records for this license, most recently completed first."}},"type":"object","required":["license_id","records"],"title":"ContinuingEducationOut","description":"Response for GET /licenses/{id}/continuing-education."},"ContinuingEducationRecordOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"Internal UUID identifier for this continuing-education record."},"course_number":{"type":"string","title":"Course Number","description":"State board's course identifier."},"course_name":{"type":"string","title":"Course Name","description":"Course title."},"hours":{"type":"number","title":"Hours","description":"Continuing-education hours credited for this course."},"completed_date":{"type":"string","format":"date","title":"Completed Date","description":"Date the course was completed."},"delisted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Delisted At","description":"When the board's CE transcripts stopped carrying this record, or null while they do."}},"type":"object","required":["id","course_number","course_name","hours","completed_date","delisted_at"],"title":"ContinuingEducationRecordOut","description":"One continuing-education course a licensee completed."},"CoverageOut":{"properties":{"states":{"items":{"$ref":"#/components/schemas/StateCoverageOut"},"type":"array","title":"States","description":"One entry per covered state."},"as_of":{"type":"string","format":"date-time","title":"As Of","description":"When these numbers were computed (they're cached for a few minutes)."}},"type":"object","required":["states","as_of"],"title":"CoverageOut","description":"Every state covered, and when the numbers were computed."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"IssuedKeyOut":{"properties":{"key":{"type":"string","title":"Key","description":"The full API key (lc_live_...). It's never shown again."},"prefix":{"type":"string","title":"Prefix","description":"The key's readable prefix, for telling keys apart."},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"The email the subscription was bought with."}},"type":"object","required":["key","prefix","email"],"title":"IssuedKeyOut","description":"A newly issued key, shown this once."},"KeyRequestIn":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name","description":"Who's asking."},"email":{"type":"string","maxLength":254,"pattern":"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$","title":"Email","description":"Where to send the key."},"company":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Company","description":"Their company, if any."},"plan":{"$ref":"#/components/schemas/KeyRequestPlan","description":"What the request is for.","default":"api"},"volume":{"$ref":"#/components/schemas/KeyRequestVolume","description":"Expected verifications a month."},"use_case":{"type":"string","maxLength":2000,"minLength":1,"title":"Use Case","description":"What they'd check, in their own words."},"website":{"type":"string","maxLength":200,"title":"Website","description":"Leave empty. A field hidden from people, which only bots fill in; a filled one is dropped.","default":""}},"type":"object","required":["name","email","volume","use_case"],"title":"KeyRequestIn","description":"One filled-in \"Get an API key\" form."},"KeyRequestOut":{"properties":{"received":{"type":"boolean","title":"Received","description":"Always true: the request was accepted."}},"type":"object","required":["received"],"title":"KeyRequestOut","description":"The acknowledgement the form shows."},"KeyRequestPlan":{"type":"string","enum":["api","monitoring","volume"],"title":"KeyRequestPlan","description":"What a \"Get an API key\" request is for, as chosen on the form."},"KeyRequestVolume":{"type":"string","enum":["under_100","100_500","500_5000","over_5000"],"title":"KeyRequestVolume","description":"How many verifications a month the requester expects, as a bucket."},"LicenseClassificationOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"Internal UUID identifier for this classification record."},"classification_code":{"type":"string","title":"Classification Code","description":"Raw code as given by the state board, e.g. \"C-10\"."},"license_type":{"$ref":"#/components/schemas/LicenseType","description":"Normalized contractor trade category for this classification."},"is_primary":{"type":"boolean","title":"Is Primary","description":"Whether this was the first-listed classification -- matches the license's own license_type."},"delisted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Delisted At","description":"When the state board stopped listing this classification on the license, or null while it does."}},"type":"object","required":["id","classification_code","license_type","is_primary","delisted_at"],"title":"LicenseClassificationOut","description":"One trade classification held under a license."},"LicenseClassificationsOut":{"properties":{"license_id":{"type":"string","format":"uuid","title":"License Id","description":"ID of the license whose classifications were queried."},"classifications":{"items":{"$ref":"#/components/schemas/LicenseClassificationOut"},"type":"array","title":"Classifications","description":"Every trade classification held under this license, primary first."}},"type":"object","required":["license_id","classifications"],"title":"LicenseClassificationsOut","description":"Response for GET /licenses/{id}/classifications."},"LicenseGraphOut":{"properties":{"license_id":{"type":"string","format":"uuid","title":"License Id","description":"ID of the license whose entity graph was queried."},"linked_licenses":{"items":{"$ref":"#/components/schemas/LinkedLicenseOut"},"type":"array","title":"Linked Licenses","description":"Other licenses resolved to the same entity cluster, strongest confidence first."},"possible_matches":{"items":{"$ref":"#/components/schemas/PossibleMatchOut"},"type":"array","title":"Possible Matches","description":"Up to 10 unconfirmed review-band matches outside the cluster, suspended/revoked/delisted first."},"possible_match_count":{"type":"integer","title":"Possible Match Count","description":"Total number of review-band matches, including any beyond the 10 returned."}},"type":"object","required":["license_id","linked_licenses","possible_matches","possible_match_count"],"title":"LicenseGraphOut","description":"Response for GET /licenses/{id}/graph."},"LicenseOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"Internal UUID identifier for this license record."},"contractor_name":{"type":"string","title":"Contractor Name","description":"Individual contractor's name as registered with the state board."},"business_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Name","description":"Registered business name, if the license is held by a business rather than an individual."},"license_number":{"type":"string","title":"License Number","description":"The license number as issued by the state board."},"license_type":{"$ref":"#/components/schemas/LicenseType","description":"Normalized contractor trade category."},"state":{"$ref":"#/components/schemas/StateAbbreviation","description":"Two-letter US state code that issued this license."},"status":{"$ref":"#/components/schemas/LicenseStatus","description":"Current license status."},"issue_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Issue Date","description":"Date the license was originally issued."},"expiration_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Expiration Date","description":"Date the license expires or expired."},"bond_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bond Number","description":"Surety bond number backing this license, if applicable."},"bond_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Bond Amount","description":"Surety bond amount in USD, if applicable."},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address","description":"Registered business or contractor address on file with the state board."},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone","description":"Business phone as 10 NANP digits with no formatting, or null when the board reports none (or only a placeholder)."},"state_business_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State Business Id","description":"The issuing state's own business-registration id (e.g. Washington's UBI). Only comparable between licenses from the same state."},"principal_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Principal Name","description":"The owner/principal of record, in the board's own name format."},"last_verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Verified At","description":"When this license was last confirmed against the state board's live record."},"delisted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Delisted At","description":"When this license disappeared from the state board's full listing, or null while the board still lists it. When set, `status` is the last value the board reported and may be stale."},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"When this license record was first ingested."}},"type":"object","required":["id","contractor_name","business_name","license_number","license_type","state","status","issue_date","expiration_date","bond_number","bond_amount","address","phone","state_business_id","principal_name","last_verified_at","delisted_at","created_at"],"title":"LicenseOut","description":"A contractor license record."},"LicenseSearchOut":{"properties":{"results":{"items":{"$ref":"#/components/schemas/LicenseOut"},"type":"array","title":"Results","description":"Matching licenses for this page."},"total":{"type":"integer","title":"Total","description":"Total number of matches across all pages, before limit/offset. When `total_is_exact` is false this is either the 10,000 count cap (a search with more matches than that) or the table's estimated row count (an unfiltered listing)."},"total_is_exact":{"type":"boolean","title":"Total Is Exact","description":"Whether `total` is an exact count rather than a cap or estimate."}},"type":"object","required":["results","total","total_is_exact"],"title":"LicenseSearchOut","description":"Response for GET /licenses (search/list)."},"LicenseStatus":{"type":"string","enum":["active","inactive","probation","expired","suspended","revoked"],"title":"LicenseStatus","description":"Current status of a contractor license, as reported by its state board."},"LicenseType":{"type":"string","enum":["general_contractor","building_contractor","residential_contractor","air_conditioning_contractor","electrical_contractor","roofing_contractor","plumbing_contractor","pool_spa_contractor","mechanical_contractor","sheet_metal_contractor","utility_excavation_contractor","solar_contractor","specialty_contractor","pollutant_storage_contractor","precision_tank_tester","other","unknown"],"title":"LicenseType","description":"Normalized contractor trade category.\n\nEach state board has its own raw code vocabulary (e.g. Florida DBPR's\n\"CBC\", \"RG\", ...); each state's ingestion DAG maps its own codes onto\nthis shared vocabulary. Folds a state's \"statewide\" vs \"local\" license\nclasses (e.g. FL's Certified vs Registered) into the same category here\n-- that distinction isn't tracked separately (yet)."},"LinkEvidence":{"type":"string","enum":["same_address","same_phone","same_business_id","same_principal","same_name"],"title":"LinkEvidence","description":"A concrete, human-checkable reason two licenses were matched."},"LinkSummaryOut":{"properties":{"license_id":{"type":"string","format":"uuid","title":"License Id","description":"The queried license's internal UUID."},"linked_licenses":{"type":"integer","title":"Linked Licenses","description":"How many other licenses are resolved to the same contractor."},"linked_states":{"type":"integer","title":"Linked States","description":"How many distinct states those other licenses are in."}},"type":"object","required":["license_id","linked_licenses","linked_states"],"title":"LinkSummaryOut","description":"How far a license's contractor reaches across licenses and states, without saying which (the keyless teaser)."},"LinkedLicenseOut":{"properties":{"license":{"$ref":"#/components/schemas/LicenseOut","description":"The linked license record."},"confidence":{"type":"number","title":"Confidence","description":"This license's strongest entity-resolution match score (0.0-1.0) into the cluster -- to whichever member it matched best, not necessarily the queried license. See `direct_edge_score` for that."},"direct_edge_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Direct Edge Score","description":"Match score (0.0-1.0) between this license and the queried one, or null when they're linked only transitively through other members."},"evidence":{"items":{"$ref":"#/components/schemas/LinkEvidence"},"type":"array","title":"Evidence","description":"What the direct match with the queried license rests on (shared address, phone, state business id, principal, or name). Empty when linked only transitively."}},"type":"object","required":["license","confidence","direct_edge_score","evidence"],"title":"LinkedLicenseOut","description":"A license resolved into the same entity cluster as the queried one."},"PossibleMatchOut":{"properties":{"license":{"$ref":"#/components/schemas/LicenseOut","description":"The possibly-related license record."},"score":{"type":"number","title":"Score","description":"Match score (0.0-1.0), within the review band: worth a human look, not a confirmed link."},"evidence":{"items":{"$ref":"#/components/schemas/LinkEvidence"},"type":"array","title":"Evidence","description":"What the match rests on (shared address, phone, state business id, principal, or name)."},"worth_review":{"type":"boolean","title":"Worth Review","description":"Whether this match deserves a reviewer's time: any suspended/revoked/delisted one, or an active one backed by more than a similar name. The verdict counts only these."}},"type":"object","required":["license","score","evidence","worth_review"],"title":"PossibleMatchOut","description":"A license that matched the queried one below the auto-link threshold: related, but unconfirmed."},"RevealIn":{"properties":{"session_id":{"type":"string","maxLength":255,"minLength":10,"pattern":"^cs_[A-Za-z0-9_]+$","title":"Session Id","description":"The `session` parameter Stripe put on the welcome page's URL."}},"type":"object","required":["session_id"],"title":"RevealIn","description":"The Checkout Session to issue a key for."},"SegmentOut":{"properties":{"text":{"type":"string","title":"Text","description":"The text."},"strong":{"type":"boolean","title":"Strong","description":"Whether this run is the emphasized part (e.g. the status)."}},"type":"object","required":["text","strong"],"title":"SegmentOut","description":"One run of a check's result text."},"StateAbbreviation":{"type":"string","enum":["AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"],"title":"StateAbbreviation","description":"USPS two-letter abbreviation for each US state.\n\nMirrored in airflow/dags/common/enums.py (kept dependency-free of this\napp -- see CLAUDE.md); test_airflow_enum_sync.py keeps the two in sync."},"StateCoverageOut":{"properties":{"state":{"$ref":"#/components/schemas/StateAbbreviation","description":"Two-letter state code."},"board":{"type":"string","title":"Board","description":"The issuing board."},"scope":{"type":"string","title":"Scope","description":"Which of the board's licenses are ingested."},"publishes":{"type":"string","title":"Publishes","description":"How often the board refreshes the files ingested; they're read daily either way."},"licenses":{"type":"integer","title":"Licenses","description":"Licenses on the board's current listing."},"last_refreshed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Refreshed At","description":"When licenscheck last confirmed this state's licenses against the board's files."}},"type":"object","required":["state","board","scope","publishes","licenses","last_refreshed_at"],"title":"StateCoverageOut","description":"One state board licenscheck ingests."},"StatsOut":{"properties":{"licenses":{"type":"integer","title":"Licenses","description":"How many licenses are on the covered boards' current listings (delisted ones left out)."},"licenses_is_exact":{"type":"boolean","title":"Licenses Is Exact","description":"Always true: `licenses` is an exact count (kept for clients that read it)."}},"type":"object","required":["licenses","licenses_is_exact"],"title":"StatsOut","description":"Headline corpus numbers for the landing page."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VerdictLevel":{"type":"string","enum":["clear","review","risk"],"title":"VerdictLevel","description":"The overall verification verdict for a license."},"VerdictOut":{"properties":{"license_id":{"type":"string","format":"uuid","title":"License Id","description":"ID of the license that was verified."},"level":{"$ref":"#/components/schemas/VerdictLevel","description":"clear (nothing adverse), review (something to look at, e.g. expiring soon or an adverse unconfirmed possible match), or risk (a fail: this license or a linked one is suspended, revoked, delisted, or expired)."},"word":{"type":"string","title":"Word","description":"The level as shown to a reader: \"Clear\", \"Review\", or \"Risk found\"."},"summary":{"type":"string","title":"Summary","description":"One plain-English sentence explaining the level."},"checks":{"items":{"$ref":"#/components/schemas/CheckOut"},"type":"array","title":"Checks","description":"Every check that applied, in reading order."}},"type":"object","required":["license_id","level","word","summary","checks"],"title":"VerdictOut","description":"Response for GET /licenses/{id}/verdict: the yes-or-no answer, with its reasons."}}}}