---
title: "Quick turnover estimate (start here) (paid)"
method: POST
path: "/v1/x402/property-turnover/quick_estimate"
tags: ["x402"]
---

# Quick turnover estimate (start here) (paid)

`POST /v1/x402/property-turnover/quick_estimate`

## Request

- Base URL: `https://tektolo.com` (the document declares no server; this is the origin it was published from)
- URL: `https://tektolo.com/v1/x402/property-turnover/quick_estimate`
- Auth: none declared

Paid lane (x402 v2, exact scheme, USDC on Base Sepolia testnet, $0.02 per call). Same body as POST /v1/property-turnover/quick_estimate, which stays free within its rate limits. Unpaid requests get HTTP 402 with PAYMENT-REQUIRED; only successful results are charged. Not available over MCP. The response adds `payment` (network, transaction, payer).

## Request body

- QuickEstimateRequest: Flat, primitive-only input: the easiest way to get an estimate.
  - `client_refs` object, nullable: Your own reference ids (e.g. unit_id, job_id). Echoed back, never used.
  - `zip` string, required: 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` integer, required: 0 for a studio.
  - `bathrooms` union, required: Half baths count as 0.5.
    - number
    - string
  - `issues` string[]: What was found in plain English, e.g. ['stained carpet in both bedrooms', 'nail holes everywhere', 'oven is filthy']. Read like pasted notes: an entry may hold several conditions ('carpet stained, nail holes'; one finding each); a room before or after the condition sets the location ('Bedroom 2 carpet torn', 'mold in bathroom'); a written count sets the quantity ('3 blinds broken'); an entry saying there is no work ('no mold', 'leak fixed by tenant') is reported as not billed.
  - `unit_type` 'apartment' | 'single_family' | 'townhome' | 'condo' | 'duplex' | 'manufactured'
  - `sq_ft` integer, nullable: Interior sq ft.
  - `year_built` integer, nullable: Drives lead-paint (pre-1978) handling.
  - `carpet` boolean, nullable: Is there wall-to-wall carpet?
  - `profile` 'minimum' | 'standard' | 'premium'
  - `price_tier` 'bulk_contract' | 'pm_vendor' | 'retail_one_off': Purchasing channel. Library prices are pm_vendor (a PM buying turns from a local vendor).
  - `detail` 'summary' | 'full': summary (default, small) or full (every line).
  - `retain` boolean: Optional (contract 0.5.1). false: keep none of this request's text, so the AI reader's answer for the issues is not stored either. By default the text is kept with contact details and access codes removed, to improve matching; the estimate is the same either way.

## Response `200`

Successful Response

- PropertyTurnoverQuickEstimatePaidResponse
  - `run` RunInfo, required
    - `id` string, required
    - `capability` string, required
    - `operation` string, required
    - `contract_version` string, required
    - `engine_version` string, required
    - `ruleset_version` string, nullable, required
    - `ruleset_hash` string, nullable, required
    - `received_at` string, date-time, required
    - `duration_ms` integer, required
  - `client_refs` object
  - `input_hash` string, required: Hash of the question the rules answered: the request, or when free text was read by AI, the request with the read findings (reading.findings) in its place.
  - `request_hash` string, nullable: Hash of the request as sent; equal to input_hash when nothing was read by AI.
  - `result_hash` string, required
  - `review` Review: How far the answer can be relied on.
    - `status` 'draft' | 'verified': draft: some findings were read by AI and nobody has confirmed them; show the person reading.findings before quoting a number. verified: no finding rests on an unconfirmed AI reading.
    - `ai_read` integer: Findings in this answer read by AI and not yet confirmed.
    - `reading_id` string, nullable: The reading's id, when one was made.
    - `note` string, nullable: Set when an AI reading was asked for but not made (capped or unavailable).
  - `reading` Reading: The findings software read from free text or a document for this answer. Send ``findings`` (edited if need be, each one checked marked ``confirmed: true``) to the rules operation to get a verified answer.
    - `id` string, required: rd_ and 24 hex characters; the same reading has the same id.
    - `kind` 'notes' | 'document', required
    - `model` string, nullable: The model that read it.
    - `prompt_version` string, nullable
    - `counts` ReadingCounts, required
      - `total` integer, required: Findings in the reading.
      - `ai` integer, required: Findings the AI model read (they carry extraction).
      - `parser` integer, required: Findings the deterministic parser and matcher placed, or sent coded.
      - `unmatched` integer, required: Findings nothing could match (manual-quote lines).
    - `findings` object[], required: Every finding the rules answered, in the shape the rules operation accepts.
    - `notes` ReadingNote[]: What the reading noticed while reading the text.
      - `kind` 'warning' | 'assumption', required
      - `code` string, required
      - `message` string, required
      - `finding_ids` string[]
  - `signature` ResultSignature: Tektolo's signature over where this result came from (docs/verify.md).
    - `jws` string, required: Compact JWS (RFC 7515), alg EdDSA (Ed25519, RFC 8037), typ tektolo-provenance+jws. Check it against the keys at /.well-known/tektolo-signing-keys.json on the site you called, never against a key a document points to.
    - `payload` ResultSignaturePayload, required: The signed statement (the JWS payload, decoded). Canonical JSON: sorted keys, compact.
      - `v` integer, required: Payload format version (1).
      - `kid` string, required: Id of the key that signed it (see the signing keys file).
      - `capability` string, required
      - `operation` string, required
      - `ruleset_version` string, nullable, required
      - `ruleset_hash` string, nullable, required
      - `engine_version` string, required
      - `result_hash` string, required: The envelope's result_hash.
      - `issued_at` string, required: When the result was computed (UTC, RFC 3339).
    - `verify_code` string, required: A short code that proves the result came from Tektolo without carrying its figures. Safe to print on a document; the payload above is not meant to be shared.
    - `verify_url` string, required: Where anyone can check the code.
  - `result` ScopeResult, required: Field order puts the answer first (summary, disclaimer, totals, refer-outs, vendor scopes), because agents and truncating clients read from the top.
    - `summary` string, required
    - `disclaimer` string, required
    - `warnings` TektoloPropertyTurnoverModelsNote[], required
      - `code` string, required
      - `message` string, required
      - `finding_ids` string[]
      - `line_ids` string[]
    - `totals` TektoloPropertyTurnoverModelsTotals, required
      - `note` string: How the totals add up.
      - `must` CostRange, required: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
      - `should` CostRange, required: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
      - `could` CostRange, required: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
      - `visit_charges` CostRange, required: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
      - `subtotal` CostRange, required: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
      - `tax` CostRange, required: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
      - `total` CostRange, required: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
      - `approved` CostRange: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
      - `to_confirm` CostRange: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
      - `allowances` CostRange: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
    - `refer_outs` ReferOutNote[], required
      - `id` string, required
      - `name` string, required
      - `professional` string, required
      - `reason` string, required
      - `kind` 'assessment' | 'compliance', required
      - `finding_ids` string[], required
      - `blocks_phases` Phase[], required
      - `sources` string[], required
      - `unconfirmed` boolean: No finding confirms it: every finding that raised it was hedged ('maybe', '?'), named the hazard only in its words (description, notes or location label) rather than through its issue code, or stated an older year built than the request. Check first; no phase is held until the condition is confirmed (see warnings).
    - `trade_scopes` TradeScope[], required
      - `trade` 'hauling' | 'handyman' | 'drywall' | 'painter' | 'flooring' | 'carpet_cleaning' | 'cleaning' | 'appliance' | 'plumber' | 'electrician' | 'hvac' | 'locksmith' | 'pest_control' | 'landscaping' | 'window_glass' | 'environmental' | 'structural', required
      - `vendor` Vendor, required
        - `name` string, required
        - `contact` string, nullable
      - `phase` 'assess' | 'trash_out' | 'repairs' | 'paint' | 'flooring' | 'appliances' | 'cleaning' | 'punch' | 'rekey', required: Make-ready order. Values sort in sequence order via PHASE_ORDER.
      - `line_ids` string[], required
      - `lines_cost` CostRange, required: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
      - `visit_charges` CostRange, required: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
      - `total` CostRange, required: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
    - `lines` ScopeLine[], required
      - `line_id` string, required
      - `task_id` string, required
      - `name` string, required
      - `trade` 'hauling' | 'handyman' | 'drywall' | 'painter' | 'flooring' | 'carpet_cleaning' | 'cleaning' | 'appliance' | 'plumber' | 'electrician' | 'hvac' | 'locksmith' | 'pest_control' | 'landscaping' | 'window_glass' | 'environmental' | 'structural', required
      - `phase` 'assess' | 'trash_out' | 'repairs' | 'paint' | 'flooring' | 'appliances' | 'cleaning' | 'punch' | 'rekey', required: Make-ready order. Values sort in sequence order via PHASE_ORDER.
      - `priority` 'must' | 'should' | 'could', required
      - `location` string, required
      - `finding_ids` string[], required
      - `quantity` string, required
      - `uom` 'each' | 'sq_ft' | 'sq_ft_floor' | 'sq_yd' | 'linear_ft' | 'room' | 'unit' | 'bedroom' | 'bathroom' | 'hour' | 'cu_yd' | 'visit', required
      - `quantity_source` 'given' | 'converted' | 'derived' | 'fixed', required
      - `price_basis` 'rate_card' | 'unit_price' | 'labor_derived' | 'placeholder', required
      - `unit_price` CostRange, required: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
      - `cost` CostRange, required: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
      - `confidence` 'sourced' | 'industry_typical' | 'assumed', required
      - `responsibility_hint` 'normal_wear' | 'likely_damage' | 'elective' | 'undetermined' | 'mixed', required
      - `responsibility_by_finding` object: Set when the hint is 'mixed': the hint of each finding the line carries.
      - `allowance` CostRange: A low / expected / high estimate. Invariant: low <= expected <= high.
        - `low` string, required
        - `expected` string, required
        - `high` string, required
      - `refer_out` string, nullable
      - `decision` 'approve' | 'decline' | 'defer', nullable
      - `vendor_note` string, nullable
      - `rule_ids` string[], required
      - `to_confirm` boolean: Every finding behind this line is uncertain, or it is a check-first assessment from the safety net: priced, but not in must/should/could, subtotal or total (see totals.to_confirm).
      - `needs_review` boolean: A finding behind this line was read by AI from free text: check it.
    - `lines_omitted` integer, required: Lines left out in summary detail.
    - `omitted_note` string, nullable: Summary detail: what the omitted lines are (routine turn tasks) and their cost.
    - `findings` FindingResolution[], required
      - `finding_id` string, required
      - `resolution` 'exact' | 'alias' | 'ai' | 'unmapped' | 'not_billed', required: exact: a taxonomy code was given. alias: the description matched an alias. ai: an AI reader chose the code from free text (see confidence, model; needs_review). unmapped: nothing matched (a manual-quote line). not_billed: the description says there is no work ('no mold', 'faucet not leaking', 'fixed by tenant'), or names no condition at all (a heading, a date, a signature, a year built); no lines, no refer-out; the issue it names is in suggestions and the reason in not_billed_reason.
      - `not_billed_reason` 'none' | 'ok' | 'done' | 'no_condition', nullable: resolution 'not_billed' only. none: says there is none ('no mold', 'mold: none'); ok: says it works or is fine; done: says it was already fixed or done; no_condition: names no condition, only a heading, small talk, a signature or the year built ('Unit 4B - Move-out inspection', 'Built 1972'), see match_note (contract 0.13.0, additive).
      - `code` string, nullable, required
      - `issue_name` string, nullable: Readable name of `code`.
      - `text` string, nullable: The finding as given (description, else code), for tracing.
      - `location` string, nullable: Where, as shown on the lines.
      - `match_note` string, nullable: Set when the match left a fixture word unexplained: check this finding.
      - `uncertain` boolean: The description hedges ('mold?', 'maybe', 'possible'). Refer-outs from uncertain findings are check-first: they add a warning instead of holding phases.
      - `extent` 'spot' | 'partial' | 'full', required
      - `suggested_codes` string[]
      - `suggestions` Suggestion[]: Suggested codes with readable names, best first.
        - `code` string, required
        - `name` string, required
      - `line_ids` string[]
      - `needs_review` boolean: True when software read this finding from free text (resolution 'ai'): check it.
      - `confidence` string, nullable: resolution 'ai' only: the AI reader's confidence, 0 to 1.
      - `model` string, nullable: resolution 'ai' only: the model used.
      - `confirmed` boolean: Read by AI and confirmed by the person (sent with confirmed: true).
    - `assumptions` TektoloPropertyTurnoverModelsNote[], required
      - `code` string, required
      - `message` string, required
      - `finding_ids` string[]
      - `line_ids` string[]
    - `unknowns` TektoloPropertyTurnoverModelsNote[], required
      - `code` string, required
      - `message` string, required
      - `finding_ids` string[]
      - `line_ids` string[]
    - `rate_card_applied` RateCardUse[]: Rate card entries that changed a price.
      - `entry` integer, required: 0-based index into the request's rate_card.
      - `target` string, required: The entry's task_id or trade.
      - `lines` string[]
      - `note` string, required
    - `rate_card_ignored` RateCardUse[]: Rate card entries that changed nothing, with why.
      - `entry` integer, required: 0-based index into the request's rate_card.
      - `target` string, required: The entry's task_id or trade.
      - `lines` string[]
      - `note` string, required
    - `detail` 'summary' | 'full', required
    - `region` Region, required
      - `zip3` string, required
      - `basis` 'metro' | 'nonmetro' | 'national', required
      - `cbsa` string, nullable
      - `cbsa_name` string, nullable
      - `vintage` string, nullable
    - `profile` 'minimum' | 'standard' | 'premium', required
    - `price_tier` 'bulk_contract' | 'pm_vendor' | 'retail_one_off': Purchasing channel. Library prices are pm_vendor (a PM buying turns from a local vendor).
    - `provenance` TektoloPropertyTurnoverModelsProvenance, required
      - `ruleset_id` string, required
      - `ruleset_version` string, required
      - `ruleset_hash` string, required
      - `sources` SourceRef[], required
        - `id` string, required
        - `title` string, required
        - `url` string, nullable
  - `payment` PaymentInfo, required
    - `protocol` string
    - `x402_version` integer
    - `scheme` string
    - `network` string, required
    - `network_name` string, required
    - `testnet` boolean, required
    - `asset` string, required
    - `amount_usd` string, required
    - `amount_atomic` string, required
    - `transaction` string, required
    - `payer` string, nullable

## Other responses

- `402`: Payment required (x402 v2). The PAYMENT-REQUIRED header carries the base64 payment requirements; retry with a PAYMENT-SIGNATURE header. Also returned for an invalid payment or a failed settlement (nothing charged).
- `412`: The ruleset named in the Tektolo-Ruleset header is not the one in force, and the call did not ask to be answered under it (Tektolo-Ruleset-Mode: serve) or that version can't be served (the body's reason says why). Nothing was computed or charged; the body names both versions.
- `422`: Invalid input. Checked before payment; never charged.
- `429`: Rate limited (per payer wallet or per client). Never charged.
- `503`: Payment facilitator unreachable. Never charged.

---

[API](https://skmtc.dev/tektolo/apis/tektolo-capabilities-api.md) · [All operations](https://skmtc.dev/tektolo/apis/tektolo-capabilities-api/llms.txt) · [OpenAPI document](https://skmtc.dev/tektolo/apis/tektolo-capabilities-api/revisions/6e667aa7b6f7?raw)
