{"openapi":"3.1.0","info":{"title":"Exayard API","version":"1.0.0"},"servers":[{"url":"/v1"}],"components":{"schemas":{},"parameters":{}},"paths":{"/v1/me":{"get":{"tags":["Account"],"summary":"Get the authenticated caller","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"clerkUserId":{"type":"string","nullable":true},"clerkOrgId":{"type":"string"},"tokenType":{"type":"string","enum":["api_key","oauth_token","session_token","agent_jwt"]},"memberships":{"type":"array","items":{"type":"object","properties":{"orgId":{"type":"string"},"role":{"type":"string"}},"required":["orgId"]}}},"required":["clerkUserId","tokenType","memberships"]}}}},"401":{"description":"Unauthenticated","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/cma/provision":{"post":{"tags":["Account"],"summary":"Provision or rotate the caller’s Managed Agents vault","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"vaultId":{"type":"string"},"tokenExpiresAt":{"type":"number"},"reused":{"type":"boolean"}},"required":["vaultId","tokenExpiresAt","reused"]}}}},"401":{"description":"Unauthenticated","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/cma/chat":{"post":{"tags":["Account"],"summary":"Send a message to the Managed Agent and return its reply","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","minLength":1},"sessionId":{"type":"string"}},"required":["message"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string"},"text":{"type":"string"},"toolUses":{"type":"array","items":{"type":"object","properties":{"server":{"type":"string"},"name":{"type":"string"}},"required":["server","name"]}},"stopReason":{"type":"string","nullable":true}},"required":["sessionId","text","toolUses","stopReason"]}}}},"401":{"description":"Unauthenticated","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/ai-sessions":{"post":{"tags":["Account"],"summary":"Start a computer-use agent session on a project page","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex project ID"},"pageId":{"type":"string","minLength":1,"description":"Convex page ID the agent will operate on."},"vendor":{"type":"string","enum":["claude","openai","gemini"]}},"required":["projectId","pageId","vendor"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string"},"agentUserId":{"type":"string"},"syntheticClerkId":{"type":"string"},"syncJwt":{"type":"string"},"syncJwtExpiresAtMs":{"type":"number"},"vendor":{"type":"string","enum":["claude","openai","gemini"]},"projectId":{"type":"string"},"pageId":{"type":"string"}},"required":["sessionId","agentUserId","syntheticClerkId","syncJwt","syncJwtExpiresAtMs","vendor","projectId","pageId"]}}}},"401":{"description":"Unauthenticated","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}},"403":{"description":"Forbidden","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/projects":{"get":{"tags":["Projects"],"summary":"List projects in an organization","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"string","enum":["lead","contacted","qualified","active","archived"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"search","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["lead","contacted","qualified","active","archived"]},"secret":{"type":"string"},"privacy":{"type":"string","enum":["private","unlisted","public"]},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","name","status","createdAt","updatedAt"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Projects"],"summary":"Create a project","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"customProperties":{"type":"object","additionalProperties":{"nullable":true}}},"required":["organizationId","name"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"secret":{"type":"string"}},"required":["id","secret"]}}}}}}},"/v1/projects/{id}":{"get":{"tags":["Projects"],"summary":"Get a single project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["lead","contacted","qualified","active","archived"]},"secret":{"type":"string"},"privacy":{"type":"string","enum":["private","unlisted","public"]},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","name","status","createdAt","updatedAt"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"patch":{"tags":["Projects"],"summary":"Update a project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"status":{"type":"string","enum":["lead","contacted","qualified","active","archived"]},"settings":{"type":"object","properties":{"currency":{"type":"string","enum":["USD","CAD","MXN","BRL","ARS","CLP","COP","PEN","UYU","EUR","GBP","CHF","NOK","SEK","DKK","PLN","CZK","HUF","RON","BGN","HRK","RSD","UAH","RUB","TRY","ISK","ILS","AED","SAR","QAR","KWD","BHD","OMR","JOD","LBP","EGP","ZAR","NGN","KES","GHS","MAD","TND","DZD","JPY","CNY","HKD","TWD","KRW","SGD","INR","PKR","BDT","LKR","NPR","IDR","MYR","PHP","THB","VND","MMK","AUD","NZD"],"description":"ISO 4217 currency code"},"measurementSystem":{"type":"string","enum":["imperial","metric"]},"defaultScale":{"type":"number"}},"required":["measurementSystem"]},"tags":{"type":"array","items":{"type":"string"}},"customProperties":{"type":"object","additionalProperties":{"nullable":true}}},"required":["organizationId"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}},"delete":{"tags":["Projects"],"summary":"Archive a project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"204":{"description":"Archived"}}}},"/v1/projects/{id}/restore":{"post":{"tags":["Projects"],"summary":"Restore an archived project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."}},"required":["organizationId"]}}}},"responses":{"204":{"description":"Restored"}}}},"/v1/projects/{id}/relations":{"get":{"tags":["Projects"],"summary":"Get a project with page/estimate counts","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["lead","contacted","qualified","active","archived"]},"secret":{"type":"string"},"privacy":{"type":"string","enum":["private","unlisted","public"]},"createdAt":{"type":"number"},"updatedAt":{"type":"number"},"pagesCount":{"type":"number"}},"required":["_id","_creationTime","organizationId","name","status","createdAt","updatedAt","pagesCount"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/projects/{id}/privacy":{"post":{"tags":["Projects"],"summary":"Change a project’s privacy setting","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"privacy":{"type":"string","enum":["private","unlisted","public"]}},"required":["organizationId","privacy"]}}}},"responses":{"204":{"description":"Updated"}}}},"/v1/projects/{id}/pages":{"get":{"operationId":"listPages","tags":["Pages"],"summary":"List pages in a project, grouped by file","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"nullable":true}}}}}}}},"/v1/pages/{id}":{"get":{"tags":["Pages"],"summary":"Get a single page","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"projectId":{"type":"string"},"fileId":{"type":"string"},"name":{"type":"string"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","projectId"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"patch":{"tags":["Pages"],"summary":"Update page name or rotation","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"rotation":{"type":"number"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}},"delete":{"tags":["Pages"],"summary":"Archive (soft-delete) a page","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Archived"}}}},"/v1/pages/{id}/restore":{"post":{"tags":["Pages"],"summary":"Restore an archived page","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Restored"}}}},"/v1/lists":{"get":{"tags":["Lists"],"summary":"List product lists and takeoff templates","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"string","enum":["product","takeoffTemplate"]},"required":false,"name":"type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"category","in":"query"},{"schema":{"type":"boolean","nullable":true},"required":false,"name":"includeInactive","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["product","takeoffTemplate"]},"status":{"type":"string","enum":["active","draft","imported","default"]},"privacy":{"type":"string","enum":["private","organization","public","system"]},"category":{"type":"string"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","name","type"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Lists"],"summary":"Create a list","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string"},"type":{"type":"string","enum":["product","takeoffTemplate"]},"privacy":{"type":"string","enum":["private","organization","public","system"]},"category":{"type":"string"},"locale":{"type":"string","nullable":true,"enum":["af-ZA","id-ID","ms-MY","ca-ES","cs-CZ","da-DK","de-DE","en-US","es-ES","es-419","fr-CA","fr-FR","hr-HR","it-IT","hu-HU","nl-NL","no-NO","pl-PL","pt-BR","pt-PT","ro-RO","sk-SK","fi-FI","sv-SE","vi-VN","tr-TR","el-GR","ru-RU","sr-SP","uk-UA","hy-AM","he-IL","ur-PK","ar-SA","hi-IN","th-TH","ko-KR","ja-JP","zh-CN","zh-TW",null],"description":"Supported BCP-47 locale code"}},"required":["organizationId","name","type","locale"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}}},"/v1/lists/{id}":{"get":{"tags":["Lists"],"summary":"Get a single list","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["product","takeoffTemplate"]},"status":{"type":"string","enum":["active","draft","imported","default"]},"privacy":{"type":"string","enum":["private","organization","public","system"]},"category":{"type":"string"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","name","type"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"patch":{"tags":["Lists"],"summary":"Update list name or metadata","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string"},"privacy":{"type":"string","enum":["private","organization","public","system"]},"category":{"type":"string"}},"required":["organizationId"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}},"delete":{"tags":["Lists"],"summary":"Archive (soft-delete) a list","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"204":{"description":"Archived"}}}},"/v1/lists/{id}/restore":{"post":{"tags":["Lists"],"summary":"Restore an archived list","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."}},"required":["organizationId"]}}}},"responses":{"204":{"description":"Restored"}}}},"/v1/products":{"get":{"tags":["Products"],"summary":"List products in an organization","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"search","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"listId":{"type":"string"},"name":{"type":"string"},"sku":{"type":"string"},"unitOfMeasure":{"type":"string"},"costPerUnit":{"type":"number"},"currency":{"type":"string"},"markupPercent":{"type":"number"},"isActive":{"type":"boolean"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","listId","isActive","createdAt","updatedAt"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Products"],"summary":"Create a product","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"listId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex product list ID"},"name":{"type":"string","minLength":1,"maxLength":200},"sku":{"type":"string","maxLength":100},"unitOfMeasure":{"type":"string","maxLength":50},"costPerUnit":{"type":"number","minimum":0},"currency":{"type":"string","enum":["USD","CAD","MXN","BRL","ARS","CLP","COP","PEN","UYU","EUR","GBP","CHF","NOK","SEK","DKK","PLN","CZK","HUF","RON","BGN","HRK","RSD","UAH","RUB","TRY","ISK","ILS","AED","SAR","QAR","KWD","BHD","OMR","JOD","LBP","EGP","ZAR","NGN","KES","GHS","MAD","TND","DZD","JPY","CNY","HKD","TWD","KRW","SGD","INR","PKR","BDT","LKR","NPR","IDR","MYR","PHP","THB","VND","MMK","AUD","NZD"],"description":"ISO 4217 currency code"},"markupPercent":{"type":"number","minimum":0},"customProperties":{"type":"object","additionalProperties":{"nullable":true}},"position":{"type":"integer","minimum":0}},"required":["organizationId","listId"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}}},"/v1/products/search":{"get":{"tags":["Products"],"summary":"Full-text search products","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"string","minLength":1},"required":true,"name":"query","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"listId":{"type":"string"},"name":{"type":"string"},"sku":{"type":"string"},"unitOfMeasure":{"type":"string"},"costPerUnit":{"type":"number"},"currency":{"type":"string"},"markupPercent":{"type":"number"},"isActive":{"type":"boolean"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","listId","isActive","createdAt","updatedAt"],"additionalProperties":{"nullable":true}}}}}}}}},"/v1/products/batch":{"post":{"tags":["Products"],"summary":"Batch-create products","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"listId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex product list ID"},"products":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"sku":{"type":"string","maxLength":100},"unitOfMeasure":{"type":"string","maxLength":50},"costPerUnit":{"type":"number","minimum":0},"currency":{"type":"string","enum":["USD","CAD","MXN","BRL","ARS","CLP","COP","PEN","UYU","EUR","GBP","CHF","NOK","SEK","DKK","PLN","CZK","HUF","RON","BGN","HRK","RSD","UAH","RUB","TRY","ISK","ILS","AED","SAR","QAR","KWD","BHD","OMR","JOD","LBP","EGP","ZAR","NGN","KES","GHS","MAD","TND","DZD","JPY","CNY","HKD","TWD","KRW","SGD","INR","PKR","BDT","LKR","NPR","IDR","MYR","PHP","THB","VND","MMK","AUD","NZD"],"description":"ISO 4217 currency code"},"markupPercent":{"type":"number","minimum":0},"customProperties":{"type":"object","additionalProperties":{"nullable":true}}}},"minItems":1,"maxItems":500}},"required":["organizationId","listId","products"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"}}},"required":["ids"]}}}}}}},"/v1/products/{id}":{"get":{"tags":["Products"],"summary":"Get a single product","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"listId":{"type":"string"},"name":{"type":"string"},"sku":{"type":"string"},"unitOfMeasure":{"type":"string"},"costPerUnit":{"type":"number"},"currency":{"type":"string"},"markupPercent":{"type":"number"},"isActive":{"type":"boolean"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","listId","isActive","createdAt","updatedAt"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"patch":{"tags":["Products"],"summary":"Update a product","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"sku":{"type":"string","maxLength":100},"unitOfMeasure":{"type":"string","maxLength":50},"costPerUnit":{"type":"number","minimum":0},"currency":{"type":"string","enum":["USD","CAD","MXN","BRL","ARS","CLP","COP","PEN","UYU","EUR","GBP","CHF","NOK","SEK","DKK","PLN","CZK","HUF","RON","BGN","HRK","RSD","UAH","RUB","TRY","ISK","ILS","AED","SAR","QAR","KWD","BHD","OMR","JOD","LBP","EGP","ZAR","NGN","KES","GHS","MAD","TND","DZD","JPY","CNY","HKD","TWD","KRW","SGD","INR","PKR","BDT","LKR","NPR","IDR","MYR","PHP","THB","VND","MMK","AUD","NZD"],"description":"ISO 4217 currency code"},"markupPercent":{"type":"number","minimum":0},"customProperties":{"type":"object","additionalProperties":{"nullable":true}}},"required":["organizationId"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}},"delete":{"tags":["Products"],"summary":"Archive (soft-delete) a product","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"204":{"description":"Archived"}}}},"/v1/lists/{id}/products":{"get":{"tags":["Products"],"summary":"List products in a list","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"listId":{"type":"string"},"name":{"type":"string"},"sku":{"type":"string"},"unitOfMeasure":{"type":"string"},"costPerUnit":{"type":"number"},"currency":{"type":"string"},"markupPercent":{"type":"number"},"isActive":{"type":"boolean"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","listId","isActive","createdAt","updatedAt"],"additionalProperties":{"nullable":true}}}}}}}}},"/v1/vendors":{"get":{"tags":["Vendors"],"summary":"List vendors in an organization","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"string","enum":["supplier","subcontractor","rental"]},"required":false,"name":"type","in":"query"},{"schema":{"type":"boolean","nullable":true},"required":false,"name":"preferredOnly","in":"query"},{"schema":{"type":"string"},"required":false,"name":"search","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["supplier","subcontractor","rental"]},"isActive":{"type":"boolean"},"isPreferred":{"type":"boolean"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","name","type","isActive"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Vendors"],"summary":"Create a vendor","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"type":{"type":"string","enum":["supplier","subcontractor","rental"]},"contactName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"website":{"type":"string"},"address":{"type":"object","properties":{"street":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zipCode":{"type":"string"},"country":{"type":"string"}},"required":["street","city","state","zipCode","country"]},"paymentTerms":{"type":"string"},"accountNumber":{"type":"string"},"notes":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"isPreferred":{"type":"boolean"}},"required":["organizationId","name","type"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}}},"/v1/vendors/search":{"get":{"tags":["Vendors"],"summary":"Full-text search vendors","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"string","minLength":1},"required":true,"name":"query","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["supplier","subcontractor","rental"]},"isActive":{"type":"boolean"},"isPreferred":{"type":"boolean"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","name","type","isActive"],"additionalProperties":{"nullable":true}}}}}}}}},"/v1/vendors/{id}":{"get":{"tags":["Vendors"],"summary":"Get a single vendor","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["supplier","subcontractor","rental"]},"isActive":{"type":"boolean"},"isPreferred":{"type":"boolean"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","name","type","isActive"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"patch":{"tags":["Vendors"],"summary":"Update a vendor","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"type":{"type":"string","enum":["supplier","subcontractor","rental"]},"contactName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"website":{"type":"string"},"address":{"type":"object","properties":{"street":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zipCode":{"type":"string"},"country":{"type":"string"}},"required":["street","city","state","zipCode","country"]},"paymentTerms":{"type":"string"},"accountNumber":{"type":"string"},"rating":{"type":"number","minimum":0,"maximum":5},"notes":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"isPreferred":{"type":"boolean"}},"required":["organizationId"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}},"delete":{"tags":["Vendors"],"summary":"Archive (soft-delete) a vendor","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"204":{"description":"Archived"}}}},"/v1/products/{id}/prices":{"get":{"tags":["Vendor prices"],"summary":"List vendor prices for a product","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"vendorId":{"type":"string"},"productId":{"type":"string"},"pricePerUnit":{"type":"number"},"currency":{"type":"string"},"minOrderQuantity":{"type":"number"},"leadTimeDays":{"type":"number"},"expirationDate":{"type":"number"},"notes":{"type":"string"}},"required":["_id","_creationTime","organizationId","vendorId","productId","pricePerUnit"],"additionalProperties":{"nullable":true}}}}}}}}},"/v1/products/{id}/best-price":{"get":{"tags":["Vendor prices"],"summary":"Best vendor price for a product","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"number","minimum":0,"exclusiveMinimum":true},"required":false,"name":"quantity","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","nullable":true,"properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"vendorId":{"type":"string"},"productId":{"type":"string"},"pricePerUnit":{"type":"number"},"currency":{"type":"string"},"minOrderQuantity":{"type":"number"},"leadTimeDays":{"type":"number"},"expirationDate":{"type":"number"},"notes":{"type":"string"}},"required":["_id","_creationTime","organizationId","vendorId","productId","pricePerUnit"],"additionalProperties":{"nullable":true}}}}}}}},"/v1/products/{productId}/prices/{vendorId}":{"put":{"tags":["Vendor prices"],"summary":"Create or update a vendor price","parameters":[{"schema":{"type":"string"},"required":true,"name":"productId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"vendorId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"pricePerUnit":{"type":"number","nullable":true,"minimum":0},"minOrderQuantity":{"type":"number","nullable":true,"minimum":0},"volumeDiscounts":{"type":"array","items":{"type":"object","properties":{"minQuantity":{"type":"number","minimum":0,"exclusiveMinimum":true},"pricePerUnit":{"type":"number","nullable":true,"minimum":0}},"required":["minQuantity","pricePerUnit"]}},"leadTimeDays":{"type":"integer","nullable":true,"minimum":0},"expirationDate":{"type":"number","nullable":true},"notes":{"type":"string"}},"required":["organizationId","pricePerUnit"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}},"delete":{"tags":["Vendor prices"],"summary":"Remove a vendor price","parameters":[{"schema":{"type":"string"},"required":true,"name":"productId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"vendorId","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"204":{"description":"Removed"}}}},"/v1/projects/{id}/documents":{"get":{"tags":["Documents"],"summary":"List documents in a project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId"],"additionalProperties":{"nullable":true}}}}}}}}},"/v1/documents/{id}":{"get":{"tags":["Documents"],"summary":"Get a single document","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/projects/{id}/spreadsheets":{"get":{"tags":["Spreadsheets"],"summary":"List spreadsheets in a project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"unitId":{"type":"string"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId"],"additionalProperties":{"nullable":true}}}}}}}}},"/v1/spreadsheets/{id}":{"get":{"tags":["Spreadsheets"],"summary":"Get a single spreadsheet","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"unitId":{"type":"string"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/files":{"get":{"tags":["Files"],"summary":"List files in a project","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"query"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"projectId":{"type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"},"fileSize":{"type":"number"},"uploadStatus":{"type":"string"},"r2Key":{"type":"string"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Files"],"summary":"Start a file upload — returns a presigned R2 URL","description":"Two-step upload: (1) POST /v1/files creates a pending file record and returns a presigned R2 upload URL; (2) client PUTs file bytes to that URL; (3) POST /v1/files/{id}/confirm finalizes the record so the file becomes visible.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex project ID"},"filename":{"type":"string","minLength":1,"maxLength":500},"mimeType":{"type":"string","minLength":1},"fileSize":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":524288000,"description":"File size in bytes (max 500 MB)"},"folderId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex folder ID"},"dimensions":{"type":"object","properties":{"width":{"type":"number","nullable":true},"height":{"type":"number","nullable":true}},"required":["width","height"]}},"required":["projectId","filename","mimeType","fileSize"]}}}},"responses":{"200":{"description":"Presigned","content":{"application/json":{"schema":{"type":"object","properties":{"fileId":{"type":"string"},"uploadUrl":{"type":"string"},"r2Key":{"type":"string"},"expiresAt":{"type":"number"},"filename":{"type":"string"}},"required":["fileId","uploadUrl","r2Key","expiresAt","filename"]}}}}}}},"/v1/files/{id}":{"get":{"tags":["Files"],"summary":"Get a file with its pages","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"projectId":{"type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"},"fileSize":{"type":"number"},"uploadStatus":{"type":"string"},"r2Key":{"type":"string"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"patch":{"tags":["Files"],"summary":"Rename or move a file","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"filename":{"type":"string","minLength":1,"maxLength":255},"folderId":{"type":"string","nullable":true,"pattern":"^[a-z0-9]{32}$","description":"Convex folder ID"}}}}}},"responses":{"204":{"description":"Updated"}}},"delete":{"tags":["Files"],"summary":"Soft-delete a file","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"}}}},"/v1/files/{id}/url":{"get":{"tags":["Files"],"summary":"Get a presigned download URL for a file","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","nullable":true}},"required":["url"]}}}}}}},"/v1/files/{id}/confirm":{"post":{"tags":["Files"],"summary":"Confirm a file upload after the client PUT succeeds","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"r2Key":{"type":"string","minLength":1}},"required":["r2Key"]}}}},"responses":{"204":{"description":"Confirmed"}}}},"/v1/folders":{"get":{"tags":["Folders"],"summary":"List folders in a project","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex project ID"},"required":true,"description":"Convex project ID","name":"projectId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"parentId":{"type":"string","nullable":true},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","projectId","name"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Folders"],"summary":"Create a folder","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex project ID"},"name":{"type":"string","minLength":1,"maxLength":200},"parentId":{"type":"string","nullable":true,"pattern":"^[a-z0-9]{32}$","description":"Convex folder ID"}},"required":["projectId","name","parentId"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}}},"/v1/folders/contents":{"get":{"tags":["Folders"],"summary":"List files and folders inside a folder","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex project ID"},"required":true,"description":"Convex project ID","name":"projectId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"parentId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"nullable":true}}}}}}},"/v1/folders/{id}":{"get":{"tags":["Folders"],"summary":"Get a folder by ID","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"parentId":{"type":"string","nullable":true},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","projectId","name"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"patch":{"tags":["Folders"],"summary":"Rename or move a folder","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"parentId":{"type":"string","nullable":true,"pattern":"^[a-z0-9]{32}$","description":"Convex folder ID"}}}}}},"responses":{"204":{"description":"Updated"}}},"delete":{"tags":["Folders"],"summary":"Delete a folder","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"}}}},"/v1/projects/{id}/layers":{"get":{"tags":["Takeoff"],"summary":"List takeoff layers in a project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"projectId":{"type":"string"},"name":{"type":"string"},"isDefault":{"type":"boolean"},"position":{"type":"number"}},"required":["_id","_creationTime","projectId","name"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Takeoff"],"summary":"Create a takeoff layer","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200}},"required":["name"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}}},"/v1/layers/{id}":{"patch":{"tags":["Takeoff"],"summary":"Rename a takeoff layer","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex project ID"},"name":{"type":"string","minLength":1,"maxLength":200}},"required":["projectId","name"]}}}},"responses":{"204":{"description":"Updated"}}},"delete":{"tags":["Takeoff"],"summary":"Delete a takeoff layer","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"projectId","in":"query"}],"responses":{"204":{"description":"Deleted"}}}},"/v1/projects/{id}/groups":{"get":{"tags":["Takeoff"],"summary":"List takeoff groups in a project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"projectId":{"type":"string"},"name":{"type":"string"},"parentId":{"type":"string","nullable":true},"position":{"type":"number"}},"required":["_id","_creationTime","projectId","name"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Takeoff"],"summary":"Create a takeoff group","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"parentId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex takeoff group ID"}},"required":["name"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}}},"/v1/groups/{id}":{"patch":{"tags":["Takeoff"],"summary":"Update a takeoff group","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex project ID"},"name":{"type":"string","minLength":1,"maxLength":200},"position":{"type":"number"},"parentId":{"type":"string","nullable":true,"pattern":"^[a-z0-9]{32}$","description":"Convex takeoff group ID"}},"required":["projectId"]}}}},"responses":{"204":{"description":"Updated"}}},"delete":{"tags":["Takeoff"],"summary":"Delete a takeoff group","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"projectId","in":"query"}],"responses":{"204":{"description":"Deleted"}}}},"/v1/projects/{id}/symbols":{"get":{"operationId":"listSymbols","tags":["Takeoff"],"summary":"List takeoff symbols in a project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","enum":["count","linear","area"]},"required":false,"name":"type","in":"query"},{"schema":{"type":"string","enum":["ai","manual"]},"required":false,"name":"source","in":"query"},{"schema":{"type":"string"},"required":false,"name":"category","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"projectId":{"type":"string"},"organizationId":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["count","linear","area"]},"color":{"type":"string"},"category":{"type":"string"}},"required":["_id","_creationTime","projectId","name","type"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Takeoff"],"summary":"Create a takeoff symbol","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"isTemplate":{"type":"boolean"},"listId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex product list ID"},"name":{"type":"string","minLength":1,"maxLength":200},"type":{"type":"string","enum":["count","linear","area"]},"color":{"type":"string"},"category":{"type":"string"},"subcategory":{"type":"string"},"groupId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex takeoff group ID"},"customProperties":{"type":"object","additionalProperties":{"nullable":true}}},"required":["name","type","color"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}}},"/v1/symbols/{id}":{"get":{"tags":["Takeoff"],"summary":"Get a takeoff symbol","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"projectId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"projectId":{"type":"string"},"organizationId":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["count","linear","area"]},"color":{"type":"string"},"category":{"type":"string"}},"required":["_id","_creationTime","projectId","name","type"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"patch":{"tags":["Takeoff"],"summary":"Update a takeoff symbol","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex project ID"},"name":{"type":"string","minLength":1,"maxLength":200},"color":{"type":"string"},"type":{"type":"string","enum":["count","linear","area"]},"category":{"type":"string"},"subcategory":{"type":"string"},"customProperties":{"type":"object","additionalProperties":{"nullable":true}}},"required":["projectId"]}}}},"responses":{"204":{"description":"Updated"}}},"delete":{"tags":["Takeoff"],"summary":"Delete a takeoff symbol","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"projectId","in":"query"}],"responses":{"204":{"description":"Deleted"}}}},"/v1/symbols/{id}/line-items":{"post":{"tags":["Takeoff"],"summary":"Add a line item to a symbol","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex project ID"},"lineItem":{"type":"object","additionalProperties":{"nullable":true}}},"required":["projectId","lineItem"]}}}},"responses":{"200":{"description":"Added","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}},"get":{"tags":["Takeoff"],"summary":"List all line items on a takeoff symbol","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"projectId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"nullable":true}}}}}}}},"/v1/symbols/{symbolId}/line-items/{id}":{"patch":{"tags":["Takeoff"],"summary":"Update a line item on a symbol","parameters":[{"schema":{"type":"string"},"required":true,"name":"symbolId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex project ID"},"patch":{"type":"object","additionalProperties":{"nullable":true}}},"required":["projectId","patch"]}}}},"responses":{"204":{"description":"Updated"}}},"delete":{"tags":["Takeoff"],"summary":"Remove a line item from a symbol","parameters":[{"schema":{"type":"string"},"required":true,"name":"symbolId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"projectId","in":"query"}],"responses":{"204":{"description":"Deleted"}}},"get":{"tags":["Takeoff"],"summary":"Get a single line item on a symbol","parameters":[{"schema":{"type":"string"},"required":true,"name":"symbolId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"projectId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"nullable":true}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/pages/{id}/measurements":{"get":{"tags":["Takeoff"],"summary":"List measurements on a page","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"projectId":{"type":"string"},"pageId":{"type":"string"},"symbolId":{"type":"string"},"shapeId":{"type":"string"},"value":{"type":"number"},"manualValue":{"type":"number","nullable":true}},"required":["_id","_creationTime","projectId","pageId","symbolId","shapeId"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Takeoff"],"summary":"Create a measurement on a page","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"symbolId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex takeoff symbol ID"},"shapeId":{"type":"string","minLength":1,"description":"Canvas shape ID"},"value":{"type":"number"},"geometry":{"type":"object","additionalProperties":{"nullable":true}},"notes":{"type":"string","maxLength":2000},"layerId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex takeoff layer ID"}},"required":["symbolId","shapeId","value"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}}},"/v1/symbols/{id}/measurements":{"get":{"tags":["Takeoff"],"summary":"List measurements for a symbol","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"projectId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"projectId":{"type":"string"},"pageId":{"type":"string"},"symbolId":{"type":"string"},"shapeId":{"type":"string"},"value":{"type":"number"},"manualValue":{"type":"number","nullable":true}},"required":["_id","_creationTime","projectId","pageId","symbolId","shapeId"],"additionalProperties":{"nullable":true}}}}}}}}},"/v1/pages/{pageId}/measurements/{shapeId}":{"get":{"tags":["Takeoff"],"summary":"Get a measurement by shape ID","parameters":[{"schema":{"type":"string"},"required":true,"name":"pageId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"shapeId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"projectId":{"type":"string"},"pageId":{"type":"string"},"symbolId":{"type":"string"},"shapeId":{"type":"string"},"value":{"type":"number"},"manualValue":{"type":"number","nullable":true}},"required":["_id","_creationTime","projectId","pageId","symbolId","shapeId"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"delete":{"tags":["Takeoff"],"summary":"Delete a measurement by shape ID","parameters":[{"schema":{"type":"string"},"required":true,"name":"pageId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"shapeId","in":"path"}],"responses":{"204":{"description":"Deleted"}}}},"/v1/measurements/{id}":{"patch":{"tags":["Takeoff"],"summary":"Update a measurement","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex project ID"},"value":{"type":"number"},"manualValue":{"type":"number","nullable":true},"geometry":{"type":"object","additionalProperties":{"nullable":true}},"notes":{"type":"string","maxLength":2000},"name":{"type":"string","maxLength":200},"layerId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex takeoff layer ID"}},"required":["projectId"]}}}},"responses":{"204":{"description":"Updated"}}}},"/v1/projects/{id}/assessments":{"get":{"tags":["Takeoff"],"summary":"List assessments for a project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"projectId":{"type":"string"},"status":{"type":"string"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","projectId"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"operationId":"createAssessment","tags":["Takeoff"],"summary":"Start a new AI assessment","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"conversationId":{"type":"string"},"fileIds":{"type":"array","items":{"type":"string"}},"pageIds":{"type":"array","items":{"type":"string"}},"imageUrls":{"type":"array","items":{"type":"string","format":"uri"}},"types":{"type":"array","items":{"type":"string","enum":["area","linear","count"]}}},"required":["organizationId"]}}}},"responses":{"200":{"description":"Started","content":{"application/json":{"schema":{"nullable":true}}}}}}},"/v1/projects/{id}/assessments/latest":{"get":{"tags":["Takeoff"],"summary":"Get the most recent assessment with elements","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","nullable":true,"properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"projectId":{"type":"string"},"status":{"type":"string"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","projectId"],"additionalProperties":{"nullable":true}}}}}}}},"/v1/assessments/{id}":{"get":{"operationId":"getAssessment","tags":["Takeoff"],"summary":"Get an assessment by ID","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"projectId":{"type":"string"},"status":{"type":"string"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId","projectId"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/assessments/{id}/approve":{"post":{"operationId":"approveAssessment","tags":["Takeoff"],"summary":"Approve detected elements on an assessment","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"approvedElementIds":{"type":"array","items":{"type":"string"}}},"required":["approvedElementIds"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"nullable":true}}}}}}},"/v1/assessments/{id}/cancel":{"post":{"tags":["Takeoff"],"summary":"Cancel a running assessment","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."}},"required":["organizationId"]}}}},"responses":{"204":{"description":"Canceled"}}}},"/v1/projects/{id}/analysis/propose":{"post":{"tags":["Takeoff"],"summary":"Propose an AI-generated analysis from a natural-language prompt","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"prompt":{"type":"string","minLength":1,"description":"Natural-language description of what to measure"},"pageIds":{"type":"array","items":{"type":"string"},"description":"Page IDs to propose against. Defaults to the project's first page."},"fileIds":{"type":"array","items":{"type":"string"},"description":"File IDs to scope the proposal to. When set, only pages belonging to these files are considered — pass the IDs from the [Attached files: ...] note in the user's message so a fresh upload doesn't pull in older project files. Wins over pageIds."}},"required":["organizationId","prompt"]}}}},"responses":{"200":{"description":"Proposal with detected elements and credit estimate","content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string"},"pageIds":{"type":"array","items":{"type":"string"}},"fileIds":{"type":"array","items":{"type":"string"}},"elements":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"category":{"type":"string","enum":["area","linear","count"]},"hexColor":{"type":"string"}},"required":["id","name","category","hexColor"]}},"creditEstimate":{"type":"number"},"prompt":{"type":"string"}},"required":["projectId","pageIds","elements","creditEstimate","prompt"]}}}}}}},"/v1/projects/{id}/analysis/run":{"post":{"tags":["Takeoff"],"summary":"Run an approved analysis (kicks off a background AI task)","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"pageIds":{"type":"array","items":{"type":"string"},"minItems":1},"elements":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"category":{"type":"string","enum":["area","linear","count"]},"hexColor":{"type":"string"}},"required":["id","name","category","hexColor"]},"minItems":1},"layerName":{"type":"string"}},"required":["organizationId","pageIds","elements"]}}}},"responses":{"200":{"description":"Assessment started; poll GET /v1/assessments/{id} for progress","content":{"application/json":{"schema":{"type":"object","properties":{"_uiType":{"type":"string","enum":["analysisRunning"]},"assessmentId":{"type":"string"},"pageIds":{"type":"array","items":{"type":"string"}}},"required":["assessmentId","pageIds"]}}}}}}},"/v1/projects/{id}/files/search":{"get":{"tags":["Files"],"summary":"Search pages in a project by name or indexed content","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"query","in":"query"}],"responses":{"200":{"description":"Matched pages","content":{"application/json":{"schema":{"type":"object","properties":{"pages":{"type":"array","items":{"type":"object","properties":{"pageId":{"type":"string"},"name":{"type":"string"},"sheetCode":{"type":"string"},"snippet":{"type":"string"}},"required":["pageId","name"]}},"count":{"type":"number"}},"required":["pages","count"]}}}}}}},"/v1/pages/{id}/elements/find":{"post":{"tags":["Takeoff"],"summary":"Detect instances of an element on a page via Claude Vision","description":"Returns bounding boxes and measurement shape specs in page-pixel coordinates. Does not write to the realtime canvas — callers persist detections themselves.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"projectId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex project ID"},"elementDescription":{"type":"string","minLength":1,"description":"Natural-language description of what to find (e.g. \"electrical outlets\", \"doors\")"},"measurementType":{"type":"string","enum":["count","linear","area"],"description":"How detections should be shaped (count marker / linear line / area rectangle)"},"persist":{"type":"boolean","description":"When true, writes the detected shapes to the realtime canvas via the sync-worker. Returns persistedShapeIds on success."}},"required":["organizationId","projectId","elementDescription","measurementType"]}}}},"responses":{"200":{"description":"Detected elements","content":{"application/json":{"schema":{"type":"object","properties":{"found":{"type":"boolean"},"elementCount":{"type":"number"},"summary":{"type":"string"},"elements":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"confidence":{"type":"string","enum":["high","medium","low"]},"boundingBox":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"}},"required":["x","y","width","height"]},"shapeSpec":{"nullable":true}},"required":["label","confidence","boundingBox"]}},"pageId":{"type":"string"},"pageName":{"type":"string"},"measurementType":{"type":"string","enum":["count","linear","area"]},"persistedShapeIds":{"type":"array","items":{"type":"string"}},"persistError":{"type":"string"}},"required":["found","elementCount","summary","elements","pageId","measurementType"]}}}}}}},"/v1/projects/{id}/estimates/generate":{"post":{"tags":["Estimates"],"summary":"Stream an AI-generated cost estimate","description":"Streams the estimator sub-agent output as an AI SDK UIMessageStream over text/event-stream. The stream emits text-delta, reasoning-delta, source-document, and source-url events. Callers are responsible for persisting the result if desired.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"query":{"type":"string","minLength":1,"description":"Natural-language prompt describing the scope of the estimate"},"notes":{"type":"string","description":"Additional notes appended to the prompt"},"measurementContext":{"type":"string","description":"Pre-serialized takeoff data to ground the estimator (see GET /v1/projects/{id}/takeoff-summary)"}},"required":["organizationId","query"]}}}},"responses":{"200":{"description":"SSE stream of UIMessageStream parts","content":{"text/event-stream":{"schema":{"type":"string"}}}},"402":{"description":"Insufficient credits","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/projects/{id}/bids":{"post":{"operationId":"createBid","tags":["Estimates"],"summary":"Generate a project-scoped bid document (blocking)","description":"Wraps the estimator with bid-formatting instructions and persists the result as a project-scoped document (templateType: bid). Callers provide pre-serialized takeoff data as measurementContext — fetch symbols via GET /v1/projects/{id}/symbols and format as needed. Requests may take 30–60s.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"notes":{"type":"string","description":"Additional context appended to the prompt"},"measurementContext":{"type":"string","description":"Pre-serialized takeoff measurements + line items (markdown). If omitted, the endpoint auto-loads the project takeoff from Convex and serializes it server-side."},"ignoreMissingVariables":{"type":"boolean","description":"When auto-loading takeoff data, skip line items with missing formula variables instead of failing with 422. Ignored if measurementContext is provided."}},"required":["organizationId"]}}}},"responses":{"200":{"description":"Bid document","content":{"application/json":{"schema":{"type":"object","properties":{"documentId":{"type":"string"},"documentUrl":{"type":"string"},"text":{"type":"string"},"html":{"type":"string"},"sourceFiles":{"type":"array","items":{"type":"string"}},"warnings":{"type":"array","items":{"type":"object","properties":{"symbolName":{"type":"string"},"symbolType":{"type":"string","enum":["count","linear","area"]},"symbolColor":{"type":"string"},"lineItemName":{"type":"string"},"lineItemIndex":{"type":"number"},"missingFields":{"type":"array","items":{"type":"string"}}},"required":["symbolName","symbolType","symbolColor","lineItemName","lineItemIndex","missingFields"]}}},"required":["documentId","text","html","sourceFiles"]}}}},"402":{"description":"Insufficient credits","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}},"422":{"description":"Takeoff has line items with missing formula variables. Retry with ignoreMissingVariables: true to proceed.","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/projects/{id}/estimates":{"post":{"tags":["Estimates"],"summary":"Generate an estimate and persist it as a document (blocking)","description":"Runs the estimator, waits for the full transcript, saves it as a document with a share link, and returns the result as JSON. Use this when you want the final text without consuming the SSE stream. Note: requests may take 30–60s.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"query":{"type":"string","minLength":1,"description":"Natural-language prompt describing the scope of the estimate"},"notes":{"type":"string","description":"Additional notes appended to the prompt"},"measurementContext":{"type":"string","description":"Pre-serialized takeoff data to ground the estimator (see GET /v1/projects/{id}/takeoff-summary)"}},"required":["organizationId","query"]}}}},"responses":{"200":{"description":"Estimate document","content":{"application/json":{"schema":{"type":"object","properties":{"documentId":{"type":"string"},"documentUrl":{"type":"string"},"text":{"type":"string"},"html":{"type":"string"},"sourceFiles":{"type":"array","items":{"type":"string"}}},"required":["documentId","text","html","sourceFiles"]}}}},"402":{"description":"Insufficient credits","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/conversations":{"get":{"tags":["Conversations"],"summary":"List conversations for the caller","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"string","enum":["ai_chat","project_activity","whatsapp_chat"]},"required":false,"name":"type","in":"query"},{"schema":{"type":"string","enum":["app","email","whatsapp"]},"required":false,"name":"channel","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"number","nullable":true},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"type":{"type":"string","enum":["ai_chat","project_activity","whatsapp_chat"]},"channel":{"type":"string","enum":["app","email","whatsapp"]},"title":{"type":"string"},"projectId":{"type":"string","nullable":true},"lastMessageAt":{"type":"number"},"createdAt":{"type":"number"}},"required":["_id","_creationTime","organizationId"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Conversations"],"summary":"Create a conversation","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"projectId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex project ID"},"title":{"type":"string","maxLength":200},"type":{"type":"string","enum":["ai_chat","project_activity"]},"model":{"type":"string"},"visibility":{"type":"string","enum":["private","shared"]}},"required":["organizationId"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}}},"/v1/projects/{id}/conversations":{"get":{"tags":["Conversations"],"summary":"List conversations in a project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"string","enum":["ai_chat","project_activity","widget_chat"]},"required":false,"name":"type","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"type":{"type":"string","enum":["ai_chat","project_activity","whatsapp_chat"]},"channel":{"type":"string","enum":["app","email","whatsapp"]},"title":{"type":"string"},"projectId":{"type":"string","nullable":true},"lastMessageAt":{"type":"number"},"createdAt":{"type":"number"}},"required":["_id","_creationTime","organizationId"],"additionalProperties":{"nullable":true}}}}}}}}},"/v1/conversations/{id}":{"get":{"tags":["Conversations"],"summary":"Get a conversation by ID","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"type":{"type":"string","enum":["ai_chat","project_activity","whatsapp_chat"]},"channel":{"type":"string","enum":["app","email","whatsapp"]},"title":{"type":"string"},"projectId":{"type":"string","nullable":true},"lastMessageAt":{"type":"number"},"createdAt":{"type":"number"}},"required":["_id","_creationTime","organizationId"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"patch":{"tags":["Conversations"],"summary":"Update conversation title or linked project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"title":{"type":"string","maxLength":200},"projectId":{"type":"string","nullable":true,"pattern":"^[a-z0-9]{32}$","description":"Convex project ID"}},"required":["organizationId"]}}}},"responses":{"204":{"description":"Updated"}}},"delete":{"tags":["Conversations"],"summary":"Archive a conversation","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"204":{"description":"Archived"}}}},"/v1/contacts":{"get":{"tags":["Contacts"],"summary":"List contacts captured by widgets","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"widgetId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"search","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"widgetId":{"type":"string"},"email":{"type":"string"},"name":{"type":"string"},"phone":{"type":"string"},"avatarUrl":{"type":"string"},"attributes":{"type":"object","additionalProperties":{"type":"string"}},"source":{"type":"string","enum":["widget","manual","api"]},"firstSeenAt":{"type":"number"},"lastSeenAt":{"type":"number"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId"],"additionalProperties":{"nullable":true}}}}}}}}},"/v1/contacts/{id}":{"get":{"tags":["Contacts"],"summary":"Get a contact by ID","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"widgetId":{"type":"string"},"email":{"type":"string"},"name":{"type":"string"},"phone":{"type":"string"},"avatarUrl":{"type":"string"},"attributes":{"type":"object","additionalProperties":{"type":"string"}},"source":{"type":"string","enum":["widget","manual","api"]},"firstSeenAt":{"type":"number"},"lastSeenAt":{"type":"number"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","_creationTime","organizationId"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"patch":{"tags":["Contacts"],"summary":"Update a contact’s details or CRM attributes","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","maxLength":200},"email":{"type":"string","maxLength":320,"format":"email"},"phone":{"type":"string","maxLength":40},"attributes":{"type":"object","additionalProperties":{"type":"string"}}},"required":["organizationId"]}}}},"responses":{"204":{"description":"Updated"}}}},"/v1/widgets/{id}/conversations":{"get":{"tags":["Conversations"],"summary":"List a widget’s inbox conversations","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"string","enum":["bot","open","snoozed","closed"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"search","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"title":{"type":"string"},"status":{"type":"string","enum":["bot","open","snoozed","closed"]},"assigneeId":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"widgetId":{"type":"string"},"contact":{"type":"object","nullable":true,"properties":{"name":{"type":"string"},"email":{"type":"string"}}},"lastMessageAt":{"type":"number"},"unread":{"type":"boolean"},"createdAt":{"type":"number"}},"required":["_id","status","tags","contact","lastMessageAt","unread","createdAt"],"additionalProperties":{"nullable":true}}}}}}}}},"/v1/projects/{id}/messages":{"get":{"tags":["Messages"],"summary":"List project activity messages","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"pageId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"}},"required":["_id"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Messages"],"summary":"Post a message to a project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string","minLength":1},"parentMessageId":{"type":"string","pattern":"^[a-z0-9]{32}$","description":"Convex chat message ID"},"pageId":{"type":"string"},"location":{"type":"object","properties":{"x":{"type":"number"},"y":{"type":"number"}},"required":["x","y"]},"mentions":{"type":"array","items":{"type":"object","additionalProperties":{"nullable":true}}}},"required":["content"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"nullable":true}}}}}}},"/v1/messages/{id}":{"patch":{"tags":["Messages"],"summary":"Update a message","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string","minLength":1}},"required":["content"]}}}},"responses":{"204":{"description":"Updated"}}},"delete":{"tags":["Messages"],"summary":"Delete a message","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted"}}}},"/v1/widgets":{"get":{"tags":["Widgets"],"summary":"List widgets in an organization","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"isActive":{"type":"boolean"}},"required":["_id","_creationTime","organizationId","name"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Widgets"],"summary":"Create a widget","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"config":{"type":"object","additionalProperties":{"nullable":true}}},"required":["organizationId","name"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}}},"/v1/widgets/{id}":{"get":{"tags":["Widgets"],"summary":"Get a widget","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"isActive":{"type":"boolean"}},"required":["_id","_creationTime","organizationId","name"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"patch":{"tags":["Widgets"],"summary":"Update a widget","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"isActive":{"type":"boolean"},"config":{"type":"object","additionalProperties":{"nullable":true}}},"required":["organizationId"]}}}},"responses":{"204":{"description":"Updated"}}},"delete":{"tags":["Widgets"],"summary":"Delete a widget","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"204":{"description":"Deleted"}}}},"/v1/credits/balance":{"get":{"tags":["Credits"],"summary":"Get credit balance for an organization","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"nullable":true}}}}}}},"/v1/credits/usage":{"get":{"tags":["Credits"],"summary":"Get credit usage history","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500},"required":false,"name":"limit","in":"query"},{"schema":{"type":"number","nullable":true},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"number","nullable":true},"required":false,"name":"dateFrom","in":"query"},{"schema":{"type":"number","nullable":true},"required":false,"name":"dateTo","in":"query"},{"schema":{"type":"string","enum":["issuance","consumption"]},"required":false,"name":"type","in":"query"},{"schema":{"type":"string","enum":["monthly","gifted","purchased"]},"required":false,"name":"kind","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"nullable":true}}}}}}},"/v1/credits/stats":{"get":{"tags":["Credits"],"summary":"Get credit usage stats","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"number","nullable":true},"required":false,"name":"dateFrom","in":"query"},{"schema":{"type":"number","nullable":true},"required":false,"name":"dateTo","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"nullable":true}}}}}}},"/v1/notifications":{"get":{"tags":["Notifications"],"summary":"List notifications for the caller","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"nullable":true}}}}}}},"/v1/notifications/unread-count":{"get":{"tags":["Notifications"],"summary":"Get unread notification count","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"number"}},"required":["count"]}}}}}}},"/v1/notifications/{id}/read":{"post":{"tags":["Notifications"],"summary":"Mark a notification as read","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Updated"}}}},"/v1/notifications/mark-all-read":{"post":{"tags":["Notifications"],"summary":"Mark all notifications as read","responses":{"204":{"description":"Updated"}}}},"/v1/custom-properties":{"get":{"tags":["Custom properties"],"summary":"List custom properties in an organization","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"string","enum":["project","countTakeoff","linearTakeoff","areaTakeoff","product"]},"required":false,"name":"recordType","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["text","textarea","number","date","checkbox","multiCheckbox","select","url","email","phone","currency","percentage"]},"recordTypes":{"type":"array","items":{"type":"string","enum":["project","countTakeoff","linearTakeoff","areaTakeoff","product"]}},"options":{"type":"array","items":{"type":"string"}},"position":{"type":"number"},"isActive":{"type":"boolean"}},"required":["_id","_creationTime","organizationId","name","type","recordTypes"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Custom properties"],"summary":"Create a custom property","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"type":{"type":"string","enum":["text","textarea","number","date","checkbox","multiCheckbox","select","url","email","phone","currency","percentage"]},"recordTypes":{"type":"array","items":{"type":"string","enum":["project","countTakeoff","linearTakeoff","areaTakeoff","product"]},"minItems":1},"options":{"type":"array","items":{"type":"string"}},"presetId":{"type":"string"}},"required":["organizationId","name","type","recordTypes"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}}},"/v1/custom-properties/{id}":{"get":{"tags":["Custom properties"],"summary":"Get a custom property","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["text","textarea","number","date","checkbox","multiCheckbox","select","url","email","phone","currency","percentage"]},"recordTypes":{"type":"array","items":{"type":"string","enum":["project","countTakeoff","linearTakeoff","areaTakeoff","product"]}},"options":{"type":"array","items":{"type":"string"}},"position":{"type":"number"},"isActive":{"type":"boolean"}},"required":["_id","_creationTime","organizationId","name","type","recordTypes"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"patch":{"tags":["Custom properties"],"summary":"Update a custom property","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"type":{"type":"string","enum":["text","textarea","number","date","checkbox","multiCheckbox","select","url","email","phone","currency","percentage"]},"recordTypes":{"type":"array","items":{"type":"string","enum":["project","countTakeoff","linearTakeoff","areaTakeoff","product"]},"minItems":1},"options":{"type":"array","items":{"type":"string"}}},"required":["organizationId"]}}}},"responses":{"204":{"description":"Updated"}}},"delete":{"tags":["Custom properties"],"summary":"Archive a custom property","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"204":{"description":"Archived"}}}},"/v1/integrations":{"get":{"tags":["Integrations"],"summary":"List integrations connected to an organization","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"platform":{"type":"string"},"status":{"type":"string"}},"required":["_id","_creationTime","organizationId","platform"],"additionalProperties":{"nullable":true}}}}}}}}},"/v1/integrations/{id}":{"delete":{"tags":["Integrations"],"summary":"Disconnect an integration","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"204":{"description":"Disconnected"}}}},"/v1/labor/rates":{"get":{"tags":["Labor"],"summary":"List labor rates","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"boolean","nullable":true},"required":false,"name":"includeInactive","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"hourlyRate":{"type":"number"},"isActive":{"type":"boolean"}},"required":["_id","_creationTime","organizationId","name","hourlyRate","isActive"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Labor"],"summary":"Create a labor rate","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":500},"hourlyRate":{"type":"number","minimum":0},"burdenRate":{"type":"number","minimum":0},"currency":{"type":"string","enum":["USD","CAD","MXN","BRL","ARS","CLP","COP","PEN","UYU","EUR","GBP","CHF","NOK","SEK","DKK","PLN","CZK","HUF","RON","BGN","HRK","RSD","UAH","RUB","TRY","ISK","ILS","AED","SAR","QAR","KWD","BHD","OMR","JOD","LBP","EGP","ZAR","NGN","KES","GHS","MAD","TND","DZD","JPY","CNY","HKD","TWD","KRW","SGD","INR","PKR","BDT","LKR","NPR","IDR","MYR","PHP","THB","VND","MMK","AUD","NZD"],"description":"ISO 4217 currency code"},"effectiveDate":{"type":"number"},"isDefault":{"type":"boolean"}},"required":["organizationId","name","hourlyRate"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}}},"/v1/labor/rates/{id}":{"get":{"tags":["Labor"],"summary":"Get a labor rate","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"hourlyRate":{"type":"number"},"isActive":{"type":"boolean"}},"required":["_id","_creationTime","organizationId","name","hourlyRate","isActive"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"patch":{"tags":["Labor"],"summary":"Update a labor rate","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":500},"hourlyRate":{"type":"number","minimum":0},"burdenRate":{"type":"number","minimum":0},"currency":{"type":"string","enum":["USD","CAD","MXN","BRL","ARS","CLP","COP","PEN","UYU","EUR","GBP","CHF","NOK","SEK","DKK","PLN","CZK","HUF","RON","BGN","HRK","RSD","UAH","RUB","TRY","ISK","ILS","AED","SAR","QAR","KWD","BHD","OMR","JOD","LBP","EGP","ZAR","NGN","KES","GHS","MAD","TND","DZD","JPY","CNY","HKD","TWD","KRW","SGD","INR","PKR","BDT","LKR","NPR","IDR","MYR","PHP","THB","VND","MMK","AUD","NZD"],"description":"ISO 4217 currency code"},"effectiveDate":{"type":"number"},"isDefault":{"type":"boolean"}},"required":["organizationId"]}}}},"responses":{"204":{"description":"Updated"}}},"delete":{"tags":["Labor"],"summary":"Archive a labor rate","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"204":{"description":"Archived"}}}},"/v1/labor/equipment":{"get":{"tags":["Labor"],"summary":"List labor equipment","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"category","in":"query"},{"schema":{"type":"boolean","nullable":true},"required":false,"name":"includeInactive","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"category":{"type":"string"},"dailyRate":{"type":"number"},"isActive":{"type":"boolean"}},"required":["_id","_creationTime","organizationId","name","category","dailyRate","isActive"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Labor"],"summary":"Create a labor equipment entry","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":500},"category":{"type":"string","minLength":1,"maxLength":100},"dailyRate":{"type":"number","minimum":0},"hourlyRate":{"type":"number","minimum":0},"currency":{"type":"string","enum":["USD","CAD","MXN","BRL","ARS","CLP","COP","PEN","UYU","EUR","GBP","CHF","NOK","SEK","DKK","PLN","CZK","HUF","RON","BGN","HRK","RSD","UAH","RUB","TRY","ISK","ILS","AED","SAR","QAR","KWD","BHD","OMR","JOD","LBP","EGP","ZAR","NGN","KES","GHS","MAD","TND","DZD","JPY","CNY","HKD","TWD","KRW","SGD","INR","PKR","BDT","LKR","NPR","IDR","MYR","PHP","THB","VND","MMK","AUD","NZD"],"description":"ISO 4217 currency code"},"isOwned":{"type":"boolean"}},"required":["organizationId","name","category","dailyRate"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}}},"/v1/labor/equipment/{id}":{"get":{"tags":["Labor"],"summary":"Get a labor equipment entry","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"category":{"type":"string"},"dailyRate":{"type":"number"},"isActive":{"type":"boolean"}},"required":["_id","_creationTime","organizationId","name","category","dailyRate","isActive"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"patch":{"tags":["Labor"],"summary":"Update a labor equipment entry","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":500},"category":{"type":"string","minLength":1,"maxLength":100},"dailyRate":{"type":"number","minimum":0},"hourlyRate":{"type":"number","minimum":0},"currency":{"type":"string","enum":["USD","CAD","MXN","BRL","ARS","CLP","COP","PEN","UYU","EUR","GBP","CHF","NOK","SEK","DKK","PLN","CZK","HUF","RON","BGN","HRK","RSD","UAH","RUB","TRY","ISK","ILS","AED","SAR","QAR","KWD","BHD","OMR","JOD","LBP","EGP","ZAR","NGN","KES","GHS","MAD","TND","DZD","JPY","CNY","HKD","TWD","KRW","SGD","INR","PKR","BDT","LKR","NPR","IDR","MYR","PHP","THB","VND","MMK","AUD","NZD"],"description":"ISO 4217 currency code"},"isOwned":{"type":"boolean"}},"required":["organizationId"]}}}},"responses":{"204":{"description":"Updated"}}},"delete":{"tags":["Labor"],"summary":"Archive a labor equipment entry","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"204":{"description":"Archived"}}}},"/v1/labor/crews":{"get":{"tags":["Labor"],"summary":"List labor crews","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"boolean","nullable":true},"required":false,"name":"includeInactive","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"members":{"type":"array","items":{"type":"object","properties":{"laborRateId":{"type":"string"},"count":{"type":"number","minimum":0}},"required":["laborRateId","count"]}},"isActive":{"type":"boolean"}},"required":["_id","_creationTime","organizationId","name","members","isActive"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"tags":["Labor"],"summary":"Create a labor crew","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":500},"members":{"type":"array","items":{"type":"object","properties":{"laborRateId":{"type":"string"},"count":{"type":"number","minimum":0}},"required":["laborRateId","count"]},"minItems":1},"equipmentIds":{"type":"array","items":{"type":"string"}},"dailyCapacity":{"type":"object","properties":{"type":{"type":"string"},"value":{"type":"number"},"unit":{"type":"string"}},"required":["type","value","unit"]}},"required":["organizationId","name","members"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}}}}},"/v1/labor/crews/{id}":{"get":{"tags":["Labor"],"summary":"Get a labor crew","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"name":{"type":"string"},"members":{"type":"array","items":{"type":"object","properties":{"laborRateId":{"type":"string"},"count":{"type":"number","minimum":0}},"required":["laborRateId","count"]}},"isActive":{"type":"boolean"}},"required":["_id","_creationTime","organizationId","name","members","isActive"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"patch":{"tags":["Labor"],"summary":"Update a labor crew","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":500},"members":{"type":"array","items":{"type":"object","properties":{"laborRateId":{"type":"string"},"count":{"type":"number","minimum":0}},"required":["laborRateId","count"]},"minItems":1},"equipmentIds":{"type":"array","items":{"type":"string"}},"dailyCapacity":{"type":"object","properties":{"type":{"type":"string"},"value":{"type":"number"},"unit":{"type":"string"}},"required":["type","value","unit"]}},"required":["organizationId"]}}}},"responses":{"204":{"description":"Updated"}}},"delete":{"tags":["Labor"],"summary":"Archive a labor crew","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"204":{"description":"Archived"}}}},"/v1/projects/{id}/quotes":{"get":{"tags":["Vendor quotes"],"summary":"List vendor quotes on a project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"string","enum":["requested","received","accepted","rejected","expired"]},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"projectId":{"type":"string"},"vendorId":{"type":"string"},"quoteNumber":{"type":"string"},"status":{"type":"string","enum":["requested","received","accepted","rejected","expired"]},"subtotal":{"type":"number"},"total":{"type":"number"}},"required":["_id","_creationTime","organizationId","projectId","vendorId","quoteNumber","status","subtotal","total"],"additionalProperties":{"nullable":true}}}}}}}},"post":{"operationId":"createVendorQuote","tags":["Vendor quotes"],"summary":"Create a vendor quote request","description":"Creates a vendor quote in `requested` status. By default a request shell (no line items); financial data may be supplied but must be internally consistent (total = subtotal + tax + shipping; each line total = quantity × unit price). Emits quote.requested.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"vendorId":{"type":"string"},"quoteNumber":{"type":"string"},"lineItems":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string"},"description":{"type":"string"},"quantity":{"type":"number","nullable":true,"minimum":0},"unit":{"type":"string"},"unitPrice":{"type":"number","nullable":true,"minimum":0},"totalPrice":{"type":"number","nullable":true,"minimum":0}},"required":["description","quantity","unit","unitPrice","totalPrice"]}},"subtotal":{"type":"number","nullable":true,"minimum":0},"tax":{"type":"number","nullable":true,"minimum":0},"shipping":{"type":"number","nullable":true,"minimum":0},"total":{"type":"number","nullable":true,"minimum":0},"validUntil":{"type":"number","nullable":true,"description":"Quote expiry as epoch milliseconds"},"notes":{"type":"string"}},"required":["organizationId","vendorId","quoteNumber"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/quotes/{id}":{"get":{"tags":["Vendor quotes"],"summary":"Get a vendor quote","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_id":{"type":"string"},"_creationTime":{"type":"number"},"organizationId":{"type":"string"},"projectId":{"type":"string"},"vendorId":{"type":"string"},"quoteNumber":{"type":"string"},"status":{"type":"string","enum":["requested","received","accepted","rejected","expired"]},"subtotal":{"type":"number"},"total":{"type":"number"}},"required":["_id","_creationTime","organizationId","projectId","vendorId","quoteNumber","status","subtotal","total"],"additionalProperties":{"nullable":true}}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/quotes/{id}/receive":{"patch":{"operationId":"receiveVendorQuote","tags":["Vendor quotes"],"summary":"Record a vendor quote response","description":"Attaches priced line items + totals and moves a `requested` quote to `received`. Totals must be internally consistent. Emits quote.received.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"lineItems":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string"},"description":{"type":"string"},"quantity":{"type":"number","nullable":true,"minimum":0},"unit":{"type":"string"},"unitPrice":{"type":"number","nullable":true,"minimum":0},"totalPrice":{"type":"number","nullable":true,"minimum":0}},"required":["description","quantity","unit","unitPrice","totalPrice"]}},"subtotal":{"type":"number","nullable":true,"minimum":0},"tax":{"type":"number","nullable":true,"minimum":0},"shipping":{"type":"number","nullable":true,"minimum":0},"total":{"type":"number","nullable":true,"minimum":0},"validUntil":{"type":"number","nullable":true}},"required":["organizationId","lineItems","subtotal","total"]}}}},"responses":{"200":{"description":"Received","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}},"400":{"description":"Invalid request or transition","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/quotes/{id}/status":{"patch":{"operationId":"updateVendorQuoteStatus","tags":["Vendor quotes"],"summary":"Accept, reject, or expire a vendor quote","description":"Records a terminal decision. `accepted` requires a `received` quote; `rejected`/`expired` are allowed from `requested` or `received`. Status-only — no pricing write-back. Emits quote.accepted | quote.rejected | quote.expired.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"status":{"type":"string","enum":["accepted","rejected","expired"]}},"required":["organizationId","status"]}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}}},"400":{"description":"Invalid transition","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/projects/{id}/takeoff-summary":{"get":{"tags":["Takeoff"],"summary":"Aggregated totals across takeoff symbols in a project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"totalSymbols":{"type":"number"},"categories":{"type":"object","additionalProperties":{"type":"object","properties":{"count":{"type":"number"},"totalCount":{"type":"number"},"totalLinear":{"type":"number"},"totalArea":{"type":"number"},"unit":{"type":"string","nullable":true,"enum":["feet","meter",null]},"uncalibrated":{"type":"boolean"}},"required":["count"]}}},"required":["totalSymbols","categories"],"additionalProperties":{"nullable":true}}}}}}}},"/v1/pages/{id}/content":{"get":{"tags":["Pages"],"summary":"Extracted text and AI description for a page","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"pageId":{"type":"string"},"name":{"type":"string"},"extractedText":{"type":"string","nullable":true},"description":{"type":"string","nullable":true}},"required":["pageId","extractedText","description"]}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/conversations/{id}/files":{"get":{"tags":["Conversations"],"summary":"List files uploaded in a conversation","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"boolean","nullable":true},"required":false,"name":"imagesOnly","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"nullable":true}}}}}}}},"/v1/projects/{id}/line-items":{"get":{"tags":["Takeoff"],"summary":"Search line items across all symbols in a project","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":false,"name":"query","in":"query"},{"schema":{"type":"string","enum":["count","linear","area"]},"required":false,"name":"takeoffType","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"nullable":true}}}}}}}},"/v1/projects/{id}/files/{fileId}/attach":{"post":{"tags":["Files"],"summary":"Attach an existing file to a project","description":"Links a file (uploaded in a conversation or another project) to this project. Does not trigger downstream PDF extraction / image processing — those run automatically on the original upload.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"fileId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."}},"required":["organizationId"]}}}},"responses":{"204":{"description":"Attached"}}}},"/v1/projects/{id}/export":{"get":{"tags":["Projects"],"summary":"Export a project as structured JSON","description":"Returns every directly-related row (pages, files, conversations, spreadsheets, documents) in one envelope. File bytes are NOT embedded — each file entry carries a `downloadHint` pointing at /v1/files/{id}/url so the consumer streams them from R2. Requires `read:projects` scope.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"nullable":true}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/help/search":{"post":{"tags":["Help"],"summary":"Search help articles by keyword","description":"Returns up to `limit` help articles ranked by keyword match against the article title, description, and curator-supplied keywords. Safe for agents to call on every turn — all matching is in-memory.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","minLength":1,"maxLength":500},"limit":{"type":"integer","minimum":1,"maximum":50},"section":{"type":"string"}},"required":["query"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"section":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"url":{"type":"string"},"score":{"type":"number"},"matchedTerms":{"type":"array","items":{"type":"string"}}},"required":["id","section","title","description","url","score","matchedTerms"]}},"total":{"type":"integer"}},"required":["results","total"]}}}}}}},"/v1/webhook_endpoints":{"get":{"tags":["Webhooks"],"summary":"List webhook endpoints in an organization","parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"organizationId":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"description":{"type":"string"},"status":{"type":"string","enum":["active","paused"]},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","organizationId","url","events","status","createdAt","updatedAt"]}}}}},"401":{"description":"Unauthenticated","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}},"post":{"operationId":"createWebhookEndpoint","tags":["Webhooks"],"summary":"Create a webhook endpoint","description":"Subscribe an HTTPS URL to one or more event types. The response includes a `secret` that is used to verify delivery HMAC signatures — it is returned exactly once, on creation. Lose it and you must delete and recreate the endpoint.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["*","project.created","project.updated","project.archived","assessment.started","assessment.completed","assessment.approved","assessment.cancelled","assessment.failed","estimate.generated","bid.generated","file.processed","quote.requested","quote.received","quote.accepted","quote.rejected","quote.expired","conversation.started","conversation.handoff_requested","conversation.closed","lead.captured","contact.created"]},"minItems":1},"description":{"type":"string","maxLength":500}},"required":["organizationId","url","events"]}}}},"responses":{"200":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"secret":{"type":"string"}},"required":["id","secret"]}}}},"400":{"description":"Invalid request","content":{"application/problem+json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"URI identifying the error class; links to the error catalog."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"HTTP status code, mirrored."},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence."},"instance":{"type":"string","description":"Request path where the error occurred."},"code":{"type":"string","description":"Stable machine-readable error code."},"param":{"type":"string","description":"Field name or JSON pointer when the error is input-related."},"doc_url":{"type":"string","description":"URL to the error documentation page. Omitted when no stable error code is present."},"request_id":{"type":"string","description":"Request id for support triage; also returned in X-Request-Id."}},"required":["type","title","status","detail","code"]}}}}}}},"/v1/webhook_endpoints/{id}":{"patch":{"tags":["Webhooks"],"summary":"Update a webhook endpoint","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["*","project.created","project.updated","project.archived","assessment.started","assessment.completed","assessment.approved","assessment.cancelled","assessment.failed","estimate.generated","bid.generated","file.processed","quote.requested","quote.received","quote.accepted","quote.rejected","quote.expired","conversation.started","conversation.handoff_requested","conversation.closed","lead.captured","contact.created"]},"minItems":1},"description":{"type":"string","maxLength":500},"status":{"type":"string","enum":["active","paused"]}},"required":["organizationId"]}}}},"responses":{"204":{"description":"Updated"}}},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook endpoint","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"}],"responses":{"204":{"description":"Deleted"}}}},"/v1/webhook_endpoints/{id}/deliveries":{"get":{"tags":["Webhooks"],"summary":"List deliveries for a webhook endpoint","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z0-9]{32}$","example":"js79m7b3kfqd3vqzwx0kpcnryx7h2k4e","description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name."},"required":true,"description":"Convex organization ID — get it from GET /v1/me or the get_me tool (memberships[].orgId), not the organization name.","name":"organizationId","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"_id":{"type":"string"},"endpointId":{"type":"string"},"eventId":{"type":"string"},"event":{"type":"string"},"status":{"type":"string","enum":["pending","retrying","success","failed"]},"attempts":{"type":"number"},"responseStatus":{"type":"number"},"responseBody":{"type":"string"},"failureReason":{"type":"string"},"deliveredAt":{"type":"number"},"createdAt":{"type":"number"},"updatedAt":{"type":"number"}},"required":["_id","endpointId","eventId","event","status","attempts","createdAt","updatedAt"]}}}}}}}}}}