{"openapi":"3.1.0","info":{"title":"BuildBid API","version":"1.0.0","description":"APIs for BuildBid’s AI construction estimating platform with agent-native workflows."},"servers":[{"url":"https://buildbid.app","description":"Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Agent"},{"name":"Estimate"},{"name":"EstimateAPI","description":"Public v1 Estimate API — agent-accessible, human-approved"},{"name":"MCP","description":"Model Context Protocol — JSON-RPC 2.0 agentic tooling"},{"name":"Upload"},{"name":"Workflow"},{"name":"Vision"},{"name":"3D"},{"name":"Billing"},{"name":"System"},{"name":"RFI"}],"paths":{"/api/agent":{"post":{"tags":["Agent"],"summary":"Run one conversational agent turn","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"estimateId":{"type":"string"},"message":{"type":"string"},"history":{"type":"array","items":{"type":"object"}}}}}}},"responses":{"200":{"description":"Agent response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"description":"Missing required fields"},"401":{"description":"Unauthorized"}}}},"/api/agent/chat":{"post":{"tags":["Agent"],"summary":"Conversational agent endpoint","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["estimateId","message"],"properties":{"estimateId":{"type":"string"},"message":{"type":"string"},"history":{"type":"array","items":{"type":"object"}}}}}}},"responses":{"200":{"description":"Agent chat response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"}}}},"/api/agent/jobs":{"post":{"tags":["Agent","Workflow"],"summary":"Submit asynchronous job","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["document_extraction","full_validation","price_check","bid_deadline_alert","price_change_alert","historical_analysis","sub_quote_intake","rfi_generation","estimate_comparison","overnight_refinement"]},"estimateId":{"type":"string"},"input":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"Job queued","content":{"application/json":{"schema":{"type":"object","properties":{"jobId":{"type":"string"},"status":{"type":"string"}}}}}},"400":{"description":"Invalid job payload"},"401":{"description":"Unauthorized"}}},"get":{"tags":["Agent","Workflow"],"summary":"Get job status","parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Job status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"id required"},"401":{"description":"Unauthorized"},"404":{"description":"Job not found"}}}},"/api/upload":{"post":{"tags":["Upload"],"summary":"Upload source files for extraction","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"200":{"description":"Extraction started"},"401":{"description":"Unauthorized"},"402":{"description":"Insufficient credits"},"413":{"description":"Payload too large"}}}},"/api/estimates":{"get":{"tags":["Estimate"],"summary":"List user estimates","responses":{"200":{"description":"Estimate list","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EstimateSummary"}}}}},"401":{"description":"Unauthorized"}}}},"/api/estimate/{id}":{"get":{"tags":["Estimate"],"summary":"Get one estimate","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Estimate object","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimatePayload"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Not found"}}},"post":{"tags":["Estimate"],"summary":"Update one estimate","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimatePayload"}}}},"responses":{"200":{"description":"Updated"},"401":{"description":"Unauthorized"},"404":{"description":"Not found"}}},"delete":{"tags":["Estimate"],"summary":"Delete an estimate","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"},"401":{"description":"Unauthorized"},"404":{"description":"Not found"}}}},"/api/estimate/{id}/approval":{"get":{"tags":["Estimate"],"summary":"Get approval state","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Approval payload"},"401":{"description":"Unauthorized"},"404":{"description":"Not found"}}},"post":{"tags":["Estimate"],"summary":"Submit approval decision","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"approved":{"type":"boolean"},"reason":{"type":"string"}}}}}},"responses":{"200":{"description":"Approval saved"},"401":{"description":"Unauthorized"},"404":{"description":"Not found"}}}},"/api/estimate/{id}/export":{"get":{"tags":["Estimate"],"summary":"Export estimate JSON","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Export payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimatePayload"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Not found"}}}},"/api/share/{estimateId}":{"post":{"tags":["Workflow"],"summary":"Create share token","parameters":[{"name":"estimateId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"days":{"type":"integer"}}}}}},"responses":{"200":{"description":"Share token generated"},"401":{"description":"Unauthorized"},"404":{"description":"Estimate not found"}}}},"/api/voice-estimate":{"post":{"tags":["Estimate","Workflow"],"summary":"Create estimate from spoken text","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["text"],"properties":{"text":{"type":"string"}}}}}},"responses":{"200":{"description":"Estimate created"},"400":{"description":"Bad payload"},"401":{"description":"Unauthorized"}}}},"/api/market-data":{"get":{"tags":["Workflow"],"summary":"Read market multipliers","parameters":[{"name":"region","in":"query","required":false,"schema":{"type":"string"}},{"name":"state","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Multiplier payload"},"401":{"description":"Unauthorized"}}}},"/api/rfi":{"post":{"tags":["RFI"],"summary":"Generate RFI text from conflict","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["conflict_type","item_description","blueprint_ref","spec_ref","project_name"],"properties":{"conflict_type":{"type":"string","enum":["SPEC_CONTRADICTION","NIC_RISK"]},"item_description":{"type":"string"},"blueprint_ref":{"type":"string"},"spec_ref":{"type":"string"},"project_name":{"type":"string"}}}}}},"responses":{"200":{"description":"RFI generated"},"400":{"description":"Missing fields"},"401":{"description":"Unauthorized"}}}},"/api/review-estimate":{"post":{"tags":["Estimate","Workflow"],"summary":"Run heuristic review","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"estimate":{"type":"object"},"location":{"type":"string"}}}}}},"responses":{"200":{"description":"Review result"},"400":{"description":"estimate missing"},"500":{"description":"review failed"}}}},"/api/review-council":{"post":{"tags":["Estimate","Workflow"],"summary":"Run AI review council","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["estimateId"],"properties":{"estimateId":{"type":"string"}}}}}},"responses":{"200":{"description":"Council report"},"401":{"description":"Unauthorized"}}}},"/api/3d/generate":{"post":{"tags":["3D","Vision"],"summary":"Generate GLB model from image input","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"imageBase64":{"type":"string"},"imageUrl":{"type":"string"},"provider":{"type":"string","enum":["tripo","fal"]}}}}}},"responses":{"200":{"description":"Model task created"},"401":{"description":"Unauthorized"},"503":{"description":"3D provider not configured"}}}},"/api/3d/qa":{"post":{"tags":["3D"],"summary":"Run QA on model","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["modelUrl"],"properties":{"modelUrl":{"type":"string"}}}}}},"responses":{"200":{"description":"Quality report"},"400":{"description":"Missing modelUrl"},"401":{"description":"Unauthorized"}}}},"/api/vision/image-to-3d":{"post":{"tags":["Vision","3D"],"summary":"Vision-driven 3D conversion","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["images"],"properties":{"images":{"type":"array","items":{"type":"string","format":"uri"}}}}}}},"responses":{"200":{"description":"Conversion result"},"401":{"description":"Unauthorized"}}}},"/api/itb/invites":{"get":{"tags":["Workflow"],"summary":"List ITB invites","responses":{"200":{"description":"Invite list"},"401":{"description":"Unauthorized"}}},"post":{"tags":["Workflow"],"summary":"Create ITB invite","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectName","email"],"properties":{"projectName":{"type":"string"},"email":{"type":"string"}}}}}},"responses":{"200":{"description":"Invite created"},"401":{"description":"Unauthorized"}}}},"/api/itb/invites/{token}":{"get":{"tags":["Workflow"],"summary":"Resolve invite token","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Invite payload"},"404":{"description":"Invite not found"}}}},"/api/itb/submissions":{"get":{"tags":["Workflow"],"summary":"List ITB submissions","responses":{"200":{"description":"Submissions list"},"401":{"description":"Unauthorized"}}},"post":{"tags":["Workflow"],"summary":"Submit bid proposal payload","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"inviteId":{"type":"string"},"payload":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"Submission accepted"},"401":{"description":"Unauthorized"}}}},"/api/stripe/checkout":{"post":{"tags":["Billing"],"summary":"Create credit checkout session","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["packId"],"properties":{"packId":{"type":"string"}}}}}},"responses":{"200":{"description":"Checkout session"},"401":{"description":"Unauthorized"}}}},"/api/stripe/subscribe":{"post":{"tags":["Billing"],"summary":"Create subscription checkout session","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tierId"],"properties":{"tierId":{"type":"string"}}}}}},"responses":{"200":{"description":"Checkout session"},"401":{"description":"Unauthorized"}}}},"/api/stripe/webhook":{"post":{"tags":["System"],"summary":"Stripe webhook receiver","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"}}}}}},"responses":{"200":{"description":"Webhook accepted"},"400":{"description":"Invalid signature"}}}},"/api/health":{"get":{"tags":["System"],"summary":"Service health check","responses":{"200":{"description":"Healthy","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"timestamp":{"type":"number"}}}}}}}}},"/api/v1/estimates":{"get":{"tags":["EstimateAPI"],"summary":"List agent draft estimates","description":"Returns draft estimates visible to the calling agent. Drafters see only their own; reviewers+ see all owner drafts.","parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["draft","pending_approval","approved","rejected","promoted"]}},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"List of drafts","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/EstimateDraft"}},"count":{"type":"integer"}}}}}},"401":{"description":"Unauthorized — missing or invalid agent API key"},"403":{"description":"Forbidden — missing required scope estimates:read"}}},"post":{"tags":["EstimateAPI"],"summary":"Create a draft estimate (agent-initiated)","description":"Creates a new draft estimate. The draft is NOT a finalized estimate — a human must approve it via POST /api/v1/estimates/:id/approve before it is promoted.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["projectName"],"properties":{"projectName":{"type":"string"},"data":{"type":"object","additionalProperties":true,"description":"Estimate payload — line items, markups, etc."}}}}}},"responses":{"201":{"description":"Draft created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateDraft"}}}},"400":{"description":"Missing projectName"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden — tier does not allow draft creation"}}}},"/api/v1/estimates/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"tags":["EstimateAPI"],"summary":"Get a single draft estimate","responses":{"200":{"description":"Draft","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateDraft"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Draft not found"}}},"patch":{"tags":["EstimateAPI"],"summary":"Update a draft estimate","description":"Only allowed while status is 'draft' or 'rejected'.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"projectName":{"type":"string"},"data":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"Updated draft"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"409":{"description":"Conflict — draft is not editable in current status"}}}},"/api/v1/estimates/{id}/submit":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"tags":["EstimateAPI"],"summary":"Submit draft for human approval","description":"Transitions status from draft/rejected → pending_approval. A human must then review.","responses":{"200":{"description":"Submitted"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"409":{"description":"Already pending/approved"}}}},"/api/v1/estimates/{id}/approve":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"tags":["EstimateAPI"],"summary":"Approve a draft (human-only)","description":"Requires a Supabase human session — agent API keys are explicitly rejected. Optionally promotes the draft to a finalized estimate (set promote=true).","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","description":"Optional approval note"},"promote":{"type":"boolean","description":"If true, automatically promote the draft to a finalized estimate"}}}}}},"responses":{"200":{"description":"Approved"},"401":{"description":"Unauthorized — missing human session"},"403":{"description":"Forbidden — agent API key used"},"404":{"description":"Not found"},"409":{"description":"Draft not in pending_approval state"}}}},"/api/v1/estimates/{id}/reject":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"post":{"tags":["EstimateAPI"],"summary":"Reject a draft (human-only)","description":"Requires a human session. The agent can then edit and resubmit.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["note"],"properties":{"note":{"type":"string","description":"Reason for rejection (required)"}}}}}},"responses":{"200":{"description":"Rejected"},"400":{"description":"Missing rejection note"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden — agent API key used"},"404":{"description":"Not found"},"409":{"description":"Draft not pending"}}}},"/api/mcp":{"get":{"tags":["MCP"],"summary":"MCP server discovery (unauthenticated)","description":"Returns server capabilities, available tools, and authentication instructions. No auth required.","responses":{"200":{"description":"MCP server manifest"}}},"post":{"tags":["MCP"],"summary":"MCP JSON-RPC 2.0 endpoint","description":"Model Context Protocol endpoint. Supports mcp/initialize, tools/list, tools/call. Auth: Bearer bb_live_... agent API key.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpRequest"}}}},"responses":{"200":{"description":"JSON-RPC response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpResponse"}}}},"400":{"description":"Parse error or invalid request"},"401":{"description":"Missing or invalid agent API key"},"403":{"description":"Missing required scopes"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"AgentResponse":{"type":"object","properties":{"reply":{"type":"string"},"toolCalls":{"type":"array","items":{"type":"object","additionalProperties":true}},"updatedEstimate":{"type":"object","nullable":true},"dirty":{"type":"boolean"}}},"Job":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"status":{"type":"string"},"result":{"type":"object","nullable":true}}},"EstimateSummary":{"type":"object","properties":{"id":{"type":"string"},"project_name":{"type":"string"},"status":{"type":"string"}}},"EstimatePayload":{"type":"object","properties":{"id":{"type":"string"},"projectName":{"type":"string"},"project_name":{"type":"string"},"line_items":{"type":"array","items":{"type":"object","additionalProperties":true}},"status":{"type":"string"},"total":{"type":"number"},"warnings":{"type":"array","items":{"type":"string"}}}}},"EstimateDraft":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"agentCredentialId":{"type":"string","format":"uuid"},"ownerUserId":{"type":"string","format":"uuid"},"projectName":{"type":"string"},"data":{"type":"object","additionalProperties":true},"status":{"type":"string","enum":["draft","pending_approval","approved","rejected","promoted"]},"submittedForApprovalAt":{"type":"string","format":"date-time","nullable":true},"reviewedBy":{"type":"string","format":"uuid","nullable":true},"reviewedAt":{"type":"string","format":"date-time","nullable":true},"reviewNote":{"type":"string","nullable":true},"promotedEstimateId":{"type":"string","format":"uuid","nullable":true},"revision":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"McpRequest":{"type":"object","required":["jsonrpc","method"],"properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}]},"method":{"type":"string","description":"mcp/initialize | tools/list | tools/call"},"params":{"type":"object","additionalProperties":true}}},"McpResponse":{"type":"object","properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}]},"result":{"type":"object","additionalProperties":true},"error":{"type":"object","properties":{"code":{"type":"integer"},"message":{"type":"string"},"data":{}}}}}}}