PlanSight Partner API

Add AI plan review to your product

Your server calls our API with a secret key; your users see results through embeddable hosted screens — no PlanSight login required for them. Every finding is cited to the exact spot on the sheet. No competitor offers a developer API like this.

v1.0.0build 7acb0c07c2f1a3ee0ae1476b4d7bf3f05dc96bbaOpenAPI spec ↗

Overview

A job is one plan set. You create a job, upload the PDF, start a scan, then read findings — or embed our hosted screens so your users never leave your app. The whole loop is server-to-server plus optional iframes.

1
CreateOpen a job for one plan set
2
UploadPUT the PDF to a presigned URL
3
ScanRun the review pipeline
4
ReadFindings + cited evidence, or embed a screen

Authentication

Send your key on every server-to-server call. Keep it server-side — never ship it to a browser. Each key is scoped to its own jobs; another partner's job id returns 404.

Header
Authorization: Bearer ps_live_xxxxxxxxxxxxxxxxxxxxxxxx

Invalid key → 401; rate limited → 429 with a Retry-After header. Errors are JSON:

json
{ "error": { "code": "...", "message": "..." } }

Quickstart — upload a plan and get results

The full flow, end to end:

cURL
# 1. Create a job
curl -X POST https://YOUR_PLANSIGHT_HOST/api/v1/jobs \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"name":"123 Main St — bid #14"}'
# -> { "jobId": "...", "versionId": "..." }

# 2. Register the PDF -> get a presigned upload URL
curl -X POST https://YOUR_PLANSIGHT_HOST/api/v1/jobs/$JOB/files \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"fileName":"plans.pdf","fileSize":8421000,"contentType":"application/pdf"}'
# -> { "fileId": "...", "uploadUrl": "https://s3..." }

# 3. PUT the raw bytes to the presigned URL
curl -X PUT "$UPLOAD_URL" -H "Content-Type: application/pdf" --data-binary @plans.pdf

# 4. Start the scan
curl -X POST https://YOUR_PLANSIGHT_HOST/api/v1/jobs/$JOB/scan -H "Authorization: Bearer $KEY"

# 5. Poll status until complete (~minutes)
curl https://YOUR_PLANSIGHT_HOST/api/v1/jobs/$JOB -H "Authorization: Bearer $KEY"
# -> { "jobId": "...", "status": "...", "pipeline": { "currentStage": "...", ... } }

# 6. Read findings
curl https://YOUR_PLANSIGHT_HOST/api/v1/jobs/$JOB/findings -H "Authorization: Bearer $KEY"
# -> { "findings": [ { "severity": "...", "rationale": "...", "evidenceAnchors": [...] } ] }

Also available: GET /api/v1/jobs/{jobId}/export/csv (findings CSV) and GET /api/v1/jobs/{jobId}/files/{fileId}/annotated (presigned URL to the marked-up PDF).

Show results to your users (embedded screens)

Mint a short-lived signed link from your server, then drop it in an <iframe>. Your user needs no PlanSight account. Links expire in ~30 minutes and are scoped to one screen + one job — mint fresh on demand.

cURL
curl -X POST https://YOUR_PLANSIGHT_HOST/api/v1/embed \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"screen":"job","jobId":"'$JOB'"}'
# -> { "url": "https://.../embed/job/JOB?t=SIGNED", "expiresAt": 1733... }
loginYour PlanSight dashboard — all your jobs. No jobId.
jobUpload + the marked-up plan and findings for one job.
chatjobChat: ask questions about the plan, AI answers.

jobChat from your own UI

Ask anything about the uploaded set; answers come back grounded with citations.

cURL
curl -X POST https://YOUR_PLANSIGHT_HOST/api/v1/jobs/$JOB/chat \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"message":"What setbacks does the site plan call out?"}'
# -> { "answer": "...", "citations": [ { "page": 4, "sheetType": "...", "excerpt": "..." } ] }

API reference

All endpoints live under https://plansight.xyz/api/v1. The machine-readable contract is the OpenAPI spec.

POST/api/v1/jobsCreate a job (one plan set). Returns jobId + versionId.
GET/api/v1/jobs/{jobId}Job status + pipeline stage. Poll until terminal.
POST/api/v1/jobs/{jobId}/filesRegister a PDF; returns a presigned upload URL.
POST/api/v1/jobs/{jobId}/scanStart the review pipeline for the job.
GET/api/v1/jobs/{jobId}/findingsFindings with severity, rationale, and evidence anchors.
GET/api/v1/jobs/{jobId}/export/csvAll findings as CSV.
GET/api/v1/jobs/{jobId}/files/{fileId}/annotatedPresigned URL to the marked-up PDF.
POST/api/v1/jobs/{jobId}/chatjobChat — ask a question, get a cited answer.
POST/api/v1/embedMint a short-lived signed link for an embedded screen.
GET/api/v1/pingAuth + connectivity check.

API Explorer

Pick an endpoint, edit the params, and watch the request build across cURL, JavaScript, and Python. Hit Run sample to see a representative response. Real calls authenticate with your ps_live key server-side.

Create a job (one plan set).

curl -X POST https://arch-ai.expertresearch.net/api/v1/jobs \
  -H "Authorization: Bearer $PLANSIGHT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"123 Main St — bid #14"}'
Example response · real calls use your ps_live key server-side

Getting a key

PlanSight mints your ps_live_… key and shares it with you once. Treat it like a password; rotate by asking for a new one (the old one is revoked). Request a key →

Building this with an AI coding agent?

Paste the prompt below into your coding agent — it has everything: auth, the upload→scan→results flow, jobChat, and the three embeddable screens. Raw copy at https://plansight.xyz/developers/prompt.

Integration prompt
[PlanSight Partner API v1.0.0 · build 7acb0c07c2f1a3ee0ae1476b4d7bf3f05dc96bba · https://plansight.xyz]

You are adding a "PlanSight" integration to our construction job-management app
(we bid, estimate, and pay for work). PlanSight is an AI building-plan code-review
service. Your job: let our users upload plans, see PlanSight's scan results, and
ask questions about a plan — all inside our app.

AUTHORITATIVE DOCS (read these first, in full):
- Guide:   https://plansight.xyz/developers
- OpenAPI: https://plansight.xyz/api/v1/openapi.json   (every endpoint + exact request/response schemas)

CREDENTIALS
- We have a PlanSight API key in the server env var PLANSIGHT_API_KEY (format ps_live_...).
- It is a SERVER-SIDE SECRET. NEVER send it to the browser, log it, or commit it.
- Every server-to-server call: header  Authorization: Bearer $PLANSIGHT_API_KEY
- Our PlanSight account owns everything we send; one "job" in PlanSight === one of our jobs.

BUILD THE FOLLOWING

1) A small server-side PlanSight client (e.g. lib/plansight.ts) that wraps:
   POST https://plansight.xyz/api/v1/jobs                         -> { jobId, versionId }   (create)
   POST https://plansight.xyz/api/v1/jobs/{jobId}/files           -> { fileId, uploadUrl }  (then PUT the PDF bytes to uploadUrl with Content-Type: application/pdf)
   POST https://plansight.xyz/api/v1/jobs/{jobId}/scan            -> starts the scan (async)
   GET  https://plansight.xyz/api/v1/jobs/{jobId}                 -> { status, pipeline }    (poll until complete/failed)
   GET  https://plansight.xyz/api/v1/jobs/{jobId}/findings        -> { findings: [...] }
   POST https://plansight.xyz/api/v1/jobs/{jobId}/chat            -> { answer, citations }
   POST https://plansight.xyz/api/v1/embed { screen, jobId? }     -> { url, expiresAt }      (signed hosted-screen link)

2) On each of our jobs, store the PlanSight jobId. Add an "Upload plans for review"
   action: create a PlanSight job, get a presigned URL, PUT the PDF, then call scan.
   Track status by polling GET /api/v1/jobs/{jobId} (or show our own progress).

3) Add a "PlanSight" screen/tab to each job offering THREE things (use the hosted
   screens — do NOT rebuild PlanSight's UI). For each, call POST /api/v1/embed from
   OUR SERVER (with the API key), then render the returned url in an <iframe>:
   - results:  POST /api/v1/embed { screen: "job",  jobId }  -> iframe the url (marked-up plan + findings, with upload)
   - jobChat:  POST /api/v1/embed { screen: "chat", jobId }  -> iframe the url (ask questions, AI answers)
   - a "Log in to PlanSight" button: POST /api/v1/embed { screen: "login" } -> open the url (their full PlanSight dashboard)
   Embed links expire in ~30 minutes and are scoped to one screen + one job — mint them
   fresh, server-side, when the user opens the screen. NEVER mint them in the browser.

4) (Optional, great for a bid/estimate app) Also pull GET /api/v1/jobs/{jobId}/findings
   server-side and show a NATIVE summary on the job card — counts by severity and any
   cost impact — with an "Open full report" button that opens the embedded results screen.

RULES
- Match the exact shapes in the OpenAPI spec. Handle 401 (bad key), 404 (job not found
  / not ours), and 429 (rate limited — respect the Retry-After header).
- Keep the API key server-side always; the browser only ever sees short-lived embed URLs.
- Scans are asynchronous (minutes); design the UI around "submitted -> processing -> ready".

Confirm your integration plan, then implement it incrementally with tests.