{"openapi":"3.1.0","info":{"title":"WayWiser API","version":"2026-09-16","description":"The bid war-room for FM contractors, for agents: every operation a member can perform in the product, authenticated with an API key. Read /docs/agents.md first — it explains keys, company pinning, the 202 + operation polling pattern, uploads, idempotency and the error vocabulary. Outputs are decision support with citations, never advice; evaluator output is a review, never a score forecast."},"servers":[{"url":"https://waywiser-api-zxgq66afoq-nw.a.run.app"}],"security":[{"apiKey":[]}],"tags":[{"name":"identity","description":"Who the caller is. Start here."},{"name":"company","description":"Company profile and settings (admin-ceiling keys for writes)."},{"name":"discovery","description":"Live tender notices, fit-ranked against the company profile; pursue or dismiss."},{"name":"tenders","description":"The pipeline: tenders and where each is on the bid journey."},{"name":"analysis","description":"ITT pack upload, extraction (background) and the bid plan."},{"name":"questions","description":"A question, its evidence and its draft blocks."},{"name":"drafting","description":"Draft blocks, grounded drafting jobs, version history."},{"name":"review","description":"Evaluator reviews, comments, reviewer assignment and sign-off."},{"name":"clarifications","description":"Questions to the buyer: log, draft, batch into an email, map the reply."},{"name":"go-no-go","description":"The bid / no-bid decision: prefill, runs, the interview, the incumbent search."},{"name":"assembly","description":"Checklist, fast path, export, submission and outcome."},{"name":"knowledge","description":"Corpora and documents — the library the drafts are grounded in."},{"name":"facts","description":"The facts bank: structured facts and graded uploads."},{"name":"search","description":"Hybrid retrieval over what the caller may read."},{"name":"pricing","description":"Winning-price benchmarks and the cost floor."},{"name":"activity","description":"Background work and the polling endpoint every 202 points at."}],"paths":{"/me":{"get":{"operationId":"getMe","tags":["identity"],"summary":"Who am I: the member this key acts as, the company it is pinned to, the role and the key itself","description":"Call this first. `actor` is the key (id, name, readOnly, expiresAt) — null for a signed-in person — and `activeCompanyId` is the one company every other call is scoped to.","parameters":[],"responses":{"200":{"description":"Identity, role and the key.","content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":["string","null"]},"isSuperAdmin":{"type":"boolean"},"activeCompanyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"role":{"anyOf":[{"type":"string","enum":["admin","member","bidwriter"]},{"type":"null"}]},"isPlatformCompany":{"type":"boolean"},"isStaff":{"type":"boolean"},"platformCompany":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"role":{"type":"string","enum":["admin","member","bidwriter"]}},"required":["id","name","role"],"additionalProperties":false},{"type":"null"}]},"actor":{"anyOf":[{"type":"object","properties":{"kind":{"type":"string","const":"api_key"},"keyId":{"type":"string","format":"uuid"},"name":{"type":"string"},"readOnly":{"type":"boolean"},"expiresAt":{"type":["string","null"]}},"required":["kind","keyId","name","readOnly","expiresAt"],"additionalProperties":false},{"type":"null"}]},"companies":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"role":{"type":"string","enum":["admin","member","bidwriter"]},"isPlatformOwner":{"type":"boolean"},"deletedAt":{"type":["string","null"]}},"required":["id","name","role","isPlatformOwner","deletedAt"],"additionalProperties":false}}},"required":["userId","email","name","isSuperAdmin","activeCompanyId","role","isPlatformCompany","isStaff","platformCompany","actor","companies"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/profile":{"get":{"operationId":"getProfile","tags":["company"],"summary":"The company profile that drives tender matching (service lines, regions, value bands, buyer types)","parameters":[],"responses":{"200":{"description":"The saved profile.","content":{"application/json":{"schema":{"type":"object","properties":{"serviceLines":{"type":"array","items":{"type":"string","enum":["hard_fm","m_and_e","cleaning","fire_safety","water_hygiene","drainage","grounds","tfm","gas_heating","security","catering","waste","pest_control","caretaking"]},"default":[]},"regions":{"type":"array","items":{"type":"string","enum":["north_west","north_east","yorkshire","midlands","london_se","south_west","east","scotland","wales","northern_ireland"]},"default":[]},"valueBands":{"type":"array","items":{"type":"string","enum":["lt_1m","1m_5m","5m_15m","gt_15m"]},"default":[]},"buyerTypes":{"type":"array","items":{"type":"string","enum":["nhs_trust","local_authority","university","school","housing","central_government","private"]},"default":[]}},"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}},"put":{"operationId":"putProfile","tags":["company"],"summary":"Replace the company profile; notices are re-scored against it in the background","parameters":[],"responses":{"200":{"description":"The profile as saved.","content":{"application/json":{"schema":{"type":"object","properties":{"serviceLines":{"type":"array","items":{"type":"string","enum":["hard_fm","m_and_e","cleaning","fire_safety","water_hygiene","drainage","grounds","tfm","gas_heating","security","catering","waste","pest_control","caretaking"]},"default":[]},"regions":{"type":"array","items":{"type":"string","enum":["north_west","north_east","yorkshire","midlands","london_se","south_west","east","scotland","wales","northern_ireland"]},"default":[]},"valueBands":{"type":"array","items":{"type":"string","enum":["lt_1m","1m_5m","5m_15m","gt_15m"]},"default":[]},"buyerTypes":{"type":"array","items":{"type":"string","enum":["nhs_trust","local_authority","university","school","housing","central_government","private"]},"default":[]}},"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Needs an admin-ceiling key acting as a company admin; or the key is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"A full replace — repeating it saves the same profile.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"x-waywiser-requires":"admin","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"serviceLines":{"type":"array","items":{"type":"string","enum":["hard_fm","m_and_e","cleaning","fire_safety","water_hygiene","drainage","grounds","tfm","gas_heating","security","catering","waste","pest_control","caretaking"]},"default":[]},"regions":{"type":"array","items":{"type":"string","enum":["north_west","north_east","yorkshire","midlands","london_se","south_west","east","scotland","wales","northern_ireland"]},"default":[]},"valueBands":{"type":"array","items":{"type":"string","enum":["lt_1m","1m_5m","5m_15m","gt_15m"]},"default":[]},"buyerTypes":{"type":"array","items":{"type":"string","enum":["nhs_trust","local_authority","university","school","housing","central_government","private"]},"default":[]}},"additionalProperties":false}}}}}},"/settings":{"get":{"operationId":"getSettings","tags":["company"],"summary":"Company settings: bid cost, export branding, digest","parameters":[],"responses":{"200":{"description":"The settings, defaults filled in.","content":{"application/json":{"schema":{"type":"object","properties":{"bidCostGbp":{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":1000000},{"type":"null"}],"default":null},"branding":{"type":"object","properties":{"logoDataUri":{"anyOf":[{"type":"string","maxLength":300000},{"type":"null"}],"default":null},"accentColor":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$","default":"#0E8A6D"},"font":{"type":"string","enum":["Calibri","Arial"],"default":"Calibri"}},"additionalProperties":false,"default":{"logoDataUri":null,"accentColor":"#0E8A6D","font":"Calibri"}},"digest":{"type":"object","properties":{"frequency":{"type":"string","enum":["off","daily","weekly"],"default":"off"},"recipients":{"type":"array","items":{"type":"string","format":"email"},"maxItems":20,"default":[]},"minFit":{"type":"number","minimum":0,"maximum":100,"default":60}},"additionalProperties":false,"default":{"frequency":"off","recipients":[],"minFit":60}}},"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}},"put":{"operationId":"putSettings","tags":["company"],"summary":"Replace company settings","parameters":[],"responses":{"200":{"description":"The settings as saved.","content":{"application/json":{"schema":{"type":"object","properties":{"bidCostGbp":{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":1000000},{"type":"null"}],"default":null},"branding":{"type":"object","properties":{"logoDataUri":{"anyOf":[{"type":"string","maxLength":300000},{"type":"null"}],"default":null},"accentColor":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$","default":"#0E8A6D"},"font":{"type":"string","enum":["Calibri","Arial"],"default":"Calibri"}},"additionalProperties":false,"default":{"logoDataUri":null,"accentColor":"#0E8A6D","font":"Calibri"}},"digest":{"type":"object","properties":{"frequency":{"type":"string","enum":["off","daily","weekly"],"default":"off"},"recipients":{"type":"array","items":{"type":"string","format":"email"},"maxItems":20,"default":[]},"minFit":{"type":"number","minimum":0,"maximum":100,"default":60}},"additionalProperties":false,"default":{"frequency":"off","recipients":[],"minFit":60}}},"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Needs an admin-ceiling key acting as a company admin; or the key is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"A full replace.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"x-waywiser-requires":"admin","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"bidCostGbp":{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":1000000},{"type":"null"}],"default":null},"branding":{"type":"object","properties":{"logoDataUri":{"anyOf":[{"type":"string","maxLength":300000},{"type":"null"}],"default":null},"accentColor":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$","default":"#0E8A6D"},"font":{"type":"string","enum":["Calibri","Arial"],"default":"Calibri"}},"additionalProperties":false,"default":{"logoDataUri":null,"accentColor":"#0E8A6D","font":"Calibri"}},"digest":{"type":"object","properties":{"frequency":{"type":"string","enum":["off","daily","weekly"],"default":"off"},"recipients":{"type":"array","items":{"type":"string","format":"email"},"maxItems":20,"default":[]},"minFit":{"type":"number","minimum":0,"maximum":100,"default":60}},"additionalProperties":false,"default":{"frequency":"off","recipients":[],"minFit":60}}},"additionalProperties":false}}}}}},"/settings/logo":{"post":{"operationId":"postSettingsLogo","tags":["company"],"summary":"Set the export logo (a PNG/JPEG data URI, ~200 KB max)","parameters":[],"responses":{"200":{"description":"`{ ok: true }`.","content":{"application/json":{"schema":{"description":"`{ ok: true }`."}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Needs an admin-ceiling key acting as a company admin; or the key is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Replaces the logo each time.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"x-waywiser-requires":"admin","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dataUri":{"type":"string","maxLength":300000}},"required":["dataUri"],"additionalProperties":false}}}}}},"/notices":{"get":{"operationId":"getNotices","tags":["discovery"],"summary":"Live tender notices for this company, fit-ranked by default","description":"Absent filters fall back to the company profile (`scope=profile`). `minFit` absent applies the saved digest threshold (the response says which as `appliedMinFit`); `minFit=0` shows everything. Notices marked \"Not for us\" are hidden unless `dismissed=show`.","parameters":[{"name":"minFit","in":"query","required":false,"schema":{"type":"number","minimum":0,"maximum":100}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0}},{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["fit","closes","value"],"default":"fit"}},{"name":"serviceLine","in":"query","required":false,"schema":{"type":"string"}},{"name":"region","in":"query","required":false,"schema":{"type":"string"}},{"name":"valueBand","in":"query","required":false,"schema":{"type":"string","enum":["lt_1m","1m_5m","5m_15m","gt_15m"]}},{"name":"scope","in":"query","required":false,"schema":{"type":"string","enum":["profile","all"],"default":"profile"}},{"name":"dismissed","in":"query","required":false,"schema":{"type":"string","enum":["hide","show"],"default":"hide"}}],"responses":{"200":{"description":"A page of notices with fit, contract value, the source portal URL and up to three document links; `total` counts the same filter.","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"notice":{"description":"the notices row (packages/db/src/schema/discovery.ts)"},"fit":{"type":["number","null"]},"valueAmountGross":{"type":["number","null"]},"sourceUrl":{"type":["string","null"]},"portalLinks":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"label":{"type":"string"}},"required":["url"],"additionalProperties":false}}},"required":["fit","valueAmountGross","sourceUrl","portalLinks"],"additionalProperties":false}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"gate":{"type":"null"},"appliedMinFit":{"type":["number","null"]}},"required":["items","total","limit","offset","gate","appliedMinFit"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/notices/{id}/pursue":{"post":{"operationId":"postNoticesIdPursue","tags":["discovery"],"summary":"Pursue a notice: create a qualifying tender from it (one click from Find to the pipeline)","description":"The buyer documents the notice links are fetched into the tender pack by a background job. 200 with the existing tender when the company already pursued this notice, 201 otherwise.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"noticeId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"title":{"type":"string"},"buyerName":{"type":"string"},"buyerType":{"type":["string","null"]},"reference":{"type":["string","null"]},"valueText":{"type":["string","null"]},"deadline":{"type":["string","null"]},"clarificationDeadline":{"type":["string","null"]},"stage":{"type":"string","enum":["qualifying","live","submitted","archived"]},"outcome":{"type":"string","enum":["pending","won","lost","no_bid"]},"weighting":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"pct":{"type":["number","null"]}},"required":["label","pct"],"additionalProperties":false}},"winSignal":{"anyOf":[{"type":"integer"},{"type":"null"}]},"winCoveragePct":{"anyOf":[{"type":"integer"},{"type":"null"}]},"estateMetrics":{"type":"object","additionalProperties":{}},"milestones":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":200},"startWeek":{"type":"integer","minimum":1,"maximum":520},"endWeek":{"type":"integer","minimum":1,"maximum":520},"owner":{"type":"string","maxLength":100},"dependsOn":{"type":"string","maxLength":200}},"required":["label","startWeek","endWeek"],"additionalProperties":false}},"bidDraftRun":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","enum":["queued","running","succeeded","failed"]},"requestedAt":{"type":"string"},"requestedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"startedAt":{"type":["string","null"]},"finishedAt":{"type":["string","null"]},"total":{"type":"integer"},"processed":{"type":"integer"},"accepted":{"type":"integer"},"reused":{"type":"integer"},"open":{"type":"integer"},"inFlight":{"type":"integer","default":0},"alreadyDone":{"type":"integer"},"error":{"type":["string","null"]}},"required":["status","requestedAt","requestedByUserId","startedAt","finishedAt","total","processed","accepted","reused","open","alreadyDone","error"],"additionalProperties":false},{"type":"null"}]},"visibility":{"type":"string","enum":["client","bidwriter"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","companyId","noticeId","title","buyerName","buyerType","reference","valueText","deadline","clarificationDeadline","stage","outcome","weighting","winSignal","winCoveragePct","estateMetrics","milestones","bidDraftRun","visibility","createdAt","updatedAt"],"additionalProperties":false}}}},"201":{"description":"The tender (201 created; 200 when it already existed).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"noticeId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"title":{"type":"string"},"buyerName":{"type":"string"},"buyerType":{"type":["string","null"]},"reference":{"type":["string","null"]},"valueText":{"type":["string","null"]},"deadline":{"type":["string","null"]},"clarificationDeadline":{"type":["string","null"]},"stage":{"type":"string","enum":["qualifying","live","submitted","archived"]},"outcome":{"type":"string","enum":["pending","won","lost","no_bid"]},"weighting":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"pct":{"type":["number","null"]}},"required":["label","pct"],"additionalProperties":false}},"winSignal":{"anyOf":[{"type":"integer"},{"type":"null"}]},"winCoveragePct":{"anyOf":[{"type":"integer"},{"type":"null"}]},"estateMetrics":{"type":"object","additionalProperties":{}},"milestones":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":200},"startWeek":{"type":"integer","minimum":1,"maximum":520},"endWeek":{"type":"integer","minimum":1,"maximum":520},"owner":{"type":"string","maxLength":100},"dependsOn":{"type":"string","maxLength":200}},"required":["label","startWeek","endWeek"],"additionalProperties":false}},"bidDraftRun":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","enum":["queued","running","succeeded","failed"]},"requestedAt":{"type":"string"},"requestedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"startedAt":{"type":["string","null"]},"finishedAt":{"type":["string","null"]},"total":{"type":"integer"},"processed":{"type":"integer"},"accepted":{"type":"integer"},"reused":{"type":"integer"},"open":{"type":"integer"},"inFlight":{"type":"integer","default":0},"alreadyDone":{"type":"integer"},"error":{"type":["string","null"]}},"required":["status","requestedAt","requestedByUserId","startedAt","finishedAt","total","processed","accepted","reused","open","alreadyDone","error"],"additionalProperties":false},{"type":"null"}]},"visibility":{"type":"string","enum":["client","bidwriter"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","companyId","noticeId","title","buyerName","buyerType","reference","valueText","deadline","clarificationDeadline","stage","outcome","weighting","winSignal","winCoveragePct","estateMetrics","milestones","bidDraftRun","visibility","createdAt","updatedAt"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"One tender per (company, notice): a repeat returns the existing row with 200.","x-waywiser-rate-limit":{"bucket":"upload","limit":"30 per minute per key"}}},"/notices/{id}/dismiss":{"post":{"operationId":"postNoticesIdDismiss","tags":["discovery"],"summary":"\"Not for us\": hide a notice from the feed","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"noticeId":{"type":"string","format":"uuid"},"dismissed":{"type":"boolean","const":true}},"required":["noticeId","dismissed"],"additionalProperties":false}}}},"201":{"description":"Dismissed.","content":{"application/json":{"schema":{"type":"object","properties":{"noticeId":{"type":"string","format":"uuid"},"dismissed":{"type":"boolean","const":true}},"required":["noticeId","dismissed"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"A second dismiss is a no-op, never an error.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}},"delete":{"operationId":"deleteNoticesIdDismiss","tags":["discovery"],"summary":"Undo \"Not for us\": the notice returns to the feed at its existing fit","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Restored (204 whether or not it was dismissed)."},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Idempotent.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/tenders":{"get":{"operationId":"getTenders","tags":["tenders"],"summary":"The pipeline: every tender with where it is on the bid journey","description":"Each row carries `nextStep` and the step statuses; filter by `stage` and `outcome` (closed vocabularies — a typo is a 400, never an empty list).","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":500}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0}},{"name":"stage","in":"query","required":false,"schema":{"type":"string","enum":["qualifying","live","submitted","archived"]}},{"name":"outcome","in":"query","required":false,"schema":{"type":"string","enum":["pending","won","lost","no_bid"]}}],"responses":{"200":{"description":"A page of tenders.","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"noticeId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"title":{"type":"string"},"buyerName":{"type":"string"},"buyerType":{"type":["string","null"]},"reference":{"type":["string","null"]},"valueText":{"type":["string","null"]},"deadline":{"type":["string","null"]},"clarificationDeadline":{"type":["string","null"]},"stage":{"type":"string","enum":["qualifying","live","submitted","archived"]},"outcome":{"type":"string","enum":["pending","won","lost","no_bid"]},"weighting":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"pct":{"type":["number","null"]}},"required":["label","pct"],"additionalProperties":false}},"winSignal":{"anyOf":[{"type":"integer"},{"type":"null"}]},"winCoveragePct":{"anyOf":[{"type":"integer"},{"type":"null"}]},"estateMetrics":{"type":"object","additionalProperties":{}},"milestones":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":200},"startWeek":{"type":"integer","minimum":1,"maximum":520},"endWeek":{"type":"integer","minimum":1,"maximum":520},"owner":{"type":"string","maxLength":100},"dependsOn":{"type":"string","maxLength":200}},"required":["label","startWeek","endWeek"],"additionalProperties":false}},"bidDraftRun":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","enum":["queued","running","succeeded","failed"]},"requestedAt":{"type":"string"},"requestedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"startedAt":{"type":["string","null"]},"finishedAt":{"type":["string","null"]},"total":{"type":"integer"},"processed":{"type":"integer"},"accepted":{"type":"integer"},"reused":{"type":"integer"},"open":{"type":"integer"},"inFlight":{"type":"integer","default":0},"alreadyDone":{"type":"integer"},"error":{"type":["string","null"]}},"required":["status","requestedAt","requestedByUserId","startedAt","finishedAt","total","processed","accepted","reused","open","alreadyDone","error"],"additionalProperties":false},{"type":"null"}]},"visibility":{"type":"string","enum":["client","bidwriter"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"nextStep":{"anyOf":[{"type":"string","enum":["find","qualify","pack","analyse","clarify","interview","gng","plan","draft","submit","outcome"]},{"type":"null"}]},"committed":{"type":"boolean"},"decision":{"anyOf":[{"type":"string","enum":["bid","no_bid"]},{"type":"null"}]},"steps":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","enum":["find","qualify","pack","analyse","clarify","interview","gng","plan","draft","submit","outcome"]},"status":{"type":"string","enum":["done","current","running","stale","failed","attention","todo","skipped"]},"required":{"type":"boolean"}},"required":["key","status","required"],"additionalProperties":false}}},"required":["id","companyId","noticeId","title","buyerName","buyerType","reference","valueText","deadline","clarificationDeadline","stage","outcome","weighting","winSignal","winCoveragePct","estateMetrics","milestones","bidDraftRun","visibility","createdAt","updatedAt","nextStep","committed","decision","steps"],"additionalProperties":false}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["items","total","limit","offset"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}},"post":{"operationId":"postTenders","tags":["tenders"],"summary":"Create a tender by hand (not from a notice)","parameters":[],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"noticeId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"title":{"type":"string"},"buyerName":{"type":"string"},"buyerType":{"type":["string","null"]},"reference":{"type":["string","null"]},"valueText":{"type":["string","null"]},"deadline":{"type":["string","null"]},"clarificationDeadline":{"type":["string","null"]},"stage":{"type":"string","enum":["qualifying","live","submitted","archived"]},"outcome":{"type":"string","enum":["pending","won","lost","no_bid"]},"weighting":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"pct":{"type":["number","null"]}},"required":["label","pct"],"additionalProperties":false}},"winSignal":{"anyOf":[{"type":"integer"},{"type":"null"}]},"winCoveragePct":{"anyOf":[{"type":"integer"},{"type":"null"}]},"estateMetrics":{"type":"object","additionalProperties":{}},"milestones":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":200},"startWeek":{"type":"integer","minimum":1,"maximum":520},"endWeek":{"type":"integer","minimum":1,"maximum":520},"owner":{"type":"string","maxLength":100},"dependsOn":{"type":"string","maxLength":200}},"required":["label","startWeek","endWeek"],"additionalProperties":false}},"bidDraftRun":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","enum":["queued","running","succeeded","failed"]},"requestedAt":{"type":"string"},"requestedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"startedAt":{"type":["string","null"]},"finishedAt":{"type":["string","null"]},"total":{"type":"integer"},"processed":{"type":"integer"},"accepted":{"type":"integer"},"reused":{"type":"integer"},"open":{"type":"integer"},"inFlight":{"type":"integer","default":0},"alreadyDone":{"type":"integer"},"error":{"type":["string","null"]}},"required":["status","requestedAt","requestedByUserId","startedAt","finishedAt","total","processed","accepted","reused","open","alreadyDone","error"],"additionalProperties":false},{"type":"null"}]},"visibility":{"type":"string","enum":["client","bidwriter"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","companyId","noticeId","title","buyerName","buyerType","reference","valueText","deadline","clarificationDeadline","stage","outcome","weighting","winSignal","winCoveragePct","estateMetrics","milestones","bidDraftRun","visibility","createdAt","updatedAt"],"additionalProperties":false}}}},"201":{"description":"The tender (201; 200 with the existing row on a repeat).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"noticeId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"title":{"type":"string"},"buyerName":{"type":"string"},"buyerType":{"type":["string","null"]},"reference":{"type":["string","null"]},"valueText":{"type":["string","null"]},"deadline":{"type":["string","null"]},"clarificationDeadline":{"type":["string","null"]},"stage":{"type":"string","enum":["qualifying","live","submitted","archived"]},"outcome":{"type":"string","enum":["pending","won","lost","no_bid"]},"weighting":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"pct":{"type":["number","null"]}},"required":["label","pct"],"additionalProperties":false}},"winSignal":{"anyOf":[{"type":"integer"},{"type":"null"}]},"winCoveragePct":{"anyOf":[{"type":"integer"},{"type":"null"}]},"estateMetrics":{"type":"object","additionalProperties":{}},"milestones":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":200},"startWeek":{"type":"integer","minimum":1,"maximum":520},"endWeek":{"type":"integer","minimum":1,"maximum":520},"owner":{"type":"string","maxLength":100},"dependsOn":{"type":"string","maxLength":200}},"required":["label","startWeek","endWeek"],"additionalProperties":false}},"bidDraftRun":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","enum":["queued","running","succeeded","failed"]},"requestedAt":{"type":"string"},"requestedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"startedAt":{"type":["string","null"]},"finishedAt":{"type":["string","null"]},"total":{"type":"integer"},"processed":{"type":"integer"},"accepted":{"type":"integer"},"reused":{"type":"integer"},"open":{"type":"integer"},"inFlight":{"type":"integer","default":0},"alreadyDone":{"type":"integer"},"error":{"type":["string","null"]}},"required":["status","requestedAt","requestedByUserId","startedAt","finishedAt","total","processed","accepted","reused","open","alreadyDone","error"],"additionalProperties":false},{"type":"null"}]},"visibility":{"type":"string","enum":["client","bidwriter"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","companyId","noticeId","title","buyerName","buyerType","reference","valueText","deadline","clarificationDeadline","stage","outcome","weighting","winSignal","winCoveragePct","estateMetrics","milestones","bidDraftRun","visibility","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Same title and buyer within 60 s ⇒ the existing row with 200 (ADR-0012: a double click is likelier than two identical bids a minute apart).","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"noticeId":{"type":"string","format":"uuid"},"title":{"type":"string","minLength":1,"maxLength":500},"buyerName":{"type":"string","minLength":1,"maxLength":300},"buyerType":{"type":"string","enum":["nhs_trust","local_authority","university","school","housing","central_government","private"]},"reference":{"type":"string","maxLength":100},"valueText":{"type":"string","maxLength":100},"deadline":{"type":"string","format":"date-time"}},"required":["title","buyerName","buyerType"],"additionalProperties":false}}}}}},"/tenders/{id}":{"get":{"operationId":"getTendersId","tags":["tenders"],"summary":"A tender in full: questions, checklist, clarifications and batches, pack documents, go/no-go, submission, extraction flags, progress","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The tender detail.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"noticeId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"title":{"type":"string"},"buyerName":{"type":"string"},"buyerType":{"type":["string","null"]},"reference":{"type":["string","null"]},"valueText":{"type":["string","null"]},"deadline":{"type":["string","null"]},"clarificationDeadline":{"type":["string","null"]},"stage":{"type":"string","enum":["qualifying","live","submitted","archived"]},"outcome":{"type":"string","enum":["pending","won","lost","no_bid"]},"weighting":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"pct":{"type":["number","null"]}},"required":["label","pct"],"additionalProperties":false}},"winSignal":{"anyOf":[{"type":"integer"},{"type":"null"}]},"winCoveragePct":{"anyOf":[{"type":"integer"},{"type":"null"}]},"estateMetrics":{"type":"object","additionalProperties":{}},"milestones":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":200},"startWeek":{"type":"integer","minimum":1,"maximum":520},"endWeek":{"type":"integer","minimum":1,"maximum":520},"owner":{"type":"string","maxLength":100},"dependsOn":{"type":"string","maxLength":200}},"required":["label","startWeek","endWeek"],"additionalProperties":false}},"bidDraftRun":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","enum":["queued","running","succeeded","failed"]},"requestedAt":{"type":"string"},"requestedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"startedAt":{"type":["string","null"]},"finishedAt":{"type":["string","null"]},"total":{"type":"integer"},"processed":{"type":"integer"},"accepted":{"type":"integer"},"reused":{"type":"integer"},"open":{"type":"integer"},"inFlight":{"type":"integer","default":0},"alreadyDone":{"type":"integer"},"error":{"type":["string","null"]}},"required":["status","requestedAt","requestedByUserId","startedAt","finishedAt","total","processed","accepted","reused","open","alreadyDone","error"],"additionalProperties":false},{"type":"null"}]},"visibility":{"type":"string","enum":["client","bidwriter"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"notice":{"anyOf":[{"type":"object","properties":{"description":{"type":["string","null"]},"sourceUrl":{"type":["string","null"]},"portalLinks":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"label":{"type":"string"}},"required":["url","label"],"additionalProperties":false}}},"required":["description","sourceUrl","portalLinks"],"additionalProperties":false},{"type":"null"}]},"interview":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","ready","failed"]},"answered":{"type":"integer","minimum":0},"total":{"type":"integer","minimum":0},"answeredAt":{"type":["string","null"]},"generationError":{"type":["string","null"]},"error":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","status","answered","total","answeredAt","generationError","error","createdAt"],"additionalProperties":false},{"type":"null"}]},"incumbent":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","complete","failed"]},"verdict":{"anyOf":[{"type":"string","enum":["found","candidates","not_found","skipped"]},{"type":"null"}]},"provider":{"type":["string","null"]},"buyerKey":{"type":["string","null"]},"queries":{"type":"array","items":{"type":"string"}},"heldNoticesChecked":{"type":"integer","minimum":0},"coverageSince":{"type":["string","null"]},"candidates":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":300},"source":{"type":"string","enum":["award_notice","web"]},"url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"title":{"type":"string","maxLength":500},"noticeId":{"type":"string","format":"uuid"},"contractStart":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"contractEnd":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"valueGbp":{"type":["number","null"]},"confidence":{"type":"string","enum":["high","medium","low"]},"quote":{"type":"string","maxLength":600},"query":{"type":"string","maxLength":300},"retrievedAt":{"type":"string"},"factId":{"type":"string","format":"uuid"}},"required":["name","source","url","confidence","quote"],"additionalProperties":false}},"error":{"type":["string","null"]},"completedAt":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","tenderId","status","verdict","provider","buyerKey","queries","heldNoticesChecked","coverageSince","candidates","error","completedAt","createdAt"],"additionalProperties":false},{"type":"null"}]},"questions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"ref":{"type":"string"},"title":{"type":"string"},"questionText":{"type":"string"},"weightPct":{"type":"number"},"wordLimit":{"anyOf":[{"type":"integer"},{"type":"null"}]},"rubric":{"type":"array","items":{"type":"object","properties":{"band":{"type":"string"},"label":{"type":"string"},"text":{"type":"string"}},"required":["band","label","text"],"additionalProperties":false}},"ownerMembershipId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"status":{"type":"string","enum":["not_started","drafting","draft_failed","in_progress","draft_complete","reviewed","signed_off"]},"visibility":{"type":"string","enum":["client","bidwriter"]},"draftError":{"type":["string","null"]},"draftRequestedAt":{"type":["string","null"]},"draftedAt":{"type":["string","null"]},"reviewRequestedAt":{"type":["string","null"]},"reviewError":{"type":["string","null"]},"reviewerUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"signedOffByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"signedOffAt":{"type":["string","null"]},"sort":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"coveragePct":{"type":["number","null"]},"wordsDrafted":{"type":"integer"}},"required":["id","tenderId","companyId","ref","title","questionText","weightPct","wordLimit","rubric","ownerMembershipId","status","visibility","draftError","draftRequestedAt","draftedAt","reviewRequestedAt","reviewError","reviewerUserId","signedOffByUserId","signedOffAt","sort","createdAt","updatedAt","coveragePct","wordsDrafted"],"additionalProperties":false}},"checklist":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"label":{"type":"string"},"status":{"type":"string","enum":["ok","missing","pending"]},"factId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"source":{"type":"string","enum":["extracted","manual"]},"sort":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","label","status","factId","source","sort","createdAt","updatedAt"],"additionalProperties":false}},"clarifications":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"topic":{"type":"string"},"draftQuestion":{"type":"string"},"status":{"type":"string","enum":["logged","sent","answered"]},"affectedQuestionRef":{"type":["string","null"]},"answer":{"type":["string","null"]},"answeredAt":{"type":["string","null"]},"appliedChange":{"anyOf":[{"type":"object","properties":{"field":{"type":"string"},"from":{"type":["number","null"]},"to":{"type":"number"}},"required":["field","from","to"],"additionalProperties":false},{"type":"null"}]},"draftRequestedAt":{"type":["string","null"]},"draftedAt":{"type":["string","null"]},"draftError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","topic","draftQuestion","status","affectedQuestionRef","answer","answeredAt","appliedChange","draftRequestedAt","draftedAt","draftError","createdAt","updatedAt"],"additionalProperties":false}},"clarificationBatches":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"version":{"type":"integer"},"status":{"type":"string","enum":["drafting","drafted","failed","sent"]},"itemIds":{"type":"array","items":{"type":"string","format":"uuid"}},"subject":{"type":["string","null"]},"emailText":{"type":"string"},"model":{"type":["string","null"]},"error":{"type":["string","null"]},"sentAt":{"type":["string","null"]},"replyText":{"type":["string","null"]},"replyStatus":{"anyOf":[{"type":"string","enum":["mapping","mapped","failed"]},{"type":"null"}]},"replyMapping":{"anyOf":[{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"n":{"type":"integer","minimum":1},"clarificationId":{"type":"string","format":"uuid"},"answer":{"type":["string","null"]},"verbatim":{"type":"boolean"},"apply":{"anyOf":[{"type":"object","properties":{"questionRef":{"type":"string","minLength":1,"maxLength":40},"field":{"type":"string","enum":["weight_pct","word_limit"]},"value":{"type":"number","minimum":0,"maximum":100000}},"required":["questionRef","field","value"],"additionalProperties":false},{"type":"null"}]},"confidence":{"type":"string","enum":["high","medium","low"]},"note":{"type":["string","null"]}},"required":["n","clarificationId","answer","verbatim","apply","confidence","note"],"additionalProperties":false}},"unassigned":{"type":"array","items":{"type":"string"}}},"required":["items","unassigned"],"additionalProperties":false},{"type":"null"}]},"replyError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","version","status","itemIds","subject","emailText","model","error","sentAt","replyText","replyStatus","replyMapping","replyError","createdAt","updatedAt"],"additionalProperties":false}},"documents":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"title":{"type":"string"},"storageUri":{"type":"string"},"mimeType":{"type":"string"},"status":{"type":"string","enum":["uploaded","parsing","parsed","failed"]},"metadata":{"type":"object","additionalProperties":{}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","title","storageUri","mimeType","status","metadata","createdAt","updatedAt"],"additionalProperties":false}},"gng":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"recommendation":{"type":"string","enum":["bid","no_bid","insufficient_evidence"]},"winSignal":{"anyOf":[{"type":"integer","minimum":0,"maximum":100},{"type":"null"}]},"coveragePct":{"type":"integer","minimum":0,"maximum":100},"savedCostEstimate":{"type":["string","null"]},"factors":{"type":"array","items":{"type":"object","properties":{"key":{"anyOf":[{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]},{"type":"null"}]},"weight":{"type":"number","minimum":0,"maximum":1},"status":{"type":"string","enum":["scored","unscored"]},"evidence":{"type":"string","enum":["computed","interview","manual","none"]},"score":{"anyOf":[{"type":"number","minimum":0,"maximum":10},{"type":"null"}]},"basis":{"type":"string"},"unscoredReason":{"type":"string"},"sources":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["fact","award_notice","award_benchmarks","feed_fit","wins","profile","web"]},"id":{"type":"string"},"label":{"type":"string"},"url":{"type":"string"}},"required":["kind","label"],"additionalProperties":false},"default":[]},"openQuestions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"prompt":{"type":"string"}},"required":["key","prompt"],"additionalProperties":false}},"label":{"type":"string"}},"required":["key","weight","status","evidence","score","basis"],"additionalProperties":false}},"decision":{"anyOf":[{"type":"string","enum":["bid","no_bid"]},{"type":"null"}]},"decisionReason":{"type":["string","null"]},"interviewId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"default":null},"incumbentSearchId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"default":null},"companyId":{"type":"string","format":"uuid"},"decidedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","recommendation","winSignal","coveragePct","savedCostEstimate","factors","decision","decisionReason","companyId","decidedByUserId","createdAt","updatedAt"],"additionalProperties":false},{"type":"null"}]},"submission":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"template":{"type":"string","enum":["branded","plain"]},"wordTotal":{"type":"integer"},"exportUri":{"type":["string","null"]},"exportedAt":{"type":["string","null"]},"submittedAt":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","template","wordTotal","exportUri","exportedAt","submittedAt","createdAt","updatedAt"],"additionalProperties":false},{"type":"null"}]},"extractionFlags":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["conflict","ambiguity","not_found"]},"field":{"type":"string"},"detail":{"type":"string"},"suggest_clarification":{"type":"boolean"}},"required":["kind","field","detail","suggest_clarification"],"additionalProperties":false}},"latestExtraction":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","complete","failed"]},"error":{"type":["string","null"]},"createdAt":{"type":"string"},"startedAt":{"type":["string","null"]},"finishedAt":{"type":["string","null"]}},"required":["id","status","error","createdAt","startedAt","finishedAt"],"additionalProperties":false},{"type":"null"}]},"hasCompleteExtraction":{"type":"boolean"},"progress":{"type":"object","properties":{"steps":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","enum":["find","qualify","pack","analyse","clarify","interview","gng","plan","draft","submit","outcome"]},"status":{"type":"string","enum":["done","current","running","stale","failed","attention","todo","skipped"]},"required":{"type":"boolean"},"detail":{"type":["string","null"]}},"required":["key","status","required","detail"],"additionalProperties":false}},"current":{"anyOf":[{"type":"string","enum":["find","qualify","pack","analyse","clarify","interview","gng","plan","draft","submit","outcome"]},{"type":"null"}]},"committed":{"type":"boolean"},"decision":{"anyOf":[{"type":"string","enum":["bid","no_bid"]},{"type":"null"}]},"planGate":{"type":"object","properties":{"open":{"type":"boolean"},"missing":{"type":"array","items":{"type":"string","enum":["extraction","gng_decision","archived","plan_exists"]}},"openClarifications":{"type":"integer"}},"required":["open","missing","openClarifications"],"additionalProperties":false}},"required":["steps","current","committed","decision","planGate"],"additionalProperties":false}},"required":["id","companyId","noticeId","title","buyerName","buyerType","reference","valueText","deadline","clarificationDeadline","stage","outcome","weighting","winSignal","winCoveragePct","estateMetrics","milestones","bidDraftRun","visibility","createdAt","updatedAt","notice","interview","incumbent","questions","checklist","clarifications","clarificationBatches","documents","gng","submission","extractionFlags","latestExtraction","hasCompleteExtraction","progress"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}},"delete":{"operationId":"deleteTendersId","tags":["tenders"],"summary":"Remove a qualifying tender the team will not pursue (its pack files go with it)","description":"Qualifying only: a live tender is refused with 409 and pointed at the go/no-go decision, which is the route that archives a live bid. Irreversible — ask the person first.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted."},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Already gone ⇒ 404.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/tenders/{id}/page":{"get":{"operationId":"getTendersIdPage","tags":["tenders"],"summary":"The whole picture in one call: detail, readiness, action log, members, time summary, go/no-go prefill, fast-path preview, interview","description":"The page aggregate (ADR-0018). Optional surfaces are null when they do not apply (prefill only before a scorecard exists, fastPath only once a plan exists, interview only when prepared). Prefer this over several per-resource reads.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Everything the tender page renders.","content":{"application/json":{"schema":{"type":"object","properties":{"tender":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"noticeId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"title":{"type":"string"},"buyerName":{"type":"string"},"buyerType":{"type":["string","null"]},"reference":{"type":["string","null"]},"valueText":{"type":["string","null"]},"deadline":{"type":["string","null"]},"clarificationDeadline":{"type":["string","null"]},"stage":{"type":"string","enum":["qualifying","live","submitted","archived"]},"outcome":{"type":"string","enum":["pending","won","lost","no_bid"]},"weighting":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"pct":{"type":["number","null"]}},"required":["label","pct"],"additionalProperties":false}},"winSignal":{"anyOf":[{"type":"integer"},{"type":"null"}]},"winCoveragePct":{"anyOf":[{"type":"integer"},{"type":"null"}]},"estateMetrics":{"type":"object","additionalProperties":{}},"milestones":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":200},"startWeek":{"type":"integer","minimum":1,"maximum":520},"endWeek":{"type":"integer","minimum":1,"maximum":520},"owner":{"type":"string","maxLength":100},"dependsOn":{"type":"string","maxLength":200}},"required":["label","startWeek","endWeek"],"additionalProperties":false}},"bidDraftRun":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","enum":["queued","running","succeeded","failed"]},"requestedAt":{"type":"string"},"requestedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"startedAt":{"type":["string","null"]},"finishedAt":{"type":["string","null"]},"total":{"type":"integer"},"processed":{"type":"integer"},"accepted":{"type":"integer"},"reused":{"type":"integer"},"open":{"type":"integer"},"inFlight":{"type":"integer","default":0},"alreadyDone":{"type":"integer"},"error":{"type":["string","null"]}},"required":["status","requestedAt","requestedByUserId","startedAt","finishedAt","total","processed","accepted","reused","open","alreadyDone","error"],"additionalProperties":false},{"type":"null"}]},"visibility":{"type":"string","enum":["client","bidwriter"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"notice":{"anyOf":[{"type":"object","properties":{"description":{"type":["string","null"]},"sourceUrl":{"type":["string","null"]},"portalLinks":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"label":{"type":"string"}},"required":["url","label"],"additionalProperties":false}}},"required":["description","sourceUrl","portalLinks"],"additionalProperties":false},{"type":"null"}]},"interview":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","ready","failed"]},"answered":{"type":"integer","minimum":0},"total":{"type":"integer","minimum":0},"answeredAt":{"type":["string","null"]},"generationError":{"type":["string","null"]},"error":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","status","answered","total","answeredAt","generationError","error","createdAt"],"additionalProperties":false},{"type":"null"}]},"incumbent":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","complete","failed"]},"verdict":{"anyOf":[{"type":"string","enum":["found","candidates","not_found","skipped"]},{"type":"null"}]},"provider":{"type":["string","null"]},"buyerKey":{"type":["string","null"]},"queries":{"type":"array","items":{"type":"string"}},"heldNoticesChecked":{"type":"integer","minimum":0},"coverageSince":{"type":["string","null"]},"candidates":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":300},"source":{"type":"string","enum":["award_notice","web"]},"url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"title":{"type":"string","maxLength":500},"noticeId":{"type":"string","format":"uuid"},"contractStart":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"contractEnd":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"valueGbp":{"type":["number","null"]},"confidence":{"type":"string","enum":["high","medium","low"]},"quote":{"type":"string","maxLength":600},"query":{"type":"string","maxLength":300},"retrievedAt":{"type":"string"},"factId":{"type":"string","format":"uuid"}},"required":["name","source","url","confidence","quote"],"additionalProperties":false}},"error":{"type":["string","null"]},"completedAt":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","tenderId","status","verdict","provider","buyerKey","queries","heldNoticesChecked","coverageSince","candidates","error","completedAt","createdAt"],"additionalProperties":false},{"type":"null"}]},"questions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"ref":{"type":"string"},"title":{"type":"string"},"questionText":{"type":"string"},"weightPct":{"type":"number"},"wordLimit":{"anyOf":[{"type":"integer"},{"type":"null"}]},"rubric":{"type":"array","items":{"type":"object","properties":{"band":{"type":"string"},"label":{"type":"string"},"text":{"type":"string"}},"required":["band","label","text"],"additionalProperties":false}},"ownerMembershipId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"status":{"type":"string","enum":["not_started","drafting","draft_failed","in_progress","draft_complete","reviewed","signed_off"]},"visibility":{"type":"string","enum":["client","bidwriter"]},"draftError":{"type":["string","null"]},"draftRequestedAt":{"type":["string","null"]},"draftedAt":{"type":["string","null"]},"reviewRequestedAt":{"type":["string","null"]},"reviewError":{"type":["string","null"]},"reviewerUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"signedOffByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"signedOffAt":{"type":["string","null"]},"sort":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"coveragePct":{"type":["number","null"]},"wordsDrafted":{"type":"integer"}},"required":["id","tenderId","companyId","ref","title","questionText","weightPct","wordLimit","rubric","ownerMembershipId","status","visibility","draftError","draftRequestedAt","draftedAt","reviewRequestedAt","reviewError","reviewerUserId","signedOffByUserId","signedOffAt","sort","createdAt","updatedAt","coveragePct","wordsDrafted"],"additionalProperties":false}},"checklist":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"label":{"type":"string"},"status":{"type":"string","enum":["ok","missing","pending"]},"factId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"source":{"type":"string","enum":["extracted","manual"]},"sort":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","label","status","factId","source","sort","createdAt","updatedAt"],"additionalProperties":false}},"clarifications":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"topic":{"type":"string"},"draftQuestion":{"type":"string"},"status":{"type":"string","enum":["logged","sent","answered"]},"affectedQuestionRef":{"type":["string","null"]},"answer":{"type":["string","null"]},"answeredAt":{"type":["string","null"]},"appliedChange":{"anyOf":[{"type":"object","properties":{"field":{"type":"string"},"from":{"type":["number","null"]},"to":{"type":"number"}},"required":["field","from","to"],"additionalProperties":false},{"type":"null"}]},"draftRequestedAt":{"type":["string","null"]},"draftedAt":{"type":["string","null"]},"draftError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","topic","draftQuestion","status","affectedQuestionRef","answer","answeredAt","appliedChange","draftRequestedAt","draftedAt","draftError","createdAt","updatedAt"],"additionalProperties":false}},"clarificationBatches":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"version":{"type":"integer"},"status":{"type":"string","enum":["drafting","drafted","failed","sent"]},"itemIds":{"type":"array","items":{"type":"string","format":"uuid"}},"subject":{"type":["string","null"]},"emailText":{"type":"string"},"model":{"type":["string","null"]},"error":{"type":["string","null"]},"sentAt":{"type":["string","null"]},"replyText":{"type":["string","null"]},"replyStatus":{"anyOf":[{"type":"string","enum":["mapping","mapped","failed"]},{"type":"null"}]},"replyMapping":{"anyOf":[{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"n":{"type":"integer","minimum":1},"clarificationId":{"type":"string","format":"uuid"},"answer":{"type":["string","null"]},"verbatim":{"type":"boolean"},"apply":{"anyOf":[{"type":"object","properties":{"questionRef":{"type":"string","minLength":1,"maxLength":40},"field":{"type":"string","enum":["weight_pct","word_limit"]},"value":{"type":"number","minimum":0,"maximum":100000}},"required":["questionRef","field","value"],"additionalProperties":false},{"type":"null"}]},"confidence":{"type":"string","enum":["high","medium","low"]},"note":{"type":["string","null"]}},"required":["n","clarificationId","answer","verbatim","apply","confidence","note"],"additionalProperties":false}},"unassigned":{"type":"array","items":{"type":"string"}}},"required":["items","unassigned"],"additionalProperties":false},{"type":"null"}]},"replyError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","version","status","itemIds","subject","emailText","model","error","sentAt","replyText","replyStatus","replyMapping","replyError","createdAt","updatedAt"],"additionalProperties":false}},"documents":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"title":{"type":"string"},"storageUri":{"type":"string"},"mimeType":{"type":"string"},"status":{"type":"string","enum":["uploaded","parsing","parsed","failed"]},"metadata":{"type":"object","additionalProperties":{}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","title","storageUri","mimeType","status","metadata","createdAt","updatedAt"],"additionalProperties":false}},"gng":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"recommendation":{"type":"string","enum":["bid","no_bid","insufficient_evidence"]},"winSignal":{"anyOf":[{"type":"integer","minimum":0,"maximum":100},{"type":"null"}]},"coveragePct":{"type":"integer","minimum":0,"maximum":100},"savedCostEstimate":{"type":["string","null"]},"factors":{"type":"array","items":{"type":"object","properties":{"key":{"anyOf":[{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]},{"type":"null"}]},"weight":{"type":"number","minimum":0,"maximum":1},"status":{"type":"string","enum":["scored","unscored"]},"evidence":{"type":"string","enum":["computed","interview","manual","none"]},"score":{"anyOf":[{"type":"number","minimum":0,"maximum":10},{"type":"null"}]},"basis":{"type":"string"},"unscoredReason":{"type":"string"},"sources":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["fact","award_notice","award_benchmarks","feed_fit","wins","profile","web"]},"id":{"type":"string"},"label":{"type":"string"},"url":{"type":"string"}},"required":["kind","label"],"additionalProperties":false},"default":[]},"openQuestions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"prompt":{"type":"string"}},"required":["key","prompt"],"additionalProperties":false}},"label":{"type":"string"}},"required":["key","weight","status","evidence","score","basis"],"additionalProperties":false}},"decision":{"anyOf":[{"type":"string","enum":["bid","no_bid"]},{"type":"null"}]},"decisionReason":{"type":["string","null"]},"interviewId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"default":null},"incumbentSearchId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"default":null},"companyId":{"type":"string","format":"uuid"},"decidedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","recommendation","winSignal","coveragePct","savedCostEstimate","factors","decision","decisionReason","companyId","decidedByUserId","createdAt","updatedAt"],"additionalProperties":false},{"type":"null"}]},"submission":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"template":{"type":"string","enum":["branded","plain"]},"wordTotal":{"type":"integer"},"exportUri":{"type":["string","null"]},"exportedAt":{"type":["string","null"]},"submittedAt":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","template","wordTotal","exportUri","exportedAt","submittedAt","createdAt","updatedAt"],"additionalProperties":false},{"type":"null"}]},"extractionFlags":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["conflict","ambiguity","not_found"]},"field":{"type":"string"},"detail":{"type":"string"},"suggest_clarification":{"type":"boolean"}},"required":["kind","field","detail","suggest_clarification"],"additionalProperties":false}},"latestExtraction":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","complete","failed"]},"error":{"type":["string","null"]},"createdAt":{"type":"string"},"startedAt":{"type":["string","null"]},"finishedAt":{"type":["string","null"]}},"required":["id","status","error","createdAt","startedAt","finishedAt"],"additionalProperties":false},{"type":"null"}]},"hasCompleteExtraction":{"type":"boolean"},"progress":{"type":"object","properties":{"steps":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","enum":["find","qualify","pack","analyse","clarify","interview","gng","plan","draft","submit","outcome"]},"status":{"type":"string","enum":["done","current","running","stale","failed","attention","todo","skipped"]},"required":{"type":"boolean"},"detail":{"type":["string","null"]}},"required":["key","status","required","detail"],"additionalProperties":false}},"current":{"anyOf":[{"type":"string","enum":["find","qualify","pack","analyse","clarify","interview","gng","plan","draft","submit","outcome"]},{"type":"null"}]},"committed":{"type":"boolean"},"decision":{"anyOf":[{"type":"string","enum":["bid","no_bid"]},{"type":"null"}]},"planGate":{"type":"object","properties":{"open":{"type":"boolean"},"missing":{"type":"array","items":{"type":"string","enum":["extraction","gng_decision","archived","plan_exists"]}},"openClarifications":{"type":"integer"}},"required":["open","missing","openClarifications"],"additionalProperties":false}},"required":["steps","current","committed","decision","planGate"],"additionalProperties":false}},"required":["id","companyId","noticeId","title","buyerName","buyerType","reference","valueText","deadline","clarificationDeadline","stage","outcome","weighting","winSignal","winCoveragePct","estateMetrics","milestones","bidDraftRun","visibility","createdAt","updatedAt","notice","interview","incumbent","questions","checklist","clarifications","clarificationBatches","documents","gng","submission","extractionFlags","latestExtraction","hasCompleteExtraction","progress"],"additionalProperties":false},"readiness":{"anyOf":[{"type":"integer","minimum":0,"maximum":100},{"type":"null"}]},"activity":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"action":{"type":"string"},"detail":{"type":"object","additionalProperties":{}},"at":{"type":"string"},"actor":{"type":"string"},"questionRef":{"type":["string","null"]}},"required":["action","detail","at","actor","questionRef"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false},"members":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"membershipId":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":"string"},"role":{"type":"string","enum":["admin","member","bidwriter"]}},"required":["membershipId","userId","email","name","role"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false},"timeSummary":{"anyOf":[{"type":"object","properties":{"stages":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"at":{"type":"string"}},"required":["label","at"],"additionalProperties":false}},"sessions":{"type":"integer"},"activeMinutes":{"type":"number"},"elapsedHours":{"type":["number","null"]}},"required":["stages","sessions","activeMinutes","elapsedHours"],"additionalProperties":false},{"type":"null"}]},"prefill":{"anyOf":[{"type":"object","properties":{"factors":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]},"weight":{"type":"number","minimum":0,"maximum":1},"status":{"type":"string","enum":["scored","unscored"]},"evidence":{"type":"string","enum":["computed","interview","manual","none"]},"score":{"anyOf":[{"type":"number","minimum":0,"maximum":10},{"type":"null"}]},"basis":{"type":"string"},"unscoredReason":{"type":"string"},"sources":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["fact","award_notice","award_benchmarks","feed_fit","wins","profile","web"]},"id":{"type":"string"},"label":{"type":"string"},"url":{"type":"string"}},"required":["kind","label"],"additionalProperties":false},"default":[]},"openQuestions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"prompt":{"type":"string"}},"required":["key","prompt"],"additionalProperties":false}},"suggestedScore":{"anyOf":[{"type":"number","minimum":0,"maximum":10},{"type":"null"}]}},"required":["key","weight","status","evidence","score","basis","suggestedScore"],"additionalProperties":false}},"coverage":{"type":"object","properties":{"scoredWeightPct":{"type":"integer","minimum":0,"maximum":100},"scoredCount":{"type":"integer","minimum":0},"unscoredCount":{"type":"integer","minimum":0},"unscoredFactors":{"type":"array","items":{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]}}},"required":["scoredWeightPct","scoredCount","unscoredCount","unscoredFactors"],"additionalProperties":false},"warnings":{"type":"array","items":{"type":"string"}},"bidCostGbp":{"type":["number","null"]},"interview":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"answered":{"type":"integer"},"total":{"type":"integer"},"answeredAt":{"type":["string","null"]},"generationError":{"type":["string","null"]}},"required":["id","status","answered","total","answeredAt","generationError"],"additionalProperties":false},{"type":"null"}],"default":null},"incumbent":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","complete","failed"]},"verdict":{"anyOf":[{"type":"string","enum":["found","candidates","not_found","skipped"]},{"type":"null"}]},"provider":{"type":["string","null"]},"buyerKey":{"type":["string","null"]},"queries":{"type":"array","items":{"type":"string"}},"heldNoticesChecked":{"type":"integer","minimum":0},"coverageSince":{"type":["string","null"]},"candidates":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":300},"source":{"type":"string","enum":["award_notice","web"]},"url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"title":{"type":"string","maxLength":500},"noticeId":{"type":"string","format":"uuid"},"contractStart":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"contractEnd":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"valueGbp":{"type":["number","null"]},"confidence":{"type":"string","enum":["high","medium","low"]},"quote":{"type":"string","maxLength":600},"query":{"type":"string","maxLength":300},"retrievedAt":{"type":"string"},"factId":{"type":"string","format":"uuid"}},"required":["name","source","url","confidence","quote"],"additionalProperties":false}},"error":{"type":["string","null"]},"completedAt":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","tenderId","status","verdict","provider","buyerKey","queries","heldNoticesChecked","coverageSince","candidates","error","completedAt","createdAt"],"additionalProperties":false},{"type":"null"}],"default":null}},"required":["factors","coverage","warnings","bidCostGbp"],"additionalProperties":false},{"type":"null"}]},"fastPath":{"anyOf":[{"type":"object","properties":{"accept":{"type":"integer"},"reuse":{"type":"integer"},"open":{"type":"integer"},"unchecked":{"type":"integer"},"done":{"type":"integer"},"inFlight":{"type":"integer"},"questions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"ref":{"type":"string"},"bucket":{"type":"string","enum":["accept","reuse","open","unchecked","done","in_flight"]},"matchedQuestion":{"type":["string","null"]}},"required":["id","ref","bucket","matchedQuestion"],"additionalProperties":false}},"run":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","enum":["queued","running","succeeded","failed"]},"requestedAt":{"type":"string"},"requestedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"startedAt":{"type":["string","null"]},"finishedAt":{"type":["string","null"]},"total":{"type":"integer"},"processed":{"type":"integer"},"accepted":{"type":"integer"},"reused":{"type":"integer"},"open":{"type":"integer"},"inFlight":{"type":"integer","default":0},"alreadyDone":{"type":"integer"},"error":{"type":["string","null"]}},"required":["status","requestedAt","requestedByUserId","startedAt","finishedAt","total","processed","accepted","reused","open","alreadyDone","error"],"additionalProperties":false},{"type":"null"}]}},"required":["accept","reuse","open","unchecked","done","inFlight","questions","run"],"additionalProperties":false},{"type":"null"}]},"interview":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","ready","failed"]},"answered":{"type":"integer","minimum":0},"total":{"type":"integer","minimum":0},"answeredAt":{"type":["string","null"]},"generationError":{"type":["string","null"]},"error":{"type":["string","null"]},"createdAt":{"type":"string"},"questions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z_]+\\.[a-z0-9_]+(:[a-z0-9_]+)?$"},"factor":{"anyOf":[{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]},{"type":"null"}]},"side":{"type":"string","enum":["bid","buy","docs"]},"scope":{"type":"string","enum":["company","buyer","tender"]},"factType":{"type":"string","enum":["cert","insurance","cv","case_study","kpi","policy","pricing_model","other","capability","capacity","appetite","relationship","buyer_intel","incumbent"]},"prompt":{"type":"string","minLength":1,"maxLength":300},"why":{"type":"string","maxLength":240},"answerKind":{"type":"string","enum":["text","number","choice","yes_no"]},"choices":{"type":"array","items":{"type":"string"},"maxItems":6},"validityMonths":{"anyOf":[{"type":"integer","minimum":1,"maximum":60},{"type":"null"}]},"source":{"type":"string","enum":["catalogue","adhoc"]},"factLabel":{"type":"string","maxLength":200},"supporting":{"type":"boolean"},"context":{"type":"string","maxLength":300},"candidateIndex":{"type":"integer","minimum":0},"current":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionKey":{"type":"string"},"scope":{"type":"string","enum":["company","buyer","tender"]},"factType":{"type":"string","enum":["cert","insurance","cv","case_study","kpi","policy","pricing_model","other","capability","capacity","appetite","relationship","buyer_intel","incumbent"]},"label":{"type":"string"},"valueText":{"type":["string","null"]},"valueJson":{"anyOf":[{"type":"object","additionalProperties":{}},{"type":"null"}]},"status":{"type":"string","enum":["ok","expiring","expired","unknown"]},"expiresAt":{"type":["string","null"]},"createdAt":{"type":"string"},"origin":{"type":"string","enum":["manual","upload","interview","award_notice","web_search"]},"url":{"type":["string","null"]},"tenderId":{"type":["string","null"]},"tenderTitle":{"type":["string","null"]},"answeredBy":{"type":["string","null"]},"version":{"type":"integer","minimum":1},"notKnown":{"type":"boolean"}},"required":["id","questionKey","scope","factType","label","valueText","valueJson","status","expiresAt","createdAt","origin","url","tenderId","tenderTitle","answeredBy","version","notKnown"],"additionalProperties":false},{"type":"null"}]},"reuse":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionKey":{"type":"string"},"scope":{"type":"string","enum":["company","buyer","tender"]},"factType":{"type":"string","enum":["cert","insurance","cv","case_study","kpi","policy","pricing_model","other","capability","capacity","appetite","relationship","buyer_intel","incumbent"]},"label":{"type":"string"},"valueText":{"type":["string","null"]},"valueJson":{"anyOf":[{"type":"object","additionalProperties":{}},{"type":"null"}]},"status":{"type":"string","enum":["ok","expiring","expired","unknown"]},"expiresAt":{"type":["string","null"]},"createdAt":{"type":"string"},"origin":{"type":"string","enum":["manual","upload","interview","award_notice","web_search"]},"url":{"type":["string","null"]},"tenderId":{"type":["string","null"]},"tenderTitle":{"type":["string","null"]},"answeredBy":{"type":["string","null"]},"version":{"type":"integer","minimum":1},"notKnown":{"type":"boolean"}},"required":["id","questionKey","scope","factType","label","valueText","valueJson","status","expiresAt","createdAt","origin","url","tenderId","tenderTitle","answeredBy","version","notKnown"],"additionalProperties":false},{"type":"null"}]},"evidence":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","enum":["scored","unscored"]},"evidence":{"type":"string","enum":["computed","interview","manual","none"]},"basis":{"type":"string"}},"required":["status","evidence","basis"],"additionalProperties":false},{"type":"null"}]}},"required":["key","factor","side","scope","factType","prompt","why","answerKind","validityMonths","source","factLabel","current","reuse","evidence"],"additionalProperties":false}},"openClarifications":{"type":"integer","minimum":0},"hasExtraction":{"type":"boolean"},"incumbent":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","complete","failed"]},"verdict":{"anyOf":[{"type":"string","enum":["found","candidates","not_found","skipped"]},{"type":"null"}]},"provider":{"type":["string","null"]},"buyerKey":{"type":["string","null"]},"queries":{"type":"array","items":{"type":"string"}},"heldNoticesChecked":{"type":"integer","minimum":0},"coverageSince":{"type":["string","null"]},"candidates":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":300},"source":{"type":"string","enum":["award_notice","web"]},"url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"title":{"type":"string","maxLength":500},"noticeId":{"type":"string","format":"uuid"},"contractStart":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"contractEnd":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"valueGbp":{"type":["number","null"]},"confidence":{"type":"string","enum":["high","medium","low"]},"quote":{"type":"string","maxLength":600},"query":{"type":"string","maxLength":300},"retrievedAt":{"type":"string"},"factId":{"type":"string","format":"uuid"}},"required":["name","source","url","confidence","quote"],"additionalProperties":false}},"error":{"type":["string","null"]},"completedAt":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","tenderId","status","verdict","provider","buyerKey","queries","heldNoticesChecked","coverageSince","candidates","error","completedAt","createdAt"],"additionalProperties":false},{"type":"null"}]}},"required":["id","status","answered","total","answeredAt","generationError","error","createdAt","questions","openClarifications","hasExtraction","incumbent"],"additionalProperties":false},{"type":"null"}]},"typical":{"type":"object","properties":{"extractTender":{"anyOf":[{"type":"object","properties":{"p50Ms":{"type":"number"},"p90Ms":{"type":"number"},"samples":{"type":"integer"}},"required":["p50Ms","p90Ms","samples"],"additionalProperties":false},{"type":"null"}]}},"required":["extractTender"],"additionalProperties":false}},"required":["tender","readiness","activity","members","timeSummary","prefill","fastPath","interview","typical"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/tenders/{id}/visibility":{"patch":{"operationId":"patchTendersIdVisibility","tags":["tenders"],"summary":"Share a bid with the client, or take it back (bid writers only)","description":"ADR-0031: a bid a WayWiser bid writer creates is private until shared. `client` shares the tender, its questions and everything keyed to them (drafts, snapshots, reviews, comments, clarifications, go/no-go runs, pack files, extractions) with the company’s members, together with the bid’s own interview answers (scope `tender`) and the answers harvested from it; `bidwriter` takes them back. The questions’ persisted evidence rows are dropped in both directions (`evidenceDropped`: the private ones on a share, every one on an un-share) and re-retrieved under the bid’s grounding on the next open. A buyer- or company-scope answer given on the bid outlives it and is shared on its own (PATCH /facts/:id/visibility). Only a bid writer (or a key acting as one) may call it — a member is refused 403 on a shared bid and sees 404 on a private one, and on every child route of one. A shared draft may cite a document or fact that is still private: the client then sees an unverified citation, never the source.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The value now carried, whether anything changed, and the child rows that followed.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"visibility":{"type":"string","enum":["client","bidwriter"]},"changed":{"type":"boolean"},"children":{"type":"object","additionalProperties":{"type":"integer"}}},"required":["id","visibility","changed","children"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"The value already carried ⇒ 200 with `changed: false`, nothing audited.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"visibility":{"type":"string","enum":["client","bidwriter"]}},"required":["visibility"],"additionalProperties":false}}}}}},"/tenders/{id}/stage":{"patch":{"operationId":"patchTendersIdStage","tags":["tenders"],"summary":"Move a tender between stages (qualifying, live, submitted, archived)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The updated tenders row — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"The updated tenders row — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Sets the stage; repeating is a no-op.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"stage":{"type":"string","enum":["qualifying","live","submitted","archived"]}},"required":["stage"],"additionalProperties":false}}}}}},"/tenders/{id}/activity":{"get":{"operationId":"getTendersIdActivity","tags":["tenders"],"summary":"The bid's action log: who changed what, when (the audit trail for this tender)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Audit rows, newest first.","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"action":{"type":"string"},"detail":{"type":"object","additionalProperties":{}},"at":{"type":"string"},"actor":{"type":"string"},"questionRef":{"type":["string","null"]}},"required":["action","detail","at","actor","questionRef"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/tenders/{id}/time-summary":{"get":{"operationId":"getTendersIdTimeSummary","tags":["tenders"],"summary":"Time spent on the bid: lifecycle stamps and editing sessions, measured, never estimated","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The summary.","content":{"application/json":{"schema":{"type":"object","properties":{"stages":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"at":{"type":"string"}},"required":["label","at"],"additionalProperties":false}},"sessions":{"type":"integer"},"activeMinutes":{"type":"number"},"elapsedHours":{"type":["number","null"]}},"required":["stages","sessions","activeMinutes","elapsedHours"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/tenders/{id}/milestones":{"put":{"operationId":"putTendersIdMilestones","tags":["tenders"],"summary":"Replace the bid-plan milestones (the timeline exhibit draws them)","description":"Either `{ milestones: [...] }` (the schema) or `{ quickEntry: \"<one milestone per line>\" }`, which the api parses; a line it cannot read is a 400 naming it.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The updated tenders row — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"The updated tenders row — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"A full replace.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"milestones":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":200},"startWeek":{"type":"integer","minimum":1,"maximum":520},"endWeek":{"type":"integer","minimum":1,"maximum":520},"owner":{"type":"string","maxLength":100},"dependsOn":{"type":"string","maxLength":200}},"required":["label","startWeek","endWeek"],"additionalProperties":false},"maxItems":60}},"required":["milestones"],"additionalProperties":false}}}}}},"/tenders/{id}/documents/upload":{"post":{"operationId":"postTendersIdDocumentsUpload","tags":["analysis"],"summary":"Upload an ITT pack file to a tender (raw bytes) — the entry point to analysis, plan, workspace and drafting","description":"Send the file bytes as the body with `Content-Type: application/octet-stream` (up to 60 MiB per file) and the name in `X-Filename`. The bytes are sniffed: the container must match the extension (an .html renamed .pdf is refused 422 `unsupported_file`, and nothing is stored).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Filename","in":"header","required":true,"description":"The file name, percent-encoded (encodeURIComponent). The extension decides the parser: .pdf, .docx, .xlsx, .pptx, .odt, .ods.","schema":{"type":"string"}},{"name":"X-Content-Type","in":"header","required":false,"description":"Optional declared document type; kept when it is one the api knows, else the extension decides.","schema":{"type":"string"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"title":{"type":"string"},"storageUri":{"type":"string"},"mimeType":{"type":"string"},"status":{"type":"string","enum":["uploaded","parsing","parsed","failed"]},"metadata":{"type":"object","additionalProperties":{}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","title","storageUri","mimeType","status","metadata","createdAt","updatedAt"],"additionalProperties":false}}}},"201":{"description":"The tender_documents row.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"title":{"type":"string"},"storageUri":{"type":"string"},"mimeType":{"type":"string"},"status":{"type":"string","enum":["uploaded","parsing","parsed","failed"]},"metadata":{"type":"object","additionalProperties":{}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","title","storageUri","mimeType","status","metadata","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"The bytes are the identity: uploading the same file twice stores two documents.","x-waywiser-rate-limit":{"bucket":"upload","limit":"30 per minute per key"},"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}}}},"/tenders/{id}/documents":{"post":{"operationId":"postTendersIdDocuments","tags":["analysis"],"summary":"Register an ITT pack object already in the bucket (the signed-URL flow; most callers want /upload)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"title":{"type":"string"},"storageUri":{"type":"string"},"mimeType":{"type":"string"},"status":{"type":"string","enum":["uploaded","parsing","parsed","failed"]},"metadata":{"type":"object","additionalProperties":{}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","title","storageUri","mimeType","status","metadata","createdAt","updatedAt"],"additionalProperties":false}}}},"201":{"description":"The tender_documents row (201; 200 when the object was already registered).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"title":{"type":"string"},"storageUri":{"type":"string"},"mimeType":{"type":"string"},"status":{"type":"string","enum":["uploaded","parsing","parsed","failed"]},"metadata":{"type":"object","additionalProperties":{}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","title","storageUri","mimeType","status","metadata","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"The same storageUri registered twice is one document (200).","x-waywiser-rate-limit":{"bucket":"upload","limit":"30 per minute per key"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1},"storageUri":{"type":"string","minLength":1},"mimeType":{"type":"string","default":"application/pdf"}},"required":["title","storageUri"],"additionalProperties":false}}}}}},"/tenders/{id}/extract":{"post":{"operationId":"postTendersIdExtract","tags":["analysis"],"summary":"Analyse the pack: parse, extract questions, weighting, deadlines and compliance items, flag low confidence","description":"Queues the extraction (typically 4–8 minutes). One analysis at a time per tender: a repeat while one is queued or running is 409 `conflict`. Poll `operation.poll`; when `state` is `done`, create the plan.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["id","status","operation"],"additionalProperties":true}}}},"202":{"description":"The extractions row plus the operation to poll.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["id","status","operation"],"additionalProperties":true}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited, or the company’s daily AI budget is spent (`ai_budget_exceeded`); `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"503":{"description":"The job queue is unavailable (`queue_unavailable`): nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Refused (409) while a run is in flight; a stale run older than the guard is superseded.","x-waywiser-rate-limit":{"bucket":"ai","limit":"10 per minute per key, and the company daily AI token ceiling"},"x-waywiser-async":{"kind":"extraction","poll":"/activity?target=<extractionId>"}}},"/tenders/{id}/extractions":{"get":{"operationId":"getTendersIdExtractions","tags":["analysis"],"summary":"Every extraction run for the tender, newest first (status, flags, error)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"`{ items: [...] }` of extractions rows — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"`{ items: [...] }` of extractions rows — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/tenders/{id}/plan":{"post":{"operationId":"postTendersIdPlan","tags":["analysis"],"summary":"Create the bid plan from the latest complete extraction (questions + checklist), once","description":"Gated: a complete extraction AND a logged bid decision on a live tender. The 409 names the missing gate in the same words the web shows. Evidence for every question is pre-warmed in the background.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"created":{"type":"boolean"}},"required":["ok","created"],"additionalProperties":false}}}},"201":{"description":"`created: false` with 200 when the plan already exists.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"created":{"type":"boolean"}},"required":["ok","created"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"One plan per tender: a repeat is 200 `{ created: false }`.","x-waywiser-rate-limit":{"bucket":"heavy","limit":"10 per minute per key"}}},"/tenders/{id}/readiness":{"get":{"operationId":"getTendersIdReadiness","tags":["analysis"],"summary":"Bid readiness: weight-averaged review coverage, 0–100 (a review measure, never a score forecast)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"null until a review exists.","content":{"application/json":{"schema":{"type":"object","properties":{"readiness":{"anyOf":[{"type":"integer","minimum":0,"maximum":100},{"type":"null"}]}},"required":["readiness"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/questions/{id}/workspace":{"get":{"operationId":"getQuestionsIdWorkspace","tags":["questions"],"summary":"A question in one call: the question, sibling list, draft blocks, comments, snapshots, latest review, members","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The workspace aggregate.","content":{"application/json":{"schema":{"type":"object","properties":{"tender":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"buyerName":{"type":"string"},"stage":{"type":"string","enum":["qualifying","live","submitted","archived"]},"deadline":{"type":["string","null"]},"visibility":{"type":"string","enum":["client","bidwriter"]}},"required":["id","title","buyerName","stage","deadline","visibility"],"additionalProperties":false},"questions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"ref":{"type":"string"},"title":{"type":"string"},"weightPct":{"type":"number"},"wordLimit":{"anyOf":[{"type":"integer"},{"type":"null"}]},"status":{"type":"string","enum":["not_started","drafting","draft_failed","in_progress","draft_complete","reviewed","signed_off"]},"reviewRequestedAt":{"type":["string","null"]},"reviewError":{"type":["string","null"]}},"required":["id","ref","title","weightPct","wordLimit","status","reviewRequestedAt","reviewError"],"additionalProperties":false}},"question":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"ref":{"type":"string"},"title":{"type":"string"},"questionText":{"type":"string"},"weightPct":{"type":"number"},"wordLimit":{"anyOf":[{"type":"integer"},{"type":"null"}]},"rubric":{"type":"array","items":{"type":"object","properties":{"band":{"type":"string"},"label":{"type":"string"},"text":{"type":"string"}},"required":["band","label","text"],"additionalProperties":false}},"ownerMembershipId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"status":{"type":"string","enum":["not_started","drafting","draft_failed","in_progress","draft_complete","reviewed","signed_off"]},"visibility":{"type":"string","enum":["client","bidwriter"]},"draftError":{"type":["string","null"]},"draftRequestedAt":{"type":["string","null"]},"draftedAt":{"type":["string","null"]},"reviewRequestedAt":{"type":["string","null"]},"reviewError":{"type":["string","null"]},"reviewerUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"signedOffByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"signedOffAt":{"type":["string","null"]},"sort":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","ref","title","questionText","weightPct","wordLimit","rubric","ownerMembershipId","status","visibility","draftError","draftRequestedAt","draftedAt","reviewRequestedAt","reviewError","reviewerUserId","signedOffByUserId","signedOffAt","sort","createdAt","updatedAt"],"additionalProperties":false},"paragraphs":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"idx":{"type":"integer"},"text":{"type":"string"},"kind":{"type":"string","enum":["text","heading","bullets","table","exhibit"]},"citations":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["response_unit","fact","chunk","exhibit"]},"id":{"type":"string"},"label":{"type":"string"}},"required":["kind","id","label"],"additionalProperties":false}},"unverified":{"type":"boolean"},"aiEdited":{"type":"boolean"},"aiRequestedAt":{"type":["string","null"]},"aiError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","questionId","companyId","idx","text","kind","citations","unverified","aiEdited","aiRequestedAt","aiError","createdAt","updatedAt"],"additionalProperties":false}},"wordCount":{"type":"integer"}},"required":["items","wordCount"],"additionalProperties":false},"comments":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"authorUserId":{"type":"string","format":"uuid"},"parentId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"body":{"type":"string"},"resolvedAt":{"type":["string","null"]},"resolvedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"authorName":{"type":"string"}},"required":["id","questionId","companyId","authorUserId","parentId","body","resolvedAt","resolvedByUserId","createdAt","updatedAt","authorName"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false},"snapshots":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionId":{"type":"string","format":"uuid"},"reason":{"type":"string","enum":["manual","review","sign_off","restore","ai_fix","ai_tighten"]},"createdAt":{"type":"string"},"createdByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"blockCount":{"type":"integer"}},"required":["id","questionId","reason","createdAt","createdByUserId","blockCount"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false},"review":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"criteria":{"type":"array","items":{"type":"object","properties":{"criterion":{"type":"string"},"covered":{"type":"boolean"},"reason":{"type":"string"}},"required":["criterion","covered","reason"],"additionalProperties":false}},"gaps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"text":{"type":"string"},"severity":{"type":"string"},"resolved":{"type":"boolean"},"sticky":{"type":"boolean"}},"required":["id","text","severity","resolved"],"additionalProperties":false}},"strengths":{"type":"array","items":{"type":"string"}},"coveragePct":{"anyOf":[{"type":"integer"},{"type":"null"}]},"createdAt":{"type":"string"}},"required":["id","criteria","gaps","strengths","coveragePct","createdAt"],"additionalProperties":false},{"type":"null"}]},"members":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"membershipId":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":"string"},"role":{"type":"string","enum":["admin","member","bidwriter"]}},"required":["membershipId","userId","email","name","role"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false},"evidencePending":{"type":"boolean"}},"required":["tender","questions","question","paragraphs","comments","snapshots","review","members","evidencePending"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/questions/{id}":{"patch":{"operationId":"patchQuestionsId","tags":["questions"],"summary":"Assign an owner or set the question status","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The updated question.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"ref":{"type":"string"},"title":{"type":"string"},"questionText":{"type":"string"},"weightPct":{"type":"number"},"wordLimit":{"anyOf":[{"type":"integer"},{"type":"null"}]},"rubric":{"type":"array","items":{"type":"object","properties":{"band":{"type":"string"},"label":{"type":"string"},"text":{"type":"string"}},"required":["band","label","text"],"additionalProperties":false}},"ownerMembershipId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"status":{"type":"string","enum":["not_started","drafting","draft_failed","in_progress","draft_complete","reviewed","signed_off"]},"visibility":{"type":"string","enum":["client","bidwriter"]},"draftError":{"type":["string","null"]},"draftRequestedAt":{"type":["string","null"]},"draftedAt":{"type":["string","null"]},"reviewRequestedAt":{"type":["string","null"]},"reviewError":{"type":["string","null"]},"reviewerUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"signedOffByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"signedOffAt":{"type":["string","null"]},"sort":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","ref","title","questionText","weightPct","wordLimit","rubric","ownerMembershipId","status","visibility","draftError","draftRequestedAt","draftedAt","reviewRequestedAt","reviewError","reviewerUserId","signedOffByUserId","signedOffAt","sort","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Sets fields; repeating is a no-op.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"ownerMembershipId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"status":{"type":"string","enum":["not_started","drafting","draft_failed","in_progress","draft_complete","reviewed","signed_off"]}},"additionalProperties":false}}}}}},"/questions/{id}/evidence":{"get":{"operationId":"getQuestionsIdEvidence","tags":["questions"],"summary":"The persisted evidence panel: passages retrieved for this question, filtered to what the caller may read","description":"`status: \"retrieving\"` means the row is being written by a background job (first open, or the question text changed) — re-read in a few seconds. Retrieval is not re-run on every read.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Evidence items.","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["chunk","response_unit","fact","qa_pair"]},"text":{"type":"string"},"score":{"type":"number"},"provenance":{"type":"object","properties":{"documentId":{"type":"string"},"title":{"type":"string"},"section":{"type":"string"},"page":{"type":"number"},"year":{"type":"number"},"evaluatorScore":{"type":["number","null"]},"outcome":{"type":"string"},"questionArchetype":{"type":["string","null"]},"corpusName":{"type":"string"},"corpusId":{"type":"string"},"isCompanyCorpus":{"type":"boolean"},"visibility":{"type":"string","enum":["client","bidwriter"]}},"required":["title","isCompanyCorpus"],"additionalProperties":false}},"required":["id","kind","text","score","provenance"],"additionalProperties":false}},"fetchedAt":{"type":["string","null"]},"status":{"type":"string","enum":["ready","retrieving"]},"retrieved":{"type":"boolean"}},"required":["items","fetchedAt","status","retrieved"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/questions/{id}/evidence/refresh":{"post":{"operationId":"postQuestionsIdEvidenceRefresh","tags":["questions"],"summary":"Re-run retrieval for the question and overwrite its evidence row (synchronous)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The fresh evidence.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"ready"},"fetchedAt":{"type":["string","null"]},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["chunk","response_unit","fact","qa_pair"]},"text":{"type":"string"},"score":{"type":"number"},"provenance":{"type":"object","properties":{"documentId":{"type":"string"},"title":{"type":"string"},"section":{"type":"string"},"page":{"type":"number"},"year":{"type":"number"},"evaluatorScore":{"type":["number","null"]},"outcome":{"type":"string"},"questionArchetype":{"type":["string","null"]},"corpusName":{"type":"string"},"corpusId":{"type":"string"},"isCompanyCorpus":{"type":"boolean"},"visibility":{"type":"string","enum":["client","bidwriter"]}},"required":["title","isCompanyCorpus"],"additionalProperties":false}},"required":["id","kind","text","score","provenance"],"additionalProperties":false}}},"required":["status","fetchedAt","items"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Re-retrieves and overwrites the same row; nothing accumulates.","x-waywiser-rate-limit":{"bucket":"heavy","limit":"10 per minute per key"}}},"/questions/{id}/paragraphs":{"get":{"operationId":"getQuestionsIdParagraphs","tags":["questions"],"summary":"The draft blocks of a question, in order, with the word count","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Blocks and word count.","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"idx":{"type":"integer"},"text":{"type":"string"},"kind":{"type":"string","enum":["text","heading","bullets","table","exhibit"]},"citations":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["response_unit","fact","chunk","exhibit"]},"id":{"type":"string"},"label":{"type":"string"}},"required":["kind","id","label"],"additionalProperties":false}},"unverified":{"type":"boolean"},"aiEdited":{"type":"boolean"},"aiRequestedAt":{"type":["string","null"]},"aiError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","questionId","companyId","idx","text","kind","citations","unverified","aiEdited","aiRequestedAt","aiError","createdAt","updatedAt"],"additionalProperties":false}},"wordCount":{"type":"integer"}},"required":["items","wordCount"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}},"post":{"operationId":"postQuestionsIdParagraphs","tags":["drafting"],"summary":"Append a draft block (prose, heading, bullets, table or exhibit) with its citations","description":"Prose without citations carries the amber `unverified` flag (grounded drafting: unresolvable claims are flagged, never silently accepted).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"idx":{"type":"integer"},"text":{"type":"string"},"kind":{"type":"string","enum":["text","heading","bullets","table","exhibit"]},"citations":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["response_unit","fact","chunk","exhibit"]},"id":{"type":"string"},"label":{"type":"string"}},"required":["kind","id","label"],"additionalProperties":false}},"unverified":{"type":"boolean"},"aiEdited":{"type":"boolean"},"aiRequestedAt":{"type":["string","null"]},"aiError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","questionId","companyId","idx","text","kind","citations","unverified","aiEdited","aiRequestedAt","aiError","createdAt","updatedAt"],"additionalProperties":false}}}},"201":{"description":"The block (201; 200 with the twin on a repeat).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"idx":{"type":"integer"},"text":{"type":"string"},"kind":{"type":"string","enum":["text","heading","bullets","table","exhibit"]},"citations":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["response_unit","fact","chunk","exhibit"]},"id":{"type":"string"},"label":{"type":"string"}},"required":["kind","id","label"],"additionalProperties":false}},"unverified":{"type":"boolean"},"aiEdited":{"type":"boolean"},"aiRequestedAt":{"type":["string","null"]},"aiError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","questionId","companyId","idx","text","kind","citations","unverified","aiEdited","aiRequestedAt","aiError","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Same text and first citation within the window ⇒ the existing block with 200.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","minLength":1},"citations":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["response_unit","fact","chunk","exhibit"]},"id":{"type":"string"},"label":{"type":"string"}},"required":["kind","id","label"],"additionalProperties":false},"default":[]},"kind":{"type":"string","enum":["text","heading","bullets","table","exhibit"],"default":"text"}},"required":["text"],"additionalProperties":false}}}}}},"/paragraphs/{id}":{"patch":{"operationId":"patchParagraphsId","tags":["drafting"],"summary":"Edit a block (text, kind, citations, or clear/set the unverified flag)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The updated block.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"idx":{"type":"integer"},"text":{"type":"string"},"kind":{"type":"string","enum":["text","heading","bullets","table","exhibit"]},"citations":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["response_unit","fact","chunk","exhibit"]},"id":{"type":"string"},"label":{"type":"string"}},"required":["kind","id","label"],"additionalProperties":false}},"unverified":{"type":"boolean"},"aiEdited":{"type":"boolean"},"aiRequestedAt":{"type":["string","null"]},"aiError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","questionId","companyId","idx","text","kind","citations","unverified","aiEdited","aiRequestedAt","aiError","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Sets fields; repeating is a no-op.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","minLength":1},"citations":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["response_unit","fact","chunk","exhibit"]},"id":{"type":"string"},"label":{"type":"string"}},"required":["kind","id","label"],"additionalProperties":false},"default":[]},"kind":{"type":"string","enum":["text","heading","bullets","table","exhibit"],"default":"text"},"unverified":{"type":"boolean"}},"additionalProperties":false}}}}},"delete":{"operationId":"deleteParagraphsId","tags":["drafting"],"summary":"Delete a block (snapshot first with POST /questions/:id/snapshots if it must be recoverable)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted."},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Idempotent.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/paragraphs/{id}/move":{"post":{"operationId":"postParagraphsIdMove","tags":["drafting"],"summary":"Move a block up or down","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The moved block — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"The moved block — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Carry `expectedIdx` (the position you saw): a stale repeat is a no-op.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"direction":{"type":"string","enum":["up","down"]},"expectedIdx":{"type":"integer","minimum":0}},"required":["direction"],"additionalProperties":false}}}}}},"/questions/{id}/exhibit":{"post":{"operationId":"postQuestionsIdExhibit","tags":["drafting"],"summary":"Insert the milestone-timeline exhibit block into the draft (needs milestones on the tender)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"idx":{"type":"integer"},"text":{"type":"string"},"kind":{"type":"string","enum":["text","heading","bullets","table","exhibit"]},"citations":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["response_unit","fact","chunk","exhibit"]},"id":{"type":"string"},"label":{"type":"string"}},"required":["kind","id","label"],"additionalProperties":false}},"unverified":{"type":"boolean"},"aiEdited":{"type":"boolean"},"aiRequestedAt":{"type":["string","null"]},"aiError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","questionId","companyId","idx","text","kind","citations","unverified","aiEdited","aiRequestedAt","aiError","createdAt","updatedAt"],"additionalProperties":false}}}},"201":{"description":"The exhibit block (201; 200 when the question already has one).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"idx":{"type":"integer"},"text":{"type":"string"},"kind":{"type":"string","enum":["text","heading","bullets","table","exhibit"]},"citations":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["response_unit","fact","chunk","exhibit"]},"id":{"type":"string"},"label":{"type":"string"}},"required":["kind","id","label"],"additionalProperties":false}},"unverified":{"type":"boolean"},"aiEdited":{"type":"boolean"},"aiRequestedAt":{"type":["string","null"]},"aiError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","questionId","companyId","idx","text","kind","citations","unverified","aiEdited","aiRequestedAt","aiError","createdAt","updatedAt"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"One exhibit block per question: a repeat returns it with 200.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/questions/{id}/snapshots":{"get":{"operationId":"getQuestionsIdSnapshots","tags":["drafting"],"summary":"Draft version history (metadata and block counts, never the blocks)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Snapshots, newest first.","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionId":{"type":"string","format":"uuid"},"reason":{"type":"string","enum":["manual","review","sign_off","restore","ai_fix","ai_tighten"]},"createdAt":{"type":"string"},"createdByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"blockCount":{"type":"integer"}},"required":["id","questionId","reason","createdAt","createdByUserId","blockCount"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}},"post":{"operationId":"postQuestionsIdSnapshots","tags":["drafting"],"summary":"Snapshot the current draft","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"description":"The draft_snapshots row — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"201":{"description":"The draft_snapshots row — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"The draft_snapshots row — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Each call writes a snapshot.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","enum":["manual","before_delete"],"default":"manual"}},"additionalProperties":false}}}}}},"/snapshots/{id}/restore":{"post":{"operationId":"postSnapshotsIdRestore","tags":["drafting"],"summary":"Restore a snapshot (the current state is snapshotted first)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"How many blocks were restored.","content":{"application/json":{"schema":{"type":"object","properties":{"restored":{"type":"integer"}},"required":["restored"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Restoring twice yields the same blocks.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/questions/{id}/draft":{"post":{"operationId":"postQuestionsIdDraft","tags":["drafting"],"summary":"Draft the answer: a grounded first draft from the evidence, as a background job","description":"The draft is built only from retrieved passages and current facts; claims it cannot ground are flagged `unverified`. Poll `operation.poll` (kind `draft`; the question row is the status machine), then read the blocks.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"queued"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["status","operation"],"additionalProperties":false}}}},"202":{"description":"Queued.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"queued"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["status","operation"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited, or the company’s daily AI budget is spent (`ai_budget_exceeded`); `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"503":{"description":"The job queue is unavailable (`queue_unavailable`): nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"A repeat while drafting returns the same 202 with `alreadyQueued: true` — one paid job.","x-waywiser-rate-limit":{"bucket":"ai","limit":"10 per minute per key, and the company daily AI token ceiling"},"x-waywiser-async":{"kind":"draft","poll":"/activity?target=<questionId>"}}},"/paragraphs/{id}/fix":{"post":{"operationId":"postParagraphsIdFix","tags":["drafting"],"summary":"Fix an amber-flagged claim from the facts bank (background job)","description":"Only a block with `unverified: true` — otherwise 409. Poll `operation.poll`: the block row carries `aiRequestedAt`/`aiError` and the rewritten text.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"queued"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["status","operation"],"additionalProperties":false}}}},"202":{"description":"Queued.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"queued"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["status","operation"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited, or the company’s daily AI budget is spent (`ai_budget_exceeded`); `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"503":{"description":"The job queue is unavailable (`queue_unavailable`): nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"A repeat while the job is in flight returns the same 202.","x-waywiser-rate-limit":{"bucket":"ai","limit":"10 per minute per key, and the company daily AI token ceiling"},"x-waywiser-async":{"kind":"paragraph_fix","poll":"/questions/<questionId>/paragraphs"}}},"/paragraphs/{id}/tighten":{"post":{"operationId":"postParagraphsIdTighten","tags":["drafting"],"summary":"Tighten a prose block (background job)","description":"Prose blocks only — otherwise 409. Poll as for /fix.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"queued"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["status","operation"],"additionalProperties":false}}}},"202":{"description":"Queued.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"queued"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["status","operation"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited, or the company’s daily AI budget is spent (`ai_budget_exceeded`); `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"503":{"description":"The job queue is unavailable (`queue_unavailable`): nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"A repeat while the job is in flight returns the same 202.","x-waywiser-rate-limit":{"bucket":"ai","limit":"10 per minute per key, and the company daily AI token ceiling"},"x-waywiser-async":{"kind":"paragraph_tighten","poll":"/questions/<questionId>/paragraphs"}}},"/questions/{id}/review":{"post":{"operationId":"postQuestionsIdReview","tags":["review"],"summary":"Run the evaluator review: criteria, gaps and coverage against the rubric (background job)","description":"A review, not a score forecast (vocabulary discipline). Poll `operation.poll` (kind `review`); then GET /questions/:id/review.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"queued"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["status","operation"],"additionalProperties":false}}}},"202":{"description":"Queued.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"queued"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["status","operation"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited, or the company’s daily AI budget is spent (`ai_budget_exceeded`); `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"503":{"description":"The job queue is unavailable (`queue_unavailable`): nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"A repeat while a review is in flight returns the same 202; re-reviewing after one lands is allowed.","x-waywiser-rate-limit":{"bucket":"ai","limit":"10 per minute per key, and the company daily AI token ceiling"},"x-waywiser-async":{"kind":"review","poll":"/activity?target=<questionId>"}},"get":{"operationId":"getQuestionsIdReview","tags":["review"],"summary":"The latest review: per-criterion findings, gaps, strengths, coverage","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"null until one exists.","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"criteria":{"type":"array","items":{"type":"object","properties":{"criterion":{"type":"string"},"covered":{"type":"boolean"},"reason":{"type":"string"}},"required":["criterion","covered","reason"],"additionalProperties":false}},"gaps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"text":{"type":"string"},"severity":{"type":"string"},"resolved":{"type":"boolean"},"sticky":{"type":"boolean"}},"required":["id","text","severity","resolved"],"additionalProperties":false}},"strengths":{"type":"array","items":{"type":"string"}},"coveragePct":{"anyOf":[{"type":"integer"},{"type":"null"}]},"createdAt":{"type":"string"}},"required":["id","criteria","gaps","strengths","coveragePct","createdAt"],"additionalProperties":false},{"type":"null"}]}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/questions/{id}/comments":{"get":{"operationId":"getQuestionsIdComments","tags":["review"],"summary":"Comment threads on a question","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Comments with author names.","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"authorUserId":{"type":"string","format":"uuid"},"parentId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"body":{"type":"string"},"resolvedAt":{"type":["string","null"]},"resolvedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"authorName":{"type":"string"}},"required":["id","questionId","companyId","authorUserId","parentId","body","resolvedAt","resolvedByUserId","createdAt","updatedAt","authorName"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}},"post":{"operationId":"postQuestionsIdComments","tags":["review"],"summary":"Add a comment (or a one-level reply with `parentId`)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"authorUserId":{"type":"string","format":"uuid"},"parentId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"body":{"type":"string"},"resolvedAt":{"type":["string","null"]},"resolvedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"authorName":{"type":"string"}},"required":["id","questionId","companyId","authorUserId","parentId","body","resolvedAt","resolvedByUserId","createdAt","updatedAt","authorName"],"additionalProperties":false}}}},"201":{"description":"The comment (201; 200 with the twin on a repeat).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"authorUserId":{"type":"string","format":"uuid"},"parentId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"body":{"type":"string"},"resolvedAt":{"type":["string","null"]},"resolvedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"authorName":{"type":"string"}},"required":["id","questionId","companyId","authorUserId","parentId","body","resolvedAt","resolvedByUserId","createdAt","updatedAt","authorName"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Same author, body and thread within the window ⇒ the existing comment with 200.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":8000},"parentId":{"type":"string","format":"uuid"}},"required":["body"],"additionalProperties":false}}}}}},"/comments/{id}/resolve":{"post":{"operationId":"postCommentsIdResolve","tags":["review"],"summary":"Resolve a comment thread","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The resolved comment.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"authorUserId":{"type":"string","format":"uuid"},"parentId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"body":{"type":"string"},"resolvedAt":{"type":["string","null"]},"resolvedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"authorName":{"type":"string"}},"required":["id","questionId","companyId","authorUserId","parentId","body","resolvedAt","resolvedByUserId","createdAt","updatedAt","authorName"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Already resolved keeps the first resolver and time.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/questions/{id}/request-review":{"post":{"operationId":"postQuestionsIdRequestReview","tags":["review"],"summary":"Assign a reviewer (a member of the company)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The question with its reviewer.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"ref":{"type":"string"},"title":{"type":"string"},"questionText":{"type":"string"},"weightPct":{"type":"number"},"wordLimit":{"anyOf":[{"type":"integer"},{"type":"null"}]},"rubric":{"type":"array","items":{"type":"object","properties":{"band":{"type":"string"},"label":{"type":"string"},"text":{"type":"string"}},"required":["band","label","text"],"additionalProperties":false}},"ownerMembershipId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"status":{"type":"string","enum":["not_started","drafting","draft_failed","in_progress","draft_complete","reviewed","signed_off"]},"visibility":{"type":"string","enum":["client","bidwriter"]},"draftError":{"type":["string","null"]},"draftRequestedAt":{"type":["string","null"]},"draftedAt":{"type":["string","null"]},"reviewRequestedAt":{"type":["string","null"]},"reviewError":{"type":["string","null"]},"reviewerUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"signedOffByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"signedOffAt":{"type":["string","null"]},"sort":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","ref","title","questionText","weightPct","wordLimit","rubric","ownerMembershipId","status","visibility","draftError","draftRequestedAt","draftedAt","reviewRequestedAt","reviewError","reviewerUserId","signedOffByUserId","signedOffAt","sort","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Sets the reviewer; repeating is a no-op.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reviewerUserId":{"type":"string","format":"uuid"}},"required":["reviewerUserId"],"additionalProperties":false}}}}}},"/questions/{id}/sign-off":{"post":{"operationId":"postQuestionsIdSignOff","tags":["review"],"summary":"Sign the answer off (a state transition — ask the person first)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The signed-off question.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"ref":{"type":"string"},"title":{"type":"string"},"questionText":{"type":"string"},"weightPct":{"type":"number"},"wordLimit":{"anyOf":[{"type":"integer"},{"type":"null"}]},"rubric":{"type":"array","items":{"type":"object","properties":{"band":{"type":"string"},"label":{"type":"string"},"text":{"type":"string"}},"required":["band","label","text"],"additionalProperties":false}},"ownerMembershipId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"status":{"type":"string","enum":["not_started","drafting","draft_failed","in_progress","draft_complete","reviewed","signed_off"]},"visibility":{"type":"string","enum":["client","bidwriter"]},"draftError":{"type":["string","null"]},"draftRequestedAt":{"type":["string","null"]},"draftedAt":{"type":["string","null"]},"reviewRequestedAt":{"type":["string","null"]},"reviewError":{"type":["string","null"]},"reviewerUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"signedOffByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"signedOffAt":{"type":["string","null"]},"sort":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","ref","title","questionText","weightPct","wordLimit","rubric","ownerMembershipId","status","visibility","draftError","draftRequestedAt","draftedAt","reviewRequestedAt","reviewError","reviewerUserId","signedOffByUserId","signedOffAt","sort","createdAt","updatedAt"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Keeps the first signature.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/tenders/{id}/clarifications":{"post":{"operationId":"postTendersIdClarifications","tags":["clarifications"],"summary":"Log a clarification to raise with the buyer; the portal question is drafted in the background unless `draftQuestion` is given","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"topic":{"type":"string"},"draftQuestion":{"type":"string"},"status":{"type":"string","enum":["logged","sent","answered"]},"affectedQuestionRef":{"type":["string","null"]},"answer":{"type":["string","null"]},"answeredAt":{"type":["string","null"]},"appliedChange":{"anyOf":[{"type":"object","properties":{"field":{"type":"string"},"from":{"type":["number","null"]},"to":{"type":"number"}},"required":["field","from","to"],"additionalProperties":false},{"type":"null"}]},"draftRequestedAt":{"type":["string","null"]},"draftedAt":{"type":["string","null"]},"draftError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","topic","draftQuestion","status","affectedQuestionRef","answer","answeredAt","appliedChange","draftRequestedAt","draftedAt","draftError","createdAt","updatedAt"],"additionalProperties":false}}}},"201":{"description":"The clarification (201; 200 with the existing row on a repeat).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"topic":{"type":"string"},"draftQuestion":{"type":"string"},"status":{"type":"string","enum":["logged","sent","answered"]},"affectedQuestionRef":{"type":["string","null"]},"answer":{"type":["string","null"]},"answeredAt":{"type":["string","null"]},"appliedChange":{"anyOf":[{"type":"object","properties":{"field":{"type":"string"},"from":{"type":["number","null"]},"to":{"type":"number"}},"required":["field","from","to"],"additionalProperties":false},{"type":"null"}]},"draftRequestedAt":{"type":["string","null"]},"draftedAt":{"type":["string","null"]},"draftError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","topic","draftQuestion","status","affectedQuestionRef","answer","answeredAt","appliedChange","draftRequestedAt","draftedAt","draftError","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Same topic on the tender ⇒ the existing row with 200.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"topic":{"type":"string","minLength":1,"maxLength":500},"affectedQuestionRef":{"type":"string","maxLength":40},"draftQuestion":{"type":"string","maxLength":4000}},"required":["topic"],"additionalProperties":false}}}}}},"/clarifications/{id}/redraft":{"post":{"operationId":"postClarificationsIdRedraft","tags":["clarifications"],"summary":"Retry drafting the portal question after a failed draft","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"queued"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["status","operation"],"additionalProperties":false}}}},"202":{"description":"Queued.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"queued"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["status","operation"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited, or the company’s daily AI budget is spent (`ai_budget_exceeded`); `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"503":{"description":"The job queue is unavailable (`queue_unavailable`): nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Refused (409) while a draft is running or once one exists.","x-waywiser-rate-limit":{"bucket":"ai","limit":"10 per minute per key, and the company daily AI token ceiling"},"x-waywiser-async":{"kind":"clarification","poll":"/activity?target=<clarificationId>"}}},"/clarifications/{id}/status":{"post":{"operationId":"postClarificationsIdStatus","tags":["clarifications"],"summary":"Mark a clarification logged or sent","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The updated row.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"topic":{"type":"string"},"draftQuestion":{"type":"string"},"status":{"type":"string","enum":["logged","sent","answered"]},"affectedQuestionRef":{"type":["string","null"]},"answer":{"type":["string","null"]},"answeredAt":{"type":["string","null"]},"appliedChange":{"anyOf":[{"type":"object","properties":{"field":{"type":"string"},"from":{"type":["number","null"]},"to":{"type":"number"}},"required":["field","from","to"],"additionalProperties":false},{"type":"null"}]},"draftRequestedAt":{"type":["string","null"]},"draftedAt":{"type":["string","null"]},"draftError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","topic","draftQuestion","status","affectedQuestionRef","answer","answeredAt","appliedChange","draftRequestedAt","draftedAt","draftError","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Sets the status.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["logged","sent"]}},"required":["status"],"additionalProperties":false}}}}}},"/clarifications/{id}/answer":{"post":{"operationId":"postClarificationsIdAnswer","tags":["clarifications"],"summary":"Record the buyer's answer, optionally applying it to the affected question's weighting or word limit with provenance","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The answered row.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"topic":{"type":"string"},"draftQuestion":{"type":"string"},"status":{"type":"string","enum":["logged","sent","answered"]},"affectedQuestionRef":{"type":["string","null"]},"answer":{"type":["string","null"]},"answeredAt":{"type":["string","null"]},"appliedChange":{"anyOf":[{"type":"object","properties":{"field":{"type":"string"},"from":{"type":["number","null"]},"to":{"type":"number"}},"required":["field","from","to"],"additionalProperties":false},{"type":"null"}]},"draftRequestedAt":{"type":["string","null"]},"draftedAt":{"type":["string","null"]},"draftError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","topic","draftQuestion","status","affectedQuestionRef","answer","answeredAt","appliedChange","draftRequestedAt","draftedAt","draftError","createdAt","updatedAt"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Keeps the first answer; applying the same change twice is a no-op.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"answer":{"type":"string","minLength":1,"maxLength":8000},"apply":{"type":"object","properties":{"questionRef":{"type":"string","minLength":1,"maxLength":40},"field":{"type":"string","enum":["weight_pct","word_limit"]},"value":{"type":"number","minimum":0,"maximum":100000}},"required":["questionRef","field","value"],"additionalProperties":false},"batchId":{"type":"string","format":"uuid"}},"required":["answer"],"additionalProperties":false}}}}}},"/tenders/{id}/clarification-batches":{"post":{"operationId":"postTendersIdClarificationBatches","tags":["clarifications"],"summary":"Compose one email covering every open clarification (background job)","description":"Versioned per tender; poll `operation.poll` — the batch row on the tender detail (`clarificationBatches`) moves drafting → drafted. 409 when nothing is open.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"version":{"type":"integer"},"status":{"type":"string","enum":["drafting","drafted","failed","sent"]},"itemIds":{"type":"array","items":{"type":"string","format":"uuid"}},"subject":{"type":["string","null"]},"emailText":{"type":"string"},"model":{"type":["string","null"]},"error":{"type":["string","null"]},"sentAt":{"type":["string","null"]},"replyText":{"type":["string","null"]},"replyStatus":{"anyOf":[{"type":"string","enum":["mapping","mapped","failed"]},{"type":"null"}]},"replyMapping":{"anyOf":[{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"n":{"type":"integer","minimum":1},"clarificationId":{"type":"string","format":"uuid"},"answer":{"type":["string","null"]},"verbatim":{"type":"boolean"},"apply":{"anyOf":[{"type":"object","properties":{"questionRef":{"type":"string","minLength":1,"maxLength":40},"field":{"type":"string","enum":["weight_pct","word_limit"]},"value":{"type":"number","minimum":0,"maximum":100000}},"required":["questionRef","field","value"],"additionalProperties":false},{"type":"null"}]},"confidence":{"type":"string","enum":["high","medium","low"]},"note":{"type":["string","null"]}},"required":["n","clarificationId","answer","verbatim","apply","confidence","note"],"additionalProperties":false}},"unassigned":{"type":"array","items":{"type":"string"}}},"required":["items","unassigned"],"additionalProperties":false},{"type":"null"}]},"replyError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["id","tenderId","companyId","version","status","itemIds","subject","emailText","model","error","sentAt","replyText","replyStatus","replyMapping","replyError","createdAt","updatedAt","operation"],"additionalProperties":false}}}},"202":{"description":"The batch row (202 while composing; 200 when a drafted, unsent one covers the same items).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"version":{"type":"integer"},"status":{"type":"string","enum":["drafting","drafted","failed","sent"]},"itemIds":{"type":"array","items":{"type":"string","format":"uuid"}},"subject":{"type":["string","null"]},"emailText":{"type":"string"},"model":{"type":["string","null"]},"error":{"type":["string","null"]},"sentAt":{"type":["string","null"]},"replyText":{"type":["string","null"]},"replyStatus":{"anyOf":[{"type":"string","enum":["mapping","mapped","failed"]},{"type":"null"}]},"replyMapping":{"anyOf":[{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"n":{"type":"integer","minimum":1},"clarificationId":{"type":"string","format":"uuid"},"answer":{"type":["string","null"]},"verbatim":{"type":"boolean"},"apply":{"anyOf":[{"type":"object","properties":{"questionRef":{"type":"string","minLength":1,"maxLength":40},"field":{"type":"string","enum":["weight_pct","word_limit"]},"value":{"type":"number","minimum":0,"maximum":100000}},"required":["questionRef","field","value"],"additionalProperties":false},{"type":"null"}]},"confidence":{"type":"string","enum":["high","medium","low"]},"note":{"type":["string","null"]}},"required":["n","clarificationId","answer","verbatim","apply","confidence","note"],"additionalProperties":false}},"unassigned":{"type":"array","items":{"type":"string"}}},"required":["items","unassigned"],"additionalProperties":false},{"type":"null"}]},"replyError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["id","tenderId","companyId","version","status","itemIds","subject","emailText","model","error","sentAt","replyText","replyStatus","replyMapping","replyError","createdAt","updatedAt","operation"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited, or the company’s daily AI budget is spent (`ai_budget_exceeded`); `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"503":{"description":"The job queue is unavailable (`queue_unavailable`): nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"One batch per open set: a repeat returns it rather than composing again.","x-waywiser-rate-limit":{"bucket":"ai","limit":"10 per minute per key, and the company daily AI token ceiling"},"x-waywiser-async":{"kind":"clarification_email","poll":"/tenders/<tenderId>"}}},"/clarification-batches/{id}/sent":{"post":{"operationId":"postClarificationBatchesIdSent","tags":["clarifications"],"summary":"Mark the batch email sent (every item it covers → sent)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The batch.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"version":{"type":"integer"},"status":{"type":"string","enum":["drafting","drafted","failed","sent"]},"itemIds":{"type":"array","items":{"type":"string","format":"uuid"}},"subject":{"type":["string","null"]},"emailText":{"type":"string"},"model":{"type":["string","null"]},"error":{"type":["string","null"]},"sentAt":{"type":["string","null"]},"replyText":{"type":["string","null"]},"replyStatus":{"anyOf":[{"type":"string","enum":["mapping","mapped","failed"]},{"type":"null"}]},"replyMapping":{"anyOf":[{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"n":{"type":"integer","minimum":1},"clarificationId":{"type":"string","format":"uuid"},"answer":{"type":["string","null"]},"verbatim":{"type":"boolean"},"apply":{"anyOf":[{"type":"object","properties":{"questionRef":{"type":"string","minLength":1,"maxLength":40},"field":{"type":"string","enum":["weight_pct","word_limit"]},"value":{"type":"number","minimum":0,"maximum":100000}},"required":["questionRef","field","value"],"additionalProperties":false},{"type":"null"}]},"confidence":{"type":"string","enum":["high","medium","low"]},"note":{"type":["string","null"]}},"required":["n","clarificationId","answer","verbatim","apply","confidence","note"],"additionalProperties":false}},"unassigned":{"type":"array","items":{"type":"string"}}},"required":["items","unassigned"],"additionalProperties":false},{"type":"null"}]},"replyError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tenderId","companyId","version","status","itemIds","subject","emailText","model","error","sentAt","replyText","replyStatus","replyMapping","replyError","createdAt","updatedAt"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Already sent ⇒ the same row.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/clarification-batches/{id}/reply":{"post":{"operationId":"postClarificationBatchesIdReply","tags":["clarifications"],"summary":"Paste the buyer's reply; a background job maps it onto the numbered items for a person to confirm","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"version":{"type":"integer"},"status":{"type":"string","enum":["drafting","drafted","failed","sent"]},"itemIds":{"type":"array","items":{"type":"string","format":"uuid"}},"subject":{"type":["string","null"]},"emailText":{"type":"string"},"model":{"type":["string","null"]},"error":{"type":["string","null"]},"sentAt":{"type":["string","null"]},"replyText":{"type":["string","null"]},"replyStatus":{"anyOf":[{"type":"string","enum":["mapping","mapped","failed"]},{"type":"null"}]},"replyMapping":{"anyOf":[{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"n":{"type":"integer","minimum":1},"clarificationId":{"type":"string","format":"uuid"},"answer":{"type":["string","null"]},"verbatim":{"type":"boolean"},"apply":{"anyOf":[{"type":"object","properties":{"questionRef":{"type":"string","minLength":1,"maxLength":40},"field":{"type":"string","enum":["weight_pct","word_limit"]},"value":{"type":"number","minimum":0,"maximum":100000}},"required":["questionRef","field","value"],"additionalProperties":false},{"type":"null"}]},"confidence":{"type":"string","enum":["high","medium","low"]},"note":{"type":["string","null"]}},"required":["n","clarificationId","answer","verbatim","apply","confidence","note"],"additionalProperties":false}},"unassigned":{"type":"array","items":{"type":"string"}}},"required":["items","unassigned"],"additionalProperties":false},{"type":"null"}]},"replyError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["id","tenderId","companyId","version","status","itemIds","subject","emailText","model","error","sentAt","replyText","replyStatus","replyMapping","replyError","createdAt","updatedAt","operation"],"additionalProperties":false}}}},"202":{"description":"The batch row (202 while mapping; 200 once mapped).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"companyId":{"type":"string","format":"uuid"},"version":{"type":"integer"},"status":{"type":"string","enum":["drafting","drafted","failed","sent"]},"itemIds":{"type":"array","items":{"type":"string","format":"uuid"}},"subject":{"type":["string","null"]},"emailText":{"type":"string"},"model":{"type":["string","null"]},"error":{"type":["string","null"]},"sentAt":{"type":["string","null"]},"replyText":{"type":["string","null"]},"replyStatus":{"anyOf":[{"type":"string","enum":["mapping","mapped","failed"]},{"type":"null"}]},"replyMapping":{"anyOf":[{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"n":{"type":"integer","minimum":1},"clarificationId":{"type":"string","format":"uuid"},"answer":{"type":["string","null"]},"verbatim":{"type":"boolean"},"apply":{"anyOf":[{"type":"object","properties":{"questionRef":{"type":"string","minLength":1,"maxLength":40},"field":{"type":"string","enum":["weight_pct","word_limit"]},"value":{"type":"number","minimum":0,"maximum":100000}},"required":["questionRef","field","value"],"additionalProperties":false},{"type":"null"}]},"confidence":{"type":"string","enum":["high","medium","low"]},"note":{"type":["string","null"]}},"required":["n","clarificationId","answer","verbatim","apply","confidence","note"],"additionalProperties":false}},"unassigned":{"type":"array","items":{"type":"string"}}},"required":["items","unassigned"],"additionalProperties":false},{"type":"null"}]},"replyError":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["id","tenderId","companyId","version","status","itemIds","subject","emailText","model","error","sentAt","replyText","replyStatus","replyMapping","replyError","createdAt","updatedAt","operation"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited, or the company’s daily AI budget is spent (`ai_budget_exceeded`); `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"503":{"description":"The job queue is unavailable (`queue_unavailable`): nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"The same text re-pasted while mapping (or after) does not run the job again.","x-waywiser-rate-limit":{"bucket":"ai","limit":"10 per minute per key, and the company daily AI token ceiling"},"x-waywiser-async":{"kind":"clarification_reply","poll":"/tenders/<tenderId>"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"replyText":{"type":"string","minLength":1,"maxLength":50000}},"required":["replyText"],"additionalProperties":false}}}}}},"/tenders/{id}/gng/prefill":{"get":{"operationId":"getTendersIdGngPrefill","tags":["go-no-go"],"summary":"What the platform can score before anyone decides: factors with evidence, coverage, the incumbent search","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The prefill.","content":{"application/json":{"schema":{"type":"object","properties":{"factors":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]},"weight":{"type":"number","minimum":0,"maximum":1},"status":{"type":"string","enum":["scored","unscored"]},"evidence":{"type":"string","enum":["computed","interview","manual","none"]},"score":{"anyOf":[{"type":"number","minimum":0,"maximum":10},{"type":"null"}]},"basis":{"type":"string"},"unscoredReason":{"type":"string"},"sources":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["fact","award_notice","award_benchmarks","feed_fit","wins","profile","web"]},"id":{"type":"string"},"label":{"type":"string"},"url":{"type":"string"}},"required":["kind","label"],"additionalProperties":false},"default":[]},"openQuestions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"prompt":{"type":"string"}},"required":["key","prompt"],"additionalProperties":false}},"suggestedScore":{"anyOf":[{"type":"number","minimum":0,"maximum":10},{"type":"null"}]}},"required":["key","weight","status","evidence","score","basis","suggestedScore"],"additionalProperties":false}},"coverage":{"type":"object","properties":{"scoredWeightPct":{"type":"integer","minimum":0,"maximum":100},"scoredCount":{"type":"integer","minimum":0},"unscoredCount":{"type":"integer","minimum":0},"unscoredFactors":{"type":"array","items":{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]}}},"required":["scoredWeightPct","scoredCount","unscoredCount","unscoredFactors"],"additionalProperties":false},"warnings":{"type":"array","items":{"type":"string"}},"bidCostGbp":{"type":["number","null"]},"interview":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"answered":{"type":"integer"},"total":{"type":"integer"},"answeredAt":{"type":["string","null"]},"generationError":{"type":["string","null"]}},"required":["id","status","answered","total","answeredAt","generationError"],"additionalProperties":false},{"type":"null"}],"default":null},"incumbent":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","complete","failed"]},"verdict":{"anyOf":[{"type":"string","enum":["found","candidates","not_found","skipped"]},{"type":"null"}]},"provider":{"type":["string","null"]},"buyerKey":{"type":["string","null"]},"queries":{"type":"array","items":{"type":"string"}},"heldNoticesChecked":{"type":"integer","minimum":0},"coverageSince":{"type":["string","null"]},"candidates":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":300},"source":{"type":"string","enum":["award_notice","web"]},"url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"title":{"type":"string","maxLength":500},"noticeId":{"type":"string","format":"uuid"},"contractStart":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"contractEnd":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"valueGbp":{"type":["number","null"]},"confidence":{"type":"string","enum":["high","medium","low"]},"quote":{"type":"string","maxLength":600},"query":{"type":"string","maxLength":300},"retrievedAt":{"type":"string"},"factId":{"type":"string","format":"uuid"}},"required":["name","source","url","confidence","quote"],"additionalProperties":false}},"error":{"type":["string","null"]},"completedAt":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","tenderId","status","verdict","provider","buyerKey","queries","heldNoticesChecked","coverageSince","candidates","error","completedAt","createdAt"],"additionalProperties":false},{"type":"null"}],"default":null}},"required":["factors","coverage","warnings","bidCostGbp"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/tenders/{id}/gng/auto":{"post":{"operationId":"postTendersIdGngAuto","tags":["go-no-go"],"summary":"One-click go/no-go: score every factor with evidence, name what could not be scored","description":"Below half the weighting the recommendation is `insufficient_evidence` — the gaps, not a mark-down (ADR-0009).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"recommendation":{"type":"string","enum":["bid","no_bid","insufficient_evidence"]},"winSignal":{"anyOf":[{"type":"integer","minimum":0,"maximum":100},{"type":"null"}]},"coveragePct":{"type":"integer","minimum":0,"maximum":100},"savedCostEstimate":{"type":["string","null"]},"factors":{"type":"array","items":{"type":"object","properties":{"key":{"anyOf":[{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]},{"type":"null"}]},"weight":{"type":"number","minimum":0,"maximum":1},"status":{"type":"string","enum":["scored","unscored"]},"evidence":{"type":"string","enum":["computed","interview","manual","none"]},"score":{"anyOf":[{"type":"number","minimum":0,"maximum":10},{"type":"null"}]},"basis":{"type":"string"},"unscoredReason":{"type":"string"},"sources":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["fact","award_notice","award_benchmarks","feed_fit","wins","profile","web"]},"id":{"type":"string"},"label":{"type":"string"},"url":{"type":"string"}},"required":["kind","label"],"additionalProperties":false},"default":[]},"openQuestions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"prompt":{"type":"string"}},"required":["key","prompt"],"additionalProperties":false}},"label":{"type":"string"}},"required":["key","weight","status","evidence","score","basis"],"additionalProperties":false}},"decision":{"anyOf":[{"type":"string","enum":["bid","no_bid"]},{"type":"null"}]},"decisionReason":{"type":["string","null"]},"interviewId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"default":null},"incumbentSearchId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"default":null},"warnings":{"type":"array","items":{"type":"string"}}},"required":["id","tenderId","recommendation","winSignal","coveragePct","savedCostEstimate","factors","decision","decisionReason"],"additionalProperties":false}}}},"201":{"description":"The run (201; 200 when an identical undecided run exists).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"recommendation":{"type":"string","enum":["bid","no_bid","insufficient_evidence"]},"winSignal":{"anyOf":[{"type":"integer","minimum":0,"maximum":100},{"type":"null"}]},"coveragePct":{"type":"integer","minimum":0,"maximum":100},"savedCostEstimate":{"type":["string","null"]},"factors":{"type":"array","items":{"type":"object","properties":{"key":{"anyOf":[{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]},{"type":"null"}]},"weight":{"type":"number","minimum":0,"maximum":1},"status":{"type":"string","enum":["scored","unscored"]},"evidence":{"type":"string","enum":["computed","interview","manual","none"]},"score":{"anyOf":[{"type":"number","minimum":0,"maximum":10},{"type":"null"}]},"basis":{"type":"string"},"unscoredReason":{"type":"string"},"sources":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["fact","award_notice","award_benchmarks","feed_fit","wins","profile","web"]},"id":{"type":"string"},"label":{"type":"string"},"url":{"type":"string"}},"required":["kind","label"],"additionalProperties":false},"default":[]},"openQuestions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"prompt":{"type":"string"}},"required":["key","prompt"],"additionalProperties":false}},"label":{"type":"string"}},"required":["key","weight","status","evidence","score","basis"],"additionalProperties":false}},"decision":{"anyOf":[{"type":"string","enum":["bid","no_bid"]},{"type":"null"}]},"decisionReason":{"type":["string","null"]},"interviewId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"default":null},"incumbentSearchId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"default":null},"warnings":{"type":"array","items":{"type":"string"}}},"required":["id","tenderId","recommendation","winSignal","coveragePct","savedCostEstimate","factors","decision","decisionReason"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"An identical undecided run is returned with 200.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/tenders/{id}/gng":{"post":{"operationId":"postTendersIdGng","tags":["go-no-go"],"summary":"Manual go/no-go run from scores (null = unknown, falls back to platform evidence; weights are never client-supplied)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"recommendation":{"type":"string","enum":["bid","no_bid","insufficient_evidence"]},"winSignal":{"anyOf":[{"type":"integer","minimum":0,"maximum":100},{"type":"null"}]},"coveragePct":{"type":"integer","minimum":0,"maximum":100},"savedCostEstimate":{"type":["string","null"]},"factors":{"type":"array","items":{"type":"object","properties":{"key":{"anyOf":[{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]},{"type":"null"}]},"weight":{"type":"number","minimum":0,"maximum":1},"status":{"type":"string","enum":["scored","unscored"]},"evidence":{"type":"string","enum":["computed","interview","manual","none"]},"score":{"anyOf":[{"type":"number","minimum":0,"maximum":10},{"type":"null"}]},"basis":{"type":"string"},"unscoredReason":{"type":"string"},"sources":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["fact","award_notice","award_benchmarks","feed_fit","wins","profile","web"]},"id":{"type":"string"},"label":{"type":"string"},"url":{"type":"string"}},"required":["kind","label"],"additionalProperties":false},"default":[]},"openQuestions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"prompt":{"type":"string"}},"required":["key","prompt"],"additionalProperties":false}},"label":{"type":"string"}},"required":["key","weight","status","evidence","score","basis"],"additionalProperties":false}},"decision":{"anyOf":[{"type":"string","enum":["bid","no_bid"]},{"type":"null"}]},"decisionReason":{"type":["string","null"]},"interviewId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"default":null},"incumbentSearchId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"default":null}},"required":["id","tenderId","recommendation","winSignal","coveragePct","savedCostEstimate","factors","decision","decisionReason"],"additionalProperties":false}}}},"201":{"description":"The run.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"recommendation":{"type":"string","enum":["bid","no_bid","insufficient_evidence"]},"winSignal":{"anyOf":[{"type":"integer","minimum":0,"maximum":100},{"type":"null"}]},"coveragePct":{"type":"integer","minimum":0,"maximum":100},"savedCostEstimate":{"type":["string","null"]},"factors":{"type":"array","items":{"type":"object","properties":{"key":{"anyOf":[{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]},{"type":"null"}]},"weight":{"type":"number","minimum":0,"maximum":1},"status":{"type":"string","enum":["scored","unscored"]},"evidence":{"type":"string","enum":["computed","interview","manual","none"]},"score":{"anyOf":[{"type":"number","minimum":0,"maximum":10},{"type":"null"}]},"basis":{"type":"string"},"unscoredReason":{"type":"string"},"sources":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["fact","award_notice","award_benchmarks","feed_fit","wins","profile","web"]},"id":{"type":"string"},"label":{"type":"string"},"url":{"type":"string"}},"required":["kind","label"],"additionalProperties":false},"default":[]},"openQuestions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"prompt":{"type":"string"}},"required":["key","prompt"],"additionalProperties":false}},"label":{"type":"string"}},"required":["key","weight","status","evidence","score","basis"],"additionalProperties":false}},"decision":{"anyOf":[{"type":"string","enum":["bid","no_bid"]},{"type":"null"}]},"decisionReason":{"type":["string","null"]},"interviewId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"default":null},"incumbentSearchId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"default":null}},"required":["id","tenderId","recommendation","winSignal","coveragePct","savedCostEstimate","factors","decision","decisionReason"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"An identical undecided run is returned with 200.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"factors":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]},"score":{"anyOf":[{"type":"number","minimum":0,"maximum":10},{"type":"null"}]},"note":{"type":"string","maxLength":500}},"required":["key","score"],"additionalProperties":false},"maxItems":5}},"required":["factors"],"additionalProperties":false}}}}}},"/tenders/{id}/gng/interview":{"post":{"operationId":"postTendersIdGngInterview","tags":["go-no-go"],"summary":"Prepare the go/no-go interview questions (background job)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["id","status","alreadyQueued","operation"],"additionalProperties":false}}}},"202":{"description":"Queued.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["id","status","alreadyQueued","operation"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited, or the company’s daily AI budget is spent (`ai_budget_exceeded`); `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"503":{"description":"The job queue is unavailable (`queue_unavailable`): nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"A repeat while queued/running returns the same row.","x-waywiser-rate-limit":{"bucket":"ai","limit":"10 per minute per key, and the company daily AI token ceiling"},"x-waywiser-async":{"kind":"gng_interview","poll":"/tenders/<tenderId>/gng/interview"}},"get":{"operationId":"getTendersIdGngInterview","tags":["go-no-go"],"summary":"The interview: questions with current answers and \"still true?\" offers (404 until prepared)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The interview.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","ready","failed"]},"answered":{"type":"integer","minimum":0},"total":{"type":"integer","minimum":0},"answeredAt":{"type":["string","null"]},"generationError":{"type":["string","null"]},"error":{"type":["string","null"]},"createdAt":{"type":"string"},"questions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","pattern":"^[a-z_]+\\.[a-z0-9_]+(:[a-z0-9_]+)?$"},"factor":{"anyOf":[{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]},{"type":"null"}]},"side":{"type":"string","enum":["bid","buy","docs"]},"scope":{"type":"string","enum":["company","buyer","tender"]},"factType":{"type":"string","enum":["cert","insurance","cv","case_study","kpi","policy","pricing_model","other","capability","capacity","appetite","relationship","buyer_intel","incumbent"]},"prompt":{"type":"string","minLength":1,"maxLength":300},"why":{"type":"string","maxLength":240},"answerKind":{"type":"string","enum":["text","number","choice","yes_no"]},"choices":{"type":"array","items":{"type":"string"},"maxItems":6},"validityMonths":{"anyOf":[{"type":"integer","minimum":1,"maximum":60},{"type":"null"}]},"source":{"type":"string","enum":["catalogue","adhoc"]},"factLabel":{"type":"string","maxLength":200},"supporting":{"type":"boolean"},"context":{"type":"string","maxLength":300},"candidateIndex":{"type":"integer","minimum":0},"current":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionKey":{"type":"string"},"scope":{"type":"string","enum":["company","buyer","tender"]},"factType":{"type":"string","enum":["cert","insurance","cv","case_study","kpi","policy","pricing_model","other","capability","capacity","appetite","relationship","buyer_intel","incumbent"]},"label":{"type":"string"},"valueText":{"type":["string","null"]},"valueJson":{"anyOf":[{"type":"object","additionalProperties":{}},{"type":"null"}]},"status":{"type":"string","enum":["ok","expiring","expired","unknown"]},"expiresAt":{"type":["string","null"]},"createdAt":{"type":"string"},"origin":{"type":"string","enum":["manual","upload","interview","award_notice","web_search"]},"url":{"type":["string","null"]},"tenderId":{"type":["string","null"]},"tenderTitle":{"type":["string","null"]},"answeredBy":{"type":["string","null"]},"version":{"type":"integer","minimum":1},"notKnown":{"type":"boolean"}},"required":["id","questionKey","scope","factType","label","valueText","valueJson","status","expiresAt","createdAt","origin","url","tenderId","tenderTitle","answeredBy","version","notKnown"],"additionalProperties":false},{"type":"null"}]},"reuse":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"questionKey":{"type":"string"},"scope":{"type":"string","enum":["company","buyer","tender"]},"factType":{"type":"string","enum":["cert","insurance","cv","case_study","kpi","policy","pricing_model","other","capability","capacity","appetite","relationship","buyer_intel","incumbent"]},"label":{"type":"string"},"valueText":{"type":["string","null"]},"valueJson":{"anyOf":[{"type":"object","additionalProperties":{}},{"type":"null"}]},"status":{"type":"string","enum":["ok","expiring","expired","unknown"]},"expiresAt":{"type":["string","null"]},"createdAt":{"type":"string"},"origin":{"type":"string","enum":["manual","upload","interview","award_notice","web_search"]},"url":{"type":["string","null"]},"tenderId":{"type":["string","null"]},"tenderTitle":{"type":["string","null"]},"answeredBy":{"type":["string","null"]},"version":{"type":"integer","minimum":1},"notKnown":{"type":"boolean"}},"required":["id","questionKey","scope","factType","label","valueText","valueJson","status","expiresAt","createdAt","origin","url","tenderId","tenderTitle","answeredBy","version","notKnown"],"additionalProperties":false},{"type":"null"}]},"evidence":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","enum":["scored","unscored"]},"evidence":{"type":"string","enum":["computed","interview","manual","none"]},"basis":{"type":"string"}},"required":["status","evidence","basis"],"additionalProperties":false},{"type":"null"}]}},"required":["key","factor","side","scope","factType","prompt","why","answerKind","validityMonths","source","factLabel","current","reuse","evidence"],"additionalProperties":false}},"openClarifications":{"type":"integer","minimum":0},"hasExtraction":{"type":"boolean"},"incumbent":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","complete","failed"]},"verdict":{"anyOf":[{"type":"string","enum":["found","candidates","not_found","skipped"]},{"type":"null"}]},"provider":{"type":["string","null"]},"buyerKey":{"type":["string","null"]},"queries":{"type":"array","items":{"type":"string"}},"heldNoticesChecked":{"type":"integer","minimum":0},"coverageSince":{"type":["string","null"]},"candidates":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":300},"source":{"type":"string","enum":["award_notice","web"]},"url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"title":{"type":"string","maxLength":500},"noticeId":{"type":"string","format":"uuid"},"contractStart":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"contractEnd":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"valueGbp":{"type":["number","null"]},"confidence":{"type":"string","enum":["high","medium","low"]},"quote":{"type":"string","maxLength":600},"query":{"type":"string","maxLength":300},"retrievedAt":{"type":"string"},"factId":{"type":"string","format":"uuid"}},"required":["name","source","url","confidence","quote"],"additionalProperties":false}},"error":{"type":["string","null"]},"completedAt":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","tenderId","status","verdict","provider","buyerKey","queries","heldNoticesChecked","coverageSince","candidates","error","completedAt","createdAt"],"additionalProperties":false},{"type":"null"}]}},"required":["id","status","answered","total","answeredAt","generationError","error","createdAt","questions","openClarifications","hasExtraction","incumbent"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/tenders/{id}/gng/interview/answers":{"post":{"operationId":"postTendersIdGngInterviewAnswers","tags":["go-no-go"],"summary":"Save interview answers (each is a versioned fact); returns the recomputed prefill","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The prefill plus counts of what was saved.","content":{"application/json":{"schema":{"type":"object","properties":{"factors":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]},"weight":{"type":"number","minimum":0,"maximum":1},"status":{"type":"string","enum":["scored","unscored"]},"evidence":{"type":"string","enum":["computed","interview","manual","none"]},"score":{"anyOf":[{"type":"number","minimum":0,"maximum":10},{"type":"null"}]},"basis":{"type":"string"},"unscoredReason":{"type":"string"},"sources":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["fact","award_notice","award_benchmarks","feed_fit","wins","profile","web"]},"id":{"type":"string"},"label":{"type":"string"},"url":{"type":"string"}},"required":["kind","label"],"additionalProperties":false},"default":[]},"openQuestions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"prompt":{"type":"string"}},"required":["key","prompt"],"additionalProperties":false}},"suggestedScore":{"anyOf":[{"type":"number","minimum":0,"maximum":10},{"type":"null"}]}},"required":["key","weight","status","evidence","score","basis","suggestedScore"],"additionalProperties":false}},"coverage":{"type":"object","properties":{"scoredWeightPct":{"type":"integer","minimum":0,"maximum":100},"scoredCount":{"type":"integer","minimum":0},"unscoredCount":{"type":"integer","minimum":0},"unscoredFactors":{"type":"array","items":{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]}}},"required":["scoredWeightPct","scoredCount","unscoredCount","unscoredFactors"],"additionalProperties":false},"warnings":{"type":"array","items":{"type":"string"}},"bidCostGbp":{"type":["number","null"]},"interview":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"answered":{"type":"integer"},"total":{"type":"integer"},"answeredAt":{"type":["string","null"]},"generationError":{"type":["string","null"]}},"required":["id","status","answered","total","answeredAt","generationError"],"additionalProperties":false},{"type":"null"}],"default":null},"incumbent":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","complete","failed"]},"verdict":{"anyOf":[{"type":"string","enum":["found","candidates","not_found","skipped"]},{"type":"null"}]},"provider":{"type":["string","null"]},"buyerKey":{"type":["string","null"]},"queries":{"type":"array","items":{"type":"string"}},"heldNoticesChecked":{"type":"integer","minimum":0},"coverageSince":{"type":["string","null"]},"candidates":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":300},"source":{"type":"string","enum":["award_notice","web"]},"url":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"title":{"type":"string","maxLength":500},"noticeId":{"type":"string","format":"uuid"},"contractStart":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"contractEnd":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"valueGbp":{"type":["number","null"]},"confidence":{"type":"string","enum":["high","medium","low"]},"quote":{"type":"string","maxLength":600},"query":{"type":"string","maxLength":300},"retrievedAt":{"type":"string"},"factId":{"type":"string","format":"uuid"}},"required":["name","source","url","confidence","quote"],"additionalProperties":false}},"error":{"type":["string","null"]},"completedAt":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","tenderId","status","verdict","provider","buyerKey","queries","heldNoticesChecked","coverageSince","candidates","error","completedAt","createdAt"],"additionalProperties":false},{"type":"null"}],"default":null},"saved":{}},"required":["factors","coverage","warnings","bidCostGbp"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Identical resubmissions write nothing.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"interviewId":{"type":"string","format":"uuid"},"answers":{"type":"array","items":{"type":"object","properties":{"questionKey":{"type":"string","pattern":"^[a-z_]+\\.[a-z0-9_]+(:[a-z0-9_]+)?$"},"action":{"type":"string","enum":["answer","not_known","confirm","skip"]},"value":{"type":"string","maxLength":2000},"expiresAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"confirmFactId":{"type":"string","format":"uuid"},"confirmCandidateIndex":{"type":"integer","minimum":0}},"required":["questionKey","action"],"additionalProperties":false},"minItems":1,"maxItems":12}},"required":["interviewId","answers"],"additionalProperties":false}}}}}},"/tenders/{id}/gng/incumbent":{"post":{"operationId":"postTendersIdGngIncumbent","tags":["go-no-go"],"summary":"Search for the current provider again (award notices, then the web) — background job","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["id","status","alreadyQueued","operation"],"additionalProperties":false}}}},"202":{"description":"Queued.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["id","status","alreadyQueued","operation"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited, or the company’s daily AI budget is spent (`ai_budget_exceeded`); `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"503":{"description":"The job queue is unavailable (`queue_unavailable`): nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"A repeat while queued/running returns the same row.","x-waywiser-rate-limit":{"bucket":"ai","limit":"10 per minute per key, and the company daily AI token ceiling"},"x-waywiser-async":{"kind":"incumbent_search","poll":"/tenders/<tenderId>/gng/prefill"}}},"/gng/{id}/decide":{"post":{"operationId":"postGngIdDecide","tags":["go-no-go"],"summary":"Record the bid / no-bid decision on a run (the only route that archives a live bid) — ask the person first","description":"Going against the recommendation needs a `reason`. Re-deciding the same way is a no-op; a different decision re-decides the run and moves the tender again (bid → live, no_bid → archived); after submission or an outcome it is 409.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The decided run.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenderId":{"type":"string","format":"uuid"},"recommendation":{"type":"string","enum":["bid","no_bid","insufficient_evidence"]},"winSignal":{"anyOf":[{"type":"integer","minimum":0,"maximum":100},{"type":"null"}]},"coveragePct":{"type":"integer","minimum":0,"maximum":100},"savedCostEstimate":{"type":["string","null"]},"factors":{"type":"array","items":{"type":"object","properties":{"key":{"anyOf":[{"type":"string","enum":["capability_match","incumbent_strength","buyer_price_behaviour","capacity_in_region","strategic_value"]},{"type":"null"}]},"weight":{"type":"number","minimum":0,"maximum":1},"status":{"type":"string","enum":["scored","unscored"]},"evidence":{"type":"string","enum":["computed","interview","manual","none"]},"score":{"anyOf":[{"type":"number","minimum":0,"maximum":10},{"type":"null"}]},"basis":{"type":"string"},"unscoredReason":{"type":"string"},"sources":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["fact","award_notice","award_benchmarks","feed_fit","wins","profile","web"]},"id":{"type":"string"},"label":{"type":"string"},"url":{"type":"string"}},"required":["kind","label"],"additionalProperties":false},"default":[]},"openQuestions":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"prompt":{"type":"string"}},"required":["key","prompt"],"additionalProperties":false}},"label":{"type":"string"}},"required":["key","weight","status","evidence","score","basis"],"additionalProperties":false}},"decision":{"anyOf":[{"type":"string","enum":["bid","no_bid"]},{"type":"null"}]},"decisionReason":{"type":["string","null"]},"interviewId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"default":null},"incumbentSearchId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"default":null}},"required":["id","tenderId","recommendation","winSignal","coveragePct","savedCostEstimate","factors","decision","decisionReason"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"The same decision repeated returns the recorded run unchanged; a different decision re-decides the run (decision, reason and the tender’s stage) until submission.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"decision":{"type":"string","enum":["bid","no_bid"]},"reason":{"type":"string","maxLength":2000}},"required":["decision"],"additionalProperties":false}}}}}},"/checklist/{id}":{"patch":{"operationId":"patchChecklistId","tags":["assembly"],"summary":"Set a compliance checklist item ok / missing / pending","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The updated checklist_items row — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"The updated checklist_items row — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Sets the status.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok","missing","pending"]}},"required":["status"],"additionalProperties":false}}}}}},"/tenders/{id}/fast-path":{"get":{"operationId":"getTendersIdFastPath","tags":["assembly"],"summary":"What the fast path would do to each question, from persisted state (no retrieval)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The preview and the last run.","content":{"application/json":{"schema":{"type":"object","properties":{"accept":{"type":"integer"},"reuse":{"type":"integer"},"open":{"type":"integer"},"unchecked":{"type":"integer"},"done":{"type":"integer"},"inFlight":{"type":"integer"},"questions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"ref":{"type":"string"},"bucket":{"type":"string","enum":["accept","reuse","open","unchecked","done","in_flight"]},"matchedQuestion":{"type":["string","null"]}},"required":["id","ref","bucket","matchedQuestion"],"additionalProperties":false}},"run":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","enum":["queued","running","succeeded","failed"]},"requestedAt":{"type":"string"},"requestedByUserId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"startedAt":{"type":["string","null"]},"finishedAt":{"type":["string","null"]},"total":{"type":"integer"},"processed":{"type":"integer"},"accepted":{"type":"integer"},"reused":{"type":"integer"},"open":{"type":"integer"},"inFlight":{"type":"integer","default":0},"alreadyDone":{"type":"integer"},"error":{"type":["string","null"]}},"required":["status","requestedAt","requestedByUserId","startedAt","finishedAt","total","processed","accepted","reused","open","alreadyDone","error"],"additionalProperties":false},{"type":"null"}]}},"required":["accept","reuse","open","unchecked","done","inFlight","questions","run"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}},"post":{"operationId":"postTendersIdFastPath","tags":["assembly"],"summary":"Run the fast path: accept every draft and fill from existing answers, question by question (background job)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"queued"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false},"run":{}},"required":["status","operation"],"additionalProperties":false}}}},"202":{"description":"Queued, with the run record.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"queued"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false},"run":{}},"required":["status","operation"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"503":{"description":"The job queue is unavailable (`queue_unavailable`): nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"One run per tender at a time: a repeat returns the same 202 and run.","x-waywiser-rate-limit":{"bucket":"heavy","limit":"10 per minute per key"},"x-waywiser-async":{"kind":"fast_path","poll":"/tenders/<tenderId>/fast-path"}}},"/tenders/{id}/export":{"post":{"operationId":"postTendersIdExport","tags":["assembly"],"summary":"Export the submission as .docx (the whole bid, or one question)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The document bytes, with a Content-Disposition filename.","content":{"application/vnd.openxmlformats-officedocument.wordprocessingml.document":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Each call renders the document; a full export records a submission row.","x-waywiser-rate-limit":{"bucket":"heavy","limit":"10 per minute per key"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"string","enum":["branded","plain"],"default":"branded"},"questionId":{"type":"string","format":"uuid"},"sources":{"type":"boolean","default":false}},"additionalProperties":false}}}}}},"/tenders/{id}/submit":{"post":{"operationId":"postTendersIdSubmit","tags":["assembly"],"summary":"Mark the bid submitted — freezes the decision and moves it out of Live (irreversible; ask the person first)","description":"Refused with 409 while a question is undrafted or over its word limit; the message names them. `force: true` is the deliberate override — never set it on your own initiative.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Submitted.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Keeps the first submission stamp.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"force":{"type":"boolean","default":false}},"additionalProperties":false}}}}}},"/tenders/{id}/outcome":{"post":{"operationId":"postTendersIdOutcome","tags":["assembly"],"summary":"Label the outcome (won / lost) with the buyer scores — closes the learning loop","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"description":"The outcomes row — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"201":{"description":"The outcomes row — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"The outcomes row — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"One outcome per tender: a repeat updates it in place (always 201).","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"outcome":{"type":"string","enum":["won","lost"]},"overallScore":{"type":"number","minimum":0,"maximum":10},"questionScores":{"type":"object","additionalProperties":{"type":"number","minimum":0,"maximum":10}},"feedbackNotes":{"type":"string","maxLength":20000}},"required":["outcome"],"additionalProperties":false}}}}}},"/corpora":{"get":{"operationId":"getCorpora","tags":["knowledge"],"summary":"The corpora the caller may browse (never the central proprietary corpus)","parameters":[],"responses":{"200":{"description":"`{ items: [...] }` of corpora rows — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"`{ items: [...] }` of corpora rows — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}},"post":{"operationId":"postCorpora","tags":["knowledge"],"summary":"Create a corpus","parameters":[],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"description":"The corpora row (201; 200 when the name exists) — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"201":{"description":"The corpora row (201; 200 when the name exists) — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"The corpora row (201; 200 when the name exists) — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Needs an admin-ceiling key acting as a company admin; or the key is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"One corpus per name in the company.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"x-waywiser-requires":"admin","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000,"default":""},"kind":{"type":"string","enum":["library","compliance","facts","general"],"default":"library"}},"required":["name"],"additionalProperties":false}}}}}},"/corpora/{id}":{"patch":{"operationId":"patchCorporaId","tags":["knowledge"],"summary":"Rename or re-describe a corpus","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The updated corpora row — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"The updated corpora row — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Needs an admin-ceiling key acting as a company admin; or the key is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Sets fields.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"x-waywiser-requires":"admin","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000,"default":""},"kind":{"type":"string","enum":["library","compliance","facts","general"],"default":"library"}},"additionalProperties":false}}}}},"delete":{"operationId":"deleteCorporaId","tags":["knowledge"],"summary":"Delete a corpus and its documents (irreversible; ask the person first)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted."},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Needs an admin-ceiling key acting as a company admin; or the key is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Already gone ⇒ 404.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"x-waywiser-requires":"admin"}},"/corpora/{id}/documents":{"get":{"operationId":"getCorporaIdDocuments","tags":["knowledge"],"summary":"Documents in a corpus, paginated, with status and quality counts","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["uploaded","parsing","parsed","chunking","embedding","enriching","ready","failed","review_needed"]}},{"name":"docType","in":"query","required":false,"schema":{"type":"string","enum":["past_bid","itt","cert","policy","case_study","pricing_workbook","standard","other"]}},{"name":"quality","in":"query","required":false,"schema":{"type":"string","enum":["high","partial","unusable"]}},{"name":"visibility","in":"query","required":false,"schema":{"type":"string","enum":["client","bidwriter"]}}],"responses":{"200":{"description":"List-view columns of the documents rows; `statusCounts`/`qualityCounts` over the whole corpus.","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"statusCounts":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string"},"n":{"type":"integer"}},"required":["status","n"],"additionalProperties":false}},"qualityCounts":{"type":"array","items":{"type":"object","properties":{"quality":{"type":["string","null"]},"n":{"type":"integer"}},"required":["quality","n"],"additionalProperties":false}}},"required":["items","total","limit","offset","statusCounts","qualityCounts"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}},"post":{"operationId":"postCorporaIdDocuments","tags":["knowledge"],"summary":"Register an object already in the bucket as a document (the signed-URL flow; most callers want /upload)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"description":"The documents row — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"201":{"description":"The documents row — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"The documents row — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"The same storageUri registered twice is one document.","x-waywiser-rate-limit":{"bucket":"upload","limit":"30 per minute per key"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1},"storageUri":{"type":"string","minLength":1},"mimeType":{"type":"string","default":"application/pdf"},"docType":{"type":"string","enum":["past_bid","itt","cert","policy","case_study","pricing_workbook","standard","other"],"default":"other"}},"required":["title","storageUri"],"additionalProperties":false}}}}}},"/corpora/{id}/documents/upload":{"post":{"operationId":"postCorporaIdDocumentsUpload","tags":["knowledge"],"summary":"Upload a document into a corpus (raw bytes); ingestion — parse, chunk, embed — runs in the background","description":"Send the file bytes as the body with `Content-Type: application/octet-stream` (up to 60 MiB per file) and the name in `X-Filename`. The bytes are sniffed: the container must match the extension (an .html renamed .pdf is refused 422 `unsupported_file`, and nothing is stored). Corpus admins only for company corpora (canWriteCorpus). Watch the document on `/activity?target=<documentId>` or the corpus list.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Filename","in":"header","required":true,"description":"The file name, percent-encoded (encodeURIComponent). The extension decides the parser: .pdf, .docx, .xlsx, .pptx, .odt, .ods.","schema":{"type":"string"}},{"name":"X-Content-Type","in":"header","required":false,"description":"Optional declared document type; kept when it is one the api knows, else the extension decides.","schema":{"type":"string"}},{"name":"X-Doc-Type","in":"header","required":false,"description":"The document type (DOC_TYPES); default `other`.","schema":{"type":"string"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"description":"The documents row — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"201":{"description":"The documents row — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"The documents row — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"The bytes are the identity: the same file twice is two documents.","x-waywiser-rate-limit":{"bucket":"upload","limit":"30 per minute per key"},"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}}}},"/documents/{id}":{"patch":{"operationId":"patchDocumentsId","tags":["knowledge"],"summary":"Edit a document title, type or metadata","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The updated documents row — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"The updated documents row — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Sets fields.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":500},"docType":{"type":"string","enum":["past_bid","itt","cert","policy","case_study","pricing_workbook","standard","other"]},"metadata":{"type":"object","additionalProperties":{}}},"additionalProperties":false}}}}},"delete":{"operationId":"deleteDocumentsId","tags":["knowledge"],"summary":"Delete a document and its stored file (irreversible; ask the person first)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted."},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Already gone ⇒ 404.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/facts/{id}/visibility":{"patch":{"operationId":"patchFactsIdVisibility","tags":["knowledge"],"summary":"Share a hand-entered fact with the client, or take it back (bid writers only)","description":"ADR-0031: a fact a WayWiser bid writer types is private until shared. Only a fact with no parent flips here — one read from an upload follows its document (PATCH /documents/:id/visibility) and a bid’s own answer (scope `tender`) follows the bid (PATCH /tenders/:id/visibility); either answers 409 naming the parent. A buyer- or company-scope answer given on a bid outlives it and flips here. Taking a fact back also drops the persisted evidence rows that copied it (`evidenceDropped`); they are re-retrieved on the next open. Only a bid writer (or a key acting as one) may call it.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The value now carried, whether anything changed, and `evidenceDropped` — the evidence rows an un-share took with it (0 on a share).","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"visibility":{"type":"string","enum":["client","bidwriter"]},"changed":{"type":"boolean"},"children":{"type":"object","additionalProperties":{"type":"integer"}}},"required":["id","visibility","changed","children"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"The value already carried ⇒ 200 with `changed: false`, nothing audited.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"visibility":{"type":"string","enum":["client","bidwriter"]}},"required":["visibility"],"additionalProperties":false}}}}}},"/documents/{id}/visibility":{"patch":{"operationId":"patchDocumentsIdVisibility","tags":["knowledge"],"summary":"Share a document with the client, or take it back (bid writers only)","description":"ADR-0031: a document a WayWiser bid writer uploads is private until shared. The document, its chunks, the response units split from it and the fact riding with it flip together; taking it back also drops the persisted evidence rows that copied a passage from it (`evidenceDropped`), re-retrieved on the next open without it. Refused 409 while the document is being read (parsing, chunking, embedding) — try again when the ingest finishes. Only a bid writer (or a key acting as one) with write access to the corpus may call it.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The value now carried, whether anything changed, and the child rows that followed.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"visibility":{"type":"string","enum":["client","bidwriter"]},"changed":{"type":"boolean"},"children":{"type":"object","additionalProperties":{"type":"integer"}}},"required":["id","visibility","changed","children"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"The value already carried ⇒ 200 with `changed: false`, nothing audited.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"visibility":{"type":"string","enum":["client","bidwriter"]}},"required":["visibility"],"additionalProperties":false}}}}}},"/documents/{id}/reingest":{"post":{"operationId":"postDocumentsIdReingest","tags":["knowledge"],"summary":"Re-process a document whose ingestion failed","description":"Failed documents only: an indexed one is 409, one still processing is 409.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"queued"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["status","operation"],"additionalProperties":false}}}},"202":{"description":"Queued.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"queued"},"alreadyQueued":{"type":"boolean"},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["status","operation"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited, or the company’s daily AI budget is spent (`ai_budget_exceeded`); `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"503":{"description":"The job queue is unavailable (`queue_unavailable`): nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Refused (409) unless the row is failed; the worker is duplicate-safe.","x-waywiser-rate-limit":{"bucket":"ai","limit":"10 per minute per key, and the company daily AI token ceiling"},"x-waywiser-async":{"kind":"document","poll":"/activity?target=<documentId>"}}},"/documents/{id}/regrade":{"post":{"operationId":"postDocumentsIdRegrade","tags":["facts"],"summary":"Re-check a facts-bank document over its stored text, optionally as another fact type","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"queued":{"type":"boolean","const":true},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["queued","operation"],"additionalProperties":false}}}},"202":{"description":"Queued.","content":{"application/json":{"schema":{"type":"object","properties":{"queued":{"type":"boolean","const":true},"operation":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export","fast_path","gng_interview","incumbent_search","paragraph_fix","paragraph_tighten","clarification_email","clarification_reply","tenant_export","corpus_import","discovery_backfill"]},"targetId":{"type":"string"},"poll":{"type":"string"}},"required":["kind","targetId","poll"],"additionalProperties":false}},"required":["queued","operation"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited, or the company’s daily AI budget is spent (`ai_budget_exceeded`); `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"503":{"description":"The job queue is unavailable (`queue_unavailable`): nothing was queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Singleton per document; the grade updates the same rows in place.","x-waywiser-rate-limit":{"bucket":"ai","limit":"10 per minute per key, and the company daily AI token ceiling"},"x-waywiser-async":{"kind":"document","poll":"/activity?target=<documentId>"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"factType":{"type":"string","enum":["cert","insurance","cv","case_study","kpi","policy","pricing_model","other","capability","capacity","appetite","relationship","buyer_intel","incumbent"]}},"additionalProperties":false}}}}}},"/corpus-capabilities":{"get":{"operationId":"getCorpusCapabilities","tags":["knowledge"],"summary":"What grounds the drafts: counts from the central corpus (never its contents)","parameters":[],"responses":{"200":{"description":"Counts.","content":{"application/json":{"schema":{"type":"object","properties":{"standards":{"type":"integer"},"scoredResponses":{"type":"integer"},"benchmarks":{"type":"integer"},"buyerProfiles":{"type":"integer"}},"required":["standards","scoredResponses","benchmarks","buyerProfiles"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/review-items":{"get":{"operationId":"getReviewItems","tags":["knowledge"],"summary":"Pending review items from corpus imports (archetype / service-line suggestions to confirm)","parameters":[],"responses":{"200":{"description":"`{ items: [...] }` of review_items rows — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"`{ items: [...] }` of review_items rows — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/review-items/{id}/resolve":{"post":{"operationId":"postReviewItemsIdResolve","tags":["knowledge"],"summary":"Resolve a review item: accept, override or dismiss","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The resolved review_items row — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"The resolved review_items row — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Already resolved ⇒ the same row.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["accept","override","dismiss"]},"questionArchetype":{"type":"string"},"serviceLine":{"type":"string"}},"required":["action"],"additionalProperties":false}}}}}},"/kb/growth":{"get":{"operationId":"getKbGrowth","tags":["knowledge"],"summary":"Response units minted from labelled outcomes in the last 30 days","parameters":[],"responses":{"200":{"description":"The growth summary.","content":{"application/json":{"schema":{"type":"object","properties":{"totalUnits":{"type":"integer"},"recent":{"type":"array","items":{"type":"object","properties":{"tenderTitle":{"type":"string"},"units":{"type":"integer"},"at":{"type":"string"}},"required":["tenderTitle","units","at"],"additionalProperties":false}}},"required":["totalUnits","recent"],"additionalProperties":false}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/facts":{"get":{"operationId":"getFacts","tags":["facts"],"summary":"The facts bank (current rows by default) with each upload’s grade; expired facts are marked and never enter drafts","parameters":[{"name":"history","in":"query","required":false,"schema":{"type":"string","enum":["1","true"]}},{"name":"scope","in":"query","required":false,"schema":{"type":"string","enum":["company","buyer","tender"]}},{"name":"origin","in":"query","required":false,"schema":{"type":"string","enum":["manual","upload","interview","award_notice","web_search"]}}],"responses":{"200":{"description":"`items[]` are facts_current rows (snake_case, as stored) each with a camelCase `document` summary; `uploads[]` are the facts-corpus documents.","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"document":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"status":{"type":"string","enum":["uploaded","parsing","parsed","chunking","embedding","enriching","ready","failed","review_needed"]},"statusDetail":{"type":["string","null"]},"quality":{"anyOf":[{"type":"string","enum":["high","partial","unusable"]},{"type":"null"}]},"qualityCode":{"anyOf":[{"type":"string","enum":["complete","required_fields_missing","low_confidence","no_structured_fields","extractor_unavailable","extractor_failed","no_text_layer","wrong_document_kind","file_unreadable","file_encrypted","file_unsupported_format"]},{"type":"null"}]},"qualityReason":{"type":["string","null"]},"qualityDetail":{"anyOf":[{"type":"object","additionalProperties":{}},{"type":"null"}]},"gradedAt":{"type":["string","null"]},"createdAt":{"type":"string"},"factId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"hasText":{"type":"boolean"},"visibility":{"type":"string","enum":["client","bidwriter"]}},"required":["id","title","status","statusDetail","quality","qualityCode","qualityReason","qualityDetail","gradedAt","createdAt","factId","hasText","visibility"],"additionalProperties":false},{"type":"null"}]}},"required":["document"],"additionalProperties":false}},"uploads":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"status":{"type":"string","enum":["uploaded","parsing","parsed","chunking","embedding","enriching","ready","failed","review_needed"]},"statusDetail":{"type":["string","null"]},"quality":{"anyOf":[{"type":"string","enum":["high","partial","unusable"]},{"type":"null"}]},"qualityCode":{"anyOf":[{"type":"string","enum":["complete","required_fields_missing","low_confidence","no_structured_fields","extractor_unavailable","extractor_failed","no_text_layer","wrong_document_kind","file_unreadable","file_encrypted","file_unsupported_format"]},{"type":"null"}]},"qualityReason":{"type":["string","null"]},"qualityDetail":{"anyOf":[{"type":"object","additionalProperties":{}},{"type":"null"}]},"gradedAt":{"type":["string","null"]},"createdAt":{"type":"string"},"factId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"hasText":{"type":"boolean"},"visibility":{"type":"string","enum":["client","bidwriter"]}},"required":["id","title","status","statusDetail","quality","qualityCode","qualityReason","qualityDetail","gradedAt","createdAt","factId","hasText","visibility"],"additionalProperties":false}}},"required":["items","uploads"],"additionalProperties":true}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}},"post":{"operationId":"postFacts","tags":["facts"],"summary":"Add a fact by hand (label, type, value, scope, expiry)","parameters":[],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"description":"The facts row (201; 200 with the twin on a repeat) — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"201":{"description":"The facts row (201; 200 with the twin on a repeat) — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"The facts row (201; 200 with the twin on a repeat) — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Same type, label and value ⇒ the existing row with 200.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":300},"factType":{"type":"string","enum":["cert","insurance","cv","case_study","kpi","policy","pricing_model","other","capability","capacity","appetite","relationship","buyer_intel","incumbent"]},"valueText":{"type":"string","maxLength":5000},"documentId":{"type":"string","format":"uuid"},"expiresAt":{"type":"string","format":"date-time"},"scope":{"type":"string","enum":["company","buyer","tender"],"default":"company"},"buyerName":{"type":"string","maxLength":300}},"required":["label","factType"],"additionalProperties":false}}}}}},"/facts/{id}":{"patch":{"operationId":"patchFactsId","tags":["facts"],"summary":"Edit a fact (a manual expiry is the human verification of a partially-graded upload)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The updated facts row — the raw table row(s) as stored (packages/db/src/schema); not typed here.","content":{"application/json":{"schema":{"description":"The updated facts row — the raw table row(s) as stored (packages/db/src/schema); not typed here."}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Sets fields; re-targeting an interview answer is 409.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":300},"factType":{"type":"string","enum":["cert","insurance","cv","case_study","kpi","policy","pricing_model","other","capability","capacity","appetite","relationship","buyer_intel","incumbent"]},"valueText":{"type":"string","maxLength":5000},"expiresAt":{"type":"string","format":"date-time"},"scope":{"type":"string","enum":["company","buyer","tender"],"default":"company"},"buyerName":{"type":"string","maxLength":300}},"additionalProperties":false}}}}},"delete":{"operationId":"deleteFactsId","tags":["facts"],"summary":"Delete a fact","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted."},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"No such row in this company.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Already gone ⇒ 404.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/facts/upload":{"post":{"operationId":"postFactsUpload","tags":["facts"],"summary":"Upload a facts-bank document (raw bytes): ingested like any document AND read against the fact type’s required fields, then graded","description":"Send the file bytes as the body with `Content-Type: application/octet-stream` (up to 60 MiB per file) and the name in `X-Filename`. The bytes are sniffed: the container must match the extension (an .html renamed .pdf is refused 422 `unsupported_file`, and nothing is stored). PDF and .docx only here. An unusable upload loses its fact row and says why (flag, don't guess).","parameters":[{"name":"X-Filename","in":"header","required":true,"description":"The file name, percent-encoded (encodeURIComponent). The extension decides the parser: .pdf, .docx, .xlsx, .pptx, .odt, .ods.","schema":{"type":"string"}},{"name":"X-Fact-Type","in":"header","required":false,"description":"The fact type (FACT_TYPES); default `other`.","schema":{"type":"string"}}],"responses":{"200":{"description":"Already there — the existing row (ADR-0012).","content":{"application/json":{"schema":{"type":"object","properties":{"fact":{},"document":{}},"additionalProperties":false}}}},"201":{"description":"The pending fact and its document row.","content":{"application/json":{"schema":{"type":"object","properties":{"fact":{},"document":{}},"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"The bytes are the identity.","x-waywiser-rate-limit":{"bucket":"upload","limit":"30 per minute per key"},"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}}}},"/search":{"post":{"operationId":"postSearch","tags":["search"],"summary":"Hybrid retrieval over what the caller may read: passages, past answers, facts — with provenance","description":"The same retrieval the drafts are grounded in. Results carry the ids the drafting routes accept as citations.","parameters":[],"responses":{"200":{"description":"Ranked results.","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["chunk","response_unit","fact","qa_pair"]},"text":{"type":"string"},"score":{"type":"number"},"provenance":{"type":"object","properties":{"documentId":{"type":"string"},"title":{"type":"string"},"section":{"type":"string"},"page":{"type":"number"},"year":{"type":"number"},"evaluatorScore":{"type":["number","null"]},"outcome":{"type":"string"},"questionArchetype":{"type":["string","null"]},"corpusName":{"type":"string"},"corpusId":{"type":"string"},"isCompanyCorpus":{"type":"boolean"},"visibility":{"type":"string","enum":["client","bidwriter"]}},"required":["title","isCompanyCorpus"],"additionalProperties":false}},"required":["id","kind","text","score","provenance"],"additionalProperties":false}}},"required":["items"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"Not in the right state; `error` says what to do.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read (an embedding call per query).","x-waywiser-rate-limit":{"bucket":"search","limit":"60 per minute per key"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","minLength":1,"maxLength":2000},"purpose":{"type":"string","enum":["evidence","drafting","claim_fix","checklist_link","general"]},"filters":{"type":"object","properties":{"buyerType":{"type":"string","enum":["nhs_trust","local_authority","university","school","housing","central_government","private"]},"serviceLine":{"type":"string","enum":["hard_fm","m_and_e","cleaning","fire_safety","water_hygiene","drainage","grounds","tfm","gas_heating","security","catering","waste","pest_control","caretaking"]},"questionArchetype":{"type":"string","enum":["mobilisation_transition","delivery_model_staffing","statutory_compliance","cafm_mi_reporting","supply_chain","risk_business_continuity","social_value","quality_assurance","health_safety","sustainability_environment","experience_case_studies","pricing_commercial","other"]},"docType":{"type":"string","enum":["past_bid","itt","cert","policy","case_study","pricing_workbook","standard","other"]},"corpusIds":{"type":"array","items":{"type":"string","format":"uuid"}},"yearFrom":{"type":"integer"}},"additionalProperties":false,"default":{}},"topN":{"type":"integer","minimum":1,"maximum":20,"default":8}},"required":["query","purpose"],"additionalProperties":false}}}}}},"/benchmarks":{"get":{"operationId":"getBenchmarks","tags":["pricing"],"summary":"Winning-price distribution for comparable lots (public award data, or the company’s own wins)","parameters":[{"name":"buyerType","in":"query","required":true,"schema":{"type":"string","enum":["nhs_trust","local_authority","university","school","housing","central_government","private"]}},{"name":"serviceLine","in":"query","required":true,"schema":{"type":"string","enum":["hard_fm","m_and_e","cleaning","fire_safety","water_hygiene","drainage","grounds","tfm","gas_heating","security","catering","waste","pest_control","caretaking"]}},{"name":"source","in":"query","required":false,"schema":{"type":"string","enum":["public","wins"],"default":"public"}},{"name":"region","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Bins, median and comparables.","content":{"application/json":{"schema":{"type":"object","properties":{"n":{"type":"integer"},"bins":{"type":"array","items":{}},"median":{"type":["number","null"]},"comparables":{"type":"array","items":{"type":"object","properties":{"buyerType":{"type":"string"},"region":{"type":["string","null"]},"year":{"type":"integer"},"unitPrice":{"type":["number","null"]},"denominatorKind":{"type":"string"},"qualityScore":{"type":["number","null"]},"confidence":{"type":["string","null"]},"normalisationMethod":{"type":["string","null"]},"confidenceNotes":{"type":["string","null"]},"crossSegment":{"type":"boolean"}},"required":["buyerType","region","year","unitPrice","denominatorKind","qualityScore","confidence","normalisationMethod","confidenceNotes","crossSegment"],"additionalProperties":false}},"denominatorKinds":{"type":"array","items":{"type":"string"}}},"required":["n","bins","median","comparables","denominatorKinds"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/cost-floor":{"get":{"operationId":"getCostFloor","tags":["pricing"],"summary":"The bottom-up cost floor from the company’s labour-load model and rate build-ups, or the named blockers","parameters":[],"responses":{"200":{"description":"Available with lines, or the blockers.","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"available":{"type":"boolean","const":false},"reason":{"type":"string"},"blockers":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["no_cost_models","labour_load_missing","rate_buildup_missing","rates_not_populated","fte_ratio_unavailable","cost_per_fte_unavailable"]},"detail":{"type":"string"}},"required":["code","detail"],"additionalProperties":false}}},"required":["available","reason","blockers"],"additionalProperties":false},{"type":"object","properties":{"available":{"type":"boolean","const":true},"lines":{"type":"array","items":{"type":"object","properties":{"item":{"type":"string"},"perM2":{"type":["number","null"]},"status":{"type":"string","enum":["priced","not_priced"]}},"required":["item","perM2","status"],"additionalProperties":false}},"totalPerM2":{"type":"number"},"complete":{"type":"boolean"},"unpricedLines":{"type":"array","items":{"type":"string"}},"basis":{"type":"object","properties":{"costPerFte":{"type":"number"},"ftePer10kM2":{"type":"number"},"weighting":{"type":["string","null"]},"method":{"type":["string","null"]}},"required":["costPerFte","ftePer10kM2","weighting","method"],"additionalProperties":false}},"required":["available","lines","totalPerM2","complete","unpricedLines","basis"],"additionalProperties":false}]}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}},"/activity":{"get":{"operationId":"getActivity","tags":["activity"],"summary":"Background work, derived from the status machines: extractions, documents, drafts, reviews, clarification drafts, exports","description":"The poller for a 202 whose `operation.poll` names it: `?target=<id>` returns that one row with `state` queued | running | done | failed, `stale`, `error`, and `progress` (real stages, or elapsed against the typical duration). `inFlight` counts everything running for the company.","parameters":[{"name":"window","in":"query","required":false,"schema":{"type":"string","enum":["24h","7d","30d"],"default":"7d"}},{"name":"state","in":"query","required":false,"schema":{"type":"string","enum":["in_flight","failed","all"],"default":"all"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200,"default":100}},{"name":"target","in":"query","required":false,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Activity items.","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["extraction","document","draft","review","clarification","export"]},"id":{"type":"string","format":"uuid"},"state":{"type":"string","enum":["queued","running","done","failed"]},"stale":{"type":"boolean"},"title":{"type":"string"},"subtitle":{"type":["string","null"]},"href":{"type":"string"},"retryHref":{"type":["string","null"]},"rawStatus":{"type":"string"},"error":{"type":["string","null"]},"requestedAt":{"type":"string"},"startedAt":{"type":["string","null"]},"finishedAt":{"type":["string","null"]},"durationMs":{"anyOf":[{"type":"integer"},{"type":"null"}]},"progress":{"anyOf":[{"anyOf":[{"type":"object","properties":{"mode":{"type":"string","const":"stages"},"stage":{"type":"integer","minimum":0},"of":{"type":"integer","minimum":1},"label":{"type":"string"}},"required":["mode","stage","of","label"],"additionalProperties":false},{"type":"object","properties":{"mode":{"type":"string","const":"elapsed"},"elapsedMs":{"type":"integer","minimum":0},"typicalMs":{"anyOf":[{"type":"integer"},{"type":"null"}]},"upperMs":{"anyOf":[{"type":"integer"},{"type":"null"}]},"basis":{"type":"string","enum":["observed","default"]},"samples":{"type":"integer","minimum":0}},"required":["mode","elapsedMs","typicalMs","upperMs","basis","samples"],"additionalProperties":false},{"type":"object","properties":{"mode":{"type":"string","const":"queued"},"waitingMs":{"type":"integer","minimum":0}},"required":["mode","waitingMs"],"additionalProperties":false}]},{"type":"null"}]},"detail":{"type":["string","null"]}},"required":["kind","id","state","stale","title","subtitle","href","retryHref","rawStatus","error","requestedAt","startedAt","finishedAt","durationMs","progress","detail"],"additionalProperties":false}},"inFlight":{"type":"integer","minimum":0},"window":{"type":"string","enum":["24h","7d","30d"]},"state":{"type":"string","enum":["in_flight","failed","all"]}},"required":["items","inFlight","window","state"],"additionalProperties":false}}}},"400":{"description":"Validation failed — `issues[]` names each field.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No usable credential (`unauthenticated`, `key_revoked`, `key_expired`, `key_membership_gone`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"Forbidden: the key is read-only (`read_only_key`), or the caller may not act on this row.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limited; `retryAfterSeconds` says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-waywiser-idempotency":"Read.","x-waywiser-rate-limit":{"bucket":"global","limit":"300 requests per minute per key (RATE_LIMIT_GLOBAL_MAX)"}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"ww_live_… (an API key minted by a company admin at /admin/api-keys)","description":"Authorization: Bearer <secret>. One key = one company = one member, with a role ceiling and an optional read-only flag; never a super admin, never the identity/tenancy plane."}},"schemas":{"ErrorBody":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["validation_failed","unauthenticated","forbidden","no_active_company","read_only_key","human_only_route","company_mismatch","api_key_required","key_revoked","key_expired","key_membership_gone","not_found","conflict","payload_too_large","unsupported_file","rate_limited","ai_budget_exceeded","queue_unavailable","service_unavailable","internal"]},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"}},"required":["path","message"],"additionalProperties":false}},"hint":{"type":"string"},"retryAfterSeconds":{"type":"integer","exclusiveMinimum":0}},"required":["error","code"],"additionalProperties":false},"ErrorCode":{"type":"string","enum":["validation_failed","unauthenticated","forbidden","no_active_company","read_only_key","human_only_route","company_mismatch","api_key_required","key_revoked","key_expired","key_membership_gone","not_found","conflict","payload_too_large","unsupported_file","rate_limited","ai_budget_exceeded","queue_unavailable","service_unavailable","internal"]}}}}