Pick a sample submission or add your own photos, then run the check against the live API. The result shows the decision, every finding with the instruction a contractor would see, the item's photo list, and what the check took and cost. Samples are real pilot submissions, down-scaled with their metadata removed; they load only with a valid key. Photo lists cover HVAC and pool items (12 types); any other item still gets the photo checks but answers not_checked (see How it decides).
No result yet.
Run a check, or (synthetic, no API call).
This session
Checks you ran from this page. Click one to load it again from the API.
| When | Check | Item | Decision | Photos | Total | Model cost |
|---|
Every endpoint of API v1 with its inputs filled in. Send any of them and see the status, the time it took from this browser, and the response. The error cases show the shape every error has.
What it covers
Photo lists exist for 12 inspection types: HVAC (mechanical rough-in; mechanical final, including equipment change-outs) and pools (shell steel and bonding, piping and pressure test, main drain, deck, perimeter bonding, underground electric, electrical final, plumbing final, barrier, final). Any other item still gets the file, pixel and duplicate checks, but its completeness isn't checked, so the answer is not_checked, never ready. In the pilot, half of the inspections with contractor photos were for items with a list; the biggest without one are building (insulation, framing, sheathing), electrical and plumbing rough-ins, roofing and gas.
The pipeline
Each submission goes through fixed stages. Each stage can be switched off and tuned in the service's configuration, and every result names the configuration it ran with.
How findings become a decision
- Only missing views hold a submission back. Photo problems ask the contractor for a retake but don't block it.
- Some problems hide the view: blurry, too dark, washed out, too small, wrong subject. A photo with one of these doesn't count toward the views it shows. An obstructed photo asks for a retake, but still counts.
- Blocking views are marked in each inspection type's photo list. A type with no blocking view blocks on its required views. If no usable photo shows anything the item needs, every missing view blocks.
- Conditional views (a split system, a rooftop unit, autofill only) apply when the model judges the condition holds, or can't tell (recall first). The caller can settle a condition it knows.
- Fail closed. If completeness can't be checked (no photo list for the item, no model, or no answer after retries), the decision is
not_checkedand the submission is never reported ready. - Advice only (severity
info): screenshots, duplicates, photos too close, cropped or too far, and labels that may be hard to read. Two model judges looking at full detail found most such flags on usable photos (decisions 0009, 0014, 0015). - Permit details settle what photos can't. A request may carry
permit_type,occupancyandahj; rules in the configuration then settle conditions (an A/C change-out rules out bath and kitchen exhaust work), with a notice saying so (decision 0013). A rule never rules out a view a photo shows. - Thumbnails: when every photo of a submission (two or more) is under 400 px on its short side, a notice asks for the original photos.
The categories
Live from GET /v1/categories; the instruction is what the contractor sees. {view} stands for the missing view's description.
Use a key to load the categories.
Benchmark: the live service against v1 and v0
The 52 submissions of the frozen benchmark, checked by the live service (two runs: the model's answers vary from run to run), by v1 as first shipped and by v0. Readiness is judged against the inspector's outcome; views and photos against the cases two model judges agree on (Claude Opus 5.5 and Gemini 4 Argon). Misses come first. With 6 items sent back for photos, read the readiness difference as directional.
| Measure | Live (two runs) | v1 | v0 |
|---|---|---|---|
| Items sent back for photos that the check let through | 0 of 6 | 0 of 6 (0–39%) | 2 of 6 (10–70%) |
| Passed items held back | 7 and 5 of 38 | 9 of 38 (13–39%) | 9 of 38 holding only for missing views; 22 of 38 as built |
| Blocking views missing but counted as shown | 2 and 4 of 23 | 3 of 23 (4–32%) | 1 of 15 (1–30%) |
| Blocking views shown but reported missing | 2 and 1 of 125 | 4 of 125 (1–8%) | 9 of 121 (4–14%) |
| Problem photos with no retake request* | 42 and 37 of 75 | 22 of 75 (20–40%) | 38 of 75 (40–62%) |
| Usable photos asked to be retaken* | 35 and 46 of 599 | 85 of 599 (12–17%) | 58 of 599 (8–12%) |
* Both photo rows use the 2026-10-19 labels, made partly from contact sheets. Since then the model's "too far" and "label may be hard to read" are advice (decisions 0014, 0015): two judges looking again at full detail found most of those photos usable, and of the retake requests that remain, 47–48% are needed against 39–41% before. The live service also has hedged model calls (0011), a 400 px resolution floor (0012) and permit-detail rules (0013). v1 and the live service count more views as blocking than v0 (a type with no blocking view blocks on its required views), hence 23 and 125 against 15 and 121.
Cost: about $0.93 for the 52 submissions (805 uploads), about $18 per 1,000 submissions at gemini-4-argon's list price. Time with hedged model calls: 12–15 s median, 28–35 s p95 and 40 s at most in two runs (v1: 16 s and 62 s), nearly all model time; photo checks 0.6 s median. The pixel checks were calibrated on 791 labeled photos and run 5.4 times faster than v0's; since decision 0012 a photo counts from 400 px on its short side (v0: 480).
Functional requirements
| ID | Requirement | Status | Evidence, or the gap |
|---|
Non-functional requirements
Targets marked proposed are to be agreed with Inspected. Load basis: up to 25,000 inspections a month with 5 checked items each and a 10× peak, that is up to 1.6 checks a second.
| ID | Requirement | Target | Status | Measured, or the gap |
|---|
The contract
The API is described by an OpenAPI 3.1 document, served at /openapi.yaml; client libraries can be generated from it. Contract tests check every kind of response against it on each build. Within v1, fields are added, never renamed or removed.
Examples with curl
Put the key in a header file so it stays out of your shell history and process list.
Request fields
The request part of the multipart body, as JSON; each photo is its own part and its filename is the photo id. Or send application/json with photos: [{"photo_id", "url"}], HTTPS links on the hosts the deployment allows.
| Field | Meaning |
|---|---|
inspection_id | The visit-activity id; it comes back in the result |
item_name, permit_category | Optional: the checklist item and the permit's category (e.g. Mechanical Final, MECHANICAL); they pick the photo list |
conditions | Optional: conditional view → true or false, when you know (e.g. {"line-set": true} for a split system) |
permit_type, occupancy, ahj | Optional permit details, as Permit Hub has them (e.g. A/C Change Out); rules settle conditions on them (decision 0013) |
For a condition, conditions wins, then the permit-detail rules, then the model.
Response fields
| Field | Meaning |
|---|---|
decision, ready_for_inspection, reasons | ready, not_ready, needs_review or not_checked; readable reasons for the decision |
findings[] | Every problem, strongest first: finding_id (used for feedback), photo_id or null for a missing view, category, severity (block, retake, info), title, retake (the instruction), detected_by, evidence |
missing_views, suggested_views | Blocking views no usable photo shows; other missing views to ask for |
views[] | The item's photo list with each view's status (present, present_unverified, missing, not_needed, unchecked) and the photos that show it |
conditions | Conditional view → yes, no, unclear or given |
versions | API, config version and digest, categories version, model, prompt |
timings_ms, usage | Time per stage; model calls and tokens |