{"openapi":"3.1.0","info":{"title":"Tektolo Capabilities API","summary":"Deterministic, source-cited capabilities for humans, developers and agents.","version":"0.1.0"},"paths":{"/v1/capabilities":{"get":{"tags":["catalog"],"summary":"List Capabilities","operationId":"list_capabilities_v1_capabilities_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Capabilities V1 Capabilities Get"}}}}}}},"/v1/capabilities/{capability_id}":{"get":{"tags":["catalog"],"summary":"Get Capability","operationId":"get_capability_v1_capabilities__capability_id__get","parameters":[{"name":"capability_id","in":"path","required":true,"schema":{"type":"string","title":"Capability Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Capability V1 Capabilities  Capability Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/property-turnover/quick_estimate":{"post":{"tags":["property-turnover"],"summary":"Quick turnover estimate (start here)","description":"The easiest way to estimate a US rental turnover: a ZIP, bedrooms, bathrooms and a list of plain-English issues in, a priced make-ready estimate out (same engine and result as property_turnover_scope, short summary by default).\nWhen to use: Start here when the user describes a move-out or turnover in words (\"carpet stained in both bedrooms, oven filthy\") and wants a cost estimate or what to tell vendors. Use property_turnover_scope instead for rate cards, owner decisions, measured quantities or per-finding control.\nNot for: Diagnosing hazards (they come back as refer-outs to a licensed professional); legal advice on deposits; remodel bids; properties outside the US.\nTip: If the ZIP is missing or not exactly 5 digits, ask the user; never guess or pad it.\nTip: Relay refer_outs first, then the totals; say the numbers are estimates, not quotes.\nDeterministic: the same input returns the same result_hash. Capability property-turnover v0.3.0 (experimental).","operationId":"property_turnover_quick_estimate","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuickEstimateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyTurnoverQuickEstimateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/property-turnover/scope":{"post":{"tags":["property-turnover"],"summary":"Scope a property turnover","description":"Turn move-out / turnover inspection findings for a US rental unit into a priced make-ready scope: standardized tasks by trade, regional low/expected/high costs, must/should/could priorities, vendor scopes, refer-outs to licensed professionals, and every assumption stated.\nWhen to use: Turnover findings for a US rental unit when you need control: rooms, measured quantities, the manager's own prices (rate_card) or owner approve/decline decisions. For a plain-English estimate, property_turnover_quick_estimate is easier.\nNot for: Diagnosing hazards (they come back as refer-outs to a licensed professional); legal advice on deposits; remodel bids; properties outside the US.\nTip: If the ZIP is missing or not exactly 5 digits, ask the user; never guess or pad it.\nTip: Describe each finding in plain words (description). Only send a code returned by property_turnover_issue_codes; unmatched findings come back as manual-quote lines with suggested codes.\nTip: Give measured quantities when you have them (e.g. 120 sq_ft); otherwise typical sizes are assumed and listed in assumptions.\nTip: Send property.floor_coverings when you know whether there is carpet, and unit_type single_family for houses; both change the baseline scope.\nTip: Relay the summary, refer_outs, assumptions and unknowns to the user; costs are estimate ranges, not quotes.\nTip: Use detail=summary unless the user asks for every line item (summary already lists every line tied to a finding).\nTip: Rate card examples - {\"trade\": \"handyman\", \"unit_price\": 65, \"uom\": \"hour\"} or {\"task_id\": \"carpet.clean\", \"unit_price\": 0.2, \"uom\": \"sq_ft\"}; check rate_card_applied and rate_card_ignored before saying a rate was used.\nTip: For the Excel workbook or owner estimate, give the user links.web_tool_prefilled (opens the free web tool with these findings) or POST the same arguments to links.downloads; do not build a spreadsheet yourself.\nDeterministic: the same input returns the same result_hash. Capability property-turnover v0.3.0 (experimental).","operationId":"property_turnover_scope","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyTurnoverScopeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/property-turnover/scope/render/xlsx":{"post":{"tags":["property-turnover"],"summary":"Scope a property turnover (rendered as xlsx)","description":"Same body as the operation. Runs it, then renders the result as application/vnd.openxmlformats-officedocument.spreadsheetml.sheet. The artifact itself is not stored. Rate limited more tightly than the JSON endpoint.","operationId":"property_turnover_scope_render_xlsx","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/property-turnover/scope/render/html":{"post":{"tags":["property-turnover"],"summary":"Scope a property turnover (rendered as html)","description":"Same body as the operation. Runs it, then renders the result as text/html; charset=utf-8. The artifact itself is not stored. Rate limited more tightly than the JSON endpoint.","operationId":"property_turnover_scope_render_html","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/html; charset=utf-8":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/property-turnover/scope/render/csv":{"post":{"tags":["property-turnover"],"summary":"Scope a property turnover (rendered as csv)","description":"Same body as the operation. Runs it, then renders the result as text/csv; charset=utf-8. The artifact itself is not stored. Rate limited more tightly than the JSON endpoint.","operationId":"property_turnover_scope_render_csv","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"text/csv; charset=utf-8":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/property-turnover/scope/render/vendor_csv":{"post":{"tags":["property-turnover"],"summary":"Scope a property turnover (rendered as vendor_csv)","description":"Same body as the operation. Runs it, then renders the result as application/zip. The artifact itself is not stored. Rate limited more tightly than the JSON endpoint.","operationId":"property_turnover_scope_render_vendor_csv","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/zip":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/property-turnover/issue_codes":{"post":{"tags":["property-turnover"],"summary":"Look up turnover issue codes","description":"Search the standard taxonomy of rental-unit turnover issues (component.issue codes) by keyword or area.\nWhen to use: Only while preparing findings for a turnover cost estimate, to find the standard issue code for something observed (e.g. \"pet stain on carpet\"). Never needed to answer a question; call with no arguments to list the taxonomy areas and the first codes.\nNot for: Legal or security-deposit questions; anything outside rental turnover and make-ready work. Not needed before quick_estimate or scope: a plain description works there.\nTip: Call with no arguments to list the taxonomy areas (in `areas`) and the first codes.\nTip: Codes are optional for scoping; a plain description also works.\nDeterministic: the same input returns the same result_hash. Capability property-turnover v0.3.0 (experimental).","operationId":"property_turnover_issue_codes","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueCodesRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyTurnoverIssueCodesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/feedback":{"post":{"tags":["feedback"],"summary":"Send feedback about the site, a tool, or an idea for a new tool","description":"Free text plus a scope. For humans (the web forms use it); there is no MCP tool for this on purpose. Messages are capped at 2000 characters, links are replaced with [link] and at most 3 are accepted. Provide an email only if you want a reply. Rate limited to 5 per minute. Leave `website` empty.","operationId":"post_feedback_v1_feedback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackOut"}}}},"422":{"description":"Invalid feedback"},"429":{"description":"Rate limited"}}}}},"components":{"schemas":{"Area":{"type":"string","enum":["whole_unit","kitchen","living_room","dining_room","bedroom","bathroom","hallway","entry","laundry","closet","garage","patio_balcony","exterior","yard","other"],"title":"Area"},"Constraints":{"properties":{"target_ready_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Target Ready Date"},"occupied":{"type":"boolean","title":"Occupied","description":"Work happens while occupied.","default":false},"access_notes":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Access Notes"}},"additionalProperties":false,"type":"object","title":"Constraints"},"CostRange":{"properties":{"low":{"type":"string","title":"Low"},"expected":{"type":"string","title":"Expected"},"high":{"type":"string","title":"High"}},"type":"object","required":["low","expected","high"],"title":"CostRange","description":"A low / expected / high estimate. Invariant: low <= expected <= high."},"Decision":{"properties":{"line_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Line Id"},"finding_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Finding Id"},"action":{"type":"string","enum":["approve","decline","defer"],"title":"Action"},"note":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Note"}},"additionalProperties":false,"type":"object","required":["action"],"title":"Decision","description":"Owner decision. Re-run the same request with decisions to get the approved scope."},"EstimateContext":{"properties":{"result_hash":{"anyOf":[{"type":"string","maxLength":71,"pattern":"^sha256:[0-9a-f]{8,64}$"},{"type":"null"}],"title":"Result Hash"},"input_hash":{"anyOf":[{"type":"string","maxLength":71,"pattern":"^sha256:[0-9a-f]{8,64}$"},{"type":"null"}],"title":"Input Hash"},"ruleset_version":{"anyOf":[{"type":"string","maxLength":40,"pattern":"^[0-9A-Za-z.+-]{1,40}$"},{"type":"null"}],"title":"Ruleset Version"},"contract_version":{"anyOf":[{"type":"string","maxLength":40,"pattern":"^[0-9A-Za-z.+-]{1,40}$"},{"type":"null"}],"title":"Contract Version"},"cbsa":{"anyOf":[{"type":"string","maxLength":5,"pattern":"^\\d{5}$"},{"type":"null"}],"title":"Cbsa"},"expected":{"anyOf":[{"type":"number","maximum":1000000000.0,"minimum":0.0},{"type":"null"}],"title":"Expected"}},"type":"object","title":"EstimateContext","description":"Identifiers of the estimate being rated. Hashes, versions, region and total only.\n\nEvery field has a strict format (security review M1): they end up in the feedback digest,\nso nothing here may carry free text."},"Extent":{"type":"string","enum":["spot","partial","full"],"title":"Extent"},"FeedbackIn":{"properties":{"scope":{"type":"string","enum":["site","tool","idea"],"title":"Scope","description":"site, a specific tool, or an idea for a new tool."},"capability":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Capability","description":"Tool id when scope is tool."},"page":{"type":"string","maxLength":200,"title":"Page","description":"Path of the page the feedback is about.","default":"/"},"kind":{"type":"string","enum":["rating","issue","idea","unmatched"],"title":"Kind","default":"issue"},"rating":{"anyOf":[{"type":"string","enum":["useful","not_quite"]},{"type":"null"}],"title":"Rating"},"reasons":{"items":{"type":"string","enum":["too_high","too_low","missing_items","wrong_items","confusing","other"]},"type":"array","maxItems":6,"title":"Reasons"},"message":{"type":"string","maxLength":2000,"title":"Message","default":""},"email":{"anyOf":[{"type":"string","maxLength":254},{"type":"null"}],"title":"Email","description":"Only if you want a reply."},"estimate":{"anyOf":[{"$ref":"#/components/schemas/EstimateContext"},{"type":"null"}]},"finding_text":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Finding Text","description":"Unmatched kind only."},"website":{"type":"string","title":"Website","description":"Leave empty (spam trap).","default":""}},"type":"object","required":["scope"],"title":"FeedbackIn","description":"What the site, a tool or an idea box sends to ``POST /v1/feedback``."},"FeedbackOut":{"properties":{"received":{"type":"boolean","title":"Received"},"id":{"type":"string","title":"Id"}},"type":"object","required":["received","id"],"title":"FeedbackOut"},"Finding":{"properties":{"id":{"anyOf":[{"type":"string","maxLength":40,"pattern":"^[A-Za-z0-9_.:-]+$"},{"type":"null"}],"title":"Id","description":"Your id for this finding; defaults to f1, f2, ... in order."},"location":{"$ref":"#/components/schemas/Location","description":"Object {\"area\": \"bedroom\", \"label\": \"Bedroom 2\"}, or a plain string such as \"Bedroom 2\" or \"kitchen\" (mapped to an area; other text becomes the label)."},"code":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Code","description":"Optional. Only a code returned by property_turnover_issue_codes (e.g. 'walls.nail_holes'); otherwise leave it out and use description."},"description":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Description","description":"Plain description if no code, e.g. 'dog urine stains in bedroom carpet'."},"extent":{"anyOf":[{"$ref":"#/components/schemas/Extent"},{"type":"null"}],"description":"spot | partial | full; defaults per issue."},"quantity":{"anyOf":[{"$ref":"#/components/schemas/Quantity"},{"type":"null"}],"description":"Measured amount, e.g. 120 sq_ft. Derived when omitted."},"notes":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Notes"}},"additionalProperties":false,"type":"object","title":"Finding","description":"One observed condition. Give a taxonomy `code` if you know it, else a `description`."},"FindingResolution":{"properties":{"finding_id":{"type":"string","title":"Finding Id"},"resolution":{"type":"string","enum":["exact","alias","unmapped"],"title":"Resolution"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"issue_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Issue Name","description":"Readable name of `code`."},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text","description":"The finding as given (description, else code), for tracing."},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location","description":"Where, as shown on the lines."},"match_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Match Note","description":"Set when the match left a fixture word unexplained: check this finding."},"uncertain":{"type":"boolean","title":"Uncertain","description":"The description hedges ('mold?', 'maybe', 'possible'). Refer-outs from uncertain findings are check-first: they add a warning instead of holding phases.","default":false},"extent":{"anyOf":[{"$ref":"#/components/schemas/Extent"},{"type":"null"}]},"suggested_codes":{"items":{"type":"string"},"type":"array","title":"Suggested Codes","default":[]},"suggestions":{"items":{"$ref":"#/components/schemas/Suggestion"},"type":"array","title":"Suggestions","description":"Suggested codes with readable names, best first."},"line_ids":{"items":{"type":"string"},"type":"array","title":"Line Ids","default":[]}},"type":"object","required":["finding_id","resolution","code","extent"],"title":"FindingResolution"},"FloorCoverings":{"properties":{"carpet_present":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Carpet Present","description":"Is there wall-to-wall carpet? Omit if unknown: carpet findings then imply carpet; with no carpet findings, whole-unit carpet cleaning is left out and listed as unknown."},"carpet_sq_ft":{"anyOf":[{"type":"integer","maximum":20000.0,"minimum":0.0},{"type":"null"}],"title":"Carpet Sq Ft","description":"Carpeted floor area. Omit to assume 60% of the unit floor area."}},"additionalProperties":false,"type":"object","title":"FloorCoverings","description":"What is on the floors. Drives the carpet-cleaning baseline and whole-unit carpet sizes."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"IssueCode":{"properties":{"code":{"type":"string","title":"Code","description":"Stable code, component.issue, e.g. 'carpet.pet_urine'."},"name":{"type":"string","title":"Name"},"area":{"type":"string","title":"Area"},"aliases":{"items":{"type":"string"},"type":"array","title":"Aliases","default":[]}},"type":"object","required":["code","name","area"],"title":"IssueCode"},"IssueCodesRequest":{"properties":{"client_refs":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Client Refs","description":"Your own reference ids (e.g. unit_id, job_id). Echoed back, never used."},"query":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Query","description":"Keywords to match against codes, names and aliases, e.g. 'pet stain carpet'."},"area":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Area","description":"Optional taxonomy area filter, e.g. 'flooring' or 'walls' (not a room). Call with no arguments to list every area in `areas`."},"limit":{"type":"integer","maximum":200.0,"minimum":1.0,"title":"Limit","default":8},"include_aliases":{"type":"boolean","title":"Include Aliases","description":"Also return each code's aliases (larger result).","default":false}},"additionalProperties":false,"type":"object","title":"IssueCodesRequest"},"IssueCodesResult":{"properties":{"ruleset_version":{"type":"string","title":"Ruleset Version"},"total_matches":{"type":"integer","title":"Total Matches"},"codes":{"items":{"$ref":"#/components/schemas/IssueCode"},"type":"array","title":"Codes"},"areas":{"items":{"type":"string"},"type":"array","title":"Areas","description":"Every taxonomy area, for the `area` filter (e.g. 'flooring', 'walls')."}},"type":"object","required":["ruleset_version","total_matches","codes"],"title":"IssueCodesResult"},"Location":{"properties":{"area":{"$ref":"#/components/schemas/Area","default":"whole_unit"},"label":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"title":"Label","description":"e.g. 'Bedroom 2'."}},"additionalProperties":false,"type":"object","title":"Location","description":"Where the finding is. Also accepted as a plain string (\"Bedroom 2\", \"kitchen\")."},"Note":{"properties":{"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"},"finding_ids":{"items":{"type":"string"},"type":"array","title":"Finding Ids","default":[]},"line_ids":{"items":{"type":"string"},"type":"array","title":"Line Ids","default":[]}},"type":"object","required":["code","message"],"title":"Note"},"Phase":{"type":"string","enum":["assess","trash_out","repairs","paint","flooring","appliances","cleaning","punch","rekey"],"title":"Phase","description":"Make-ready order. Values sort in sequence order via PHASE_ORDER."},"PriceBasis":{"type":"string","enum":["rate_card","unit_price","labor_derived","placeholder"],"title":"PriceBasis"},"PriceTier":{"type":"string","enum":["bulk_contract","pm_vendor","retail_one_off"],"title":"PriceTier","description":"Purchasing channel. Library prices are pm_vendor (a PM buying turns from a local vendor)."},"Priority":{"type":"string","enum":["must","should","could"],"title":"Priority"},"Profile":{"type":"string","enum":["minimum","standard","premium"],"title":"Profile"},"PropertyProfile":{"properties":{"zip":{"type":"string","pattern":"^\\d{5}$","title":"Zip","description":"5-digit US ZIP code (no street address)."},"unit_type":{"$ref":"#/components/schemas/UnitType","description":"Single-family homes and townhomes get house-sized defaults (floor area, locks).","default":"apartment"},"bedrooms":{"type":"integer","maximum":12.0,"minimum":0.0,"title":"Bedrooms","description":"0 for a studio."},"bathrooms":{"anyOf":[{"type":"number","multipleOf":0.5,"maximum":12.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Bathrooms","description":"Half baths count as 0.5."},"sq_ft":{"anyOf":[{"type":"integer","maximum":20000.0,"minimum":150.0},{"type":"null"}],"title":"Sq Ft","description":"Interior sq ft."},"year_built":{"anyOf":[{"type":"integer","maximum":2100.0,"minimum":1700.0},{"type":"null"}],"title":"Year Built","description":"Drives lead-paint (pre-1978) handling."},"floor_coverings":{"$ref":"#/components/schemas/FloorCoverings"}},"additionalProperties":false,"type":"object","required":["zip","bedrooms","bathrooms"],"title":"PropertyProfile"},"PropertyTurnoverIssueCodesResponse":{"properties":{"run":{"$ref":"#/components/schemas/RunInfo"},"client_refs":{"additionalProperties":true,"type":"object","title":"Client Refs","default":{}},"input_hash":{"type":"string","title":"Input Hash"},"result_hash":{"type":"string","title":"Result Hash"},"result":{"$ref":"#/components/schemas/IssueCodesResult"}},"type":"object","required":["run","input_hash","result_hash","result"],"title":"PropertyTurnoverIssueCodesResponse"},"PropertyTurnoverQuickEstimateResponse":{"properties":{"run":{"$ref":"#/components/schemas/RunInfo"},"client_refs":{"additionalProperties":true,"type":"object","title":"Client Refs","default":{}},"input_hash":{"type":"string","title":"Input Hash"},"result_hash":{"type":"string","title":"Result Hash"},"result":{"$ref":"#/components/schemas/ScopeResult"}},"type":"object","required":["run","input_hash","result_hash","result"],"title":"PropertyTurnoverQuickEstimateResponse"},"PropertyTurnoverScopeResponse":{"properties":{"run":{"$ref":"#/components/schemas/RunInfo"},"client_refs":{"additionalProperties":true,"type":"object","title":"Client Refs","default":{}},"input_hash":{"type":"string","title":"Input Hash"},"result_hash":{"type":"string","title":"Result Hash"},"result":{"$ref":"#/components/schemas/ScopeResult"}},"type":"object","required":["run","input_hash","result_hash","result"],"title":"PropertyTurnoverScopeResponse"},"Provenance":{"properties":{"ruleset_id":{"type":"string","title":"Ruleset Id"},"ruleset_version":{"type":"string","title":"Ruleset Version"},"ruleset_hash":{"type":"string","title":"Ruleset Hash"},"sources":{"items":{"$ref":"#/components/schemas/SourceRef"},"type":"array","title":"Sources"}},"type":"object","required":["ruleset_id","ruleset_version","ruleset_hash","sources"],"title":"Provenance"},"Quantity":{"properties":{"value":{"anyOf":[{"type":"number","maximum":100000.0,"exclusiveMinimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Value"},"uom":{"$ref":"#/components/schemas/Uom"}},"additionalProperties":false,"type":"object","required":["value","uom"],"title":"Quantity"},"QuickEstimateRequest":{"properties":{"client_refs":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Client Refs","description":"Your own reference ids (e.g. unit_id, job_id). Echoed back, never used."},"zip":{"type":"string","pattern":"^\\d{5}$","title":"Zip","description":"The user's 5-digit US ZIP code. If it is missing or not exactly 5 digits, ask the user; never guess, pad or correct it."},"bedrooms":{"type":"integer","maximum":12.0,"minimum":0.0,"title":"Bedrooms","description":"0 for a studio."},"bathrooms":{"anyOf":[{"type":"number","multipleOf":0.5,"maximum":12.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Bathrooms","description":"Half baths count as 0.5."},"issues":{"items":{"type":"string"},"type":"array","maxItems":100,"title":"Issues","description":"What was found, one plain-English item per entry, e.g. ['stained carpet in both bedrooms', 'nail holes everywhere', 'oven is filthy']. A room at the start sets the location ('Bedroom 2 carpet torn')."},"unit_type":{"$ref":"#/components/schemas/UnitType","default":"apartment"},"sq_ft":{"anyOf":[{"type":"integer","maximum":20000.0,"minimum":150.0},{"type":"null"}],"title":"Sq Ft","description":"Interior sq ft."},"year_built":{"anyOf":[{"type":"integer","maximum":2100.0,"minimum":1700.0},{"type":"null"}],"title":"Year Built"},"carpet":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Carpet","description":"Is there wall-to-wall carpet?"},"profile":{"$ref":"#/components/schemas/Profile","default":"standard"},"price_tier":{"$ref":"#/components/schemas/PriceTier","default":"pm_vendor"},"detail":{"type":"string","enum":["summary","full"],"title":"Detail","description":"summary (default, small) or full (every line).","default":"summary"}},"additionalProperties":false,"type":"object","required":["zip","bedrooms","bathrooms"],"title":"QuickEstimateRequest","description":"Flat, primitive-only input: the easiest way to get an estimate."},"RateCardEntry":{"properties":{"task_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Id","description":"A task_id from a result line, e.g. 'carpet.clean'."},"trade":{"anyOf":[{"$ref":"#/components/schemas/Trade"},{"type":"null"}]},"unit_price":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Unit Price","description":"USD per uom. On a trade entry, uom 'hour' is an hourly labor rate (replaces the labor part of that trade's prices); another uom prices that trade's tasks in it."},"uom":{"anyOf":[{"$ref":"#/components/schemas/Uom"},{"type":"null"}],"description":"Unit your price is quoted in. Required with a trade unit_price. If it differs from a task's uom, the entry is not applied to that task (see rate_card_ignored)."},"min_charge":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Min Charge","description":"USD per trade visit."},"trip_charge":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Trip Charge","description":"USD per trade visit."}},"additionalProperties":false,"type":"object","title":"RateCardEntry","description":"Your own price. Examples: {\"trade\": \"handyman\", \"unit_price\": 65, \"uom\": \"hour\"} (an\nhourly labor rate for that trade); {\"trade\": \"painter\", \"min_charge\": 150} (visit minimum);\n{\"task_id\": \"carpet.clean\", \"unit_price\": 0.2, \"uom\": \"sq_ft\"} (task_id from a result line).\nA task_id entry beats a trade entry; both beat the library. The result lists what was\napplied and what was ignored (rate_card_applied / rate_card_ignored)."},"RateCardUse":{"properties":{"entry":{"type":"integer","title":"Entry","description":"0-based index into the request's rate_card."},"target":{"type":"string","title":"Target","description":"The entry's task_id or trade."},"lines":{"items":{"type":"string"},"type":"array","title":"Lines","default":[]},"note":{"type":"string","title":"Note"}},"type":"object","required":["entry","target","note"],"title":"RateCardUse"},"ReferOutNote":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"professional":{"type":"string","title":"Professional"},"reason":{"type":"string","title":"Reason"},"kind":{"type":"string","enum":["assessment","compliance"],"title":"Kind"},"finding_ids":{"items":{"type":"string"},"type":"array","title":"Finding Ids"},"blocks_phases":{"items":{"$ref":"#/components/schemas/Phase"},"type":"array","title":"Blocks Phases"},"sources":{"items":{"type":"string"},"type":"array","title":"Sources"},"unconfirmed":{"type":"boolean","title":"Unconfirmed","description":"Every triggering finding was hedged ('maybe', '?'): check first; no phase is held until the condition is confirmed (see warnings).","default":false}},"type":"object","required":["id","name","professional","reason","kind","finding_ids","blocks_phases","sources"],"title":"ReferOutNote"},"Region":{"properties":{"zip3":{"type":"string","title":"Zip3"},"basis":{"type":"string","enum":["metro","nonmetro","national"],"title":"Basis"},"cbsa":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cbsa"},"cbsa_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cbsa Name"},"vintage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vintage"}},"type":"object","required":["zip3","basis"],"title":"Region"},"Responsibility":{"type":"string","enum":["normal_wear","likely_damage","elective","undetermined","mixed"],"title":"Responsibility"},"RunInfo":{"properties":{"id":{"type":"string","title":"Id"},"capability":{"type":"string","title":"Capability"},"operation":{"type":"string","title":"Operation"},"contract_version":{"type":"string","title":"Contract Version"},"engine_version":{"type":"string","title":"Engine Version"},"ruleset_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ruleset Version"},"ruleset_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ruleset Hash"},"received_at":{"type":"string","format":"date-time","title":"Received At"},"duration_ms":{"type":"integer","title":"Duration Ms"}},"type":"object","required":["id","capability","operation","contract_version","engine_version","ruleset_version","ruleset_hash","received_at","duration_ms"],"title":"RunInfo"},"ScopeLine":{"properties":{"line_id":{"type":"string","title":"Line Id"},"task_id":{"type":"string","title":"Task Id"},"name":{"type":"string","title":"Name"},"trade":{"$ref":"#/components/schemas/Trade"},"phase":{"$ref":"#/components/schemas/Phase"},"priority":{"$ref":"#/components/schemas/Priority"},"location":{"type":"string","title":"Location"},"finding_ids":{"items":{"type":"string"},"type":"array","title":"Finding Ids"},"quantity":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Quantity"},"uom":{"$ref":"#/components/schemas/Uom"},"quantity_source":{"type":"string","enum":["given","converted","derived","fixed"],"title":"Quantity Source"},"price_basis":{"$ref":"#/components/schemas/PriceBasis"},"unit_price":{"$ref":"#/components/schemas/CostRange"},"cost":{"$ref":"#/components/schemas/CostRange"},"confidence":{"type":"string","enum":["sourced","industry_typical","assumed"],"title":"Confidence"},"responsibility_hint":{"$ref":"#/components/schemas/Responsibility"},"responsibility_by_finding":{"additionalProperties":{"$ref":"#/components/schemas/Responsibility"},"type":"object","title":"Responsibility By Finding","description":"Set when the hint is 'mixed': the hint of each finding the line carries."},"allowance":{"anyOf":[{"$ref":"#/components/schemas/CostRange"},{"type":"null"}],"description":"Quote-required lines only: a non-binding budget range. NOT included in any total; summed separately in totals.allowances."},"refer_out":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refer Out"},"decision":{"anyOf":[{"type":"string","enum":["approve","decline","defer"]},{"type":"null"}],"title":"Decision"},"vendor_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor Note"},"rule_ids":{"items":{"type":"string"},"type":"array","title":"Rule Ids"}},"type":"object","required":["line_id","task_id","name","trade","phase","priority","location","finding_ids","quantity","uom","quantity_source","price_basis","unit_price","cost","confidence","responsibility_hint","rule_ids"],"title":"ScopeLine"},"ScopeRequest":{"properties":{"client_refs":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Client Refs","description":"Your own reference ids (e.g. unit_id, job_id). Echoed back, never used."},"property":{"$ref":"#/components/schemas/PropertyProfile"},"findings":{"items":{"$ref":"#/components/schemas/Finding"},"type":"array","maxItems":200,"title":"Findings"},"standards":{"$ref":"#/components/schemas/Standards"},"rate_card":{"items":{"$ref":"#/components/schemas/RateCardEntry"},"type":"array","maxItems":300,"title":"Rate Card"},"trade_vendors":{"additionalProperties":{"$ref":"#/components/schemas/Vendor"},"propertyNames":{"$ref":"#/components/schemas/Trade"},"type":"object","title":"Trade Vendors"},"constraints":{"$ref":"#/components/schemas/Constraints"},"tax_rate":{"anyOf":[{"type":"number","maximum":0.2,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Tax Rate","description":"Applied to all lines, e.g. 0.07."},"decisions":{"items":{"$ref":"#/components/schemas/Decision"},"type":"array","maxItems":500,"title":"Decisions"},"detail":{"type":"string","enum":["summary","full"],"title":"Detail","description":"summary: totals, trade scopes, every line tied to a finding (capped at 40) plus the largest must-fix/refer-out lines, a one-line note on the routine lines left out, notes, and only findings needing attention (small). full: every line, finding and source.","default":"full"}},"additionalProperties":false,"type":"object","required":["property"],"title":"ScopeRequest"},"ScopeResult":{"properties":{"summary":{"type":"string","title":"Summary"},"disclaimer":{"type":"string","title":"Disclaimer"},"warnings":{"items":{"$ref":"#/components/schemas/Note"},"type":"array","title":"Warnings"},"totals":{"$ref":"#/components/schemas/Totals"},"refer_outs":{"items":{"$ref":"#/components/schemas/ReferOutNote"},"type":"array","title":"Refer Outs"},"trade_scopes":{"items":{"$ref":"#/components/schemas/TradeScope"},"type":"array","title":"Trade Scopes"},"lines":{"items":{"$ref":"#/components/schemas/ScopeLine"},"type":"array","title":"Lines"},"lines_omitted":{"type":"integer","title":"Lines Omitted","description":"Lines left out in summary detail."},"omitted_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Omitted Note","description":"Summary detail: what the omitted lines are (routine turn tasks) and their cost."},"findings":{"items":{"$ref":"#/components/schemas/FindingResolution"},"type":"array","title":"Findings"},"assumptions":{"items":{"$ref":"#/components/schemas/Note"},"type":"array","title":"Assumptions"},"unknowns":{"items":{"$ref":"#/components/schemas/Note"},"type":"array","title":"Unknowns"},"rate_card_applied":{"items":{"$ref":"#/components/schemas/RateCardUse"},"type":"array","title":"Rate Card Applied","description":"Rate card entries that changed a price."},"rate_card_ignored":{"items":{"$ref":"#/components/schemas/RateCardUse"},"type":"array","title":"Rate Card Ignored","description":"Rate card entries that changed nothing, with why."},"detail":{"type":"string","enum":["summary","full"],"title":"Detail"},"region":{"$ref":"#/components/schemas/Region"},"profile":{"$ref":"#/components/schemas/Profile"},"price_tier":{"$ref":"#/components/schemas/PriceTier","default":"pm_vendor"},"provenance":{"$ref":"#/components/schemas/Provenance"}},"type":"object","required":["summary","disclaimer","warnings","totals","refer_outs","trade_scopes","lines","lines_omitted","findings","assumptions","unknowns","detail","region","profile","provenance"],"title":"ScopeResult","description":"Field order puts the answer first (summary, disclaimer, totals, refer-outs, vendor\nscopes), because agents and truncating clients read from the top."},"SourceRef":{"properties":{"id":{"type":"string","title":"Id"},"title":{"type":"string","title":"Title"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"}},"type":"object","required":["id","title"],"title":"SourceRef"},"Standards":{"properties":{"profile":{"$ref":"#/components/schemas/Profile","description":"minimum (rent-ready basics) | standard | premium (higher finish).","default":"standard"},"overrides":{"$ref":"#/components/schemas/StandardsOverrides"},"price_tier":{"$ref":"#/components/schemas/PriceTier","description":"bulk_contract (portfolio contract prices) | pm_vendor (default: a property manager buying turns from local vendors) | retail_one_off (an owner hiring one contractor).","default":"pm_vendor"}},"additionalProperties":false,"type":"object","title":"Standards"},"StandardsOverrides":{"properties":{"paint_policy":{"anyOf":[{"type":"string","enum":["touch_up","full_if_needed","always_full"]},{"type":"null"}],"title":"Paint Policy"},"carpet_policy":{"anyOf":[{"type":"string","enum":["clean","replace_if_damaged","always_replace"]},{"type":"null"}],"title":"Carpet Policy"},"cleaning_policy":{"anyOf":[{"type":"string","enum":["standard","deep"]},{"type":"null"}],"title":"Cleaning Policy"},"always_rekey":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Always Rekey"},"markup_pct":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Markup Pct","description":"Management markup applied to every line, %."}},"additionalProperties":false,"type":"object","title":"StandardsOverrides"},"Suggestion":{"properties":{"code":{"type":"string","title":"Code"},"name":{"type":"string","title":"Name"}},"type":"object","required":["code","name"],"title":"Suggestion"},"Totals":{"properties":{"note":{"type":"string","title":"Note","description":"How the totals add up.","default":"must, should and could are work lines only. visit_charges (minimum call-out and trip fees, once per trade) are added on top: subtotal = must + should + could + visit_charges; total = subtotal + tax. allowances are outside the total."},"must":{"$ref":"#/components/schemas/CostRange"},"should":{"$ref":"#/components/schemas/CostRange"},"could":{"$ref":"#/components/schemas/CostRange"},"visit_charges":{"$ref":"#/components/schemas/CostRange"},"subtotal":{"$ref":"#/components/schemas/CostRange"},"tax":{"$ref":"#/components/schemas/CostRange"},"total":{"$ref":"#/components/schemas/CostRange"},"approved":{"anyOf":[{"$ref":"#/components/schemas/CostRange"},{"type":"null"}]},"allowances":{"$ref":"#/components/schemas/CostRange","description":"Budget allowance for quote-required lines (refer-outs, manual quotes). Shown outside the totals: subtotal and total never include it."}},"type":"object","required":["must","should","could","visit_charges","subtotal","tax","total"],"title":"Totals"},"Trade":{"type":"string","enum":["hauling","handyman","drywall","painter","flooring","carpet_cleaning","cleaning","appliance","plumber","electrician","hvac","locksmith","pest_control","landscaping","window_glass","environmental","structural"],"title":"Trade"},"TradeScope":{"properties":{"trade":{"$ref":"#/components/schemas/Trade"},"vendor":{"anyOf":[{"$ref":"#/components/schemas/Vendor"},{"type":"null"}]},"phase":{"$ref":"#/components/schemas/Phase"},"line_ids":{"items":{"type":"string"},"type":"array","title":"Line Ids"},"lines_cost":{"$ref":"#/components/schemas/CostRange"},"visit_charges":{"$ref":"#/components/schemas/CostRange"},"total":{"$ref":"#/components/schemas/CostRange"}},"type":"object","required":["trade","vendor","phase","line_ids","lines_cost","visit_charges","total"],"title":"TradeScope"},"UnitType":{"type":"string","enum":["apartment","single_family","townhome","condo","duplex","manufactured"],"title":"UnitType"},"Uom":{"type":"string","enum":["each","sq_ft","sq_ft_floor","sq_yd","linear_ft","room","unit","bedroom","bathroom","hour","cu_yd","visit"],"title":"Uom"},"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"},"Vendor":{"properties":{"name":{"type":"string","maxLength":120,"title":"Name"},"contact":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Contact"}},"additionalProperties":false,"type":"object","required":["name"],"title":"Vendor"}}}}