{"openapi":"3.1.0","info":{"title":"Stipple API","summary":"Evidence-backed verification for the documents you receive.","description":"Stipple is the document infrastructure layer: evidence-backed checks on the documents you receive.\n\nEvery endpoint reports **coverage, not a verdict** — an explainable signal a human acts on, never an\nautomated decision. Most tools accept a document as a multipart `file`, JSON `bytes_b64`, or a public\n`url`; long-running calls support `?stream=1` (Server-Sent Events). Every tool is free. Anonymous callers get a free-checks cap per week, shared per IP; add a free key from a signed-in account (`POST /v1/keys` with the session, no card) for a free-checks cap of your own (100 a week, sent as `Authorization: Bearer <key>`). Result reads, tender browsing, and the sandbox need no key. Links to other sites (a tender's or grant's original portal, a contract award's or a plan's notice) are returned only to a key or a signed-in account.\n\n- **Sandbox** — add `sandbox: true` (or the header `Stp-Sandbox: true`) to any tool to get a\n  deterministic, clearly-labelled fixture response, free.\n- **Idempotency** — send an `Idempotency-Key` header on a POST so a retry never processes twice.\n- **Free with a weekly cap** — every tool here is free; a key gets a weekly free-checks cap\n  reported on `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset`. The only paid\n  thing on the platform is preparing a bid, priced at `/v1/pricing`.\n","contact":{"name":"Stipple","url":"https://www.stipple.sh/contact"},"license":{"name":"Security & terms","url":"https://www.stipple.sh/security"},"version":"0.6.0"},"servers":[{"url":"https://www.stipple.sh","description":"Production"}],"paths":{"/livez":{"get":{"summary":"Healthz","operationId":"healthz_livez_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Healthz Livez Get"}}}}}}},"/health":{"get":{"summary":"Healthz","operationId":"healthz_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Healthz Health Get"}}}}}}},"/healthz":{"get":{"summary":"Healthz","operationId":"healthz_healthz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Healthz Healthz Get"}}}}}}},"/agents.md":{"get":{"summary":"Agents Md","description":"Public agent guide — the distribution channel for the long tail of agent builders.","operationId":"agents_md_agents_md_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/llms.txt":{"get":{"summary":"Llms","operationId":"llms_llms_txt_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/agent-card.json":{"get":{"summary":"Agent Card Route","description":"Machine-readable discovery card, served at the conventional agent-card paths that agent\ndirectories probe (several were 404ing on these). Describes the real MCP + REST surface.","operationId":"agent_card_route_v1_agent_card_json_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/agent.json":{"get":{"summary":"Agent Card Route","description":"Machine-readable discovery card, served at the conventional agent-card paths that agent\ndirectories probe (several were 404ing on these). Describes the real MCP + REST surface.","operationId":"agent_card_route_v1_agent_json_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/agent-card.json":{"get":{"summary":"Agent Card Route","description":"Machine-readable discovery card, served at the conventional agent-card paths that agent\ndirectories probe (several were 404ing on these). Describes the real MCP + REST surface.","operationId":"agent_card_route__well_known_agent_card_json_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/.well-known/agent.json":{"get":{"summary":"Agent Card Route","description":"Machine-readable discovery card, served at the conventional agent-card paths that agent\ndirectories probe (several were 404ing on these). Describes the real MCP + REST surface.","operationId":"agent_card_route__well_known_agent_json_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/warrants":{"post":{"tags":["Documents"],"summary":"Create Warrant","description":"Inspect one document. Intake: multipart ``file``, or a JSON body with\n``bytes_b64`` (+ optional ``filename``). Returns the WarrantBundle as JSON, or — with\n``?stream=1`` — a lifecycle SSE stream (``received`` → ``inspecting`` → ``result``).\n\nIdentical documents (same sha256) reuse the stored bundle to skip the paid VLM call;\npass ``?fresh=1`` to force a re-inspection.","operationId":"create_warrant_v1_warrants_post","parameters":[{"name":"stream","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Stream"}},{"name":"fresh","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Fresh"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_warrant_v1_warrants_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/warrants/{warrant_id}/feedback":{"post":{"summary":"Submit Feedback","description":"Record a thumbs up/down on a prior warrant. The precision-flywheel label source.","operationId":"submit_feedback_v1_warrants__warrant_id__feedback_post","parameters":[{"name":"warrant_id","in":"path","required":true,"schema":{"type":"string","title":"Warrant Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Submit Feedback V1 Warrants  Warrant Id  Feedback Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/feedback":{"post":{"tags":["Meta"],"summary":"Submit Tool Feedback","description":"Thumbs up/down for the stateless analysis tools (`detect_ai_text`, `verify_references`),\nwhich mint no warrant id. Records a short, non-sensitive label. The rated text is stored ONLY\nplus the rated text when the caller sends it; retention and use are disclosed in the privacy\npolicy. Best-effort: a write failure never fails the response.","operationId":"submit_tool_feedback_v1_feedback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolFeedbackBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Submit Tool Feedback V1 Feedback Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/contact":{"post":{"tags":["Meta"],"summary":"Submit Contact","description":"Receive a contact-form message, from the /contact form or the site chat widget.\n\nTwo sinks, and both matter. The message is written as ONE structured stdout line\n(jsonPayload.event=\"contact_message\") that Cloud Run lands in Cloud Logging - the durable,\nqueryable record - AND emailed to CONTACT_NOTIFY_TO, which is the part a person actually\nsees. The log alone was the original design and it failed in the obvious way: nobody\nqueries a log, so real enquiries sat unread.\n\nBot submissions (honeypot or impossibly-fast) are silently dropped before both sinks, on\ntop of the rate limit.","operationId":"submit_contact_v1_contact_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Submit Contact V1 Contact Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/warrants/check":{"get":{"tags":["Meta"],"summary":"Check Warrant","description":"Cache check: has this exact document (by sha256) already been inspected? Lets an\nagent skip a redundant (paid) inspection. Declared BEFORE the ``{warrant_id}`` route so\nthe literal path wins. Returns ``{cached, warrant_id, permalink}`` or ``{cached: false}``.","operationId":"check_warrant_v1_warrants_check_get","parameters":[{"name":"sha256","in":"query","required":true,"schema":{"type":"string","title":"Sha256"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Check Warrant V1 Warrants Check Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/warrants/{warrant_id}":{"get":{"tags":["Documents"],"summary":"Get Warrant","description":"Retrieve a stored warrant by id — the permalink/share + agent fetch surface.\n``?format=json`` (default) returns the bundle; ``?format=md`` a Markdown report.","operationId":"get_warrant_v1_warrants__warrant_id__get","parameters":[{"name":"warrant_id","in":"path","required":true,"schema":{"type":"string","title":"Warrant Id"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","default":"json","title":"Format"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"title":"Response Get Warrant V1 Warrants  Warrant Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/warrants/{warrant_id}/report.pdf":{"get":{"tags":["Documents"],"summary":"Get Warrant Report","description":"A branded, audit-ready PDF of the warrant — fetchable by a human or an agent.","operationId":"get_warrant_report_v1_warrants__warrant_id__report_pdf_get","parameters":[{"name":"warrant_id","in":"path","required":true,"schema":{"type":"string","title":"Warrant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/detect-ai-text":{"post":{"tags":["Generated content"],"summary":"Detect Ai Text Route","description":"Estimate the probability a document's PROSE was AI-written — the engine behind the\n`/ai-detector` page, mirroring the `/mcp-aitext` tool. Send multipart `file` (PDF/text), or\nJSON `{\"text\": \"...\"}` / `{\"bytes_b64\": \"...\", \"filename\": \"...\"}` / `{\"url\": \"https://...\"}`\n(public hosts only, SSRF-guarded, size-capped). Returns\n`{applicable, probability, lean, tells, reasoning, limitations}` — it ABSTAINS on non-prose\n(forms/tables/scans) with `applicable: false`. The probability is the model's CONFIDENCE,\nnot a calibrated truth.","operationId":"detect_ai_text_route_v1_detect_ai_text_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_detect_ai_text_route_v1_detect_ai_text_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Detect Ai Text Route V1 Detect Ai Text Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/check-source-overlap":{"post":{"tags":["Generated content"],"summary":"Check Source Overlap Route","description":"Check whether submitted text OVERLAPS text published on the public web — the engine\nbehind the `/plagiarism-checker` page, mirroring the `/mcp-plagiarism` tool. Send\nmultipart `file` (PDF/text/.docx), or JSON `{\"text\": \"...\"}` / `{\"bytes_b64\": \"...\",\n\"filename\": \"...\"}` / `{\"url\": \"https://...\"}` (public hosts only, SSRF-guarded; the\npage's own host is excluded from matches). Two evidence tiers: `matches` are exact/\nnear-verbatim quotes confirmed against the FETCHED source page, with char spans on both\nsides; `possible_paraphrases` are model judgements, clearly labelled and never quotes.\nReports overlap, never accusations — see `limitations`. Charged 3 credits ONLY for a\ncompleted assessment: abstentions (`applicable: false`), `search_unavailable` and\nengine failures cost 0 (the `outcome` field is the receipt).","operationId":"check_source_overlap_route_v1_check_source_overlap_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_check_source_overlap_route_v1_check_source_overlap_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Check Source Overlap Route V1 Check Source Overlap Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/extract":{"post":{"tags":["Documents"],"summary":"Extract Fields Route","description":"Extract structured FIELDS from any document — the engine behind the `/extract` page,\nmirroring the `extract_fields` MCP tool. A vision model reads up to a few pages and returns\nthe values you ask for. Four ways to say WHAT to pull: `fields` (an ad-hoc list — names, or\n{name,type,description|question}; type = text|amount|date|boolean), `template` (a named\npreset: payslip, tax_invoice, bank_statement, receipt, contract), NEITHER (auto — classify\nthe document then apply that type's fields), or auto on an unknown type (schema-free —\nevery labelled field). `options` turns on extra capabilities, every one OFF by default:\ntables, grounding, classify, redact, layout, links, figures, chunks, split, flag_below —\nasking for one this server lacks is a 400 naming it, never a silent no-op, and\n`GET /v1/extract/capabilities` (free) is the machine-readable contract. `render_scale`\n(1.0|1.5|2.0|3.0|4.0) raises rasterisation for dense print.\nSend multipart `file` with optional `?template=`/`?country=`/`?max_pages=`/repeated\n`?fields=` and flat option params, or JSON `{bytes_b64|url, filename, fields, template,\ncountry, max_pages, render_scale, options}` (URLs SSRF-guarded). Add `?stream=1` for\nsafe lifecycle progress, heartbeat, result, and error events. Returns `{mode,\ndocument_type, fields{name:{value,confidence,page}}, not_found, pages_read, page_limit,\npage_count, ...}` plus one key per option. Costs 1 credit per page a model reads (minimum\n1); deterministic work is free, and option surcharges are listed in the capabilities\nendpoint. CAPABILITY-ONLY: `options.classify` and/or `options.redact` with no fields,\ntemplate or other option skips field extraction — classify-only costs 1 credit and\nredact-only 1 per page (the retired classify/redact prices). EXTRACTION, not\nverification — values are what the document shows, not proof it is genuine; the\ndocument is never stored.","operationId":"extract_fields_route_v1_extract_post","parameters":[{"name":"stream","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Stream"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_extract_fields_route_v1_extract_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/extract/capabilities":{"get":{"tags":["Documents"],"summary":"Extract Capabilities Route","description":"What `/v1/extract` can actually do on THIS server — free, no key, 0 credits.\n\nAn agent should not have to discover capability by trial and error, and it should not\nhave to trust prose. This is the machine-readable answer: every option, what it\naccepts, which inputs it works on, the mechanism behind it, and — the honest part —\nwhether it has been MEASURED. `available: false` means the option is planned and will\nbe rejected with a 400 today, so an agent can plan around it instead of guessing.","operationId":"extract_capabilities_route_v1_extract_capabilities_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Extract Capabilities Route V1 Extract Capabilities Get"}}}}}}},"/v1/adverse-media":{"post":{"tags":["Screening"],"summary":"Adverse Media Route","description":"Screen a subject for ADVERSE MEDIA and SANCTIONS exposure — the engine behind the\n`/adverse-media` page, mirroring the `screen_adverse_media` MCP tool. PEP lists are not\nscreened, and the result says so. Two layers: a deterministic, corroboration-gated match\nagainst four primary sanctions lists (OFAC, EU, UK, AU DFAT), and\nan entity-disambiguated pass over public news/web sources classifying adverse coverage. Identify\nthe subject by JSON `{\"name\", \"dob\", \"country\", \"aliases\", \"employer\", \"role\"}`, or pass an\nidentity document (multipart `file`, or JSON `bytes_b64`/`url`) to read the subject from it\n(disambiguators may be added as query params or JSON alongside). Returns `{subject, sanctions,\nadverse_media, risk_flag, headline, limitations}`. Screening COVERAGE, not a determination — a\nhit means \"review\", not \"guilty\", and \"nothing found\" is not a clean record. Stateless.","operationId":"adverse_media_route_v1_adverse_media_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_adverse_media_route_v1_adverse_media_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Adverse Media Route V1 Adverse Media Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/identity-check":{"post":{"tags":["Identity"],"summary":"Identity Check Route","description":"Run an Australian identity check over a SET of documents — the engine behind the\n`/identity` page, mirroring the `verify_identity` MCP tool. A vision model reads each\ndocument (type + which N/P/A/S fields it shows + issue date); a deterministic engine then\ntallies them against a scheme: `afp_100_point` (points, default) or `austrac_safe_harbour`\n(category combinations). Send multipart `files` (one or more PDFs/images) with an optional\n`?scheme=`, or JSON `{\"documents\": [{\"url\": ...} | {\"bytes_b64\": ..., \"filename\": ...}],\n\"scheme\": ...}` (URLs are SSRF-guarded). Stateless — documents are never stored. Returns\n`{established, points/target or satisfied_path, documents[], reason, ...}`. This is identity\nCOVERAGE, not a forgery judgment (use /v1/warrants for authenticity).","operationId":"identity_check_route_v1_identity_check_post","parameters":[{"name":"scheme","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scheme"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_identity_check_route_v1_identity_check_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Identity Check Route V1 Identity Check Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/check-pack":{"post":{"tags":["Identity"],"summary":"Check Pack Route","description":"Check whether a SET of documents satisfies a checklist — the engine behind the\n`/check-pack` page, mirroring the `check_pack` MCP tool. Each document is CLASSIFIED (one cheap\npage-1 read, hash-cached — never field extraction or multi-page reads), then a deterministic\nengine maps the document types onto the checklist's required slots and reports what's present\nand what's missing. Supply a named `?scheme=` (`income_proof` / `lending_prequal` /\n`rental_application`) OR a `requirements` checklist (JSON: a list of type names or\n`{key, accepts:[types], optional}`; multipart: repeated `?requirements=`). Send multipart\n`files`, or JSON `{\"documents\":[{\"url\"}|{\"bytes_b64\",\"filename\"}], \"scheme\"|\"requirements\"}`\n(URLs SSRF-guarded; up to 12 documents). Returns `{complete, slots[], missing[], documents[],\nunmatched_documents[]}`. COVERAGE, not approval — that the right document TYPES are present, not\nthat any is genuine (use /v1/warrants) or that an application is approved.","operationId":"check_pack_route_v1_check_pack_post","parameters":[{"name":"scheme","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scheme"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_check_pack_route_v1_check_pack_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Check Pack Route V1 Check Pack Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/fact-checks/{check_id}":{"get":{"tags":["Generated content"],"summary":"Get Fact Check","description":"Retrieve a stored fact-check result by its content-hash id (``fc_<16 hex>``) — the\ndata source for the shareable /fc/<id> permalink pages.","operationId":"get_fact_check_v1_fact_checks__check_id__get","parameters":[{"name":"check_id","in":"path","required":true,"schema":{"type":"string","title":"Check Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Fact Check V1 Fact Checks  Check Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/keys":{"get":{"tags":["Keys & usage"],"summary":"List Api Keys","description":"List this account's key metadata. Plaintext keys and hashes never leave storage.","operationId":"list_api_keys_v1_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Api Keys V1 Keys Get"}}}}}},"post":{"tags":["Keys & usage"],"summary":"Create Api Key","description":"Self-serve API key issuance. The key is returned ONCE and never stored in plaintext —\nonly its hash. A keyed caller gets a weekly allowance of its own instead of sharing the\nper-IP one, and can read its metered usage via ``GET /v1/usage``.\n\nSign in first and the key is linked to your account (``user_id``), so keys, credits and\nhistory are one identity rather than three that share an unproven email. Whether an\nanonymous caller may mint is ``config.key_mint_needs_session``: never under the TRIAL\nmodel (the balance a key spends is the account's), and never while\nOPENWARRANT_REQUIRE_KEY_LOGIN is on and sign-in is configured (owner decision\n2026-08-23; this route stopped reading the flag on 2026-08-28 and reads it again from\n2026-09-30). Keys minted anonymously before that stay valid and can be linked to an\naccount by proving possession (``POST /v1/account/keys/link``).","operationId":"create_api_key_v1_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateKeyBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Create Api Key V1 Keys Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/mcp/connector":{"post":{"tags":["Keys & usage"],"summary":"Create Mcp Connector","description":"Mint this account's MCP connector URL — ``/mcp/c/<token>`` — for chat-assistant\nconnector dialogs that take a server URL and no header. The token is an API key\nscoped to MCP (see ``keys.build_key_record``); it is shown ONCE, counts toward the\nper-account key cap, and is revoked like any key (``DELETE /v1/keys/{key_id}``).","operationId":"create_mcp_connector","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Create Mcp Connector"}}}}}}},"/v1/keys/{key_id}":{"delete":{"tags":["Keys & usage"],"summary":"Revoke Api Key","description":"Disable one owned key. Revocation is immediate and cannot expose the key material.","operationId":"revoke_api_key_v1_keys__key_id__delete","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Revoke Api Key V1 Keys  Key Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/account/keys/link":{"post":{"tags":["Keys & usage"],"summary":"Link Api Key","description":"Prove possession of an anonymous key and attach it to the signed-in account.","operationId":"link_api_key_v1_account_keys_link_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkKeyBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Link Api Key V1 Account Keys Link Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs":{"get":{"tags":["Orgs"],"summary":"List Orgs","description":"The orgs this account belongs to, with the role it holds in each.","operationId":"list_orgs_v1_orgs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Orgs V1 Orgs Get"}}}}}},"post":{"tags":["Orgs"],"summary":"Create Org","description":"Create an org from a company name; the caller becomes its owner.","operationId":"create_org_v1_orgs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrgBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Create Org V1 Orgs Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/{org}/invites":{"post":{"tags":["Orgs"],"summary":"Create Org Invite","description":"Invite an address to this org at a role no higher than the inviter's own.\n\n409 if that address is already a member: acceptance refuses an existing membership, so\nthe invite would be a link that can never work. Errors: 400, 401, 403, 404, 409.","operationId":"create_org_invite_v1_orgs__org__invites_post","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","title":"Org"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgInviteBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Org Invite V1 Orgs  Org  Invites Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/invites/{token}/accept":{"post":{"tags":["Orgs"],"summary":"Accept Org Invite","description":"Redeem an invitation. Bad, expired, already-used and wrong-recipient all answer 404.","operationId":"accept_org_invite_v1_orgs_invites__token__accept_post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Accept Org Invite V1 Orgs Invites  Token  Accept Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/{org}/members":{"get":{"tags":["Orgs"],"summary":"List Org Members","description":"This org's members and their roles. Members only — a non-member gets the same 404 as\nsomeone asking about an org that does not exist.","operationId":"list_org_members_v1_orgs__org__members_get","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","title":"Org"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Org Members V1 Orgs  Org  Members Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/{org}/profile":{"get":{"tags":["Orgs"],"summary":"Get Org Profile","description":"The onboarding profile: company name, ABN, region, what the org does, and progress.","operationId":"get_org_profile_v1_orgs__org__profile_get","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","title":"Org"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Org Profile V1 Orgs  Org  Profile Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Orgs"],"summary":"Patch Org Profile","description":"Any subset of the profile fields plus `onboarding`. -> the full profile.\n\nA plain ``dict`` body, not a Pydantic model: an unknown field must reach\n``update_org_profile``'s own 400, the same way ``create_requirement`` does it, rather\nthan being swallowed by ``extra: forbid`` into a 422 nobody in the contract promised.","operationId":"patch_org_profile_v1_orgs__org__profile_patch","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","title":"Org"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Patch Org Profile V1 Orgs  Org  Profile Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/{org}/documents":{"get":{"tags":["Orgs"],"summary":"List Org Documents","description":"The company document library: uploaded once in onboarding, reused by every bid.","operationId":"list_org_documents_v1_orgs__org__documents_get","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","title":"Org"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Org Documents V1 Orgs  Org  Documents Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Orgs"],"summary":"Upload Org Documents","operationId":"upload_org_documents_v1_orgs__org__documents_post","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","title":"Org"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_org_documents_v1_orgs__org__documents_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Upload Org Documents V1 Orgs  Org  Documents Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/orgs/{org}/documents/{doc_id}":{"patch":{"tags":["Orgs"],"summary":"Patch Org Document","description":"Q112 (owner, 2026-10-08): the document's one expiry date, set by the person. Anyone\nwho may upload to the library may date what is in it.","operationId":"patch_org_document_v1_orgs__org__documents__doc_id__patch","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","title":"Org"}},{"name":"doc_id","in":"path","required":true,"schema":{"type":"string","title":"Doc Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgDocumentPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Patch Org Document V1 Orgs  Org  Documents  Doc Id  Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Orgs"],"summary":"Delete Org Document","operationId":"delete_org_document_v1_orgs__org__documents__doc_id__delete","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","title":"Org"}},{"name":"doc_id","in":"path","required":true,"schema":{"type":"string","title":"Doc Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Org Document V1 Orgs  Org  Documents  Doc Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids":{"post":{"tags":["Bids"],"summary":"Create Bid","operationId":"create_bid_v1_bids_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBidBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Bid V1 Bids Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["Bids"],"summary":"List Bids","operationId":"list_bids_v1_bids_get","parameters":[{"name":"org_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Org Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Bids V1 Bids Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}":{"get":{"tags":["Bids"],"summary":"Get Bid","operationId":"get_bid_v1_bids__bid__get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Bid V1 Bids  Bid  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Bids"],"summary":"Patch Bid","operationId":"patch_bid_v1_bids__bid__patch","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchBidBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Patch Bid V1 Bids  Bid  Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/files":{"get":{"tags":["Bids"],"summary":"List Bid Files","operationId":"list_bid_files_v1_bids__bid__files_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Bid Files V1 Bids  Bid  Files Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Bids"],"summary":"Upload Bid Files","operationId":"upload_bid_files_v1_bids__bid__files_post","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_bid_files_v1_bids__bid__files_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Upload Bid Files V1 Bids  Bid  Files Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/files/{file_id}/url":{"get":{"tags":["Bids"],"summary":"Bid File Url","operationId":"bid_file_url_v1_bids__bid__files__file_id__url_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}},{"name":"file_id","in":"path","required":true,"schema":{"type":"string","title":"File Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Bid File Url V1 Bids  Bid  Files  File Id  Url Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/files/{file_id}/pages/{n}":{"get":{"tags":["Bids"],"summary":"Bid File Page","operationId":"bid_file_page_v1_bids__bid__files__file_id__pages__n__get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}},{"name":"file_id","in":"path","required":true,"schema":{"type":"string","title":"File Id"}},{"name":"n","in":"path","required":true,"schema":{"type":"integer","title":"N"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Bid File Page V1 Bids  Bid  Files  File Id  Pages  N  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/pack/fetch":{"get":{"tags":["Bids"],"summary":"Bid Pack Fetch Status","description":"Whether this bid's page offers \"Get the documents\" / \"Check for updates\" or the\nupload message, and the last fetch with what it changed.","operationId":"bid_pack_fetch_status_v1_bids__bid__pack_fetch_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Bid Pack Fetch Status V1 Bids  Bid  Pack Fetch Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Bids"],"summary":"Bid Pack Fetch","description":"Queue one document fetch for this bid (plan #44): buy.nsw tenders only (17b), for a\nperson who may (17a), at most 5 a Sydney day (17c). Runs in the background at once;\n`POST /v1/jobs/drain` picks up whatever a stopped instance left (Q120).","operationId":"bid_pack_fetch_v1_bids__bid__pack_fetch_post","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Bid Pack Fetch V1 Bids  Bid  Pack Fetch Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/requirements":{"get":{"tags":["Bids"],"summary":"Bid Requirements","operationId":"bid_requirements_v1_bids__bid__requirements_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"}},{"name":"mandatory","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Mandatory"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Bids"],"summary":"Create Requirement","operationId":"create_requirement_v1_bids__bid__requirements_post","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/requirements/{requirement}":{"patch":{"tags":["Bids"],"summary":"Patch Requirement","operationId":"patch_requirement_v1_bids__bid__requirements__requirement__patch","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}},{"name":"requirement","in":"path","required":true,"schema":{"type":"string","title":"Requirement"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/requirements/{requirement}/split":{"post":{"tags":["Bids"],"summary":"Split Requirement","operationId":"split_requirement_v1_bids__bid__requirements__requirement__split_post","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}},{"name":"requirement","in":"path","required":true,"schema":{"type":"string","title":"Requirement"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/requirements/merge":{"post":{"tags":["Bids"],"summary":"Merge Requirements","operationId":"merge_requirements_v1_bids__bid__requirements_merge_post","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/drafts":{"get":{"tags":["Bids"],"summary":"List Bid Drafts","operationId":"list_bid_drafts_v1_bids__bid__drafts_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/drafts/{requirement}":{"patch":{"tags":["Bids"],"summary":"Patch Bid Draft","operationId":"patch_bid_draft_v1_bids__bid__drafts__requirement__patch","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}},{"name":"requirement","in":"path","required":true,"schema":{"type":"string","title":"Requirement"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/export":{"get":{"tags":["Bids"],"summary":"Export Bid Response","operationId":"export_bid_response_v1_bids__bid__export_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/plan":{"get":{"tags":["Bids"],"summary":"Get Bid Plan","operationId":"get_bid_plan_v1_bids__bid__plan_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/plan/recompute":{"post":{"tags":["Bids"],"summary":"Recompute Bid Plan","operationId":"recompute_bid_plan_v1_bids__bid__plan_recompute_post","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/jobs/{job}":{"get":{"tags":["Bids"],"summary":"Get Bid Job","description":"A background job's status, by id. 404 when the job belongs to a different bid —\nsame existence-leak rule as everywhere else in this file.","operationId":"get_bid_job_v1_bids__bid__jobs__job__get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}},{"name":"job","in":"path","required":true,"schema":{"type":"string","title":"Job"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/gaps":{"get":{"tags":["Bids"],"summary":"List Bid Gaps","description":"The stored gap list, recomputed by whatever last changed a file or a requirement.\nFrom BL-115: each row also carries the partners that serve its category and region,\nand the response carries a count of rows per category.","operationId":"list_bid_gaps_v1_bids__bid__gaps_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/partners":{"get":{"tags":["Bids"],"summary":"List Partners Route","description":"The operator-owned partner catalogue, active rows only. Same auth level as the bid\nroutes above: a signed-in session that belongs to at least one org.","operationId":"list_partners_route_v1_partners_get","parameters":[{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/gaps/{gap}":{"patch":{"tags":["Bids"],"summary":"Patch Bid Gap","description":"Phase 0 has no vault, so the only status a human may set is NA, and only with a\nreason. Everything else is derived by the recompute.","operationId":"patch_bid_gap_v1_bids__bid__gaps__gap__patch","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}},{"name":"gap","in":"path","required":true,"schema":{"type":"string","title":"Gap"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/thread":{"get":{"tags":["Bids"],"summary":"List Bid Thread","operationId":"list_bid_thread_v1_bids__bid__thread_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Bids"],"summary":"Post Bid Thread","operationId":"post_bid_thread_v1_bids__bid__thread_post","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/chat":{"get":{"tags":["Bids"],"summary":"Get Bid Chat","description":"The Bid page's one read: stage, goal, jobs, what is running and the recap.","operationId":"get_bid_chat_v1_bids__bid__chat_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/runs":{"post":{"tags":["Bids"],"summary":"Create Bid Run","operationId":"create_bid_run_v1_bids__bid__runs_post","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/runs/quote":{"get":{"tags":["Bids"],"summary":"Quote Bid Run","operationId":"quote_bid_run_v1_bids__bid__runs_quote_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/worth-bidding":{"get":{"tags":["Bids"],"summary":"Get Bid Worth Bidding","description":"The chat's \"Worth bidding?\" card for this bid's own tender, built by code from what\nStipple holds: its buyer's contract awards, awards for similar work (a labelled\nheuristic) and the checks. The buyer comes from the bid, never a parameter. A member's\nread, like the thread's. 503 while the intelligence store loads.","operationId":"get_bid_worth_bidding_v1_bids__bid__worth_bidding_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/checkout":{"post":{"tags":["Bids"],"summary":"Create Bid Checkout","description":"Start a flat-fee tender purchase: returns the hosted Stripe Checkout URL. BL-210 —\nthe Bidline pricing pivot away from credit packs (``credits.billing_checkout``).\n\nCheckout review finding 4: the pending guard is a reservation, not a check-then-write —\none ``BID_STORE.mutate`` claims ``checkout_reserved_at`` (or refuses 409) before the\nStripe call happens at all, so two concurrent requests can never both create a session.\nA Stripe failure clears the reservation so the caller can retry immediately.\n\nRound 3, finding 2: the session id is bound to the reservation BEFORE the URL is\nreturned. If that write fails, the just-created Stripe session is expired (never left\npaid-but-unbound, which the webhook could otherwise never attach to a bid) and the\ncaller gets a 503 to retry.","operationId":"create_bid_checkout_v1_bids__bid__checkout_post","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Bid Checkout V1 Bids  Bid  Checkout Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/runs/{run}":{"get":{"tags":["Bids"],"summary":"Get Bid Run","operationId":"get_bid_run_v1_bids__bid__runs__run__get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}},{"name":"run","in":"path","required":true,"schema":{"type":"string","title":"Run"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/runs/{run}/events":{"get":{"tags":["Bids"],"summary":"Stream Bid Run Events","operationId":"stream_bid_run_events_v1_bids__bid__runs__run__events_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}},{"name":"run","in":"path","required":true,"schema":{"type":"string","title":"Run"}},{"name":"since_seq","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Since Seq"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/findings":{"get":{"tags":["Bids"],"summary":"List Bid Findings","description":"Section 5 shape plus `finding_id`, `run_id`, `created_at` — so the rail can hydrate\na `finding` stream event (which carries only `finding_id`/`requirement_id`/`kind`) with\ntext and cite. `since_seq`, when given, scopes to findings recorded at or after that\nchain position rather than the whole bid.","operationId":"list_bid_findings_v1_bids__bid__findings_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}},{"name":"since_seq","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Since Seq"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/runs/{run}/stop":{"post":{"tags":["Bids"],"summary":"Stop Bid Run","operationId":"stop_bid_run_v1_bids__bid__runs__run__stop_post","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}},{"name":"run","in":"path","required":true,"schema":{"type":"string","title":"Run"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/actions":{"get":{"tags":["Bids"],"summary":"List Bid Actions","operationId":"list_bid_actions_v1_bids__bid__actions_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/actions/{action}/{decision}":{"post":{"tags":["Bids"],"summary":"Decide Bid Action","description":"Approve or reject one pending action. The decision flips state and is audited. A\nPhase 0 action (no `run_id`) is approved as before -- state flip only. An action a\nHermes run raised also executes the stored args once and resumes that run (BL-111) --\nthe response carries `hermes_run_id` only then, and a fresh `run_consumer` is scheduled\nfor that resumed run (BL-142), exactly like `POST /runs` does for a new one.\n\nRound 3, finding 1: an unpaid bid's approval of a run-tied action is refused BEFORE\n`decide()` flips its state, so a 402 here changes nothing -- the action stays `pending`,\nretryable once the bid is paid, instead of stranded `approved`-but-never-executed.","operationId":"decide_bid_action_v1_bids__bid__actions__action___decision__post","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}},{"name":"action","in":"path","required":true,"schema":{"type":"string","title":"Action"}},{"name":"decision","in":"path","required":true,"schema":{"type":"string","title":"Decision"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/runs/{run}/replay":{"post":{"tags":["Bids"],"summary":"Replay Bid Run","operationId":"replay_bid_run_v1_bids__bid__runs__run__replay_post","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}},{"name":"run","in":"path","required":true,"schema":{"type":"string","title":"Run"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/events":{"get":{"tags":["Bids"],"summary":"List Bid Events","operationId":"list_bid_events_v1_bids__bid__events_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}},{"name":"since_seq","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Since Seq"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/events/export":{"get":{"tags":["Bids"],"summary":"Export Bid Events","description":"The whole chain as newline-delimited JSON, for audit. Manager-only: the payloads\ncarry every edit anyone made.","operationId":"export_bid_events_v1_bids__bid__events_export_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/bids/{bid}/readiness":{"get":{"tags":["Bids"],"summary":"Bid Readiness","description":"Computed on request from a fresh in-memory gap recompute; stored gaps are never\nread here, so a stale subcollection can never report a bid ready.","operationId":"bid_readiness_v1_bids__bid__readiness_get","parameters":[{"name":"bid","in":"path","required":true,"schema":{"type":"string","title":"Bid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/account/onboarding":{"post":{"tags":["Auth"],"summary":"Mark Account Onboarding","operationId":"mark_account_onboarding_v1_account_onboarding_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Mark Account Onboarding V1 Account Onboarding Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/account/overview":{"get":{"tags":["Auth"],"summary":"Account Overview","operationId":"account_overview_v1_account_overview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Account Overview V1 Account Overview Get"}}}}}}},"/v1/account/marketing":{"get":{"tags":["Auth"],"summary":"Get Marketing Consent","description":"Read from the store, not the 60-second session cache, so Settings shows a change\nthe moment it is made. ``prompt_due`` says whether the one-time product-news prompt\nmay be shown (api/auth.py prompt_due).","operationId":"get_marketing_consent_v1_account_marketing_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Marketing Consent V1 Account Marketing Get"}}}}}},"post":{"tags":["Auth"],"summary":"Set Marketing Consent","description":"Settings' switch (owner 2026-09-30) and the prompt's buttons (owner 2026-10-03): one\ncall turns tender tips and news on or off. Turning it off never fails on the version,\nso unsubscribing is always one click.","operationId":"set_marketing_consent_v1_account_marketing_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketingConsentBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Set Marketing Consent V1 Account Marketing Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/account/marketing/prompt-dismissed":{"post":{"tags":["Auth"],"summary":"Marketing Prompt Dismissed","description":"The product-news prompt was closed without an answer (owner 2026-10-03). It is not\nshown again for a week, and not at all after a second dismissal.","operationId":"marketing_prompt_dismissed_v1_account_marketing_prompt_dismissed_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Marketing Prompt Dismissed V1 Account Marketing Prompt Dismissed Post"}}}}}}},"/v1/account/shortlist":{"get":{"tags":["Auth"],"summary":"Get Shortlist","description":"The signed-in account's shortlist, newest last, each tender read again.","operationId":"get_shortlist_v1_account_shortlist_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Shortlist V1 Account Shortlist Get"}}}}}},"post":{"tags":["Auth"],"summary":"Add To Shortlist","description":"Mark one tender \"Worth bidding\". Adding one already there changes nothing.","operationId":"add_to_shortlist_v1_account_shortlist_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShortlistBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Add To Shortlist V1 Account Shortlist Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/account/shortlist/{page_key}":{"delete":{"tags":["Auth"],"summary":"Remove From Shortlist","description":"Unmark one tender. Removing one that is not there is fine.\n\nOne tender can sit under an older key: a row's \"f\" address stays valid after it gains\nan entity key, and tender_match.tender resolves both to one canonical page. So an item\ngoes when its key is the one given, or resolves to the same canonical page.","operationId":"remove_from_shortlist_v1_account_shortlist__page_key__delete","parameters":[{"name":"page_key","in":"path","required":true,"schema":{"type":"string","title":"Page Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Remove From Shortlist V1 Account Shortlist  Page Key  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/request-link":{"post":{"tags":["Auth"],"summary":"Auth Request Link","description":"Email a single-use sign-in link.\n\nALWAYS returns 202 with the same body, whether or not the address has an account and\nwhether or not delivery succeeded. Any difference here — status, timing, wording — turns\nthis endpoint into an account-enumeration oracle, which is the standard flaw in\nself-serve login. The caller learns nothing about who has an account.\n\nThe email link's marketing cookie is set whenever the box was sent, account or not, so\nit tells the caller nothing either.","operationId":"auth_request_link_v1_auth_request_link_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestLinkBody"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Auth Request Link V1 Auth Request Link Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/magic":{"get":{"tags":["Auth"],"summary":"Auth Magic","description":"Redeem a magic link: consume the token, start a session, set the cookie, redirect.","operationId":"auth_magic_v1_auth_magic_get","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","title":"Token"}},{"name":"next","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/marketing-intent":{"post":{"tags":["Auth"],"summary":"Auth Marketing Intent","description":"The sign-in page calls this just before sending someone to Google (see\nGOOGLE_MARKETING_COOKIE): the box they saw rides in a cookie that lives 120 s and is\nconsumed by the very next /v1/auth/google/start. A version this service never shipped\nis refused rather than stored against the wrong sentence.","operationId":"auth_marketing_intent_v1_auth_marketing_intent_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketingIntentBody"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/google/start":{"get":{"tags":["Auth"],"summary":"Auth Google Start","description":"Begin the Google authorization-code flow.\n\n`marketing=1` says the page that sent this browser here showed the sign-up box; the\nbox's VALUE comes only from GOOGLE_MARKETING_COOKIE, which this route always deletes.\nA start without the flag (a header or docs button, or the sign-in probe) therefore\ndiscards any tick left in this browser, and a crafted link with the flag but no cookie\ncarries nothing.","operationId":"auth_google_start_v1_auth_google_start_get","parameters":[{"name":"next","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next"}},{"name":"marketing","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Marketing"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/google/callback":{"get":{"tags":["Auth"],"summary":"Auth Google Callback","operationId":"auth_google_callback_v1_auth_google_callback_get","parameters":[{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/me":{"get":{"tags":["Auth"],"summary":"Auth Me","description":"The signed-in user, or 401. The only fields a browser needs — never the session token,\nnever the API keys, never internal flags.","operationId":"auth_me_v1_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Auth Me V1 Auth Me Get"}}}}}}},"/v1/scans":{"get":{"tags":["Auth"],"summary":"List Scans","description":"This account's scan history, newest first. Requires a session — history is keyed to an\naccount and there is no anonymous variant.\n\nRows carry the VERDICT, not the input: no submitted text, no uploaded file, no extracted\ncontent. Signing in buys you a record of what you checked, not a repository of the\ndocuments themselves.","operationId":"list_scans_v1_scans_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Scans V1 Scans Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/auth/logout":{"post":{"tags":["Auth"],"summary":"Auth Logout","description":"Delete the session server-side, then clear the cookie. Server-side first: clearing only\nthe cookie would leave a token that still works if it was captured.","operationId":"auth_logout_v1_auth_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/usage":{"get":{"tags":["Keys & usage"],"summary":"Get Usage","description":"Metered usage and credit balance for the caller — an API key (Authorization: Bearer)\nor a signed-in session (the account page reads this). Reads the same daily counters the\nrate limiter writes, so reported usage always matches enforcement.","operationId":"get_usage_v1_usage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Usage V1 Usage Get"}}}}}}},"/v1/billing/history":{"get":{"tags":["Keys & usage"],"summary":"Billing History","description":"Safe account credit ledger: no Stripe ids, key hashes, or customer details.","operationId":"billing_history_v1_billing_history_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Billing History V1 Billing History Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/pricing":{"get":{"tags":["Keys & usage"],"summary":"Get Pricing","description":"Public pricing document: the weekly free-checks cap on every free tool, and\nthe flat price per tender for preparing a bid. The frontend pricing page and the docs read THIS —\napi/credits.py is the single source of truth.","operationId":"get_pricing_v1_pricing_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Pricing V1 Pricing Get"}}}}}}},"/v1/tenders":{"get":{"tags":["Tenders"],"summary":"List Tenders","description":"Browse open tenders. Free — burst-guarded, not metered, no key required.\n\nFilters: kind (`grant` or `tender`: grant rounds from every grant source, or everything\nelse), trade (a market page's trade, a labelled heuristic: tender_ingest/trades.py),\nclosing_within_days (0 to 366: closing between today and today + N in the buyer's own\nday, 0 is today; no closing date never matches), changed_within_days (1 to 31: a\nclosing or published date changed in the last N days, UTC),\njurisdiction, tier, source, category, closing_before (ISO date), q, buyer\n(the organisation name as published, exact and case-insensitive - what a buyer page\nor a state page deep-links to), first_seen_after (ISO-8601 UTC; strictly newer than\n— rows WE first saw after that instant, which is the honest \"new since\" clock: a\ntender published a month ago but only reachable today is new to the reader).\n`location` is deliberately NOT a filter: it is populated on 16% of rows while\njurisdiction is populated on all of them, so filtering by it would silently hide most\nof the corpus. Every result carries resolved source identity and `page_key` (the key\nGET /v1/tenders/{key} answers to), and every response carries `coverage`\ndistinguishing nightly and snapshot sources. Australian rows unless asked otherwise:\nNew Zealand rows only when you ask for them (jurisdiction=NZ). The link to the original\nportal (`link`, `url`, `listing_url`, `source_url`) comes only with an API key or a\nsigned-in session.","operationId":"list_tenders_v1_tenders_get","parameters":[{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"}},{"name":"tier","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tier"}},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}},{"name":"closing_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Closing Before"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"buyer","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer"}},{"name":"first_seen_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Seen After"}},{"name":"include_closed","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Closed"}},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"}},{"name":"trade","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trade"}},{"name":"closing_within_days","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":366,"minimum":0},{"type":"null"}],"title":"Closing Within Days"}},{"name":"changed_within_days","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":31,"minimum":1},{"type":"null"}],"title":"Changed Within Days"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Tenders V1 Tenders Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/tenders/strip":{"get":{"tags":["Tenders"],"summary":"Tender Strip","description":"The /tenders quick strip: open tenders closing within 48 hours (today or tomorrow, in\nthe buyer's day), with a date changed in the last 7 days, and first seen in the last 7\ndays. Each number is the `total` of the matching list request (closing_within_days=1,\nchanged_within_days=7, first_seen_after=seven days ago), kept for up to a minute. Free,\nburst-guarded, no key. Registered before `/v1/tenders/{key}`.","operationId":"tender_strip_v1_tenders_strip_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"integer"},"type":"object","title":"Response Tender Strip V1 Tenders Strip Get"}}}}}}},"/v1/tenders/sources":{"get":{"tags":["Tenders"],"summary":"List Tender Sources","description":"Every nightly and observed snapshot source, including resolved display metadata.\n\nFree, and free on purpose: this is the honesty surface. Charging to answer \"what did\nyou actually search\" would make the one endpoint that qualifies every other answer the\none people skip. A source's address (`source_url`) comes only with an API key or a\nsigned-in session, like every portal link.","operationId":"list_tender_sources_v1_tenders_sources_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Tender Sources V1 Tenders Sources Get"}}}}}}},"/v1/awards":{"get":{"tags":["Tenders"],"summary":"List Awards","description":"Contract awards as published (AusTender OCDS, Queensland disclosure reports).\nValues are the published amount and currency, never converted. `jurisdiction` takes a\ncountry or a subdivision code. Anonymous callers see every field but the supplier's\nname and identifier.","operationId":"list_awards_v1_awards_get","parameters":[{"name":"buyer","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer"}},{"name":"buyer_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer Key"}},{"name":"supplier","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Supplier"}},{"name":"supplier_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Supplier Key"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"}},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since"}},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":25,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Awards V1 Awards Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/awards/buyers/lookup":{"get":{"tags":["Tenders"],"summary":"Lookup Buyer","description":"The buyer payload for an organisation name as published (what the tender drawer\nhas), resolved to its key: with a jurisdiction the key is computed, without one the\nstore is asked which key the spelling appears under. `source` is the tender's\nsource_id: a source that labels every tender with the country alone never resolves to\na national buyer.","operationId":"lookup_buyer_v1_awards_buyers_lookup_get","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","title":"Name"}},{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"}},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Lookup Buyer V1 Awards Buyers Lookup Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/awards/buyers":{"get":{"tags":["Tenders"],"summary":"List Buyers","description":"The buyer cohort for a country: every buyer with a page (the owner's threshold,\n2026-09-15: at least 20 contract awards in the window or at least 5 open tenders),\nwith its key, slug, jurisdiction and counts. The buyer index and the sitemap read\nthis; a buyer that drops below the threshold leaves it the same night.","operationId":"list_buyers_v1_awards_buyers_get","parameters":[{"name":"country","in":"query","required":false,"schema":{"type":"string","default":"AU","title":"Country"}},{"name":"order","in":"query","required":false,"schema":{"type":"string","default":"count","title":"Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Buyers V1 Awards Buyers Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/awards/buyers/new":{"get":{"tags":["Tenders"],"summary":"Count New Buyers","description":"Buyers first seen in the contract awards on or after the supplied ISO date,\nwith the date of the nightly rollup.","operationId":"count_new_buyers_v1_awards_buyers_new_get","parameters":[{"name":"since","in":"query","required":true,"schema":{"type":"string","title":"Since"}},{"name":"country","in":"query","required":false,"schema":{"type":"string","default":"AU","title":"Country"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Count New Buyers V1 Awards Buyers New Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/awards/buyers/{buyer_key}":{"get":{"tags":["Tenders"],"summary":"Get Buyer","description":"One buyer: the nightly rollup (awards in the window, value quartiles, response\nwindow), the contracts ending within 12 months, planned procurements, the suppliers\nwho win from them (a name and a share, for a signed-in caller), and the open\ntenders published under the same name.","operationId":"get_buyer_v1_awards_buyers__buyer_key__get","parameters":[{"name":"buyer_key","in":"path","required":true,"schema":{"type":"string","title":"Buyer Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Buyer V1 Awards Buyers  Buyer Key  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/awards/suppliers/{identifier}":{"get":{"tags":["Tenders"],"summary":"Get Supplier","description":"The supplier entity behind a registered identifier (an ABN): its contracts, the\nbuyers it wins from, its categories and its registry standing. The website's supplier\npage (/suppliers/au/<ABN>, owner 2026-10-12, reversing 2026-09-14's \"no public supplier\npage\") is for signed-in people only and reads this. Signed-in callers only see the\nnames; an anonymous call returns the shape with the names withheld.","operationId":"get_supplier_v1_awards_suppliers__identifier__get","parameters":[{"name":"identifier","in":"path","required":true,"schema":{"type":"string","title":"Identifier"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Supplier V1 Awards Suppliers  Identifier  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/signals":{"get":{"tags":["Tenders"],"summary":"List Signals","description":"Signals: contract_expiry (a contract ending, with its incumbent), planned_procurement\n(a buyer's stated plan, with its quarter and spend band as published), and\nrecurring_tender (derived from our own history, and labelled so). `confidence` is\n`published` or `derived`, never a score.","operationId":"list_signals_v1_signals_get","parameters":[{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"}},{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"}},{"name":"buyer","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer"}},{"name":"buyer_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer Key"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"window_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Window Before"}},{"name":"window_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Window After"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":25,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Signals V1 Signals Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/intelligence/planned":{"get":{"tags":["Tenders"],"summary":"Get Planned","description":"The planned-procurement explorer payload. Rows (a withdrawn plan is never returned;\n`released` is the agency's \"To Market\") after the row filters - `jurisdiction` (with\n`exact=1`, that code alone: `AU` is then the Commonwealth, not its states), `buyer_key`,\n`quarter` (an id from `by_quarter`, `later` or `ended`), `window_after` (a date; plans\nwhose window has not ended by it) - sorted `soon` (default) or `buyer`.\nThe facets ignore the row filters: `by_jurisdiction`, `figures`, `by_quarter`,\n`top_buyers` and `top_categories`. A plan has no supplier, so no name is withheld.","operationId":"get_planned_v1_intelligence_planned_get","parameters":[{"name":"jurisdiction","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"}},{"name":"buyer","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer"}},{"name":"buyer_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer Key"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"quarter","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quarter"}},{"name":"window_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Window After"}},{"name":"sort","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort"}},{"name":"exact","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Exact"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Planned V1 Intelligence Planned Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/intelligence/planned/{plan_id}/context":{"get":{"tags":["Tenders"],"summary":"Get Planned Context","description":"What the explorer's detail panel adds to one plan: its buyer's rollup and contract\nawards for similar work (a heuristic, labelled by `match`). Counts only; no name.","operationId":"get_planned_context_v1_intelligence_planned__plan_id__context_get","parameters":[{"name":"plan_id","in":"path","required":true,"schema":{"type":"string","title":"Plan Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Planned Context V1 Intelligence Planned  Plan Id  Context Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/intelligence/trades":{"get":{"tags":["Tenders"],"summary":"Get Market Index","description":"Every trade and Australian state with the figures its market page would show - open\ntenders, contracts ending within 12 months, planned procurements this quarter, contract\nawards in the last complete financial year - and whether it meets the page minimum,\nlargest first. The trade is a labelled heuristic (`match`). Counts only, no names.","operationId":"get_market_index_v1_intelligence_trades_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Market Index V1 Intelligence Trades Get"}}}}}}},"/v1/intelligence/trades/{trade}/{state}":{"get":{"tags":["Tenders"],"summary":"Get Market Page","description":"One trade in one Australian state, \"what is coming up\": its open tenders, contracts\nending (by month, with the 90-day and 12-month counts), planned procurements this\nquarter, recurring tenders (derived), and the largest buyers of the last complete\nfinancial year with how concentrated the suppliers are. Every figure carries `covers`,\nthe jurisdictions its rows came from (\"AU\" is the Commonwealth, placed in a state by the\nbuyer's published office region). Supplier and holder names, and the re-tender calendar\n(`ending.calendar`), come with a key or a signed-in session only.","operationId":"get_market_page_v1_intelligence_trades__trade___state__get","parameters":[{"name":"trade","in":"path","required":true,"schema":{"type":"string","title":"Trade"}},{"name":"state","in":"path","required":true,"schema":{"type":"string","title":"State"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Market Page V1 Intelligence Trades  Trade   State  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/intelligence/summary":{"get":{"tags":["Tenders"],"summary":"Get Intelligence Summary","description":"The one payload the front page reads: tenders open today, new this week, contracts\nending within 12 months, planned procurements this quarter, buyers who published this\nmonth, per jurisdiction, with three preview rows a card - counts only, no names.","operationId":"get_intelligence_summary_v1_intelligence_summary_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Intelligence Summary V1 Intelligence Summary Get"}}}}}}},"/v1/intelligence/{jurisdiction}":{"get":{"tags":["Tenders"],"summary":"Get Intelligence Block","description":"The live block for a state page: contracts ending within 12 months, planned\nprocurements this quarter, the most active buyers, open tenders now, each with a\ndate. Commonwealth contracts attribute to a state by the buyer's published office\nregion, and the payload says so.","operationId":"get_intelligence_block_v1_intelligence__jurisdiction__get","parameters":[{"name":"jurisdiction","in":"path","required":true,"schema":{"type":"string","title":"Jurisdiction"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Intelligence Block V1 Intelligence  Jurisdiction  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/grants/summary":{"get":{"tags":["Tenders"],"summary":"Get Grants Summary","description":"The /grants live block: open rounds, rounds closing this month, the value open (a\nsum of the rounds that state one, with that coverage said), per jurisdiction, and the\nrounds closing soonest with value and eligibility where published. Read from the\ntender corpus alone, so it never waits on the intelligence store. Grants folded into\nthe model, no new sources (owner decision 2026-09-14).","operationId":"get_grants_summary_v1_grants_summary_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Grants Summary V1 Grants Summary Get"}}}}}}},"/v1/tenders/match":{"post":{"tags":["Tenders"],"summary":"Match Tenders","description":"Rank open tenders against what a company actually does. Free, inside the weekly cap.\n\nGive `url` (a company website), `text` (a typed sentence, when there's no site to\nread), `example` (one of the built-in profiles, which make no model call and cost\nnothing to demonstrate), or `profile` (one an earlier answer returned, edited: no site\nread and no profile model call). `jurisdictions` narrows to several states at once.\n\n`score` is RELATIVE FIT within these results — how well a tender matches the stated\ncapabilities compared with the others returned. It is not a probability of winning.\n`band` \"high\" also needs two `why` reasons worded as in the profile, an open tender and\nno outside-states check; `checks[]` lists the computed checks, each with a `label`.\n\nIf scoring is unavailable the response still returns, ranked by keyword relevance,\nwith `degraded: true` and no `why`/`gaps`. It never fabricates a reason.\n\n`?stream=1` answers `text/event-stream` with each step as it finishes: `stage` (a site\nis being read), `profile`, `candidates` (`count`), then `result` (this route's JSON\nanswer), or `error` (`status`, `message`, `reason`, `can_describe`) in their place. A\nbad input, a burst or the weekly cap still answer as plain HTTP errors, before it.","operationId":"match_tenders_v1_tenders_match_post","parameters":[{"name":"stream","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Stream"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenderMatchBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Match Tenders V1 Tenders Match Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/companies/resolve":{"post":{"tags":["Companies"],"summary":"Resolve Company","description":"Resolve a company name or identifier to ONE company, or say why it could not.\nCosts 2 credits.\n\n`query` takes a name (\"Fonterra Australia\") or an identifier (ABN, ACN, NZBN). An\nidentifier resolves DIRECTLY - no name search and no ranking - so an exact number can\nnever land on a near-miss.\n\nREAD `status` BEFORE `candidates`:\n\n- `resolved`   exactly one company. `selected` is it.\n- `ambiguous`  more than one. `selected` is null ON PURPOSE. Several real companies\n               match and choosing between them is yours to do, with the evidence here.\n- `not_found`  every register answered, and none of them has it.\n- `inconclusive` a register could not be read, so absence proves nothing.\n\n`coverage` lists every source and how well it was read, INCLUDING the ones that were\nblocked or unreadable. A source that was not read is never silently dropped, because\nthat is what would let `not_found` mean \"we could not look\".\n\n`match_quality` orders candidates and nothing more. It never promotes one to `selected`.","operationId":"resolve_company_v1_companies_resolve_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyResolveBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Resolve Company V1 Companies Resolve Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/tenders/watch":{"get":{"tags":["Tenders"],"summary":"Get Tender Watches","description":"The signed-in account's saved watches, with the cadence each will ACTUALLY get —\ncomputed from the same store the digest spends from, so the promise cannot drift\nfrom delivery.","operationId":"get_tender_watches_v1_tenders_watch_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Tender Watches V1 Tenders Watch Get"}}}}}},"post":{"tags":["Tenders"],"summary":"Set Tender Watch","description":"Save a watch and get new tenders by email. Free, and every watch sends on the\ndaily run (owner decision 2026-09-10; there is no paid cadence).\n\nFive kinds of watch, five of each kind except the profile (one per account):\n  - PROFILE (`url`, `example`, or `profile` - one a match returned, kept as given and\n    never re-read; `jurisdictions` for several states): the capability match, ranked,\n    with the reasoning.\n  - QUERY (`q`/`jurisdiction`/`tier`/`category`): a saved search - a plain list of new\n    tenders matching the filters, not ranked.\n  - BUYER (`buyer`, the organisation name as published): what that buyer publishes,\n    awards, and has ending within 90 days, with the incumbent.\n  - SIGNALS (`type: \"signals\"` with `kind`, `jurisdiction` or `q`): contracts ending\n    and planned procurements as they appear.\n  - GRANTS (`type: \"grants\"` with the query filters): the saved search over grants.\n  - CLOSING, \"Watch this tender\" (`type: \"closing\"` with `page_key`; a grant round too):\n    the morning after its dates move or its source publishes more documents, and\n    reminders 7 and 3 days before it closes (1 day for a tender in one of your bids) and\n    2 days before a question cut-off; it ends when the tender closes; twenty at a time.\n\n`active: false` alone stops ALL emails; with `watch_id` it pauses that one watch.\n`active: true` with `watch_id` resumes it. Nothing is sent when nothing new appeared.","operationId":"set_tender_watch_v1_tenders_watch_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenderWatchBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Set Tender Watch V1 Tenders Watch Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/tenders/watch/{watch_id}":{"delete":{"tags":["Tenders"],"summary":"Delete Tender Watch","description":"Remove one watch permanently. Pausing (POST with active:false + watch_id) keeps it.","operationId":"delete_tender_watch_v1_tenders_watch__watch_id__delete","parameters":[{"name":"watch_id","in":"path","required":true,"schema":{"type":"string","title":"Watch Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Tender Watch V1 Tenders Watch  Watch Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/tenders/unsubscribe":{"get":{"tags":["Tenders"],"summary":"Tender Unsubscribe","operationId":"tender_unsubscribe_v1_tenders_unsubscribe_get","parameters":[{"name":"u","in":"query","required":false,"schema":{"type":"string","default":"","title":"U"}},{"name":"t","in":"query","required":false,"schema":{"type":"string","default":"","title":"T"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Tenders"],"summary":"Tender Unsubscribe One Click","operationId":"tender_unsubscribe_one_click_v1_tenders_unsubscribe_post","parameters":[{"name":"u","in":"query","required":false,"schema":{"type":"string","default":"","title":"U"}},{"name":"t","in":"query","required":false,"schema":{"type":"string","default":"","title":"T"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/news/unsubscribe":{"get":{"tags":["Auth"],"summary":"News Unsubscribe","operationId":"news_unsubscribe_v1_news_unsubscribe_get","parameters":[{"name":"u","in":"query","required":false,"schema":{"type":"string","default":"","title":"U"}},{"name":"t","in":"query","required":false,"schema":{"type":"string","default":"","title":"T"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Auth"],"summary":"News Unsubscribe One Click","operationId":"news_unsubscribe_one_click_v1_news_unsubscribe_post","parameters":[{"name":"u","in":"query","required":false,"schema":{"type":"string","default":"","title":"U"}},{"name":"t","in":"query","required":false,"schema":{"type":"string","default":"","title":"T"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/tenders/{key}":{"get":{"tags":["Tenders"],"summary":"Get Tender","description":"One tender, open or closed, by its `page_key` (on every row GET /v1/tenders\nreturns: 32 hex, or \"f\" + 32 hex for a tender with no reference or buyer): the same row\nshape as the list, plus `open` by the list's own rule and the date facts\n(tender_match.date_facts: key_dates, dates_checked, extended_from, absent_since). A\nclosed tender still resolves - what closed is still what was published. Free,\nburst-guarded, no key; the link to the original portal only with a key or a signed-in\nsession, as on the list. An unknown and a malformed key get the same 404.","operationId":"get_tender_v1_tenders__key__get","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Tender V1 Tenders  Key  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/tenders/{key}/portal":{"get":{"tags":["Tenders"],"summary":"Get Tender Portal","description":"The link to a tender's or grant's original portal, for a page to show a signed-in\nperson after it loads (owner, 2026-10-08, Q52): `{url, portal_name, link_is_listing}`.\n`portal_name` is read from the link's host (the portal table, else the registered\nsource on that host, else the host itself); `link_is_listing` is true when the portal\npublishes no page per tender and the link opens the list it appeared on. Needs a\nsigned-in session or an API key: 401 otherwise, and for the web server's own renders.\n404 for an unknown key and for a tender we hold no link for (an Australian Tenders row\nwithout its original notice is never linked, 2026-09-26).","operationId":"get_tender_portal_v1_tenders__key__portal_get","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Tender Portal V1 Tenders  Key  Portal Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/tenders/{key}/context":{"get":{"tags":["Tenders"],"summary":"Get Tender Context","description":"Everything a tender's public page shows beside the tender, in one read (owner,\n2026-09-30): its buyer's rollup with the 5 most recent contract awards and the 5\ncontracts ending soonest; `similar` - keywords chosen from the title (a labelled\nheuristic), the contract awards whose titles carry them (count, values as published,\nthe most recent rows) and up to 5 open tenders like it, each with its page_key; and\nthe sources and dates behind each. Free, burst-guarded, no key; supplier names on the\nsigned-in rung, redacted like every intelligence route. 404 for an unknown key, 503\nwhile the intelligence store loads.","operationId":"get_tender_context_v1_tenders__key__context_get","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Tender Context V1 Tenders  Key  Context Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/billing/checkout":{"post":{"tags":["Keys & usage"],"summary":"Billing Checkout","description":"Start a credit-pack purchase: returns the hosted Stripe Checkout URL.\n\nRequires a durable identity to attach the credits to — either a signed-in session\n(the website's one-click path) or an API key as ``Authorization: Bearer``. Both prove\nownership of the balance being topped up; an anonymous caller has nowhere to put\ncredits, so it is asked to sign in first.","operationId":"billing_checkout_v1_billing_checkout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Billing Checkout V1 Billing Checkout Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/verify-references":{"post":{"tags":["Generated content"],"summary":"Verify References Route","description":"Verify a document's citations + internal arithmetic — the engine behind the `/fact-check`\npage, mirroring the `/mcp-verify` tool. Send multipart `file` (PDF), or JSON `{\"text\": \"...\"}`\n/ `{\"bytes_b64\": \"...\", \"filename\": \"...\"}` / `{\"url\": \"https://...\"}` (public hosts only,\nSSRF-guarded, size-capped). `?deep=1` adds the slower web claim-entailment pass; `?stream=1`\nreturns an SSE lifecycle stream (``received`` → ``working`` … → ``result``) so the long deep\npass survives proxy timeouts. Reports verification COVERAGE, not truth.","operationId":"verify_references_route_v1_verify_references_post","parameters":[{"name":"deep","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Deep"}},{"name":"stream","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Stream"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_verify_references_route_v1_verify_references_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Body_adverse_media_route_v1_adverse_media_post":{"properties":{"file":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"File"}},"type":"object","title":"Body_adverse_media_route_v1_adverse_media_post"},"Body_check_pack_route_v1_check_pack_post":{"properties":{"files":{"anyOf":[{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array"},{"type":"null"}],"title":"Files"}},"type":"object","title":"Body_check_pack_route_v1_check_pack_post"},"Body_check_source_overlap_route_v1_check_source_overlap_post":{"properties":{"file":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"File"}},"type":"object","title":"Body_check_source_overlap_route_v1_check_source_overlap_post"},"Body_create_warrant_v1_warrants_post":{"properties":{"file":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"File"}},"type":"object","title":"Body_create_warrant_v1_warrants_post"},"Body_detect_ai_text_route_v1_detect_ai_text_post":{"properties":{"file":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"File"}},"type":"object","title":"Body_detect_ai_text_route_v1_detect_ai_text_post"},"Body_extract_fields_route_v1_extract_post":{"properties":{"file":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"File"}},"type":"object","title":"Body_extract_fields_route_v1_extract_post"},"Body_identity_check_route_v1_identity_check_post":{"properties":{"files":{"anyOf":[{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array"},{"type":"null"}],"title":"Files"}},"type":"object","title":"Body_identity_check_route_v1_identity_check_post"},"Body_upload_bid_files_v1_bids__bid__files_post":{"properties":{"file":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"File"},"gap_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gap Id"},"class":{"type":"string","title":"Class","default":"pack"}},"type":"object","required":["file"],"title":"Body_upload_bid_files_v1_bids__bid__files_post"},"Body_upload_org_documents_v1_orgs__org__documents_post":{"properties":{"file":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"File"},"item":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Item"}},"type":"object","required":["file"],"title":"Body_upload_org_documents_v1_orgs__org__documents_post"},"Body_verify_references_route_v1_verify_references_post":{"properties":{"file":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"File"}},"type":"object","title":"Body_verify_references_route_v1_verify_references_post"},"CheckoutBody":{"properties":{"pack":{"type":"string","title":"Pack"}},"type":"object","required":["pack"],"title":"CheckoutBody"},"CompanyResolveBody":{"properties":{"query":{"type":"string","title":"Query"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"}},"type":"object","required":["query"],"title":"CompanyResolveBody"},"ContactBody":{"properties":{"name":{"type":"string","title":"Name"},"email":{"type":"string","title":"Email"},"company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company"},"topic":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Topic"},"message":{"type":"string","title":"Message"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"},"elapsed_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Elapsed Ms"}},"type":"object","required":["name","email","message"],"title":"ContactBody"},"CreateBidBody":{"properties":{"org_id":{"type":"string","title":"Org Id"},"title":{"type":"string","title":"Title"},"tender_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tender Key"}},"additionalProperties":false,"type":"object","required":["org_id","title"],"title":"CreateBidBody"},"CreateKeyBody":{"properties":{"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"}},"type":"object","title":"CreateKeyBody"},"CreateOrgBody":{"properties":{"name":{"type":"string","title":"Name"}},"type":"object","required":["name"],"title":"CreateOrgBody"},"FeedbackBody":{"properties":{"verdict":{"type":"string","enum":["up","down"],"title":"Verdict"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","required":["verdict"],"title":"FeedbackBody"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LinkKeyBody":{"properties":{"api_key":{"type":"string","title":"Api Key"}},"type":"object","required":["api_key"],"title":"LinkKeyBody"},"MarketingConsentBody":{"properties":{"opted_in":{"type":"boolean","title":"Opted In"},"version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version"},"via":{"type":"string","enum":["settings","prompt"],"title":"Via","default":"settings"}},"type":"object","required":["opted_in"],"title":"MarketingConsentBody"},"MarketingIntentBody":{"properties":{"opted_in":{"type":"boolean","title":"Opted In"},"version":{"type":"string","title":"Version"}},"type":"object","required":["opted_in","version"],"title":"MarketingIntentBody"},"OnboardingBody":{"properties":{"milestone":{"type":"string","enum":["sample_result","first_real_result"],"title":"Milestone"}},"type":"object","required":["milestone"],"title":"OnboardingBody"},"OrgDocumentPatch":{"properties":{"expires_on":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expires On"}},"additionalProperties":false,"type":"object","required":["expires_on"],"title":"OrgDocumentPatch"},"OrgInviteBody":{"properties":{"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role"}},"type":"object","required":["email","role"],"title":"OrgInviteBody"},"PatchBidBody":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"deadline":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deadline"},"decision":{"title":"Decision"}},"additionalProperties":false,"type":"object","title":"PatchBidBody"},"RequestLinkBody":{"properties":{"email":{"type":"string","title":"Email"},"next":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next"},"marketing_opt_in":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Marketing Opt In"},"marketing_consent_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Marketing Consent Version"}},"type":"object","required":["email"],"title":"RequestLinkBody"},"ShortlistBody":{"properties":{"page_key":{"type":"string","title":"Page Key"}},"type":"object","required":["page_key"],"title":"ShortlistBody"},"TenderMatchBody":{"properties":{"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"example":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Example"},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"},"tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tier"},"closing_before":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Closing Before"},"jurisdictions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Jurisdictions"},"profile":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Profile"}},"type":"object","title":"TenderMatchBody"},"TenderWatchBody":{"properties":{"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"example":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Example"},"q":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"},"jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jurisdiction"},"tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tier"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"trade":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trade"},"active":{"type":"boolean","title":"Active","default":true},"watch_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Watch Id"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"},"buyer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Buyer"},"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"},"page_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Page Key"},"profile":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Profile"},"jurisdictions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Jurisdictions"}},"type":"object","title":"TenderWatchBody"},"ToolFeedbackBody":{"properties":{"tool":{"type":"string","enum":["detect_ai_text","verify_references","verify_identity","extract_fields","check_pack","screen_adverse_media","check_source_overlap","verify_document","tender_match"],"title":"Tool"},"verdict":{"type":"string","enum":["up","down"],"title":"Verdict"},"ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ref"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"sample":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sample"}},"type":"object","required":["tool","verdict"],"title":"ToolFeedbackBody"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"tags":[{"name":"Documents","description":"Verify, classify, extract from, and redact documents."},{"name":"Identity","description":"Identity and document-pack completeness checks."},{"name":"Screening","description":"Adverse-media and sanctions screening (PEP not screened)."},{"name":"Generated content","description":"Fact-check sources and detect AI-written text."},{"name":"Keys & usage","description":"Self-serve API keys and usage metering."},{"name":"Auth","description":"Sign-in sessions for the web app (magic link + Google)."},{"name":"Meta","description":"Health, discovery, feedback, and cache-check endpoints."}]}