{"openapi":"3.1.0","info":{"title":"PlanSight Partner API","version":"1.0.0","x-build":"7acb0c07c2f1a3ee0ae1476b4d7bf3f05dc96bba","description":"Integrate PlanSight (AI building-plan code review) into your app. Server-to-server calls use your API key as `Authorization: Bearer ps_live_...`. The typical flow: create a job → upload a PDF to the returned presigned URL → start a scan → poll status until `complete` → read findings. To SHOW results to your users, mint a short-lived signed link with POST /api/v1/embed and embed the hosted screen (login / upload+results / jobChat) in an iframe — no PlanSight login required for your users. Each partner key is scoped to its own jobs; cross-partner access returns 404."},"servers":[{"url":"/","description":"Same origin as this spec."}],"security":[{"ApiKey":[]}],"components":{"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer","description":"Your partner API key (`ps_live_...`). Server-side only — never expose it in a browser."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}},"Job":{"type":"object","properties":{"jobId":{"type":"string","description":"PlanSight job id (use everywhere a {jobId} path param appears)."},"versionId":{"type":"string"}}},"Finding":{"type":"object","description":"A single code-review finding (RuleResult).","properties":{"findingId":{"type":"string"},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"confidence":{"type":"number"},"rationale":{"type":"string"},"governingRefs":{"type":"string"},"evidenceAnchors":{"type":"array","items":{"type":"object","properties":{"page":{"type":"integer"},"bbox":{"type":"object"}}}}}}}},"paths":{"/api/v1/ping":{"get":{"summary":"Health/auth check","responses":{"200":{"description":"Authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"partnerId":{"type":"string"}}}}}},"401":{"description":"Missing/invalid key"}}}},"/api/v1/jobs":{"post":{"summary":"Create a job","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"Invalid body"},"401":{"description":"Unauthorized"}}},"get":{"summary":"List your jobs","responses":{"200":{"description":"OK"}}}},"/api/v1/jobs/{jobId}":{"get":{"summary":"Job status + pipeline summary","parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Not found / not yours"}}}},"/api/v1/jobs/{jobId}/files":{"post":{"summary":"Register a PDF and get a presigned S3 upload URL (then PUT the bytes to it)","parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["fileName","fileSize","contentType"],"properties":{"fileName":{"type":"string"},"fileSize":{"type":"integer","description":"<= 104857600 (100MB)"},"contentType":{"type":"string","enum":["application/pdf"]},"fileTag":{"type":"string"}}}}}},"responses":{"201":{"description":"Returns { fileId, uploadUrl }"},"400":{"description":"Invalid (non-PDF or too large)"}}},"get":{"summary":"List a job's files","parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK"}}}},"/api/v1/jobs/{jobId}/scan":{"post":{"summary":"Start the PlanSight scan (async)","parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Scan started"},"400":{"description":"No files / no version"},"429":{"description":"Quota exceeded (see Retry-After)"}}}},"/api/v1/jobs/{jobId}/findings":{"get":{"summary":"Findings JSON","parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"}},{"name":"versionId","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { findings: Finding[] }","content":{"application/json":{"schema":{"type":"object","properties":{"findings":{"type":"array","items":{"$ref":"#/components/schemas/Finding"}}}}}}}}}},"/api/v1/jobs/{jobId}/export/csv":{"get":{"summary":"Findings as CSV","parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"text/csv"}}}},"/api/v1/jobs/{jobId}/files/{fileId}/annotated":{"get":{"summary":"Presigned URL to the marked-up PDF (404 until the scan finishes)","parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"}},{"name":"fileId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { url }"},"404":{"description":"Not ready / not found"}}}},"/api/v1/jobs/{jobId}/chat":{"post":{"summary":"jobChat — ask a question about the plan; AI answers with citations","parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string"},"history":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string"},"content":{"type":"string"}}}}}}}}},"responses":{"200":{"description":"Returns { answer, citations }"},"400":{"description":"Missing message"}}}},"/api/v1/embed":{"post":{"summary":"Mint a short-lived signed link to a hosted screen (embed it in an iframe)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["screen"],"properties":{"screen":{"type":"string","enum":["login","job","chat"]},"jobId":{"type":"string","description":"Required for screen=job|chat"}}}}}},"responses":{"200":{"description":"Returns { url, expiresAt }"},"400":{"description":"Invalid screen / missing jobId"},"404":{"description":"Job not yours"}}}}}}