{"openapi":"3.2.0","info":{"title":"TrustFoundry API Reference","version":"1.0","description":"AI-powered legal research API. Search US laws, regulations, and case law.\n\n**Authentication:** All requests require an API key via the `X-API-Key` header.\nCreate keys at [dashboard.trustfoundry.ai](https://dashboard.trustfoundry.ai).\n\n**Streaming:** Research, review, draft, and search endpoints return NDJSON streams.\nEach line is a JSON object — dispatch on the `type` field. See event schemas below.\n\n**Timing:** Non-streaming responses include a standard `Server-Timing`\nmetric named `server_response_duration`. Search stream `citations_ready`\npayloads include `server_response_duration_ms`.\n"},"tags":[{"name":"Agentic","description":"AI-powered legal research, review, and drafting"},{"name":"Search","description":"Direct legal search and result retrieval"},{"name":"Treatment (Beta Preview)","description":"Treatment (Beta Preview) analysis endpoints for case search results"},{"name":"Validation","description":"Legal citation extraction and validation"},{"name":"Feedback","description":"Submit and retrieve feedback on prior API requests"},{"name":"Files","description":"File upload and management for document analysis"},{"name":"Compliance","description":"Compliance package checks"},{"name":"Utilities","description":"Usage, quota, and billing status"}],"security":[{"ApiKeyAuth":[]}],"paths":{"/public/v1/research":{"post":{"operationId":"postResearch","summary":"Execute a legal research query (streaming). 45 second -> 3 minute response time.","tags":["Agentic"],"x-product-category":["focused_research","broad_research"],"security":[{"ApiKeyAuth":[]}],"description":"Executes a legal research query using a natural-language `query`. The AI agent\nautomatically determines which content types to search, constructs a search plan,\nretrieves primary legal authority, and synthesizes a research response.\n\n**Response format:**\n- `response_format: \"lens\"` (default) — Returns a structured JSON\n  **ResearchLens** with authorities, issue map, and excerpts. Best\n  for programmatic consumption.\n- `response_format: \"text\"` — Returns streamed markdown text with\n  sources and disclaimer appended. Best for human-facing UIs.\n- `response_format: \"text_and_lens\"` — Streams the markdown via\n  `response_delta` events during the run **and** emits the\n  structured `lens_ready` at the end. Use when you want to show\n  progressive UI to a user while also consuming the machine-parseable\n  payload.\n\n**Event sequence (lens):** `execution_started` → `task_started` → `task_progress`* → `task_completed` → `lens_ready` → `done`\n\n**Event sequence (text):** `execution_started` → `task_started` → `task_progress`* → `response_delta`* → `task_completed` → `done`\n\n**Event sequence (text_and_lens):** `execution_started` → `task_started` → `task_progress`* → `response_delta`* → `task_completed` → `lens_ready` → `done`\n\nThe `lens` object in `lens_ready` events conforms to **ResearchLens**.\n\n**Embedded links in text responses:** For `response_format: \"text\"` and\n`\"text_and_lens\"`, `response_delta.content` contains markdown that\nembeds URLs pointing at this API — e.g. `https://api.trustfoundry.ai\n/public/v1/search/results/items/describe/{uuid}`. Call those URLs\nwith the same `X-API-Key` header that made this request to retrieve\nthe underlying case/law/regulation summary. The API key that\npersisted the search result is the only key that can retrieve it —\nsee the [describe endpoint](#/Search/describeSearchResultItem).\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"query":{"type":"string","maxLength":2000,"description":"The natural language legal research query.","examples":["What are the elements of a breach of fiduciary duty claim in Delaware?"]},"response_format":{"type":"string","enum":["text","lens","text_and_lens"],"default":"lens","description":"Output format. \"lens\" for structured JSON, \"text\" for streamed markdown, \"text_and_lens\" to stream markdown during the run and emit the lens at the end."},"model_type":{"type":"string","enum":["extended","deep_research"],"default":"extended","description":"Research depth. \"extended\" for focused research, \"deep_research\" for broad multi-source research."},"default_state":{"type":"string","description":"Two-letter uppercase jurisdiction code. Use \"FED\" for federal.","examples":["DE"]},"target_file_id":{"type":"string","description":"ID of a previously uploaded file to use as the primary target document. Other attachment_ids become reference documents."},"attachment_ids":{"type":"array","items":{"type":"string"},"description":"IDs of previously uploaded files to include as context."},"conversation_id":{"type":"string","description":"Optional session identifier for stateful interactions. Enables attachment sharing across calls."}}}}}},"responses":{"200":{"description":"Streaming NDJSON response.","content":{"application/x-ndjson":{"itemSchema":{"oneOf":[{"$ref":"#/components/schemas/ExecutionStartedEvent"},{"$ref":"#/components/schemas/TaskStartedEvent"},{"$ref":"#/components/schemas/TaskProgressEvent"},{"$ref":"#/components/schemas/ResponseDeltaEvent"},{"$ref":"#/components/schemas/LensReadyEvent"},{"$ref":"#/components/schemas/TaskCompletedEvent"},{"$ref":"#/components/schemas/HeartbeatEvent"},{"$ref":"#/components/schemas/DoneEvent"},{"$ref":"#/components/schemas/StreamErrorEvent"}],"discriminator":{"propertyName":"type"}},"examples":{"text_stream":{"summary":"Text mode stream","value":"{\"type\":\"execution_started\",\"execution_id\":\"abc-123\"}\n{\"type\":\"task_started\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"task_type\":\"legal_research\"}\n{\"type\":\"task_progress\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"upstream_event\":{\"type\":\"search_start\"}}\n{\"type\":\"response_delta\",\"execution_id\":\"abc-123\",\"content\":\"## Elements of Breach of Fiduciary Duty\\n\\n\"}\n{\"type\":\"response_delta\",\"execution_id\":\"abc-123\",\"content\":\"Under Delaware law, the elements are...\"}\n{\"type\":\"task_completed\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"task_type\":\"legal_research\"}\n{\"type\":\"done\",\"execution_id\":\"abc-123\",\"status\":\"completed\",\"usage\":{\"category\":\"focused_research\",\"credits_used\":1}}\n"},"lens_stream":{"summary":"Lens mode stream","value":"{\"type\":\"execution_started\",\"execution_id\":\"abc-123\"}\n{\"type\":\"task_started\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"task_type\":\"legal_research\"}\n{\"type\":\"heartbeat\",\"timestamp\":\"2026-06-13T18:30:00Z\"}\n{\"type\":\"task_progress\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"upstream_event\":{\"type\":\"search_start\"}}\n{\"type\":\"task_completed\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"task_type\":\"legal_research\"}\n{\"type\":\"lens_ready\",\"execution_id\":\"abc-123\",\"lens\":{\"lens_type\":\"research_lens\",\"generated_at\":\"2026-06-13T18:30:00Z\",\"confidence\":\"high\",\"assumptions\":[],\"gaps\":[],\"query\":\"...\",\"issue_map\":[],\"authorities\":[{\"authority_id\":\"a1\",\"citation\":\"Foo v. Bar\",\"title\":\"Foo v. Bar\",\"url\":\"https://example.test/foo\",\"result_type\":\"case\",\"jurisdiction\":\"DE\"}],\"relevant_legal_text\":[]}}\n{\"type\":\"done\",\"execution_id\":\"abc-123\",\"status\":\"completed\",\"usage\":{\"category\":\"focused_research\",\"credits_used\":1}}\n"},"text_and_lens_stream":{"summary":"text_and_lens mode stream (co-emits streamed markdown and final lens)","value":"{\"type\":\"execution_started\",\"execution_id\":\"abc-123\"}\n{\"type\":\"task_started\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"task_type\":\"legal_research\"}\n{\"type\":\"task_progress\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"upstream_event\":{\"type\":\"search_start\"}}\n{\"type\":\"response_delta\",\"execution_id\":\"abc-123\",\"content\":\"## Elements of Breach of Fiduciary Duty\\n\\n\"}\n{\"type\":\"response_delta\",\"execution_id\":\"abc-123\",\"content\":\"Under Delaware law, the elements are...\"}\n{\"type\":\"task_completed\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"task_type\":\"legal_research\"}\n{\"type\":\"lens_ready\",\"execution_id\":\"abc-123\",\"lens\":{\"lens_type\":\"research_lens\",\"generated_at\":\"2026-06-13T18:30:00Z\",\"confidence\":\"high\",\"assumptions\":[],\"gaps\":[],\"query\":\"...\",\"issue_map\":[],\"authorities\":[{\"authority_id\":\"a1\",\"citation\":\"Foo v. Bar\",\"title\":\"Foo v. Bar\",\"url\":\"https://example.test/foo\",\"result_type\":\"case\",\"jurisdiction\":\"DE\"}],\"relevant_legal_text\":[]}}\n{\"type\":\"done\",\"execution_id\":\"abc-123\",\"status\":\"completed\",\"usage\":{\"category\":\"focused_research\",\"credits_used\":1}}\n"}}}}},"400":{"description":"Invalid or missing fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"$ref":"#/components/responses/InsufficientCredits"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"description":"Upstream service failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v1/agentic-search":{"post":{"operationId":"postAgenticSearch","summary":"Execute an agentic citation search (streaming). [DEPRECATED — use /research]","tags":["Agentic"],"x-product-category":"agentic_search","deprecated":true,"x-replaced-by":"postResearch","x-deprecation-message":"For equivalent behavior, call POST /public/v1/research with model_type: \"extended\" (Focused Research) and response_format: \"lens\". The lens response contains a search_set field with the same citation set this endpoint streams via the citations_ready event — plus the agent's research findings and authorities.","security":[{"ApiKeyAuth":[]}],"description":"Executes an AI-planned legal citation search. The agent builds a search plan\nfrom the natural-language `query`, retrieves matching authorities, and\nstreams results as NDJSON.\n\n**Event sequence:** `start` → `search_start` → `search_end` → `citations_ready` → `end`\n\nThe `content.uuid` field of the `citations_ready` event references a saved\nSearchSet that can be retrieved via `GET /public/v1/search/results/{uuid}`.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query","default_state"],"properties":{"query":{"type":"string","minLength":1,"maxLength":2000,"description":"The natural-language citation search query.","examples":["exhaust emission standards for diesel engines"]},"default_state":{"type":"string","description":"Two-letter uppercase jurisdiction code. Use `FED` for federal.","examples":["FED"]}}}}}},"responses":{"200":{"description":"Streaming NDJSON response. Each line is a JSON object with a `type` field.","content":{"application/x-ndjson":{"itemSchema":{"$ref":"#/components/schemas/SearchStreamEvent"},"examples":{"full_stream":{"summary":"Example agentic search stream output","value":"{\"type\":\"start\",\"query\":\"exhaust emission standards for diesel engines\"}\n{\"type\":\"search_start\",\"content\":\"Planning agentic search\"}\n{\"type\":\"search_end\",\"content\":\"Retrieved 12 authorities\"}\n{\"type\":\"citations_ready\",\"content\":{\"uuid\":\"e29a934c-26cb-48e5-8324-3cadea9dd9b8\",\"query\":\"exhaust emission standards for diesel engines\",\"created_at\":\"2025-10-06T17:15:40.125604\",\"search_results\":[{\"uuid\":\"d416bfc7-230e-4428-81ee-22e29c88c0cb\",\"header\":\"40 CFR § 89.112\",\"citation\":\"40 CFR § 89.112\",\"url\":\"https://www.ecfr.gov/...\",\"excerpt\":\"Exhaust emission standards...\",\"relevance_score\":0.95,\"result_type\":\"reg\",\"first_level_geo\":\"USA\",\"second_level_geo\":\"FED\"}]}}\n{\"type\":\"end\"}\n"}}}}},"400":{"description":"Invalid or missing fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"$ref":"#/components/responses/InsufficientCredits"},"404":{"description":"Organization not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"description":"Upstream service failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v1/review":{"post":{"operationId":"postReview","summary":"Execute a legal document review (streaming). 1 -> 4 minute response time.","tags":["Agentic"],"x-product-category":["concise_review","indepth_review"],"security":[{"ApiKeyAuth":[]}],"description":"Reviews a legal document by first conducting targeted research to identify relevant\nlegal authority, then analyzing the document against that authority. Requires either\nuploaded file attachments (`target_file_id` / `attachment_ids`) or inline document text (`content`).\n\nThis is a **2-step operation**: internal legal research → document review.\n\n**Response format:**\n- `response_format: \"lens\"` (default) — Returns a structured ReviewLens with findings,\n  issue matrix, and authorities.\n- `response_format: \"text\"` — Returns streamed markdown text with sources and disclaimer.\n- `response_format: \"text_and_lens\"` — Streams the markdown via `response_delta`\n  events during the review task **and** emits the structured `lens_ready` at the\n  end. Use when you want to show progressive UI to a user while also consuming\n  the machine-parseable payload.\n\n**Event sequence (lens):** `execution_started` → `task_started`(research) → `task_completed`(research) → `task_started`(review) → `task_completed`(review) → `lens_ready` → `done`\n\n**Event sequence (text):** `execution_started` → `task_started`(research) → `task_completed`(research) → `task_started`(review) → `response_delta`* → `task_completed`(review) → `done`\n\n**Event sequence (text_and_lens):** `execution_started` → `task_started`(research) → `task_completed`(research) → `task_started`(review) → `response_delta`* → `task_completed`(review) → `lens_ready` → `done`\n\nThe `lens` object in `lens_ready` events conforms to **ReviewLens**.\n\n**Embedded links in text responses:** For `response_format: \"text\"` and\n`\"text_and_lens\"`, `response_delta.content` contains markdown that\nembeds URLs pointing at this API — e.g. `https://api.trustfoundry.ai\n/public/v1/search/results/items/describe/{uuid}`. Call those URLs\nwith the same `X-API-Key` header that made this request to retrieve\nthe underlying case/law/regulation summary. See the\n[describe endpoint](#/Search/describeSearchResultItem).\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"query":{"type":"string","maxLength":2000,"description":"Describe what to review or look for in the document.","examples":["Review this contract for indemnification risks"]},"response_format":{"type":"string","enum":["text","lens","text_and_lens"],"default":"lens","description":"Output format. \"lens\" for structured JSON, \"text\" for streamed markdown, \"text_and_lens\" to stream markdown during the review task and emit the lens at the end."},"review_type":{"type":"string","enum":["succinct","in_depth"],"default":"succinct","description":"Review depth. \"succinct\" for high-level findings, \"in_depth\" for comprehensive analysis."},"model_type":{"type":"string","enum":["extended","deep_research"],"default":"extended"},"default_state":{"type":"string","description":"Two-letter uppercase jurisdiction code.","examples":["NY"]},"target_file_id":{"type":"string","description":"ID of a previously uploaded file to review as the primary target document. Required if `content` is not provided."},"attachment_ids":{"type":"array","items":{"type":"string"},"description":"IDs of previously uploaded files to include as reference documents (not the review target)."},"content":{"type":"string","description":"Inline document text to review. Required if `target_file_id` is not provided."},"conversation_id":{"type":"string","description":"Optional session identifier for stateful interactions."}}}}}},"responses":{"200":{"description":"Streaming NDJSON response.","content":{"application/x-ndjson":{"itemSchema":{"oneOf":[{"$ref":"#/components/schemas/ExecutionStartedEvent"},{"$ref":"#/components/schemas/TaskStartedEvent"},{"$ref":"#/components/schemas/TaskProgressEvent"},{"$ref":"#/components/schemas/ResponseDeltaEvent"},{"$ref":"#/components/schemas/LensReadyEvent"},{"$ref":"#/components/schemas/TaskCompletedEvent"},{"$ref":"#/components/schemas/HeartbeatEvent"},{"$ref":"#/components/schemas/DoneEvent"},{"$ref":"#/components/schemas/StreamErrorEvent"}],"discriminator":{"propertyName":"type"}},"examples":{"text_stream":{"summary":"Review text mode stream (2-step)","value":"{\"type\":\"execution_started\",\"execution_id\":\"abc-123\"}\n{\"type\":\"task_started\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"task_type\":\"legal_research\",\"output_visibility\":\"internal\"}\n{\"type\":\"task_completed\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"task_type\":\"legal_research\"}\n{\"type\":\"task_started\",\"execution_id\":\"abc-123\",\"task_id\":\"t2\",\"task_type\":\"doc_review\",\"output_visibility\":\"final\"}\n{\"type\":\"response_delta\",\"execution_id\":\"abc-123\",\"content\":\"## Review Findings\\n\\n\"}\n{\"type\":\"response_delta\",\"execution_id\":\"abc-123\",\"content\":\"The indemnification clause in section 4...\"}\n{\"type\":\"task_completed\",\"execution_id\":\"abc-123\",\"task_id\":\"t2\",\"task_type\":\"doc_review\"}\n{\"type\":\"done\",\"execution_id\":\"abc-123\",\"status\":\"completed\",\"usage\":{\"category\":\"concise_review\",\"credits_used\":1}}\n"},"lens_stream":{"summary":"Review lens mode stream (2-step)","value":"{\"type\":\"execution_started\",\"execution_id\":\"abc-123\"}\n{\"type\":\"task_started\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"task_type\":\"legal_research\",\"output_visibility\":\"internal\"}\n{\"type\":\"task_completed\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"task_type\":\"legal_research\"}\n{\"type\":\"task_started\",\"execution_id\":\"abc-123\",\"task_id\":\"t2\",\"task_type\":\"doc_review\",\"output_visibility\":\"final\"}\n{\"type\":\"task_completed\",\"execution_id\":\"abc-123\",\"task_id\":\"t2\",\"task_type\":\"doc_review\"}\n{\"type\":\"lens_ready\",\"execution_id\":\"abc-123\",\"lens\":{\"lens_type\":\"review_lens\",\"generated_at\":\"2026-06-13T18:30:00Z\",\"confidence\":\"high\",\"assumptions\":[],\"gaps\":[],\"review_mode\":\"succinct\",\"coverage_status\":\"complete\",\"findings\":[],\"review_inventory\":[],\"authorities\":[],\"relevant_legal_text\":[]}}\n{\"type\":\"done\",\"execution_id\":\"abc-123\",\"status\":\"completed\",\"usage\":{\"category\":\"concise_review\",\"credits_used\":1}}\n"},"text_and_lens_stream":{"summary":"Review text_and_lens mode stream (streamed review markdown + final lens)","value":"{\"type\":\"execution_started\",\"execution_id\":\"abc-123\"}\n{\"type\":\"task_started\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"task_type\":\"legal_research\",\"output_visibility\":\"internal\"}\n{\"type\":\"task_completed\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"task_type\":\"legal_research\"}\n{\"type\":\"task_started\",\"execution_id\":\"abc-123\",\"task_id\":\"t2\",\"task_type\":\"doc_review\",\"output_visibility\":\"final\"}\n{\"type\":\"response_delta\",\"execution_id\":\"abc-123\",\"content\":\"## Review Findings\\n\\n\"}\n{\"type\":\"response_delta\",\"execution_id\":\"abc-123\",\"content\":\"The indemnification clause in section 4...\"}\n{\"type\":\"task_completed\",\"execution_id\":\"abc-123\",\"task_id\":\"t2\",\"task_type\":\"doc_review\"}\n{\"type\":\"lens_ready\",\"execution_id\":\"abc-123\",\"lens\":{\"lens_type\":\"review_lens\",\"generated_at\":\"2026-06-13T18:30:00Z\",\"confidence\":\"high\",\"assumptions\":[],\"gaps\":[],\"review_mode\":\"succinct\",\"coverage_status\":\"complete\",\"findings\":[],\"review_inventory\":[],\"authorities\":[],\"relevant_legal_text\":[]}}\n{\"type\":\"done\",\"execution_id\":\"abc-123\",\"status\":\"completed\",\"usage\":{\"category\":\"concise_review\",\"credits_used\":1}}\n"}}}}},"400":{"description":"Invalid or missing fields. Review requires either target_file_id/attachment_ids or content.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"$ref":"#/components/responses/InsufficientCredits"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"description":"Upstream service failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v1/draft":{"post":{"operationId":"postDraft","summary":"Draft a legal document (streaming). 1 -> 4 minute response time.","tags":["Agentic"],"x-product-category":"drafting","security":[{"ApiKeyAuth":[]}],"description":"Drafts a legal document by first conducting targeted research to identify relevant\nlegal authority, then generating a draft grounded in that authority.\n\nThis is a **2-step operation**: internal legal research → drafting.\n\n**Response format:** drafting only supports `response_format: \"text\"`.\nThe rendered draft streams via `response_delta` events; concatenate\nall `response_delta.content` values for the final output.\n\n**Event sequence:** `execution_started` → `task_started`(research) → `task_completed`(research) → `task_started`(draft) → `response_delta`* → `task_completed`(draft) → `done`\n\n**Embedded links in text responses:** `response_delta.content` contains\nmarkdown that embeds URLs pointing at this API — e.g.\n`https://api.trustfoundry.ai/public/v1/search/results/items/describe/{uuid}`.\nCall those URLs with the same `X-API-Key` header that made this\nrequest to retrieve the underlying case/law/regulation summary. See\nthe [describe endpoint](#/Search/describeSearchResultItem).\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"query":{"type":"string","maxLength":2000,"description":"Describe what to draft.","examples":["Draft a force majeure clause for a commercial lease in Texas"]},"response_format":{"type":"string","enum":["text"],"default":"text","description":"Draft only supports rendered text output."},"model_type":{"type":"string","enum":["extended","deep_research"],"default":"extended"},"default_state":{"type":"string","description":"Two-letter uppercase jurisdiction code.","examples":["TX"]},"target_file_id":{"type":"string","description":"ID of a previously uploaded file to use as the primary target document for drafting context."},"attachment_ids":{"type":"array","items":{"type":"string"},"description":"IDs of previously uploaded files to include as reference documents."},"conversation_id":{"type":"string","description":"Optional session identifier for stateful interactions."}}}}}},"responses":{"200":{"description":"Streaming NDJSON response.","content":{"application/x-ndjson":{"itemSchema":{"oneOf":[{"$ref":"#/components/schemas/ExecutionStartedEvent"},{"$ref":"#/components/schemas/TaskStartedEvent"},{"$ref":"#/components/schemas/TaskProgressEvent"},{"$ref":"#/components/schemas/ResponseDeltaEvent"},{"$ref":"#/components/schemas/TaskCompletedEvent"},{"$ref":"#/components/schemas/HeartbeatEvent"},{"$ref":"#/components/schemas/DoneEvent"},{"$ref":"#/components/schemas/StreamErrorEvent"}],"discriminator":{"propertyName":"type"}},"examples":{"text_stream":{"summary":"Draft text mode stream (2-step)","value":"{\"type\":\"execution_started\",\"execution_id\":\"abc-123\"}\n{\"type\":\"task_started\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"task_type\":\"legal_research\",\"output_visibility\":\"internal\"}\n{\"type\":\"task_completed\",\"execution_id\":\"abc-123\",\"task_id\":\"t1\",\"task_type\":\"legal_research\"}\n{\"type\":\"task_started\",\"execution_id\":\"abc-123\",\"task_id\":\"t2\",\"task_type\":\"drafting\",\"output_visibility\":\"final\"}\n{\"type\":\"response_delta\",\"execution_id\":\"abc-123\",\"content\":\"Dear [Defendant],\\n\\n\"}\n{\"type\":\"response_delta\",\"execution_id\":\"abc-123\",\"content\":\"This office represents...\"}\n{\"type\":\"task_completed\",\"execution_id\":\"abc-123\",\"task_id\":\"t2\",\"task_type\":\"drafting\"}\n{\"type\":\"done\",\"execution_id\":\"abc-123\",\"status\":\"completed\",\"usage\":{\"category\":\"drafting\",\"credits_used\":1}}\n"}}}}},"400":{"description":"Invalid or missing fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"$ref":"#/components/responses/InsufficientCredits"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"description":"Upstream service failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v1/search":{"post":{"operationId":"postSearch","summary":"Execute a direct legal search (streaming). 5 -> 15 second response time.","tags":["Search"],"x-product-category":"fast_citation_search","security":[{"ApiKeyAuth":[]}],"description":"Executes a direct legal search for a specific content type without AI planning or LLM\ninteraction. You specify the target content type via `model_type`, and the query is passed\nstraight to the search index. This is the fastest search option.\n\nSearch results retrieved via API are stored for up to 24 hours.\n\n**Valid model_type values:**\n- `case_question` — Match to cases based on a natural language query.\n- `law_question` — Match to laws based on a natural language query.\n- `reg_question` — Match to regulations based on a natural language query.\n- `case_key_fact` — Match to cases based on key facts in the query.\n- `case_name` — Direct lookup of a case by its name. Returns a ranked,\n  deduplicated page of the closest matching case names, so a near-miss\n  spelling or a reversed party order still surfaces candidates.\n- `citation_search` — Treat `query` as a single citation string and retrieve positive-confidence citation matches.\n\n**Restrictions:**\n- `query` is limited to 750 characters.\n- `model_type: citation_search` cannot be combined with a `state` value.\n\n**Court filtering:** Direct case searches may be restricted to a specific court via\n`court_id` or `court_name`. Only applies to `case_question`, `case_key_fact`, and `case_name`.\n\n**Date filtering:** Case searches may be bounded by published date via\n`published_date_min` / `published_date_max` (`YYYY-MM-DD`, inclusive). Only applies\nto `case_question`, `case_key_fact`, and `case_name`; ignored for law/reg/citation_search.\n\n**Event sequence:** `start` → `search_start` → `search_end` → `citations_ready` → `citation_validation_info`* → `end`\n\nZero or more `citation_validation_info` events follow `citations_ready`\nand carry per-citation signals (ML fallback used, partial match,\nlookup failure). Each `citation_validation_info.content.citation_index`\nis a 0-based index into the `search_results` array of the preceding\n`citations_ready` event.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query","model_type"],"properties":{"query":{"type":"string","maxLength":750,"description":"The legal search query. Limited to 750 characters.","examples":["exhaust emission standards for diesel engines"]},"state":{"type":"string","description":"Two-letter uppercase jurisdiction code. Use `FED` for federal.\nRequired unless `model_type` is `citation_search`; cannot be\ncombined with `citation_search`.\n","examples":["FED"]},"model_type":{"type":"string","enum":["case_question","law_question","reg_question","case_key_fact","case_name","citation_search"],"description":"The content type to search.\n- `case_question` — case law, question-style query.\n- `law_question` — statutes, question-style query.\n- `reg_question` — regulations, question-style query.\n- `case_key_fact` — case law, fact-pattern-style query.\n- `case_name` — direct lookup of a case by its name; returns a\n  ranked, deduplicated page of the closest matching case names.\n- `citation_search` — treats `query` as a citation string.\n","examples":["reg_question"]},"court_id":{"type":"string","maxLength":100,"description":"Court identifier for filtering case law results (e.g. `scotus`, `ca11`).\nOnly applies to `case_question`, `case_key_fact`, and `case_name` searches.\nTakes precedence over `court_name` if both are provided.\n","examples":["scotus"]},"court_name":{"type":"string","maxLength":200,"description":"Human-readable court name for filtering case law results.\nResolved to a `court_id` via fuzzy matching. Returns `400` if unresolved.\n","examples":["Supreme Court of the United States"]},"published_date_min":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Inclusive lower bound on a case's published date (`YYYY-MM-DD`, UTC).\nOnly applies to `case_question`, `case_key_fact`, and `case_name` searches;\nsilently ignored for `law_question`, `reg_question`, and `citation_search`.\n","examples":["2010-01-01"]},"published_date_max":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Inclusive upper bound on a case's published date (`YYYY-MM-DD`, UTC).\nOnly applies to `case_question`, `case_key_fact`, and `case_name` searches;\nsilently ignored for `law_question`, `reg_question`, and `citation_search`.\nMust be on or after `published_date_min` when both are provided.\n","examples":["2015-12-31"]},"limit":{"type":"integer","minimum":1,"maximum":25,"description":"Maximum number of results to return in the resulting search\nset. When omitted, the gateway substitutes the\ndeployment-configured default (set via the\n`PUBLIC_API_SEARCH_DEFAULT_LIMIT` environment variable,\ncurrently 10). Retrieval and reranking always operate on\nthe full candidate pool; only the final emission count is\ntruncated.\n","examples":[25]}}},"examples":{"case_search_with_court_id":{"summary":"Search Supreme Court cases by court_id","value":{"query":"qualified immunity for law enforcement","state":"FED","model_type":"case_question","court_id":"scotus"}},"case_key_fact_with_court_name":{"summary":"Search Ninth Circuit cases by court_name","value":{"query":"police used force during arrest after suspect fled on foot","state":"FED","model_type":"case_key_fact","court_name":"United States Court of Appeals for the Ninth Circuit"}},"case_search_with_date_range":{"summary":"Search federal cases within a published-date window","value":{"query":"commerce clause","state":"FED","model_type":"case_question","published_date_min":"2010-01-01","published_date_max":"2015-12-31"}}}}}},"responses":{"200":{"description":"Streaming NDJSON response. Each line is a JSON object with a `type` field.","content":{"application/x-ndjson":{"itemSchema":{"$ref":"#/components/schemas/SearchStreamEvent"},"examples":{"full_stream":{"summary":"Example basic search stream output","value":"{\"type\":\"start\",\"query\":\"exhaust emission standards for diesel engines\"}\n{\"type\":\"search_start\",\"content\":\"Searching regulations in FED\"}\n{\"type\":\"search_end\",\"content\":\"Finished searching regulations in FED\"}\n{\"type\":\"citations_ready\",\"content\":{\"uuid\":\"e29a934c-26cb-48e5-8324-3cadea9dd9b8\",\"query\":\"exhaust emission standards for diesel engines\",\"created_at\":\"2025-10-06T17:15:40.125604\",\"server_response_duration_ms\":984,\"search_results\":[{\"uuid\":\"d416bfc7-230e-4428-81ee-22e29c88c0cb\",\"header\":\"40 CFR § 89.112\",\"citation\":\"40 CFR § 89.112\",\"url\":\"https://www.ecfr.gov/...\",\"excerpt\":\"Exhaust emission standards...\",\"relevance_score\":0.95,\"result_type\":\"reg\",\"first_level_geo\":\"USA\",\"second_level_geo\":\"FED\"}]}}\n{\"type\":\"end\"}\n"},"citation_search_with_info":{"summary":"citation_search stream with an ML-fallback info message","value":"{\"type\":\"start\",\"query\":\"Tenn Code 45 20 101\"}\n{\"type\":\"search_start\",\"content\":\"Looking up citations\"}\n{\"type\":\"search_end\",\"content\":\"Retrieved 1 authority\"}\n{\"type\":\"citations_ready\",\"content\":{\"uuid\":\"4f3e0d12-1c8a-4ad1-9af7-9c9f8cf3a000\",\"query\":\"Tenn Code 45 20 101\",\"created_at\":\"2026-06-25T15:20:11.000000\",\"search_results\":[{\"uuid\":\"a1c1b8d6-0e22-4f1f-8c11-2c1c0bdfe000\",\"header\":\"Tenn. Code Ann. § 45-20-101\",\"citation\":\"Tenn. Code Ann. § 45-20-101\",\"url\":\"https://example.com/...\",\"excerpt\":\"...\",\"result_type\":\"law\"}],\"info_messages\":[{\"citation_index\":0,\"level\":\"info\",\"message\":\"Citation interpreted with ML fallback.\",\"interpreted_citation\":\"Tenn. Code Ann. § 45-20-101\",\"citation_example\":null}]}}\n{\"type\":\"citation_validation_info\",\"content\":{\"citation_index\":0,\"level\":\"info\",\"message\":\"Citation interpreted with ML fallback.\",\"interpreted_citation\":\"Tenn. Code Ann. § 45-20-101\",\"citation_example\":null}}\n{\"type\":\"end\"}\n"},"citation_search_no_match_with_example":{"summary":"citation_search stream with a no-match info message + Bluebook example","value":"{\"type\":\"start\",\"query\":\"NJSA § 46:10B-22\"}\n{\"type\":\"search_start\",\"content\":\"Looking up citations\"}\n{\"type\":\"search_end\",\"content\":\"Retrieved 0 authorities\"}\n{\"type\":\"citations_ready\",\"content\":{\"uuid\":\"7a91b3e4-6c1d-4a5f-9b23-1c8f0a2b4d1a\",\"query\":\"NJSA § 46:10B-22\",\"created_at\":\"2026-07-02T14:22:00.000000\",\"search_results\":[],\"info_messages\":[{\"citation_index\":0,\"level\":\"warning\",\"message\":\"No match found in database.\",\"interpreted_citation\":\"N.J. Rev. Stat. § 46:10B-22\",\"citation_example\":\"N.J. Stat. Ann. § 1:1\"}]}}\n{\"type\":\"citation_validation_info\",\"content\":{\"citation_index\":0,\"level\":\"warning\",\"message\":\"No match found in database.\",\"interpreted_citation\":\"N.J. Rev. Stat. § 46:10B-22\",\"citation_example\":\"N.J. Stat. Ann. § 1:1\"}}\n{\"type\":\"end\"}\n"}}}}},"400":{"description":"Invalid or missing fields in request body.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"error":{"type":"string"}}}]},"examples":{"query_too_long":{"summary":"query exceeds 750 characters","value":{"error":"query must be 750 characters or fewer"}},"unresolved_court_name":{"summary":"court_name could not be resolved","value":{"detail":"Could not resolve court_name 'Totally Fake Court XYZ 999' to a known court ID. Please verify the court name or use court_id directly."}},"citation_search_with_state":{"summary":"citation_search cannot include state","value":{"error":"model_type \"citation_search\" cannot be combined with a state value"}},"published_date_invalid":{"summary":"published_date_min after published_date_max","value":{"error":"published_date_min must be on or before published_date_max"}}}}}},"401":{"description":"Unauthorized. API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"$ref":"#/components/responses/InsufficientCredits"},"404":{"description":"Organization not found.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"error":{"type":"string","examples":["Organization not found"]}}}]}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream service failed.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"error":{"type":"string","examples":["Upstream service failed"]}}}]}}}}}}},"/public/v1/search/case-text":{"post":{"operationId":"postSearchCaseText","summary":"Search within a case's full text.","tags":["Search"],"x-product-category":"fast_citation_search","security":[{"ApiKeyAuth":[]}],"description":"Search within a case's full text using BM25 relevance matching. Provide either a\n`citation` string or a `uuid` from a prior search result to identify the case, plus\na `query` for the text to find within it. Returns matching passages with relevance scores.\n\nExactly one of `citation` or `search_set_result_uuid` must be provided.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"citation":{"type":"string","description":"Legal citation to resolve to a document (mutually exclusive\nwith `search_set_result_uuid`).\n","examples":["Miranda v. Arizona, 384 U.S. 436"]},"search_set_result_uuid":{"type":"string","format":"uuid","description":"UUID of a saved search result item (mutually exclusive with\n`citation`). Obtained from the search endpoint response.\n","examples":["e29a934c-26cb-48e5-8324-3cadea9dd9b8"]},"query":{"type":"string","maxLength":2000,"description":"The text to search for within the case opinion.","examples":["right to remain silent"]},"top_k":{"type":"integer","minimum":1,"maximum":25,"default":10,"description":"Number of matching text chunks to return."}}},"examples":{"citation_search":{"summary":"Search by citation","value":{"citation":"Miranda v. Arizona, 384 U.S. 436","query":"right to remain silent","top_k":5}},"uuid_search":{"summary":"Search by saved result UUID","value":{"search_set_result_uuid":"e29a934c-26cb-48e5-8324-3cadea9dd9b8","query":"due process"}}}}}},"responses":{"200":{"description":"Matching text chunks from the case opinion.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseTextSearchResponse"},"example":{"results":[{"matched_text":"The person must be warned that he has a right to remain silent...","relevance_score":1},{"matched_text":"...the right to remain silent means that unless and until...","relevance_score":0.82}]}}}},"400":{"description":"Invalid request body or parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized. API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"$ref":"#/components/responses/InsufficientCredits"},"404":{"description":"Document not found for the given citation or UUID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream service failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v1/search/results/{uuid}":{"get":{"operationId":"getSearchResults","summary":"Retrieve a saved search result set.","tags":["Search"],"x-product-category":"search_result_retrieval","security":[{"ApiKeyAuth":[]}],"description":"Retrieve a previously saved search result set by UUID. The UUID comes from the\n`citations_ready` event's `content.uuid` field during a search stream.\nReturns a **SearchSet** containing **SearchSetResult** items.\n","parameters":[{"name":"uuid","in":"path","required":true,"description":"The UUID of the search set to retrieve.","schema":{"type":"string","format":"uuid","examples":["e29a934c-26cb-48e5-8324-3cadea9dd9b8"]}}],"responses":{"200":{"description":"Search set retrieved successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchSet"},"examples":{"search_set":{"summary":"Search result set","value":{"uuid":"e29a934c-...","query":"qualified immunity for law enforcement","created_at":"2026-06-14T16:24:51.139090+00:00","search_results":[{"uuid":"d9810783-...","header":"City and County of San Francisco v. Sheehan","citation_tag":"[City and County of San Francisco v. Sheehan - 2015 U.S. LEXIS 3200](...)","url":"https://www.courtlistener.com/...","excerpt":"Supreme Court case addressing qualified immunity...","relevance_score":3.31,"result_type":"case","first_level_geo":"USA","second_level_geo":"FED"}]}}}}}},"400":{"description":"Invalid or missing UUID.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"error":{"type":"string","examples":["Required field(s) are missing"]}}}]}}}},"401":{"description":"Unauthorized. API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Organization or search set not found.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"error":{"type":"string","examples":["Organization not found"]}}}]}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v1/search/results/items/describe/{uuid}":{"get":{"operationId":"describeSearchResultItem","summary":"Retrieve a summarized legal description for a saved search result item.","tags":["Search"],"x-product-category":"document_description","security":[{"ApiKeyAuth":[]}],"description":"Given a saved search result UUID, returns a summarized description of the item.\nCase results return `SearchResultDescriptionCaseResponse`; law/reg results return\n`SearchResultDescriptionLawRegResponse`. Dispatch on the `type` field.\n\n**How to reach this endpoint:** URLs pointing at this endpoint are\nembedded in `response_delta.content` from `/public/v1/research`,\n`/public/v1/draft`, and `/public/v1/review` for `response_format:\n\"text\"` and `\"text_and_lens\"`. Parse those absolute URLs directly\nfrom the text, or construct them yourself from search-result item\nUUIDs surfaced in a `ResearchLens` or `ReviewLens`.\n\n**Auth scoping:** search-set items are strictly scoped to the auth\nprincipal that persisted them. A search result created by an API\nkey is retrievable only with that same API key. A search result\ncreated by an OAuth session is retrievable only within that session\nby the same user. Cross-mode retrieval (API key → OAuth or vice\nversa) returns 404 by design — do not attempt to share item UUIDs\nacross auth contexts.\n","parameters":[{"name":"uuid","in":"path","required":true,"description":"The UUID of the saved search result.","schema":{"type":"string","format":"uuid","examples":["e29a934c-26cb-48e5-8324-3cadea9dd9b8"]}},{"name":"full_text","in":"query","required":false,"description":"When true, include the full text of the search result in the response.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Description retrieved successfully.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/SearchResultDescriptionCaseResponse"},{"$ref":"#/components/schemas/SearchResultDescriptionLawRegResponse"}]}}}},"400":{"description":"Invalid request, missing/invalid UUID, or invalid upstream response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized. API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Organization, search result, or summary not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v1/treatment/records":{"post":{"operationId":"postTreatmentRecords","summary":"Retrieve incoming treatment records for a case. [DEPRECATED — use /treatment/records/incoming] (Beta Preview)","tags":["Treatment (Beta Preview)"],"x-product-category":"treatment_details_page","x-beta":true,"deprecated":true,"x-replaced-by":"postTreatmentRecordsIncoming","x-deprecation-message":"Use `POST /public/v1/treatment/records/incoming` instead. Behavior is identical — this path is a compile-time alias retained during the deprecation window. `/records/incoming` is the target-anchored half of a directional pair with `/records/outgoing`; the new names make the citation direction explicit.","security":[{"ApiKeyAuth":[]}],"description":"**Deprecated — use `POST /public/v1/treatment/records/incoming`.**\n\nReturns incoming treatment records for a case (later cases that cite\nthis case, and how they treat it). Identifier: either a saved search\nresult item UUID or a treatment signal UUID in the JSON body.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"description":"Exactly one of `search_item_uuid` or `treatment_signal_uuid` is required. `treatment_label` and `labels` are mutually exclusive.","oneOf":[{"required":["search_item_uuid"]},{"required":["treatment_signal_uuid"]}],"properties":{"search_item_uuid":{"type":"string","format":"uuid","description":"Saved search result item UUID for a case result. Must refer to a *case* result — passing a law/reg search item returns 400."},"treatment_signal_uuid":{"type":"string","format":"uuid","description":"Treatment (Beta Preview) signal UUID for the target case. If the signal has not yet been computed, the response returns `results: []` rather than 404."},"treatment_label":{"allOf":[{"$ref":"#/components/schemas/TreatmentLabel"}],"description":"Exact single treatment label filter. Mutually exclusive with `labels`."},"polarity":{"$ref":"#/components/schemas/TreatmentPolarity"},"labels":{"type":"array","description":"One or more exact treatment labels to include. Mutually exclusive with `treatment_label`.","items":{"$ref":"#/components/schemas/TreatmentLabel"}},"recency":{"type":"object","additionalProperties":false,"required":["amount","unit"],"description":"Only include treatment from source documents (the citing cases) in this trailing time window.","properties":{"amount":{"type":"integer","minimum":1,"maximum":100,"description":"Positive integer window size (1–100)."},"unit":{"$ref":"#/components/schemas/TreatmentRecencyUnit"}}},"cursor":{"type":"string","description":"Opaque pagination cursor obtained from the previous response's `next_cursor`. Do not construct manually."},"page_size":{"type":"integer","minimum":1,"maximum":100,"default":100,"description":"Number of records to return per page (1–100). Defaults to 100."}}},"examples":{"negative_recent":{"summary":"Negative treatment in the last 5 years","value":{"search_item_uuid":"e29a934c-26cb-48e5-8324-3cadea9dd9b8","polarity":"negative","recency":{"amount":5,"unit":"years"},"page_size":100}},"selected_labels":{"summary":"Specific treatment labels","value":{"treatment_signal_uuid":"9a7b6c5d-1111-4222-8333-123456789abc","labels":["distinguished","criticized"],"page_size":50}}}}}},"responses":{"200":{"description":"Treatment (Beta Preview) records with cursor pagination metadata.","content":{"application/json":{"schema":{"type":"object","required":["results"],"properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/TreatmentRecord"}},"next_cursor":{"type":"string","nullable":true,"description":"Cursor string to pass on the next request; `null` when there is no next page."}}}}}},"400":{"description":"Invalid UUID or request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized. API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Organization or search result not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream service failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v1/treatment/records/incoming":{"post":{"operationId":"postTreatmentRecordsIncoming","summary":"Retrieve incoming treatment records — later cases that cite this case. (Beta Preview)","tags":["Treatment (Beta Preview)"],"x-product-category":"treatment_details_page","x-beta":true,"security":[{"ApiKeyAuth":[]}],"description":"How later authorities treat your case. Returns treatment records for a\ncase you identify — later cases that cite your case and how they treat\nit.\n\nIdentify the case with exactly one of `search_item_uuid` (a saved\nsearch result item UUID for a case result) or `treatment_signal_uuid`\n(a computed treatment signal UUID). Filter with `treatment_label` /\n`labels`, `polarity`, and `recency`; paginate with `cursor` and\n`page_size`.\n\nRecency binds on the source date of each record (when the later\nciting case was published). `treatment_label` and `labels` are\nmutually exclusive.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"description":"Exactly one of `search_item_uuid` or `treatment_signal_uuid` is required. `treatment_label` and `labels` are mutually exclusive.","oneOf":[{"required":["search_item_uuid"]},{"required":["treatment_signal_uuid"]}],"properties":{"search_item_uuid":{"type":"string","format":"uuid","description":"Saved search result item UUID for a case result. Must refer to a *case* result — passing a law/reg search item returns 400."},"treatment_signal_uuid":{"type":"string","format":"uuid","description":"Treatment (Beta Preview) signal UUID for the target case. If the signal has not yet been computed, the response returns `results: []` rather than 404."},"treatment_label":{"allOf":[{"$ref":"#/components/schemas/TreatmentLabel"}],"description":"Exact single treatment label filter. Mutually exclusive with `labels`."},"polarity":{"$ref":"#/components/schemas/TreatmentPolarity"},"labels":{"type":"array","description":"One or more exact treatment labels to include. Mutually exclusive with `treatment_label`.","items":{"$ref":"#/components/schemas/TreatmentLabel"}},"recency":{"type":"object","additionalProperties":false,"required":["amount","unit"],"description":"Only include treatment from source documents (the citing cases) in this trailing time window.","properties":{"amount":{"type":"integer","minimum":1,"maximum":100,"description":"Positive integer window size (1–100)."},"unit":{"$ref":"#/components/schemas/TreatmentRecencyUnit"}}},"cursor":{"type":"string","description":"Opaque pagination cursor obtained from the previous response's `next_cursor`. Do not construct manually."},"page_size":{"type":"integer","minimum":1,"maximum":100,"default":100,"description":"Number of records to return per page (1–100). Defaults to 100."}}},"examples":{"negative_recent":{"summary":"Negative treatment in the last 5 years","value":{"search_item_uuid":"e29a934c-26cb-48e5-8324-3cadea9dd9b8","polarity":"negative","recency":{"amount":5,"unit":"years"},"page_size":100}},"selected_labels":{"summary":"Specific treatment labels","value":{"treatment_signal_uuid":"9a7b6c5d-1111-4222-8333-123456789abc","labels":["distinguished","criticized"],"page_size":50}}}}}},"responses":{"200":{"description":"Incoming treatment records with cursor pagination metadata.","content":{"application/json":{"schema":{"type":"object","required":["results"],"properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/TreatmentRecord"}},"next_cursor":{"type":"string","nullable":true,"description":"Cursor string to pass on the next request; `null` when there is no next page."}}}}}},"400":{"description":"Invalid UUID or request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized. API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Organization or search result not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream service failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v1/treatment/records/outgoing":{"post":{"operationId":"postTreatmentRecordsOutgoing","summary":"Retrieve outgoing treatment records — how this case treats other authorities. (Beta Preview)","tags":["Treatment (Beta Preview)"],"x-product-category":"treatment_details_page","x-beta":true,"security":[{"ApiKeyAuth":[]}],"description":"How your case treats earlier authorities. Returns treatment records for\na case you identify — how your case treats the earlier authorities it\ncites, scoped to a set of target documents.\n\nSupply the scope via `search_set_uuid`, typically the search set\nreturned by `/public/v1/research`. Filter with `treatment_label` /\n`labels`, `polarity`, and `recency`; paginate with `cursor` and\n`page_size`.\n\nRecency binds on the target document's date on this endpoint (\"how\ndoes this case treat priors from the last N years?\").\n`treatment_label` and `labels` are mutually exclusive.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["treatment_record_uuid","search_set_uuid"],"description":"`treatment_record_uuid` identifies the source case; `search_set_uuid` defines the target-document scope. `treatment_label` and `labels` are mutually exclusive.","properties":{"treatment_record_uuid":{"type":"string","format":"uuid","description":"Any treatment record whose source is the case of interest. The endpoint resolves the source-case document from this record and returns treatment records where source = that case."},"search_set_uuid":{"type":"string","format":"uuid","description":"Search set that defines the target-document scope. Only treatment records whose target is in this set are returned. Typically the search set returned alongside a `/public/v1/research` response."},"treatment_label":{"allOf":[{"$ref":"#/components/schemas/TreatmentLabel"}],"description":"Exact single treatment label filter. Mutually exclusive with `labels`."},"polarity":{"$ref":"#/components/schemas/TreatmentPolarity"},"labels":{"type":"array","description":"One or more exact treatment labels to include. Mutually exclusive with `treatment_label`.","items":{"$ref":"#/components/schemas/TreatmentLabel"}},"recency":{"type":"object","additionalProperties":false,"required":["amount","unit"],"description":"Only include treatment records where the **target** document falls in this trailing time window (i.e. 'how does this case treat priors from the last N years'). Recency binds on target-document date, not source, since the source case is fixed by `treatment_record_uuid`.","properties":{"amount":{"type":"integer","minimum":1,"maximum":100,"description":"Positive integer window size (1–100)."},"unit":{"$ref":"#/components/schemas/TreatmentRecencyUnit"}}},"cursor":{"type":"string","description":"Opaque pagination cursor obtained from the previous response's `next_cursor`. Do not construct manually."},"page_size":{"type":"integer","minimum":1,"maximum":100,"default":100,"description":"Number of records to return per page (1–100). Defaults to 100."}}},"examples":{"basic":{"summary":"Case-level outgoing treatment scoped to a search set","value":{"treatment_record_uuid":"9a7b6c5d-1111-4222-8333-123456789abc","search_set_uuid":"0d1e2f3a-4b5c-6d7e-8f90-abcdef012345"}},"filtered_paginated":{"summary":"Only negative treatment from the last 10 years, page 25","value":{"treatment_record_uuid":"9a7b6c5d-1111-4222-8333-123456789abc","search_set_uuid":"0d1e2f3a-4b5c-6d7e-8f90-abcdef012345","polarity":"negative","recency":{"amount":10,"unit":"years"},"page_size":25}}}}}},"responses":{"200":{"description":"Source case header plus scoped outgoing treatment records with cursor pagination metadata.","content":{"application/json":{"schema":{"type":"object","required":["source_case","records"],"properties":{"source_case":{"$ref":"#/components/schemas/OutgoingTreatmentSourceCase"},"records":{"type":"array","items":{"$ref":"#/components/schemas/OutgoingTreatmentRecord"}},"next_cursor":{"type":"string","nullable":true,"description":"Cursor string to pass on the next request; `null` when there is no next page."}}}}}},"400":{"description":"Invalid UUID or request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized. API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Organization or treatment record not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream service failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v1/treatment/signal":{"post":{"operationId":"getTreatmentSignal","summary":"Retrieve treatment signal data by search result item or treatment signal. (Beta Preview)","tags":["Treatment (Beta Preview)"],"x-product-category":"treatment_search","x-beta":true,"security":[{"ApiKeyAuth":[]}],"description":"Returns aggregate treatment signal data. Provide exactly one of\n`search_item_uuid` or `treatment_signal_uuid`.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"search_item_uuid":{"type":"string","format":"uuid","description":"Search result item UUID for a case result."},"treatment_signal_uuid":{"type":"string","format":"uuid","description":"Treatment (Beta Preview) signal UUID for a case."}},"oneOf":[{"required":["search_item_uuid"]},{"required":["treatment_signal_uuid"]}],"additionalProperties":false},"examples":{"searchItem":{"value":{"search_item_uuid":"e29a934c-26cb-48e5-8324-3cadea9dd9b8"}},"treatmentSignal":{"value":{"treatment_signal_uuid":"e29a934c-26cb-48e5-8324-3cadea9dd9b8"}}}}}},"responses":{"200":{"description":"Treatment (Beta Preview) signal summary.","content":{"application/json":{"schema":{"type":"object","required":["uuid","treatment_status","total_treatment_records","explanation","label_counts"],"properties":{"uuid":{"type":"string","format":"uuid"},"treatment_status":{"type":"string"},"total_treatment_records":{"type":"integer"},"explanation":{"type":"string"},"label_counts":{"type":"object","required":["positive","negative","neutral"],"properties":{"positive":{"type":"integer"},"negative":{"type":"integer"},"neutral":{"type":"integer"}}}}}}}},"400":{"description":"Invalid UUID or invalid parameter combination.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized. API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Organization or search result not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream service failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v1/citation/validate":{"post":{"operationId":"postCitationValidate","summary":"Validate legal citations in text.","tags":["Validation"],"x-product-category":"citation_validation","security":[{"ApiKeyAuth":[]}],"description":"Extracts legal citations from the provided text and validates them against the database.\nReturns match confidence, citation details, and a snippet from the matched document for\neach citation found.\n\n- Citations are extracted using eyecite and validated in parallel batches.\n- Each citation receives a `confidence` score between `0.0` and `1.0` indicating\n  match quality (`1.0` = exact match, `0.8` = citation matched but name differs,\n  `0.6` = name matched but citation differs, `0.0` = not found). `-1` = error/unchecked.\n- `text` is limited to **10,000 characters**.\n- `context_before` and `context_after` accept **0-250** characters each (default 0).\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["text"],"properties":{"text":{"type":"string","maxLength":10000,"description":"The text to extract and validate citations from.","examples":["The court relied on 42 U.S.C. § 1983 and Smith v. Jones, 123 F.3d 456 (2nd Cir. 2020)."]},"context_before":{"type":"integer","minimum":0,"maximum":250,"default":0,"description":"Number of characters before each citation to include as context."},"context_after":{"type":"integer","minimum":0,"maximum":250,"default":0,"description":"Number of characters after each citation to include as context."}}}}}},"responses":{"200":{"description":"Citation validation results.","content":{"application/json":{"schema":{"type":"object","properties":{"citations":{"type":"array","items":{"type":"object","properties":{"confidence":{"type":"number","description":"Match confidence score. `1.0` = exact match, `0.8` = citation matched\nbut name differs, `0.6` = name matched but citation differs, `0.0` = not\nfound, `-1` = error/unchecked.\n"},"result_type":{"type":"string","nullable":true,"enum":["law","case"],"description":"The type of legal document matched."},"title":{"type":"string","nullable":true,"description":"Citation string for laws or case name for cases."},"citation":{"type":"string","nullable":true,"description":"The clean citation string."},"citation_link_md":{"type":"string","nullable":true,"description":"Markdown-formatted link combining title, citation, and URL."},"url":{"type":"string","nullable":true,"description":"URL to the matched document."},"cited_opinion_snippet":{"type":"string","nullable":true,"description":"A short text snippet from the matched document."},"citation_context":{"type":"string","nullable":true,"description":"Surrounding text from the input with a [CITATION] marker."},"jurisdiction_id":{"type":"string","nullable":true,"description":"Jurisdiction identifier for the matched document."}}}},"stats":{"type":"object","properties":{"extracted":{"type":"integer","description":"Total citations extracted from the text."},"validated":{"type":"integer","description":"Citations queried against the database."},"matched":{"type":"integer","description":"Citations found in the database."},"errors":{"type":"integer","description":"Citations that encountered query errors."},"unchecked":{"type":"integer","description":"Citations not checked (over limit)."}}}}},"examples":{"law_match":{"summary":"Law citation match","value":{"citations":[{"confidence":1,"result_type":"law","title":"42 U.S.C. § 1983","citation":"42 U.S.C. § 1983","citation_link_md":"[42 U.S.C. § 1983](https://uscode.house.gov/view.xhtml?req=granuleid:USC-prelim-title42-section1983)","url":"https://uscode.house.gov/view.xhtml?req=granuleid:USC-prelim-title42-section1983","cited_opinion_snippet":"Every person who, under color of any statute, ordinance, regulation, custom, or usage...","citation_context":"The court relied on [CITATION] and related statutes.","jurisdiction_id":"us"}],"stats":{"extracted":1,"validated":1,"matched":1,"errors":0,"unchecked":0}}},"case_match":{"summary":"Case citation match","value":{"citations":[{"confidence":1,"result_type":"case","title":"Miranda v. Arizona","citation":"384 U.S. 436","citation_link_md":"[Miranda v. Arizona - 384 U.S. 436](https://www.courtlistener.com/opinion/107252/miranda-v-arizona/)","url":"https://www.courtlistener.com/opinion/107252/miranda-v-arizona/","cited_opinion_snippet":"The cases before us raise questions which go to the roots of our concepts of American criminal jurisprudence...","citation_context":"as established in [CITATION], the defendant must be informed of their rights.","jurisdiction_id":"us"}],"stats":{"extracted":1,"validated":1,"matched":1,"errors":0,"unchecked":0}}}}}}},"400":{"description":"Invalid or missing fields in request body.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"error":{"type":"string","examples":["text is required"]}}}]}}}},"401":{"description":"Unauthorized. API key is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"$ref":"#/components/responses/InsufficientCredits"},"404":{"description":"Organization not found.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"error":{"type":"string","examples":["Organization not found"]}}}]}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream service failed.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","properties":{"error":{"type":"string","examples":["Upstream service failed"]}}}]}}}}}}},"/public/v1/files":{"get":{"operationId":"listFiles","summary":"List uploaded files","tags":["Files"],"x-product-category":"utility","security":[{"ApiKeyAuth":[]}],"description":"Returns all files currently staged for this API key. Files expire after 1 hour.\n","responses":{"200":{"description":"List of uploaded files.","content":{"application/json":{"schema":{"type":"object","properties":{"files":{"type":"array","items":{"$ref":"#/components/schemas/UploadedFile"}}}}}}},"401":{"description":"Unauthorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"operationId":"uploadFile","summary":"Upload a file","tags":["Files"],"x-product-category":"utility","security":[{"ApiKeyAuth":[]}],"description":"Upload a document for use with the review, draft, or research endpoints.\nSupported formats: `.txt`, `.pdf`, `.docx`, `.rtf`. Maximum ~50,000 words per file.\n\nFiles expire after **1 hour**. A per-tier byte budget limits total upload volume\nper rolling hour.\n","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"The file to upload (.txt, .pdf, .docx, .rtf)."}}}}}},"responses":{"200":{"description":"File uploaded successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"files":{"type":"array","items":{"$ref":"#/components/schemas/UploadedFile"}}}}}},"headers":{"X-File-Budget-Limit":{"schema":{"type":"integer"},"description":"Total byte budget for this tier (per hour)."},"X-File-Budget-Used":{"schema":{"type":"integer"},"description":"Bytes used in current window."},"X-File-Budget-Remaining":{"schema":{"type":"integer"},"description":"Bytes remaining in current window."},"X-File-Budget-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the current window resets."}}},"400":{"description":"Missing or invalid file.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"File too large.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/public/v1/files/{fileId}":{"delete":{"operationId":"deleteFile","summary":"Delete an uploaded file","tags":["Files"],"x-product-category":"utility","security":[{"ApiKeyAuth":[]}],"description":"Permanently deletes an uploaded file. This frees up storage in the\nper-hour byte budget immediately.\n","parameters":[{"name":"fileId","in":"path","required":true,"schema":{"type":"string"},"description":"The file ID returned from the upload endpoint."}],"responses":{"204":{"description":"File deleted successfully."},"401":{"description":"Unauthorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"File not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/public/v1/feedback":{"post":{"operationId":"postFeedback","summary":"Submit feedback on a prior API request","tags":["Feedback"],"x-product-category":"utility","security":[{"ApiKeyAuth":[]}],"description":"Submit thumbs-up/thumbs-down feedback — plus an optional comment and\nstructured reason codes — on any prior API result, keyed by the\n`X-Request-Id` returned in the response headers.\n\nAt least one of `sentiment` or `comment` must be present. The endpoint\npublishes a `feedback-events` Pub/Sub message and returns after ack;\nresponses are eventually consistent (GET may lag by seconds).\n\nFeedback is rate-limited under its own bucket and does not consume\nresearch or search credits.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["request_id"],"properties":{"request_id":{"type":"string","format":"uuid","description":"UUID from the `X-Request-Id` header of the prior API call."},"sentiment":{"type":"string","enum":["positive","negative"],"nullable":true,"description":"Thumbs-up or thumbs-down. At least one of `sentiment` or `comment` must be present."},"comment":{"type":"string","maxLength":2000,"nullable":true,"description":"Free-text comment. **Required (non-empty after trim) when `sentiment` is `negative`** — negative submissions without a comment are rejected with 400 `comment_required`. Values exceeding 2000 characters are silently truncated; the 201 body includes warnings: [\"comment_truncated\"] when this fires."},"reasons":{"type":"array","maxItems":4,"nullable":true,"description":"Structured reason codes. Maximum 4 values.","items":{"$ref":"#/components/schemas/FeedbackReason"}},"target":{"$ref":"#/components/schemas/FeedbackTarget"},"mode":{"type":"string","enum":["live","test"],"default":"live","description":"`live` (default) — production feedback counted in analytics.\n`test` — staging/debug submissions; filtered from analytics by default.\n"},"client_reference_id":{"type":"string","maxLength":128,"description":"Opaque caller-controlled identifier (e.g. a session ID). Must not\ncontain `@` or match an email pattern. Max 128 characters.\n"}}},"examples":{"positive":{"summary":"Positive sentiment (no reasons)","value":{"request_id":"9f2c81d0-1234-4abc-8def-000000000001","sentiment":"positive"}},"negative_with_reasons":{"summary":"Negative sentiment with reasons and comment","value":{"request_id":"9f2c81d0-1234-4abc-8def-000000000002","sentiment":"negative","reasons":["inaccurate","incomplete"],"comment":"The third citation was wrong and the analysis missed the 2024 amendment."}},"comment_only":{"summary":"Comment without explicit sentiment","value":{"request_id":"9f2c81d0-1234-4abc-8def-000000000003","comment":"Good answer but the excerpt for authority a2 was cut off."}}}}}},"responses":{"201":{"description":"Feedback recorded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackSubmitResponse"},"examples":{"success":{"summary":"Successful submission","value":{"feedback_id":"a1b2c3d4-0000-4000-8000-111111111111","request_id":"9f2c81d0-1234-4abc-8def-000000000001","received_at":"2026-07-17T14:32:11.000Z","warnings":[]}},"comment_truncated":{"summary":"Submission with truncated comment","value":{"feedback_id":"a1b2c3d4-0000-4000-8000-222222222222","request_id":"9f2c81d0-1234-4abc-8def-000000000002","received_at":"2026-07-17T14:32:12.000Z","warnings":["comment_truncated"]}}}}}},"400":{"description":"Validation error. The `error` field identifies the failure:\n- `empty_feedback` — neither `sentiment` nor `comment` provided.\n- `comment_required` — `sentiment` is `negative` but `comment` is missing or whitespace-only.\n- `invalid_request_id` — `request_id` is missing or not a UUID.\n- `invalid_sentiment` — unrecognised sentiment value.\n- `invalid_reason_code` — one or more reason codes not in the accepted set; `accepted` array included in body.\n- `too_many_reasons` — more than 4 reason codes supplied.\n- `invalid_mode` — `mode` value not `live` or `test`.\n- `client_reference_contains_pii` — `client_reference_id` contains `@` or matches an email pattern.\n- `client_reference_id_too_long` — `client_reference_id` exceeds 128 characters.\n- `unknown_field` — unrecognised top-level or `target` key; `field` name included in body.\n","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"field":{"type":"string","description":"Present for `unknown_field` errors; names the offending key."},"accepted":{"type":"array","items":{"type":"string"},"description":"Present for `invalid_reason_code`; lists all valid reason codes."}}}]}}}},"401":{"description":"Unauthorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"description":"Pub/Sub publish failed; client should retry. Error body `{\"error\":\"feedback_publish_failed\"}`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"operationId":"getFeedback","summary":"List submitted feedback for the caller's org (audit read)","tags":["Feedback"],"x-product-category":"utility","security":[{"ApiKeyAuth":[]}],"description":"Returns a deduplicated, org-scoped list of feedback submissions for\naudit purposes. Results are eventually consistent — POST responses are\nthe authoritative write receipt; GET may lag by seconds.\n\n**Deduplication:** when the same `request_id` appears multiple times,\nonly the earliest submission in the requested window is returned.\n\n**Default filters:** `mode=live`, `since=7d`, `limit=100`.\n","parameters":[{"in":"query","name":"since","schema":{"type":"string","default":"7d","pattern":"^\\d+d$"},"description":"Lookback window as an integer number of days with a `d` suffix\n(e.g. `7d`, `30d`). Values exceeding 30 days are clamped to `30d`;\na `warnings` entry is added to the response when clamping occurs.\n"},{"in":"query","name":"sentiment","schema":{"type":"string","enum":["positive","negative"]},"description":"Filter to a specific sentiment. Omit to return all."},{"in":"query","name":"mode","schema":{"type":"string","enum":["live","test","all"],"default":"live"},"description":"Filter by submission mode. Default `live` hides test submissions."},{"in":"query","name":"cursor","schema":{"type":"string"},"description":"Opaque pagination token from a prior response's `next_cursor`. Do not construct manually."},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"description":"Maximum items per page. Requests outside 1..100 return HTTP 400."}],"responses":{"200":{"description":"Deduplicated feedback list.","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/FeedbackItem"}},"next_cursor":{"type":"string","nullable":true,"description":"Pagination token for the next page. Absent or null when no further pages exist."},"warnings":{"type":"array","items":{"type":"string"},"description":"Non-fatal notices such as `since_clamped` or `upstream_unavailable`."}}},"examples":{"list":{"summary":"Feedback list","value":{"items":[{"feedback_id":"a1b2c3d4-0000-4000-8000-111111111111","request_id":"9f2c81d0-1234-4abc-8def-000000000001","sentiment":"negative","target":{"search_set_id":null,"search_set_result_id":"result-uuid-here","citation_id":null,"chat_message_id":null},"timestamp":"2026-07-17T14:32:11.000Z"}],"next_cursor":null,"warnings":[]}}}}}},"400":{"description":"Validation error. The `error` field is one of:\n`invalid_since`, `invalid_sentiment`, `invalid_mode`.\n","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","required":["error"],"properties":{"error":{"type":"string"}}}]}}}},"401":{"description":"Unauthorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/public/v1/usage":{"get":{"operationId":"getUsage","summary":"Get usage and billing status","tags":["Utilities"],"x-product-category":"utility","security":[{"ApiKeyAuth":[]}],"description":"Returns per-category quota usage, subscription credit status, prepaid\ncredit balance, and 30-day daily credit history for the authenticated\norganization.\n","responses":{"200":{"description":"Usage status with per-category breakdown.","content":{"application/json":{"schema":{"type":"object","required":["quotaPeriod","daysRemaining","creditBalance","subscriptionCredits","categories","creditHistory"],"properties":{"quotaPeriod":{"type":"string","enum":["monthly","lifetime","daily"],"description":"Reset window for billable categories."},"daysRemaining":{"type":"integer","nullable":true,"description":"Days until the next quota reset (null for lifetime plans)."},"creditBalance":{"type":"integer","description":"Prepaid overage credit balance."},"subscriptionCredits":{"type":"object","required":["allowance","used","remaining","resetAt"],"properties":{"allowance":{"type":"integer","description":"Monthly subscription credit allowance."},"used":{"type":"integer","description":"Subscription credits consumed in the current period."},"remaining":{"type":"integer","description":"Subscription credits left in the current period."},"resetAt":{"type":"string","format":"date-time","nullable":true,"description":"When subscription credits reset."}}},"categories":{"type":"array","items":{"type":"object","required":["slug","displayName","limit","totalUsed","overageUsed","subscriptionCreditsUsed","overageCreditsUsed","overageCreditsUsedToday","overageCreditCost","subscriptionCreditCost","creditCost","subscriptionCreditsAllowed","overageAllowed","quotaPeriod","resetAt"],"properties":{"slug":{"type":"string","description":"Stable identifier for this product category."},"displayName":{"type":"string"},"limit":{"type":"integer","nullable":true,"description":"Quota limit for the current period; null = unlimited."},"totalUsed":{"type":"integer","description":"Requests in this category for the current period."},"overageUsed":{"type":"integer","description":"Requests beyond `limit` in the current period (0 when below limit or unlimited)."},"subscriptionCreditsUsed":{"type":"integer","description":"Subscription credits spent in this category during the current period."},"overageCreditsUsed":{"type":"integer","description":"Prepaid overage credits spent in this category during the current period."},"overageCreditsUsedToday":{"type":"integer","description":"Prepaid overage credits spent in this category today."},"overageCreditCost":{"type":"integer","description":"Cost per request when paying with prepaid overage credits."},"subscriptionCreditCost":{"type":"integer","description":"Cost per request when paying with subscription credits."},"creditCost":{"type":"integer","description":"Effective per-call credit cost given the current subscription credit state. Equal to subscriptionCreditCost while subscription credits remain in the period, then overageCreditCost."},"subscriptionCreditsAllowed":{"type":"boolean","description":"Whether subscription credits may be spent on over-quota requests in this category."},"overageAllowed":{"type":"boolean","description":"Whether requests past the quota are allowed at all (charged to prepaid credits)."},"quotaPeriod":{"type":"string","enum":["monthly","lifetime","daily"],"description":"Reset window for this category's quota."},"resetAt":{"type":"string","format":"date-time","nullable":true,"description":"When this category's quota resets (null for lifetime)."}}}},"creditHistory":{"type":"array","description":"Daily ending prepaid-credit balance over the last 30 days.","items":{"type":"object","required":["date","endBalance","isToday"],"properties":{"date":{"type":"string","description":"ISO-8601 date (YYYY-MM-DD)."},"endBalance":{"type":"integer","description":"Prepaid credit balance at end of day."},"isToday":{"type":"boolean","description":"True for the live (current-day) point."}}}}}},"examples":{"usage":{"summary":"Usage response","value":{"quotaPeriod":"monthly","daysRemaining":15,"creditBalance":500,"subscriptionCredits":{"allowance":1000,"used":150,"remaining":850,"resetAt":"2026-07-01T00:00:00.000Z"},"categories":[{"slug":"focused_research","displayName":"Focused Research","limit":100,"totalUsed":42,"overageUsed":0,"subscriptionCreditsUsed":0,"overageCreditsUsed":0,"overageCreditsUsedToday":0,"overageCreditCost":2,"subscriptionCreditCost":1,"creditCost":1,"subscriptionCreditsAllowed":true,"overageAllowed":true,"quotaPeriod":"monthly","resetAt":"2026-07-01T00:00:00.000Z"}],"creditHistory":[{"date":"2026-06-14","endBalance":510,"isToday":false},{"date":"2026-06-15","endBalance":500,"isToday":true}]}}}}}},"401":{"description":"Unauthorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"description":"Quota service unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/public/v1/compliance/scan-text":{"post":{"operationId":"postCompliancePerformCheck","summary":"Run a compliance check against a published package","tags":["Compliance"],"x-product-category":"compliance","security":[{"ApiKeyAuth":[]}],"description":"Extract evidence from free text and evaluate it against the rules in a\ncompliance package. Returns named checks with passed, failed, or unknown\nstatus and human-readable reasoning based on the package's field descriptions.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["identifier","agent_tag","request_id","free_text"],"properties":{"identifier":{"type":"string","pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$","description":"Kebab-case identifier of the compliance package."},"version":{"type":"integer","minimum":1,"description":"Package version. Omit to use the latest published version."},"agent_tag":{"type":"string","minLength":1,"maxLength":200},"request_id":{"type":"string","description":"Caller-supplied conversation identifier. Reuse one request_id\nacross the turns of a single conversation so state accumulates.\nState expires after roughly one hour of inactivity.\n"},"free_text":{"type":"string","minLength":1,"maxLength":100000,"description":"Unstructured text describing the activity. The service extracts\nframe field values before evaluating rules.\n"},"test_state":{"type":"object","additionalProperties":{"type":"string"},"description":"Optional testing-only state override for one request. It does not\npersist and must not be used to seed a conversation.\n"}}},"examples":{"free_text":{"summary":"Free-text evidence","value":{"identifier":"hipaa-privacy","request_id":"conversation-123","free_text":"The patient provided verbal consent and records are retained for 90 days."}},"versioned":{"summary":"Pinned to a specific version","value":{"identifier":"hipaa-privacy","version":2,"request_id":"conversation-123","free_text":"The patient did not provide consent."}}}}}},"responses":{"200":{"description":"Compliance check results.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","required":["identifier","checks"],"properties":{"identifier":{"type":"string","description":"Kebab-case package identifier."},"checks":{"type":"array","description":"Ordered check results with human-readable names.","items":{"type":"object","required":["name","status","reasoning"],"properties":{"name":{"type":"string"},"status":{"type":"string","enum":["passed","failed","unknown"],"description":"Unknown means the scenario or condition could not be established from the provided text."},"reasoning":{"type":"string","description":"Human-readable reasoning using frame field descriptions."}}}}}}},"examples":{"pass":{"summary":"All rules pass","value":[{"identifier":"hipaa-privacy","checks":[{"name":"Consent obtained","status":"passed","reasoning":"The check passed because patient consent was obtained."}]}]},"fail":{"summary":"One rule fails","value":[{"identifier":"hipaa-privacy","checks":[{"name":"Consent obtained","status":"failed","reasoning":"The check failed because it was not the case that patient consent was obtained."}]}]},"unknown":{"summary":"A rule cannot be evaluated","value":[{"identifier":"hipaa-privacy","checks":[{"name":"Consent obtained","status":"unknown","reasoning":"The check was unknown because it could not be established whether patient consent was obtained."}]}]}}}}},"400":{"description":"Validation error (missing identifier, request_id, or free_text, or invalid version).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Compliance package not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict (e.g. package has no published version).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"description":"Frame extraction unavailable (upstream LLM failure).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"responses":{"RateLimited":{"description":"Rate limit, quota, or (for file uploads) upload budget exceeded. Limits apply per organization and product category; the gateway may also apply a per-client-IP budget to requests whose credentials are missing or invalid. Back off for `Retry-After` seconds.","headers":{"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Requests allowed in the current window."},"RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the current window."},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until the window resets (delta-seconds). Legacy `X-RateLimit-*` duplicates are also sent; `X-RateLimit-Reset` is an epoch timestamp."},"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"X-Quota-Category":{"schema":{"type":"string"},"description":"Product category whose per-organization limit or quota was hit. Absent when the per-client-IP budget for unauthenticated requests was exceeded."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"InsufficientCredits":{"description":"Quota exceeded, overage is allowed for this tier, but the organization does not have enough credits. Only operations that bill a charged product category can return this.","headers":{"X-Credits-Required":{"schema":{"type":"integer"},"description":"Credits the request needs; same value as `credits_required` in the body."}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"type":"object","required":["error","credits_required","category"],"properties":{"error":{"type":"string","examples":["Insufficient credits"]},"credits_required":{"type":"integer"},"subscription_credits_available":{"type":"integer","description":"Subscription credits left in the current period."},"prepaid_credits_available":{"type":"integer","description":"Prepaid (overage) credit balance."},"category":{"type":"string","description":"Product category the request was billed against."}}}]}}}}},"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"}},"schemas":{"ErrorResponse":{"type":"object","description":"Error body returned by the endpoints documented here. `error` is a short machine-readable code or message (e.g. `invalid_token`, `Rate limit exceeded`). A few endpoints relay an upstream validation failure verbatim, which uses `detail` instead; treatment endpoints may add `details`. Endpoint-specific 400s may add fields; see each response. Unknown paths and unsupported methods (404/405) return a nested `{\"error\": {\"code\", \"message\", \"hint\"}}` — see llms.txt.","properties":{"error":{"type":"string","description":"Machine-readable error code or short message.","examples":["invalid_token"]},"detail":{"type":"string","description":"Human-readable detail for relayed upstream validation failures."},"details":{"description":"Structured validation details on treatment endpoints."},"credits_required":{"type":"integer","description":"Present with `Insufficient credits` (402); credits needed to complete the request."}},"additionalProperties":true},"FeedbackReason":{"type":"string","description":"Feedback — Structured reason code for negative (or qualified positive) feedback.","enum":["inaccurate","hallucinated","irrelevant","incomplete","outdated","unsafe","formatting","other"]},"FeedbackTarget":{"type":"object","nullable":true,"description":"Feedback — Optional pointers to the specific output element being rated.","properties":{"search_set_id":{"type":"string","description":"UUID of the search set returned by a prior research or search call."},"search_set_result_id":{"type":"string","description":"UUID of a specific search result item within the search set."},"citation_id":{"type":"string","description":"Identifier of a specific citation within a result."},"chat_message_id":{"type":"string","description":"Identifier of a specific chat message in a conversation."},"treatment_record_id":{"type":"string","description":"UUID of a specific treatment record within a treatment records response."}}},"FeedbackSubmitResponse":{"type":"object","description":"Feedback — 201 response body for a successful POST /v1/feedback.","required":["feedback_id","request_id","received_at","warnings"],"properties":{"feedback_id":{"type":"string","format":"uuid","description":"Server-assigned UUID for this feedback record."},"request_id":{"type":"string","format":"uuid","description":"Echo of the `request_id` from the request body."},"received_at":{"type":"string","format":"date-time","description":"ISO-8601 timestamp at which the server received the submission."},"warnings":{"type":"array","items":{"type":"string"},"description":"Non-fatal notices. `comment_truncated` fires when `comment` exceeded 2000 chars and was silently trimmed."}}},"FeedbackItem":{"type":"object","description":"Feedback — A single feedback record returned by GET /v1/feedback. The public response is intentionally minimal: it echoes the identifiers, sentiment, and target so integrators can join back to their own request logs. Comment text, reason codes, and close-workflow state are internal-only and not exposed here.\n","required":["feedback_id","request_id","target","timestamp"],"properties":{"feedback_id":{"type":"string","format":"uuid"},"request_id":{"type":"string","format":"uuid"},"sentiment":{"type":"string","enum":["positive","negative"],"nullable":true},"target":{"$ref":"#/components/schemas/FeedbackTarget"},"timestamp":{"type":"string","format":"date-time","description":"When the feedback was submitted (ISO-8601, Zulu)."}}},"AuthorityReference":{"type":"object","description":"Agentic — A legal authority (case, statute, or regulation) referenced\nby a lens. Items are ordered by relevance; first is most relevant.\n\nCase authorities carry embedded treatment metadata mirroring what our\ninternal renderer sees: a signal badge (`treatment_status`), the total\nrecord count, the top 3 fully-hydrated treatment records, and up to 5\nadditional record UUIDs for records 4–8 that an integrator can hydrate\non demand via `POST /public/v1/treatment/records/incoming` (pagination\nordering matches this list's — call with `treatment_signal_uuid` and\n`page_size=8`, then slice `results[3:8]`). Non-case authorities (laws,\nregulations) always carry null / empty treatment fields.\n","required":["authority_id","citation","title","url","result_type","jurisdiction"],"properties":{"authority_id":{"type":"string","description":"Opaque identifier scoped to this lens; used for cross-reference from `issue_map`, `findings`, and `relevant_legal_text`."},"citation":{"type":"string","description":"Full citation string."},"title":{"type":"string","description":"Display title."},"url":{"type":"string","description":"Direct link to the source document."},"result_type":{"type":"string","enum":["case","law","reg"]},"jurisdiction":{"type":"string","description":"2-letter state code or `FED`."},"treatment_signal_uuid":{"type":"string","format":"uuid","nullable":true,"description":"Aggregated treatment-signal identifier for this authority case. Pivot key for `POST /public/v1/treatment/records/incoming`. `null` when no signal has been computed yet or the authority is a non-case result."},"treatment_status":{"type":"string","nullable":true,"enum":["positive","negative","neutral","no_signal"],"description":"Badge-level treatment status for the authority case. `no_signal` means the case has been scored but no treatment records exist. `null` for non-case authorities."},"total_treatment_records":{"type":"integer","nullable":true,"minimum":0,"description":"Total incoming treatment record count for this authority (not capped at 8). `null` when no signal."},"top_treatment_records":{"type":"array","description":"Up to 3 fully-hydrated treatment records, sorted by `abs(score)` descending — the same top the internal renderer uses. Each record has the same shape returned by `/public/v1/treatment/records/incoming`.","items":{"$ref":"#/components/schemas/TreatmentRecord"}},"remaining_treatment_record_uuids":{"type":"array","description":"Treatment record UUIDs for records 4–8 (up to 5 items) that the integrator can hydrate via `/records/incoming` if they want full detail. Ordering matches — call with `treatment_signal_uuid` and `page_size=8`, then `results[3:8]`. Empty when ≤3 records exist.","items":{"type":"string","format":"uuid"}}}},"LegalFinding":{"type":"object","description":"Agentic — A structured legal finding produced by document review.","required":["finding_id","summary","severity","confidence","status","recommendation","supporting_authority_ids"],"properties":{"finding_id":{"type":"string"},"summary":{"type":"string","description":"Finding text, capped at 280 characters."},"severity":{"type":"string","enum":["critical","high","medium","low","unknown"]},"confidence":{"type":"string","enum":["high","medium","low","unknown"]},"status":{"type":"string","enum":["present","missing","inconsistent","ambiguous","not_applicable","partial"]},"recommendation":{"type":"string","description":"Recommended action, capped at 400 characters."},"supporting_authority_ids":{"type":"array","items":{"type":"string"},"description":"References to `AuthorityReference.authority_id`."}}},"LegalTextExcerpt":{"type":"object","description":"Agentic — A relevant text excerpt from a legal authority.","required":["authority_id","text"],"properties":{"authority_id":{"type":"string","description":"References `AuthorityReference.authority_id`. Citation and URL are joinable from the authority."},"text":{"type":"string","description":"Excerpt text, capped at 500 characters."}}},"ResearchLens":{"type":"object","description":"Agentic — Structured research result from POST /research\n(lens_type: research_lens). Internal IDs, scoring internals, and\nagent-to-agent handoff fields are stripped from the public surface.\n\nEach entry in `authorities` carries embedded treatment metadata for\ncase results (see `AuthorityReference` schema): a signal badge, total\nrecord count, top 3 fully-hydrated treatment records, and up to 5\nadditional record UUIDs for records 4–8. Hydrate records 4–8 via\n`POST /public/v1/treatment/records/incoming` with the parent's\n`treatment_signal_uuid` and `page_size=8` — the response ordering\nmatches this list's, so `results[3:8]` yields records 4–8.\n","required":["lens_type","generated_at","confidence","assumptions","gaps","query","search_set_id","issue_map","authorities","relevant_legal_text"],"properties":{"lens_type":{"type":"string","enum":["research_lens"]},"generated_at":{"type":"string","format":"date-time"},"confidence":{"type":"string","enum":["high","medium","low","unknown"]},"assumptions":{"type":"array","items":{"type":"string"}},"gaps":{"type":"array","items":{"type":"string"}},"query":{"type":"string","description":"Original research query."},"search_set_id":{"type":"string","description":"UUID of the search set that produced this lens's authorities. Empty string when unavailable. Use with the search-set retrieval endpoints to fetch the underlying result rows."},"issue_map":{"type":"array","description":"Issues identified and the authorities addressing each.","items":{"type":"object","required":["issue_id","issue","authority_ids"],"properties":{"issue_id":{"type":"string"},"issue":{"type":"string","description":"Issue text, capped at 280 characters."},"authority_ids":{"type":"array","items":{"type":"string"}}}}},"authorities":{"type":"array","items":{"$ref":"#/components/schemas/AuthorityReference"}},"relevant_legal_text":{"type":"array","items":{"$ref":"#/components/schemas/LegalTextExcerpt"}}}},"ReviewLens":{"type":"object","description":"Agentic — Structured review result from POST /review (lens_type: review_lens). Internal IDs, agent handoff fields, and web-planner-only fields (`issue_matrix`, `legal_triggers`, `constant_ledger`, `reviewed_document_ref`) are stripped from the public surface.","required":["lens_type","generated_at","confidence","assumptions","gaps","review_mode","coverage_status","search_set_id","findings","review_inventory","authorities","relevant_legal_text"],"properties":{"lens_type":{"type":"string","enum":["review_lens"]},"generated_at":{"type":"string","format":"date-time"},"confidence":{"type":"string","enum":["high","medium","low","unknown"]},"assumptions":{"type":"array","items":{"type":"string"}},"gaps":{"type":"array","items":{"type":"string"}},"review_mode":{"type":"string","enum":["succinct","in_depth"]},"coverage_status":{"type":"string","enum":["complete","needs_repair","unknown"]},"search_set_id":{"type":"string","description":"UUID of the search set that produced this lens's authorities (inherited from the upstream research task, when present). Empty string when unavailable."},"findings":{"type":"array","items":{"$ref":"#/components/schemas/LegalFinding"},"description":"Review findings with severity and recommendations."},"review_inventory":{"type":"array","description":"Clause / area-level inventory of concerns.","items":{"type":"object","required":["area_id","concern","severity"],"properties":{"area_id":{"type":"string"},"concern":{"type":"string","description":"Concern text, capped at 280 characters."},"severity":{"type":"string","enum":["critical","high","medium","low","unknown"]}}}},"authorities":{"type":"array","items":{"$ref":"#/components/schemas/AuthorityReference"}},"relevant_legal_text":{"type":"array","items":{"$ref":"#/components/schemas/LegalTextExcerpt"}}}},"ExecutionStartedEvent":{"type":"object","description":"Agentic — Stream begins.","required":["type"],"properties":{"type":{"type":"string","const":"execution_started"},"plan_id":{"type":"string"}}},"TaskStartedEvent":{"type":"object","description":"Agentic — A DAG task is starting.","required":["type"],"properties":{"type":{"type":"string","const":"task_started"},"task_id":{"type":"string"},"task_type":{"type":"string"},"output_visibility":{"type":"string","enum":["internal","child","final"]}}},"TaskProgressEvent":{"type":"object","description":"Agentic — Status update (search activity, thinking).","required":["type"],"properties":{"type":{"type":"string","const":"task_progress"},"task_id":{"type":"string"},"upstream_event":{"type":"object","properties":{"type":{"type":"string","enum":["thinking_delta","search_start","search_end"]},"content":{"type":"string"}}}}},"ResponseDeltaEvent":{"type":"object","description":"Agentic — Text chunk (text mode only).","required":["type"],"properties":{"type":{"type":"string","const":"response_delta"},"content":{"type":"string"}}},"LensReadyEvent":{"type":"object","description":"Agentic — Structured result (lens mode only). Emitted by /research and /review. The /draft endpoint does not emit this event. Dispatch on lens.lens_type for the schema.","required":["type","lens"],"properties":{"type":{"type":"string","const":"lens_ready"},"lens":{"oneOf":[{"$ref":"#/components/schemas/ResearchLens"},{"$ref":"#/components/schemas/ReviewLens"}],"discriminator":{"propertyName":"lens_type"}}}},"TaskCompletedEvent":{"type":"object","description":"Agentic — A DAG task finished.","required":["type"],"properties":{"type":{"type":"string","const":"task_completed"},"task_id":{"type":"string"},"task_type":{"type":"string"},"output_visibility":{"type":"string","enum":["internal","child","final"]}}},"HeartbeatEvent":{"type":"object","description":"Agentic — Keep-alive signal. Filter these in production.","required":["type"],"properties":{"type":{"type":"string","const":"heartbeat"},"timestamp":{"type":"string","format":"date-time"}}},"DoneEvent":{"type":"object","description":"Agentic — Stream finished successfully.","required":["type"],"properties":{"type":{"type":"string","const":"done"},"plan_id":{"type":"string"},"status":{"type":"string"},"usage":{"type":"object","properties":{"category":{"type":"string"},"credits_used":{"type":"integer"}}}}},"StreamErrorEvent":{"type":"object","description":"Agentic — An error occurred during streaming.","required":["type"],"properties":{"type":{"type":"string","const":"error"},"content":{"type":"object","properties":{"message":{"type":"string"}}},"usage":{"type":"object","nullable":true,"properties":{"category":{"type":"string"}}}}},"SearchStreamEvent":{"type":"object","description":"Search — NDJSON event emitted by search streams. Dispatch on the `type` field.","required":["type"],"properties":{"type":{"type":"string","enum":["start","thinking_delta","search_start","search_end","citations_ready","citation_validation_info","confused","error","end"],"description":"Discriminates the event type."},"query":{"type":"string","description":"Present on `start` events. The original query."},"content":{"description":"Varies by event type: string for status events, SearchSet for citations_ready, InfoMessage for citation_validation_info, {message} for error.","oneOf":[{"type":"string"},{"$ref":"#/components/schemas/SearchSet"},{"$ref":"#/components/schemas/InfoMessage"},{"type":"object","properties":{"message":{"type":"string"}}}]}}},"InfoMessage":{"type":"object","description":"Search — Generic in-band informational signal envelope. First use\ncase is per-citation validation info emitted by\n`citation_validation_info` events on a citation search (parse\nconfirmation, eyecite ML fallback used, partial DB match, lookup\nfailure, citation-format hint). The shape is intentionally\ngeneric so the same envelope can carry future non-citation\nsignals (tool timing, search-quality notes, etc.) without\nbreaking the schema. Only `level` and `message` are required;\nthe citation-specific optional fields stay null for non-citation\nuses. Additive — clients that do not recognise the event can\nsafely ignore it.\n","required":["level","message"],"properties":{"level":{"type":"string","enum":["info","warning","error"],"description":"Severity: `info` (benign, e.g. parse confirmation, ML\nfallback used), `warning` (partial database match, no match\nfound, or eyecite resolution warning), `error` (lookup failed).\n"},"message":{"type":"string","description":"Human-readable explanation safe to surface in UI tooltips."},"citation_index":{"type":"integer","minimum":0,"nullable":true,"description":"Citation-specific. 0-based index into the `search_results`\narray of the most recent `citations_ready` event in the same\nstream. `null` for set-level signals or non-citation uses.\n"},"interpreted_citation":{"type":"string","nullable":true,"description":"Citation-specific. The citation as eyecite (deterministic\nparser or ML cascade) interpreted it. Useful when the parsed\nform diverges from the user's raw input (e.g. `42 USC sec 1983`\n→ `42 U.S. 1983`). Populated on every successful parse,\nincluding exact matches, so clients can always show how the\ninput was interpreted. `null` when there is no parsed form to\nsurface or for non-citation uses. All entries for the same\n`citation_index` carry the same `interpreted_citation` value.\n"},"citation_example":{"type":"string","nullable":true,"description":"Citation-specific. A curated Bluebook-format example for the\nparsed reporter (sourced from vendored reporters-db).\nPopulated only on partial-match and no-match branches so the\nUI can show users what a well-formed citation of this\nreporter looks like — helpful when input parsed correctly\nbut the section identifier was mis-formatted (e.g. `:` vs\n`-`). `null` on exact matches, ML-fallback-only info, error\nbranches, and non-citation uses.\n"}}},"SearchSet":{"type":"object","description":"Search — A saved search result set. Returned in `citations_ready` events and GET /search/results/{uuid}.","properties":{"uuid":{"type":"string","format":"uuid","description":"Use with GET /search/results/{uuid} to retrieve later."},"query":{"type":"string"},"title":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"request_id":{"type":"string","nullable":true,"description":"X-Request-Id of the public-api entry-point call that produced this search set. Send this back as `request_id` when submitting feedback on the set or any of its results. Null on legacy rows.\n"},"server_response_duration_ms":{"type":"number","description":"Present on direct search stream `citations_ready` payloads; server-side elapsed milliseconds until results were ready and emitted."},"search_results":{"type":"array","items":{"$ref":"#/components/schemas/SearchSetResult"}},"info_messages":{"type":"array","description":"Per-citation informational signals (ML cascade used, partial\nmatch, lookup failure) attached to this search set. Mirrors the\nstreaming `citation_validation_info` events but bundled with\nthe final SearchSet for clients that consume the snapshot via\n`GET /public/v1/search/results/{uuid}`. Optional — absent or\nempty on clean searches.\n","items":{"$ref":"#/components/schemas/InfoMessage"}}}},"SearchSetResult":{"type":"object","description":"Search — An individual result within a SearchSet. Use uuid with GET /search/results/items/describe/{uuid}.","properties":{"uuid":{"type":"string","format":"uuid","description":"Use with describe endpoint for full details."},"header":{"type":"string","description":"Citation header (e.g. \"40 CFR § 89.112\")."},"citation":{"type":"string","nullable":true,"description":"Clean canonical citation text without markdown. For cases this is the reporter citation; for laws and regulations this is the section citation."},"citation_tag":{"type":"string","description":"Markdown citation with hyperlink."},"url":{"type":"string","format":"uri"},"excerpt":{"type":"string","description":"Relevant text excerpt."},"relevance_score":{"type":"number"},"result_type":{"type":"string","enum":["law","reg","case"]},"first_level_geo":{"type":"string","examples":["USA"]},"second_level_geo":{"type":"string","examples":["FED"]},"court_id":{"type":"string","nullable":true,"description":"Court identifier (cases only)."},"court_name":{"type":"string","nullable":true,"description":"Human-readable court name (cases only)."},"published_date":{"type":"string","nullable":true,"description":"Publication date (cases only)."},"created_at":{"type":"string","format":"date-time"}}},"CaseTextSearchResult":{"type":"object","properties":{"matched_text":{"type":"string","description":"The matched text chunk from the case opinion."},"relevance_score":{"type":"number","format":"float","minimum":0,"maximum":1,"description":"BM25 relevance score normalized to 0-1."}}},"CaseTextSearchResponse":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/CaseTextSearchResult"}}}},"SearchResultDescriptionCase":{"type":"object","properties":{"cases_overruled_distinguished_by_this_case":{"type":"array","description":"List of cases that were overruled or distinguished.","nullable":true,"items":{"type":"string"}},"categories":{"type":"array","description":"Heuristic topical labels for the case.","nullable":true,"items":{"type":"string"}},"context_summary":{"type":"string","description":"High-level summary of what happened procedurally / factually.","nullable":true},"exceptions_created":{"type":"string","description":"Any carve-outs or exceptions this case created.","nullable":true},"additional_highlights":{"type":"string","description":"Which considerations actually drove the holding.","nullable":true},"legal_principle_created_modified":{"type":"string","description":"Core doctrine established or changed.","nullable":true},"legal_test_established":{"type":"string","description":"The test / prongs / standard announced.","nullable":true},"primary_holding":{"type":"string","description":"The main holding in plain English.","nullable":true},"scope_of_application":{"type":"string","description":"Where / when this holding applies.","nullable":true}}},"SearchResultDescriptionLawReg":{"type":"object","properties":{"categories":{"type":"array","description":"Heuristic topical labels for the law/reg text.","nullable":true,"items":{"type":"string"}},"context_summary":{"type":"string","description":"What this law/reg is about and when it matters.","nullable":true},"key_points":{"type":"string","description":"Bullet-style important obligations/thresholds.","nullable":true}}},"SearchResultDescriptionCaseResponse":{"type":"object","required":["type","description"],"properties":{"type":{"type":"string","enum":["case"],"description":"Discriminator telling the client this came from case law."},"description":{"$ref":"#/components/schemas/SearchResultDescriptionCase"},"full_text":{"type":"string","nullable":true,"description":"Full text of the search result when requested with full_text=true."}}},"SearchResultDescriptionLawRegResponse":{"type":"object","required":["type","description"],"properties":{"type":{"type":"string","enum":["law_reg"],"description":"Discriminator telling the client this came from a statute/regulation."},"description":{"$ref":"#/components/schemas/SearchResultDescriptionLawReg"},"full_text":{"type":"string","nullable":true,"description":"Full text of the search result when requested with full_text=true."}}},"TreatmentLabel":{"type":"string","description":"Treatment (Beta Preview) label values accepted by treatment filters and returned on records.","enum":["overruled","abrogated","superseded_by_statute","reversed","remanded","vacated","questioned","criticized","limited","distinguished","declined_to_follow","followed","affirmed","cited","explained"]},"TreatmentPolarity":{"type":"string","description":"Directional treatment grouping.","enum":["positive","negative"]},"TreatmentRecencyUnit":{"type":"string","description":"Unit for a trailing recency window.","enum":["days","months","years"]},"TreatmentRecord":{"type":"object","description":"Treatment (Beta Preview) — A treatment record for a case search result.","required":["uuid","source_document_title","source_document_url","treatment_label","depth","rationale","supporting_text","score","source_authority_display_name","source_authority_identifier","treatment_signal_uuid"],"properties":{"uuid":{"type":"string","format":"uuid","description":"Stable treatment record identifier used by clients for list rendering and pagination state."},"source_document_title":{"type":"string","nullable":true,"description":"Display title for the source document containing this treatment."},"source_document_url":{"type":"string","nullable":true,"description":"Link to the source document, used to open supporting quotes when available."},"treatment_label":{"allOf":[{"$ref":"#/components/schemas/TreatmentLabel"}],"nullable":true},"depth":{"type":"integer","nullable":true,"description":"Discussion depth on a 1-5 scale."},"rationale":{"type":"string","nullable":true},"supporting_text":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Source-document quote or quotes supporting the treatment label."},"score":{"type":"number","nullable":true,"description":"Directional treatment score displayed by the UI."},"source_authority_display_name":{"type":"string","nullable":true},"source_authority_identifier":{"type":"string","nullable":true},"treatment_signal_uuid":{"type":"string","format":"uuid","nullable":true}}},"OutgoingTreatmentSourceCase":{"type":"object","description":"Treatment (Beta Preview) — Source-case header for an outgoing-treatment lookup.","required":["document_uuid","title"],"properties":{"document_uuid":{"type":"string","format":"uuid","description":"Document UUID of the source case whose outgoing treatment is being returned."},"title":{"type":"string","description":"Display title for the source case."},"url":{"type":"string","nullable":true,"description":"Link to the source case, when available."},"date":{"type":"string","format":"date","nullable":true,"description":"Publication date of the source case (ISO YYYY-MM-DD)."},"authority_identifier":{"type":"string","nullable":true,"description":"Machine identifier for the issuing authority (e.g. court identifier)."},"authority_display_name":{"type":"string","nullable":true,"description":"Human-readable authority label (e.g. court name)."}}},"OutgoingTreatmentRecord":{"type":"object","description":"Treatment (Beta Preview) — A single outgoing treatment record between the source case and one of the scoped target documents.","required":["uuid","source_document_uuid","target_document_uuid","treatment_label"],"properties":{"uuid":{"type":"string","format":"uuid","description":"Stable treatment record identifier."},"cited_from_uuid":{"type":"string","format":"uuid","description":"Source document UUID (alias of `source_document_uuid`, retained for compatibility with internal callers)."},"cited_to_uuid":{"type":"string","format":"uuid","description":"Target document UUID (alias of `target_document_uuid`, retained for compatibility with internal callers)."},"source_document_uuid":{"type":"string","format":"uuid","description":"UUID of the source case for this treatment record."},"target_document_uuid":{"type":"string","format":"uuid","description":"UUID of the target document being cited by the source case."},"target_document_title":{"type":"string","nullable":true},"target_document_url":{"type":"string","nullable":true},"target_document_date":{"type":"string","format":"date","nullable":true},"target_authority_identifier":{"type":"string","nullable":true},"target_authority_display_name":{"type":"string","nullable":true},"treatment_label":{"allOf":[{"$ref":"#/components/schemas/TreatmentLabel"}],"nullable":true},"sort_order":{"type":"integer","nullable":true,"description":"Optional display order hint from the upstream treatment signal."},"depth":{"type":"integer","nullable":true,"description":"Discussion depth on a 1-5 scale."},"score":{"type":"number","nullable":true,"description":"Directional treatment score. Positive = affirming, negative = adverse."},"rationale":{"type":"string","nullable":true},"supporting_text":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Source-case quote or quotes supporting the treatment label."},"created_at":{"type":"string","format":"date-time","nullable":true}}},"TreatmentSignalResponse":{"type":"object","required":["uuid","treatment_status","total_treatment_records","explanation","label_counts"],"properties":{"uuid":{"type":"string","format":"uuid"},"treatment_status":{"type":"string"},"total_treatment_records":{"type":"integer"},"explanation":{"type":"string"},"label_counts":{"type":"object","required":["positive","negative","neutral"],"properties":{"positive":{"type":"integer"},"negative":{"type":"integer"},"neutral":{"type":"integer"}}}}},"UploadedFile":{"type":"object","description":"Files — Metadata for an uploaded file. Files expire after 1 hour.","properties":{"id":{"type":"string","description":"File ID. Pass as target_file_id or in attachment_ids to research/review/draft."},"name":{"type":"string","description":"Original filename."},"mime_type":{"type":"string","description":"Detected MIME type."},"size_bytes":{"type":"integer","description":"File size in bytes."},"expires_at":{"type":"string","format":"date-time","description":"When this file will be auto-deleted."},"status":{"type":"string","enum":["uploaded"],"description":"Upload status."}}}}}}