openapi: 3.2.0 info: title: CallidusAI Document API description: Callidus AI backend API version: 0.1.0 tags: - name: Document paths: /document/redlines: post: summary: Optp Redlines operationId: optp_redlines_document_redlines_post requestBody: content: application/x-www-form-urlencoded: schema: $ref: '#/components/schemas/Body_optp_redlines_document_redlines_post' responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' tags: - Document /document/export: post: summary: Optp Export operationId: optp_export_document_export_post requestBody: content: application/x-www-form-urlencoded: schema: $ref: '#/components/schemas/Body_optp_export_document_export_post' responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' tags: - Document /document/upload-url: post: tags: - Document summary: Create Document Upload Url description: 'Return a short-lived SAS URL the client can use to upload a document. Container name follows: storage.get_container_name(user_id), i.e. document- Storage account: filesystembeta (or AZURE_STORAGE_* fallback) Client should upload via HTTP PUT to the returned URL.' operationId: create_document_upload_url_document_upload_url_post responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/CreateUploadUrlResponse' /document/upload-state: post: tags: - Document summary: Get Upload State description: 'What storage already holds for blobs the caller is about to send. A desktop upload interrupted by a closed laptop has two ways of having done work that must not be repeated: a file whose bytes all arrived but whose manifest never did, and a large file staged in blocks partway through. Both questions are reads against blob storage. Answered here rather than by the client so the upload SAS stays write-only. A token that can read is a token that can take a customer''s documents if it leaks, and an interrupted upload is not worth that. This endpoint uses the API''s own credentials and answers only about the caller''s own container -- the path is a blob name within it, so there is nothing to scope wrong. Every failure answers "we do not know", which sends the file. Sending something already there costs a transfer; skipping something that is not costs the document.' operationId: get_upload_state_document_upload_state_post requestBody: content: application/json: schema: $ref: '#/components/schemas/UploadStateRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/UploadStateResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/add-document: post: tags: - Document summary: Add Document description: 'Add document metadata to the user''s document list in the filesystem. If task_id or matter_id is provided but the link fails (e.g. permission or not found), the document is still added and a 200 response is returned; task_linked or matter_linked in the response will be False so the caller can detect and handle the partial failure.' operationId: add_document_document_add_document_post requestBody: content: application/json: schema: $ref: '#/components/schemas/AddDocumentRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/AddDocumentResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' deprecated: true /document/batch-start: post: tags: - Document summary: Batch Start description: 'Declare an upload batch for a dataset task. Creates a DocHubUploadBatch row with no docs enrolled yet. Returns the batch_id for the frontend to pass on each subsequent upload call.' operationId: batch_start_document_batch_start_post requestBody: content: application/json: schema: $ref: '#/components/schemas/BatchStartRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/BatchStartResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/batch-finalize: post: tags: - Document summary: Batch Finalize description: 'Seal an upload batch with the true count of registered docs (ENG-16159). The frontend calls this when its upload loop ends so completion gates on the real manifest size — reconciling any file that failed to upload. Re-checks completion in case every doc already drained before the seal arrived.' operationId: batch_finalize_document_batch_finalize_post requestBody: content: application/json: schema: $ref: '#/components/schemas/BatchFinalizeRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/BatchFinalizeResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/add-documents: post: tags: - Document summary: Add Documents Batch description: 'Batch-register multiple uploaded documents. Each document is registered independently — a failure on one item does not block the others. The response array is in the same order as the request. After registration, all successful documents are bulk-linked to the task/matter in a single operation.' operationId: add_documents_batch_document_add_documents_post requestBody: content: application/json: schema: $ref: '#/components/schemas/BatchAddDocumentsRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/BatchAddDocumentsResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/add-documents-v2: post: tags: - Document summary: Add Documents V2 description: 'Fire-and-forget document registration from a manifest blob (ENG-21063). The frontend uploads files to Azure, writes a JSON manifest listing them, then calls this endpoint. A Temporal workflow handles registration in the background — the user can disconnect immediately.' operationId: add_documents_v2_document_add_documents_v2_post requestBody: content: application/json: schema: $ref: '#/components/schemas/AddDocumentsV2Request' required: true responses: '202': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/AddDocumentsV2Response' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/poll-documents-v2: post: tags: - Document summary: Poll Documents V2 description: 'Poll registration and processing status for a v2 upload batch. Returns aggregate counts by status plus up to 3 sample documents per category for the frontend progress display.' operationId: poll_documents_v2_document_poll_documents_v2_post requestBody: content: application/json: schema: $ref: '#/components/schemas/PollDocumentsV2Request' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/PollDocumentsV2Response' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/cancel-upload-v2: post: tags: - Document summary: Cancel Upload V2 description: 'Cancel all documents in a v2 upload batch. Finds all docs by batch_id, cancels their jobs, unlinks from task/matter, archives them, and cleans up ediscovery state. Reuses the same logic as POST /cancel-upload but operates by batch_id instead of individual doc IDs.' operationId: cancel_upload_v2_document_cancel_upload_v2_post requestBody: content: application/json: schema: $ref: '#/components/schemas/CancelUploadV2Request' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/CancelUploadV2Response' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/batch/{batch_id}/documents: get: tags: - Document summary: Batch Documents description: 'Return paginated document IDs and names for a v2 upload batch. Called by the frontend upload pipeline after poll-documents-v2 reports completion, so it can populate real doc IDs for downstream consumers (task linking, SmartBot, LR intake, etc.).' operationId: batch_documents_document_batch__batch_id__documents_get parameters: - name: batch_id in: path required: true schema: type: string format: uuid title: Batch Id - name: page in: query required: false schema: type: integer minimum: 1 default: 1 title: Page - name: page_size in: query required: false schema: type: integer maximum: 1000 minimum: 1 default: 100 title: Page Size responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/BatchDocumentsResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/get-document-metadata: get: tags: - Document summary: Get Document Metadata description: 'Get document metadata summary for a single document. Allowed if the user is the document owner or has can_view on a matter the document is linked to.' operationId: get_document_metadata_document_get_document_metadata_get parameters: - name: document_id in: query required: true schema: type: string format: uuid title: Document Id responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/GetDocumentResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/poll-documents: post: tags: - Document summary: Poll Documents description: 'Poll document progress by ID. Returns document id, status, size, and percent_complete for documents the user can view (owner or has can_view on a linked matter). Documents not found or not accessible are omitted from the response.' operationId: poll_documents_document_poll_documents_post requestBody: content: application/json: schema: $ref: '#/components/schemas/PollDocumentsRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/PollDocumentsResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/list: get: tags: - Document summary: List Documents description: Paginated, filterable document listing. Replaces list-all-documents. operationId: list_documents_document_list_get parameters: - name: page in: query required: false schema: type: integer minimum: 1 description: 1-indexed page number. default: 1 title: Page description: 1-indexed page number. - name: page_size in: query required: false schema: type: integer maximum: 100 minimum: 1 description: Items per page. default: 25 title: Page Size description: Items per page. - name: view in: query required: false schema: $ref: '#/components/schemas/DocumentListView' description: Tab scope. default: all description: Tab scope. - name: categories in: query required: false schema: type: array items: type: string description: Filter by file_content_type. default: [] title: Categories description: Filter by file_content_type. - name: types in: query required: false schema: type: array items: type: string description: Filter by listing type key (pdf, docx, ...), Folder or Unknown. default: [] title: Types description: Filter by listing type key (pdf, docx, ...), Folder or Unknown. - name: matter_ids in: query required: false schema: type: array items: type: string description: Filter by linked matter IDs. default: [] title: Matter Ids description: Filter by linked matter IDs. - name: module_types in: query required: false schema: type: array items: type: string description: Filter by module type numeric keys. default: [] title: Module Types description: Filter by module type numeric keys. - name: added_by_user_ids in: query required: false schema: type: array items: type: string description: Filter by uploader user IDs. default: [] title: Added By User Ids description: Filter by uploader user IDs. - name: date_from in: query required: false schema: anyOf: - type: string format: date-time - type: 'null' description: Only docs uploaded at or after this instant. title: Date From description: Only docs uploaded at or after this instant. - name: date_to in: query required: false schema: anyOf: - type: string format: date-time - type: 'null' description: Only docs uploaded at or before this instant. title: Date To description: Only docs uploaded at or before this instant. - name: search in: query required: false schema: anyOf: - type: string - type: 'null' description: Case-insensitive text search. title: Search description: Case-insensitive text search. - name: filenames_only in: query required: false schema: type: boolean description: When true, search matches only file names (not matter/task names or content type). default: false title: Filenames Only description: When true, search matches only file names (not matter/task names or content type). - name: sort_by in: query required: false schema: $ref: '#/components/schemas/DocumentSortField' description: Sort field. default: date_added description: Sort field. - name: sort_order in: query required: false schema: $ref: '#/components/schemas/SortOrder' description: Sort direction. default: desc description: Sort direction. - name: target_user_id in: query required: false schema: anyOf: - type: string - type: 'null' description: Enterprise delegation. title: Target User Id description: Enterprise delegation. - name: linked_task_id in: query required: false schema: anyOf: - type: string - type: 'null' description: When provided, each doc includes already_linked_to_task boolean. title: Linked Task Id description: When provided, each doc includes already_linked_to_task boolean. responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/PaginatedDocumentListResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/filter-options: get: tags: - Document summary: Get Filter Options description: Return available filter values with counts for faceted search. operationId: get_filter_options_document_filter_options_get parameters: - name: view in: query required: false schema: $ref: '#/components/schemas/DocumentListView' description: Tab scope. default: all description: Tab scope. - name: categories in: query required: false schema: type: array items: type: string description: Filter by file_content_type. default: [] title: Categories description: Filter by file_content_type. - name: types in: query required: false schema: type: array items: type: string description: Filter by listing type key (pdf, docx, ...), Folder or Unknown. default: [] title: Types description: Filter by listing type key (pdf, docx, ...), Folder or Unknown. - name: matter_ids in: query required: false schema: type: array items: type: string description: Filter by linked matter IDs. default: [] title: Matter Ids description: Filter by linked matter IDs. - name: module_types in: query required: false schema: type: array items: type: string description: Filter by module type numeric keys. default: [] title: Module Types description: Filter by module type numeric keys. - name: added_by_user_ids in: query required: false schema: type: array items: type: string description: Filter by uploader user IDs. default: [] title: Added By User Ids description: Filter by uploader user IDs. - name: date_from in: query required: false schema: anyOf: - type: string format: date-time - type: 'null' description: Only docs uploaded at or after this instant. title: Date From description: Only docs uploaded at or after this instant. - name: date_to in: query required: false schema: anyOf: - type: string format: date-time - type: 'null' description: Only docs uploaded at or before this instant. title: Date To description: Only docs uploaded at or before this instant. - name: search in: query required: false schema: anyOf: - type: string - type: 'null' description: Case-insensitive text search. title: Search description: Case-insensitive text search. - name: target_user_id in: query required: false schema: anyOf: - type: string - type: 'null' description: Enterprise delegation. title: Target User Id description: Enterprise delegation. - name: dochub_only in: query required: false schema: type: boolean description: Scope to user's own docs only (DocHub folder listing context). Bypasses the 3-way UNION. default: false title: Dochub Only description: Scope to user's own docs only (DocHub folder listing context). Bypasses the 3-way UNION. - name: include_folders in: query required: false schema: type: boolean description: 'Prepend ''Folder'' to the Type options, counting the folders in the browsed tree. Only the folder browser should set this: the flat /document/list has no folder rows.' default: false title: Include Folders description: 'Prepend ''Folder'' to the Type options, counting the folders in the browsed tree. Only the folder browser should set this: the flat /document/list has no folder rows.' - name: folder_matter_id in: query required: false schema: anyOf: - type: string - type: 'null' description: With include_folders, count the folders of this matter's tree instead of the caller's DocHub tree. Same semantics as matter_id on GET /document/folders. title: Folder Matter Id description: With include_folders, count the folders of this matter's tree instead of the caller's DocHub tree. Same semantics as matter_id on GET /document/folders. responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/DocumentFilterOptionsResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/list-all-documents: get: tags: - Document summary: List All Documents description: 'List all documents the user can access. Includes: - Documents the user owns (doc_metadata.user_id == user_id) - Documents linked to matters the user can access (via matter_docs) - Documents linked to tasks the user can access (via task_docs)' operationId: list_all_documents_document_list_all_documents_get deprecated: true parameters: - name: target_user_id in: query required: false schema: anyOf: - type: string - type: 'null' description: Optional target user id. If omitted, defaults to the authenticated user. title: Target User Id description: Optional target user id. If omitted, defaults to the authenticated user. - name: limit in: query required: false schema: type: integer maximum: 5000 minimum: 1 description: Max number of documents to return. default: 5000 title: Limit description: Max number of documents to return. - name: offset in: query required: false schema: type: integer minimum: 0 description: Number of documents to skip for pagination. default: 0 title: Offset description: Number of documents to skip for pagination. responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/ListDocumentsResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/get-documents-by-task: get: tags: - Document summary: Get Documents By Task description: 'Get all documents associated with a task (Conversation). Requires can_view on the task. ``FAILED_NO_RETRY`` docs are filtered out by default; pass ``include_failed_no_retry=true`` when the caller needs to surface per-file failure reasons in the UI (e.g. Case Timeline "Analysis skipped" state — ENG-11670). Optional ``limit``/``offset`` enable pagination. When ``limit`` is set the response includes ``total_count`` for paging controls; when omitted the full list is returned (backward-compatible default). Optional ``search``, ``categories``, ``module_types``, ``exclude_ids``, ``sort_by``, and ``sort_order`` mirror the ``/list`` endpoint filters.' operationId: get_documents_by_task_document_get_documents_by_task_get parameters: - name: task_id in: query required: true schema: type: string title: Task Id - name: include_failed_no_retry in: query required: false schema: type: boolean default: false title: Include Failed No Retry - name: limit in: query required: false schema: anyOf: - type: integer minimum: 1 - type: 'null' description: Max documents to return (omit for all) title: Limit description: Max documents to return (omit for all) - name: offset in: query required: false schema: anyOf: - type: integer minimum: 0 - type: 'null' description: Number of documents to skip (requires limit) title: Offset description: Number of documents to skip (requires limit) - name: search in: query required: false schema: anyOf: - type: string - type: 'null' description: Case-insensitive text search on file name. title: Search description: Case-insensitive text search on file name. - name: categories in: query required: false schema: type: array items: type: string description: Filter by file_content_type. default: [] title: Categories description: Filter by file_content_type. - name: module_types in: query required: false schema: type: array items: type: string description: Filter by module type. default: [] title: Module Types description: Filter by module type. - name: exclude_ids in: query required: false schema: type: array items: type: string description: Exclude specific document IDs. default: [] title: Exclude Ids description: Exclude specific document IDs. - name: source in: query required: false schema: anyOf: - enum: - user - strongsuit type: string - type: 'null' description: Filter by document source. title: Source description: Filter by document source. - name: sort_by in: query required: false schema: $ref: '#/components/schemas/DocumentSortField' description: Sort field. default: date_added description: Sort field. - name: sort_order in: query required: false schema: $ref: '#/components/schemas/SortOrder' description: 'Sort direction: asc or desc.' default: desc description: 'Sort direction: asc or desc.' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/ListDocumentsResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/get-documents-by-matter: get: tags: - Document summary: Get Documents By Matter description: 'Get all documents associated with a matter. Requires can_view on the matter. Optional ``limit``/``offset`` enable pagination. When ``limit`` is set the response includes ``total_count`` for paging controls; when omitted the full list is returned (backward-compatible default). Optional ``search``, ``categories``, ``module_types``, ``exclude_ids``, ``sort_by``, and ``sort_order`` mirror the ``/list`` endpoint filters. When ``linked_task_id`` is provided, each document in the response carries ``already_linked_to_task=True/False`` so the caller can grey out files the task already references (replaces the unbounded ``useDocumentsByTask`` fetch on the frontend — ENG-22493).' operationId: get_documents_by_matter_document_get_documents_by_matter_get parameters: - name: matter_id in: query required: true schema: type: string title: Matter Id - name: limit in: query required: false schema: anyOf: - type: integer minimum: 1 - type: 'null' description: Max documents to return (omit for all) title: Limit description: Max documents to return (omit for all) - name: offset in: query required: false schema: anyOf: - type: integer minimum: 0 - type: 'null' description: Number of documents to skip (requires limit) title: Offset description: Number of documents to skip (requires limit) - name: search in: query required: false schema: anyOf: - type: string - type: 'null' description: Case-insensitive text search on file name. title: Search description: Case-insensitive text search on file name. - name: categories in: query required: false schema: type: array items: type: string description: Filter by file_content_type. default: [] title: Categories description: Filter by file_content_type. - name: module_types in: query required: false schema: type: array items: type: string description: Filter by module type. default: [] title: Module Types description: Filter by module type. - name: exclude_ids in: query required: false schema: type: array items: type: string description: Exclude specific document IDs. default: [] title: Exclude Ids description: Exclude specific document IDs. - name: source in: query required: false schema: anyOf: - enum: - user - strongsuit type: string - type: 'null' description: Filter by document source. title: Source description: Filter by document source. - name: sort_by in: query required: false schema: $ref: '#/components/schemas/DocumentSortField' description: Sort field. default: date_added description: Sort field. - name: sort_order in: query required: false schema: $ref: '#/components/schemas/SortOrder' description: 'Sort direction: asc or desc.' default: desc description: 'Sort direction: asc or desc.' - name: linked_task_id in: query required: false schema: anyOf: - type: string - type: 'null' description: When provided, each doc includes already_linked_to_task boolean. title: Linked Task Id description: When provided, each doc includes already_linked_to_task boolean. responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/ListDocumentsResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/add-to-matter: post: tags: - Document summary: Add Document To Matter description: Associate a document with a matter. Requires can_view on the document and can_edit on the matter. operationId: add_document_to_matter_document_add_to_matter_post requestBody: content: application/json: schema: $ref: '#/components/schemas/AddDocumentToMatterRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/AddDocumentToMatterResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/add-documents-to-matter: post: tags: - Document summary: Add Documents To Matter description: Associate multiple documents with a matter in one call. Single DB write via bulk INSERT. operationId: add_documents_to_matter_document_add_documents_to_matter_post requestBody: content: application/json: schema: $ref: '#/components/schemas/AddDocumentsToMatterRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/AddDocumentsToMatterResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/add-to-task: post: tags: - Document summary: Add Document To Task description: Associate a document with a task (Conversation). Requires can_view on the document and can_edit on the task. operationId: add_document_to_task_document_add_to_task_post requestBody: content: application/json: schema: $ref: '#/components/schemas/AddDocumentToTaskRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/AddDocumentToTaskResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/add-documents-to-task: post: tags: - Document summary: Add Documents To Task description: Associate multiple documents with a task in one call. Resolves the conversation once. operationId: add_documents_to_task_document_add_documents_to_task_post requestBody: content: application/json: schema: $ref: '#/components/schemas/AddDocumentsToTaskRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/AddDocumentsToTaskResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/add-folders-to-task: post: tags: - Document summary: Add Folders To Task description: 'Link every file under the given folders (and any loose docs) to a task. Expands folder ids in SQL so the client does not page listings. Folder tree scope comes from body.matter_id via ``_authorize_folder_scope`` (omit = DocHub), not from conversation.matter_id — the picker on All Files always sends DocHub ids even when the task is matter-linked (ENG-22548). Requires edit on the task (and the conversation''s matter when it has one). ENG-22527. Set return_doc_ids to include the expanded id list (ENG-22548); default is counts only.' operationId: add_folders_to_task_document_add_folders_to_task_post requestBody: content: application/json: schema: $ref: '#/components/schemas/AddFoldersToTaskRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/AddFoldersToTaskResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/remove-from-task: post: tags: - Document summary: Remove Document From Task description: Remove the association between a document and a task (Conversation). Requires can_edit on both the document and the task. operationId: remove_document_from_task_document_remove_from_task_post requestBody: content: application/json: schema: $ref: '#/components/schemas/RemoveDocumentFromTaskRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/DocumentLinkResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/remove-from-matter: post: tags: - Document summary: Remove Document From Matter description: Remove the association between a document and a matter. Requires can_edit on both the document and the matter. operationId: remove_document_from_matter_document_remove_from_matter_post requestBody: content: application/json: schema: $ref: '#/components/schemas/RemoveDocumentFromMatterRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/DocumentLinkResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/delete-document: post: tags: - Document summary: Delete Document description: 'Hard-delete a document. Only the document owner can perform this action. Removes the doc_metadata row (and join rows), the Azure blob (main file + manifest), and pgvector nodes for the document. No tombstone is left behind — the document is gone after this call.' operationId: delete_document_document_delete_document_post requestBody: content: application/json: schema: $ref: '#/components/schemas/DeleteDocumentRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/DocumentLinkResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/delete-documents: post: tags: - Document summary: Delete Documents description: 'Tombstone a batch of the caller''s documents and kick the durable background purge (ENG-17809). Accepts ``folder_ids`` (resolved server-side to all files in the subtree) and/or loose ``document_ids``. Returns immediately: eligible docs flip to ``deleting`` (they disappear from all listings at once) and a Temporal workflow purges them — blobs, vectors, DB rows — in the background, resumable across worker restarts. Non-owned/missing docs, and archives still being extracted (ENG-22114), are reported in ``failed``. Progress is available via ``GET /delete-status``.' operationId: delete_documents_document_delete_documents_post requestBody: content: application/json: schema: $ref: '#/components/schemas/DeleteDocumentsRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/DeleteDocumentsResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/delete-status: get: tags: - Document summary: Delete Status description: 'Return ``{pending, failed}`` for the caller''s background deletes (ENG-17809). Sourced entirely from the ``delete_state`` count — no Temporal query. Strictly scoped to the caller''s own docs (``user_id``); ``matter_id`` only narrows within that set, so no cross-user data is exposed.' operationId: delete_status_document_delete_status_get parameters: - name: matter_id in: query required: false schema: anyOf: - type: string - type: 'null' description: Narrow counts to one matter's docs. title: Matter Id description: Narrow counts to one matter's docs. responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/DeleteStatusResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/processing-status: get: tags: - Document summary: Processing Status description: 'Scope-wide in-flight ingestion counts for the Doc Hub processing banner. The folder listing only describes one page, so the banner built on it cannot see a zip extracting into a subfolder. This is the same scope and visibility as the folder tree, authorised the same way, so the banner and the rows always agree. The banner polls counts only; the file list is requested while its dialog is open.' operationId: processing_status_document_processing_status_get parameters: - name: matter_id in: query required: false schema: anyOf: - type: string - type: 'null' description: Count one matter's docs instead of the caller's Doc Hub. title: Matter Id description: Count one matter's docs instead of the caller's Doc Hub. - name: include_files in: query required: false schema: type: boolean description: Also return the in-flight documents (newest first, capped) with their folders. Resolving folders loads the scope's directory tree, so request this while a file list is open, not on the banner's poll interval. default: false title: Include Files description: Also return the in-flight documents (newest first, capped) with their folders. Resolving folders loads the scope's directory tree, so request this while a file list is open, not on the banner's poll interval. responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/ProcessingStatusResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/deletion-impact: post: tags: - Document summary: Deletion Impact description: 'Read-only preview of a delete: the distinct files affected and the matters they''re linked to. Mutates nothing. Folders resolve recursively (whole subtree); loose ``document_ids`` union in; the count is deduped across multi-placements. ``matters`` is the union across all affected files — so the UI can warn ''deleting these also removes N files from these matters''. Same scope/ownership checks as the delete endpoints (edit-on-matter for matter scope; the caller''s own tree for DocHub).' operationId: deletion_impact_document_deletion_impact_post requestBody: content: application/json: schema: $ref: '#/components/schemas/DeletionImpactRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/DeletionImpactResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/select-all-shared-count: post: tags: - Document summary: Select All Shared Count description: 'Read-only: how many files a DocHub select-all shows that a delete would skip (ENG-23079). ``delete-documents`` with ``select_all`` resolves to the caller''s own docs only, so files shared in via a matter would silently survive; the confirm dialog asks this first and blocks instead. Mutates nothing. Scoped to the caller by construction: it counts only docs in matters the caller can already access. Shared docs appear only at the DocHub root, so a select-all taken inside a folder contains none.' operationId: select_all_shared_count_document_select_all_shared_count_post requestBody: content: application/json: schema: $ref: '#/components/schemas/SelectAllSharedCountRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/SelectAllSharedCountResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/cancel-upload: post: tags: - Document summary: Cancel Upload description: 'Cancel in-flight document uploads. The three upload flows map to different parameter combos: 1. ``(matter=None, task=None)`` — standalone upload. 2. ``(matter, task=None)`` — matter-scoped: unlinks from that matter. 3. ``(matter=None, task)`` — task-scoped: unlinks from the task.' operationId: cancel_upload_document_cancel_upload_post requestBody: content: application/json: schema: $ref: '#/components/schemas/CancelUploadRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/CancelUploadResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/rename-document: post: tags: - Document summary: Rename Document description: Rename a document's display name. Does not affect the blob in Azure Storage. operationId: rename_document_document_rename_document_post requestBody: content: application/json: schema: $ref: '#/components/schemas/RenameDocumentRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/RenameDocumentResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/check-duplicates: post: tags: - Document summary: Check Duplicates operationId: check_duplicates_document_check_duplicates_post requestBody: content: application/json: schema: $ref: '#/components/schemas/CheckDuplicatesRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/CheckDuplicatesResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/create-alias: post: tags: - Document summary: Create Alias description: 'Hardwire a symlink alias for content already in DocHub — no blob upload (ENG-17767). Send this when /check-duplicates returned action=''alias'': the bytes are already stored under a canonical, so we create a named alias record pointing at it (no Azure transfer, no ingestion) and link it to a task/matter exactly like /add-document. Returns 409 if no canonical exists for the hash (a race, e.g. the canonical was deleted) — the client should upload the file instead.' operationId: create_alias_document_create_alias_post requestBody: content: application/json: schema: $ref: '#/components/schemas/CreateAliasRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/AddDocumentResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/generated-docs-by-tasks: get: tags: - Document summary: Get Generated Docs By Tasks description: 'Map each task id → newest generated ``.docx`` document id owned by the user. AI-generated outputs (e.g. agent-drafted contracts) are linked to their task via the ``generated_by_task_id`` column, so this lets the Draft Contracts table make those contracts downloadable by document id. Only the caller''s own docs.' operationId: get_generated_docs_by_tasks_document_generated_docs_by_tasks_get parameters: - name: task_ids in: query required: true schema: type: string description: Comma-separated task/conversation ids title: Task Ids description: Comma-separated task/conversation ids responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/GeneratedDocsByTasksResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/get-download-url: get: tags: - Document summary: Get Full Document Url description: 'Return a short-lived SAS URL for the document''s blob. Uses the document''s metadata (storage_account_alias, storage_container, location) to resolve where the file actually is, then generates a blob-level read SAS.' operationId: get_full_document_url_document_get_download_url_get parameters: - name: document_id in: query required: true schema: type: string format: uuid description: UUID of the document to access title: Document Id description: UUID of the document to access responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/GetDownloadURLResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/admin-download-url: get: tags: - Document summary: Admin Get Document Download Url description: Return a SAS URL when the caller has an internal admin role and the doc belongs to ``target_user_id``. operationId: admin_get_document_download_url_document_admin_download_url_get parameters: - name: document_id in: query required: true schema: type: string format: uuid description: Document UUID title: Document Id description: Document UUID - name: target_user_id in: query required: true schema: type: string description: Doc owner user id (must match document) title: Target User Id description: Doc owner user id (must match document) responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/GetDownloadURLResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/admin/failed-docs: get: tags: - Document summary: Admin List Failed Docs description: List FAILED_NO_RETRY DocHub files for a customer. Internal admin only. operationId: admin_list_failed_docs_document_admin_failed_docs_get parameters: - name: target_user_id in: query required: false schema: anyOf: - type: string - type: 'null' description: Customer user id title: Target User Id description: Customer user id - name: email in: query required: false schema: anyOf: - type: string - type: 'null' description: Customer email (case-insensitive) title: Email description: Customer email (case-insensitive) - name: limit in: query required: false schema: type: integer maximum: 500 minimum: 1 default: 500 title: Limit responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/AdminFailedIngestListResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/admin/upload-summary: get: tags: - Document summary: Admin Upload Summary description: Count a customer's uploads by status over a window. Internal admin only. operationId: admin_upload_summary_document_admin_upload_summary_get parameters: - name: since in: query required: true schema: type: string format: date-time description: Window start, inclusive. title: Since description: Window start, inclusive. - name: until in: query required: true schema: type: string format: date-time description: Window end, exclusive. title: Until description: Window end, exclusive. - name: target_user_id in: query required: false schema: anyOf: - type: string - type: 'null' description: Customer user id title: Target User Id description: Customer user id - name: email in: query required: false schema: anyOf: - type: string - type: 'null' description: Customer email (case-insensitive) title: Email description: Customer email (case-insensitive) responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/AdminUploadSummaryResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/admin/ingest-health: get: tags: - Document summary: Admin Ingest Health description: 'Platform-wide Doc Hub ingestion health. Internal admin only. Polled by the utility service''s ingestion monitor. Unlike ``/admin/upload-summary``, which answers "what happened to this customer''s files", this answers "is ingestion healthy for everyone" — success rate, throughput, failure causes, queue wait and per-account slot concentration. Every field maps to a distinct 2026-09-23 failure mode; see ``admin_ingest_health`` for why each one is here.' operationId: admin_ingest_health_document_admin_ingest_health_get parameters: - name: window_minutes in: query required: false schema: type: integer maximum: 360 minimum: 1 description: Look-back window. default: 15 title: Window Minutes description: Look-back window. responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/AdminIngestHealthResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/admin/requeue-docs: post: tags: - Document summary: Admin Requeue Failed Docs description: Reset retryable FAILED_NO_RETRY docs and queue StandardIngestionFlow jobs. Internal admin only. operationId: admin_requeue_failed_docs_document_admin_requeue_docs_post requestBody: content: application/json: schema: $ref: '#/components/schemas/AdminFailedIngestRequeueRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/AdminFailedIngestRequeueResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/admin/download-urls: post: tags: - Document summary: Admin Mint Failed Doc Download Urls description: Mint short-lived SAS URLs for customer docs (inspect failed uploads). Internal admin only. operationId: admin_mint_failed_doc_download_urls_document_admin_download_urls_post requestBody: content: application/json: schema: $ref: '#/components/schemas/AdminFailedIngestDownloadRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/AdminFailedIngestDownloadResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/export-matter-documents: post: tags: - Document summary: Export Matter Documents description: Kick off a Temporal workflow to zip all matter documents and return a download URL. operationId: export_matter_documents_document_export_matter_documents_post parameters: - name: matter_id in: query required: true schema: type: string description: Matter ID to export documents for title: Matter Id description: Matter ID to export documents for responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/ExportDocumentsResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/export-status/{workflow_id}: get: tags: - Document summary: Get Export Status description: 'Poll the status of a document export workflow. The workflow_id must belong to the requesting user (embedded in the ID by convention).' operationId: get_export_status_document_export_status__workflow_id__get parameters: - name: workflow_id in: path required: true schema: type: string title: Workflow Id responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/ExportStatusResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/view-document: get: tags: - Document summary: View Document description: 'Return a short-lived SAS URL for the document''s blob. Uses the document''s metadata (storage_account_alias, storage_container, location) to resolve where the file actually is, then generates a blob-level read SAS.' operationId: view_document_document_view_document_get parameters: - name: document_id in: query required: true schema: type: string format: uuid description: UUID of the document to access title: Document Id description: UUID of the document to access responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/ViewDocumentResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/clear-docs: post: tags: - Document summary: Clear Docs description: 'Hard-delete documents matching the given names owned by the authenticated user, and all associated data. Restricted to user with email CLEAR_DOCS_ALLOWED_EMAIL (see top of file). Deletes: Azure blobs (main file + manifest), vector nodes in db_collections (filesystem_{user_id}), then doc_hub_jobs, doc_processing_audit, task_docs, matter_docs, doc_metadata.' operationId: clear_docs_document_clear_docs_post requestBody: content: application/json: schema: $ref: '#/components/schemas/ClearDocsRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/ClearDocsResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/credits: get: tags: - Document summary: Get Document Credits description: 'Return credits used for document processing. Default: current calendar month for the authenticated user. ``since``: optional ISO lower bound (inclusive) through now (Doc Hub audit rows only). Validated to the same **730-day** lookback as other ``since`` credit queries. ``target_user_id``: admin-only; same role gate as ``GET /platform/credits/used``.' operationId: get_document_credits_document_credits_get parameters: - name: target_user_id in: query required: false schema: anyOf: - type: string - type: 'null' title: Target User Id - name: since in: query required: false schema: anyOf: - type: string - type: 'null' title: Since responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/DocumentCreditsResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/estimate: post: tags: - Document summary: Estimate Document Processing description: 'Estimate processing credits for a list of documents before upload. Accepts file metadata (name, size, optional page count) and returns a per-document and aggregate credit estimate, plus the budget verdict. Pass the files the user picked — not the transport archives they will be bundled into — and honour ``would_exceed_budget``: it is computed exactly as the registration gate computes it, so a client that blocks on it never uploads a batch that will be refused afterwards.' operationId: estimate_document_processing_document_estimate_post requestBody: content: application/json: schema: $ref: '#/components/schemas/DocumentEstimateRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/DocumentEstimateResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/estimate/tokens: post: tags: - Document summary: Estimate Document Processing From Tokens description: 'Price documents the client has already read and tokenized (the desktop uploader). The bytes-and-type estimate above guesses at text from file size; this one is handed the text token count and the number of pages that will need OCR, and only turns them into credits. Model rates, the per-OCR-page figure and rounding stay here so a price change is one edit. Same response shape and the same budget verdict as ``/estimate``.' operationId: estimate_document_processing_from_tokens_document_estimate_tokens_post requestBody: content: application/json: schema: $ref: '#/components/schemas/DocumentTokenEstimateRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/DocumentEstimateResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/folders: post: tags: - Document summary: Create Folder Endpoint operationId: create_folder_endpoint_document_folders_post requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateFolderRequest' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/FolderResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' get: tags: - Document summary: List Folders Endpoint operationId: list_folders_endpoint_document_folders_get parameters: - name: matter_id in: query required: false schema: anyOf: - type: string - type: 'null' title: Matter Id - name: folder_id in: query required: false schema: anyOf: - type: string format: uuid - type: 'null' title: Folder Id - name: search in: query required: false schema: anyOf: - type: string - type: 'null' description: Text search over the current folder's subtree. title: Search description: Text search over the current folder's subtree. - name: categories in: query required: false schema: type: array items: type: string description: Filter by file_content_type. default: [] title: Categories description: Filter by file_content_type. - name: types in: query required: false schema: type: array items: type: string description: Filter by listing type key (pdf, docx, ...), Folder or Unknown. default: [] title: Types description: Filter by listing type key (pdf, docx, ...), Folder or Unknown. - name: matter_ids in: query required: false schema: type: array items: type: string description: Filter by linked matter IDs. default: [] title: Matter Ids description: Filter by linked matter IDs. - name: module_types in: query required: false schema: type: array items: type: string description: Filter by module type numeric keys. default: [] title: Module Types description: Filter by module type numeric keys. - name: added_by_user_ids in: query required: false schema: type: array items: type: string description: Filter by uploader user IDs. default: [] title: Added By User Ids description: Filter by uploader user IDs. - name: date_from in: query required: false schema: anyOf: - type: string format: date-time - type: 'null' description: Only docs uploaded at or after this instant. title: Date From description: Only docs uploaded at or after this instant. - name: date_to in: query required: false schema: anyOf: - type: string format: date-time - type: 'null' description: Only docs uploaded at or before this instant. title: Date To description: Only docs uploaded at or before this instant. - name: view in: query required: false schema: $ref: '#/components/schemas/DocumentListView' description: View tab scope (all, strongsuit, unassigned, matter_files). default: all description: View tab scope (all, strongsuit, unassigned, matter_files). - name: search_scope in: query required: false schema: $ref: '#/components/schemas/SearchScope' description: 'How far a search/filter query reaches: subtree (default) matches at and below folder_id, current matches only what sits directly at folder_id. No effect outside query mode.' default: subtree description: 'How far a search/filter query reaches: subtree (default) matches at and below folder_id, current matches only what sits directly at folder_id. No effect outside query mode.' - name: cursor in: query required: false schema: anyOf: - type: string - type: 'null' description: Opaque cursor from a previous page's next_cursor. Mutually exclusive with page. Forward-only navigation; backward = reset cursor to null. title: Cursor description: Opaque cursor from a previous page's next_cursor. Mutually exclusive with page. Forward-only navigation; backward = reset cursor to null. - name: page in: query required: false schema: type: integer minimum: 1 description: 1-indexed page over the combined folders-then-files sequence. Ignored when cursor is provided. default: 1 title: Page description: 1-indexed page over the combined folders-then-files sequence. Ignored when cursor is provided. - name: page_size in: query required: false schema: type: integer maximum: 200 minimum: 1 description: Items per page, counting folders and files together. default: 100 title: Page Size description: Items per page, counting folders and files together. - name: sort_by in: query required: false schema: $ref: '#/components/schemas/FolderSortField' description: Sort field. default: date_added description: Sort field. - name: sort_order in: query required: false schema: $ref: '#/components/schemas/SortOrder' description: Sort direction. default: desc description: Sort direction. responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/FolderListingResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/folders/{folder_id}: patch: tags: - Document summary: Rename Folder Endpoint operationId: rename_folder_endpoint_document_folders__folder_id__patch parameters: - name: folder_id in: path required: true schema: type: string format: uuid title: Folder Id requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/RenameFolderRequest' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/FolderResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' delete: tags: - Document summary: Delete Folder Endpoint description: 'Delete a folder and cascade its contents. Matter: un-associate the subtree''s docs from the matter (docs survive in DocHub). DocHub: tombstone files whose only home is the subtree (they vanish from listings immediately) and purge them in the background via BulkDeleteWorkflow — restart-safe and non-blocking even for folders with thousands of files; files also filed elsewhere are untagged. Empty folders just drop the row. ``prune_empty_folders`` additionally clears the folders this delete left empty — the deleted folder''s ancestor chain, plus the matter folders its files vacated — never unrelated empty folders elsewhere in the scope (ENG-21711). Matter scope prunes inline (synchronous); DocHub scope prunes after the background purge drains (so it can''t race the async doc removal). The UI should confirm against the listing''s `total_file_count` first. Requires edit on the scope.' operationId: delete_folder_endpoint_document_folders__folder_id__delete parameters: - name: folder_id in: path required: true schema: type: string format: uuid title: Folder Id - name: matter_id in: query required: false schema: anyOf: - type: string - type: 'null' title: Matter Id - name: prune_empty_folders in: query required: false schema: type: boolean description: Also delete the deleted folder's ancestors if this delete left them with no files. default: false title: Prune Empty Folders description: Also delete the deleted folder's ancestors if this delete left them with no files. responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/DeleteFolderResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/folders/{folder_id}/move: post: tags: - Document summary: Move Folder Endpoint operationId: move_folder_endpoint_document_folders__folder_id__move_post parameters: - name: folder_id in: path required: true schema: type: string format: uuid title: Folder Id requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MoveFolderRequest' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/FolderResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/folder-tree: get: tags: - Document summary: Folder Tree Endpoint description: 'All folders in the scope as a flat list — no files, no counts, no pagination. Designed for the folder-picker dialog ("Move to", "Add to folder") where only the tree shape and names matter. Loads in one lightweight query regardless of how many files the scope contains.' operationId: folder_tree_endpoint_document_folder_tree_get parameters: - name: matter_id in: query required: false schema: anyOf: - type: string - type: 'null' title: Matter Id responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/FolderTreeResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/move-document-to-folder: post: tags: - Document summary: Move Document Endpoint description: 'Move a document''s placement between folders (target/source null = root). Requires edit on the scope (matter or the caller''s DocHub) and view on the doc (a user may file a shared-in doc into their own DocHub tree).' operationId: move_document_endpoint_document_move_document_to_folder_post requestBody: content: application/json: schema: $ref: '#/components/schemas/MoveDocumentRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/DocumentLinkResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/move-documents-to-folder: post: tags: - Document summary: Move Documents Endpoint description: 'Bulk-move N documents into a folder (target/source null = root) in one transaction. Requires edit on the scope (matter, or the caller''s own DocHub). Matter moves only affect docs linked to the matter; DocHub moves relocate the source placement and preserve each doc''s other tags.' operationId: move_documents_endpoint_document_move_documents_to_folder_post requestBody: content: application/json: schema: $ref: '#/components/schemas/MoveDocumentsRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/MoveDocumentsResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/move-items-to-folder: post: tags: - Document summary: Move Items Endpoint description: 'Move a mixed selection of folders and files one level to another (target null = root). Anything that would collide is refused and reported in ``skipped`` with a reason; the rest of the selection moves. Nothing is ever overwritten, merged, deleted, or unlinked by a move. Set ``move_all_at_source`` to move an entire level without enumerating it — required when the level is bigger than one page, since a paged client only holds the ids it has rendered.' operationId: move_items_endpoint_document_move_items_to_folder_post requestBody: content: application/json: schema: $ref: '#/components/schemas/MoveItemsRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/MoveItemsResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/move-items-to-folder/preflight: post: tags: - Document summary: Move Items Preflight Endpoint description: 'Report what a move would skip, changing nothing. Advisory only: the destination can change between this call and the move, so the move re-validates independently rather than trusting this result. ``moved_*`` counts are 0 here by construction — read ``skipped`` and subtract.' operationId: move_items_preflight_endpoint_document_move_items_to_folder_preflight_post requestBody: content: application/json: schema: $ref: '#/components/schemas/MoveItemsRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/MoveItemsResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/add-folders-to-matter: post: tags: - Document summary: Add Folders To Matter Endpoint description: 'Add selected DocHub folders (and loose files) to a matter, mirroring the folder subtree under the matter''s current folder. Requires edit on the matter + view on each loose doc; folder-sourced docs are the caller''s own DocHub files.' operationId: add_folders_to_matter_endpoint_document_add_folders_to_matter_post requestBody: content: application/json: schema: $ref: '#/components/schemas/AddFoldersToMatterRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/AddFoldersToMatterResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /document/remove-folders-from-matter: post: tags: - Document summary: Remove Folders From Matter Endpoint description: 'Remove selected matter folders (and loose files) from a matter: un-associate every contained doc (recursively) and drop the emptied folder nodes. Docs stay in DocHub. Requires edit on the matter.' operationId: remove_folders_from_matter_endpoint_document_remove_folders_from_matter_post requestBody: content: application/json: schema: $ref: '#/components/schemas/RemoveFoldersFromMatterRequest' required: true responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/RemoveFoldersFromMatterResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' components: schemas: Body_optp_export_document_export_post: properties: file_content_base: anyOf: - type: string - type: 'null' title: File Content Base file_content_new: anyOf: - type: string - type: 'null' title: File Content New file_type: anyOf: - type: string - type: 'null' title: File Type module_name: anyOf: - type: string - type: 'null' title: Module Name type: object title: Body_optp_export_document_export_post ValidationError: properties: loc: items: anyOf: - type: string - type: integer type: array title: Location msg: type: string title: Message type: type: string title: Error Type input: title: Input ctx: type: object title: Context type: object required: - loc - msg - type title: ValidationError HTTPValidationError: properties: detail: items: $ref: '#/components/schemas/ValidationError' type: array title: Detail type: object title: HTTPValidationError Body_optp_redlines_document_redlines_post: properties: file_content_base: anyOf: - type: string - type: 'null' title: File Content Base file_content_new: anyOf: - type: string - type: 'null' title: File Content New file_type: anyOf: - type: string - type: 'null' title: File Type module_name: anyOf: - type: string - type: 'null' title: Module Name type: object title: Body_optp_redlines_document_redlines_post DeletionImpactResponse: properties: total_file_count: type: integer title: Total File Count description: Distinct files affected (deduped across placements). default: 0 matters: items: $ref: '#/components/schemas/AffectedMatter' type: array title: Matters description: Distinct matters any affected file is linked to; [] if none. type: object title: DeletionImpactResponse description: 'Result for POST deletion-impact: read-only; mutates nothing. ``total_file_count`` is every file under the folders (recursive) plus the loose files, de-duped across multi-placements. ``matters`` is the union of distinct matters any affected file is linked to (empty if none) — so the UI can warn that deleting also removes those files from the listed matters.' BatchAddDocumentItem: properties: filename: type: string maxLength: 4096 minLength: 1 title: Filename hash: type: string title: Hash original_filename: anyOf: - type: string - type: 'null' title: Original Filename description: Display name (e.g. user's filename). source: anyOf: - $ref: '#/components/schemas/DocumentSource' - type: 'null' description: 'Origin of the document: ''user'' (uploaded) or ''strongsuit'' (system-generated). Defaults to ''user'' when omitted.' chunking_strategy: anyOf: - type: string - type: 'null' title: Chunking Strategy description: 'Text splitting strategy for ingestion. When set, overrides automatic classification-based splitter selection. Values: ''financial'' (transaction-aware, zero overlap), ''contract'' (default sentence splitter).' matter_id: anyOf: - type: string - type: 'null' title: Matter Id description: Optional matter ID to link the document to. task_id: anyOf: - type: string - type: 'null' title: Task Id description: Optional task (Conversation) ID to link the document to. file_content_type: anyOf: - $ref: '#/components/schemas/DocumentType' - type: 'null' description: Document classification (e.g. MATTER_MEMORY, TASK_MEMORY). When provided, bypasses LLM classification during ingestion. purpose: anyOf: - $ref: '#/components/schemas/DocumentPurpose' - type: 'null' description: Intended use of this upload. When set to 'template', the file is content-sniffed and rejected unless it's a genuine .docx (ENG-17640). Omit for ordinary document uploads — this never restricts those. relative_path: anyOf: - type: string - type: 'null' title: Relative Path description: Folder-relative path from a folder upload (e.g. 'Taxes/2024/w2.pdf'). Its directory part builds the user's DocHub folder tree and the basename becomes the display name. If omitted but original_filename contains '/', it is split as a fallback. target_directory_id: anyOf: - type: string format: uuid - type: 'null' title: Target Directory Id description: Optional DocHub folder to upload into (the 'current folder'); defaults to root. Any relative_path is created beneath it. matter_directory_id: anyOf: - type: string format: uuid - type: 'null' title: Matter Directory Id description: 'Optional folder in the MATTER''s tree to file the doc into (requires matter_id). Distinct from target_directory_id, which is always a DocHub folder — folder ids do not cross scopes. When set, the doc is placed here explicitly and its DocHub folder ancestry is NOT mirrored into the matter, since the user picked the matter location directly (ENG-19239). NOTE: resolved batch-wide like matter_id — the request-level value wins, else the first item that sets one, and it then applies to EVERY doc in the batch. Per-item folders are not supported; send separate batches if files need different matter folders.' total_bytes: type: integer minimum: 0.0 title: Total Bytes description: File size in bytes for pre-registration credit estimation (0 = per-doc floor). default: 0 pages: type: integer minimum: 0.0 title: Pages description: Known page count for pre-registration credit estimation (0 if unknown). default: 0 archive_member_names_url_encoded: type: boolean title: Archive Member Names Url Encoded description: Set when this upload is an archive whose member names were percent-encoded by the producer (e.g. a Dropbox folder-download zip). Extraction decodes member names before registering the children. default: false archive_member_path_prefix: anyOf: - type: string maxLength: 255 - type: 'null' title: Archive Member Path Prefix description: Folder path to nest this archive's extracted members under, so the archive itself can sit beside the folder it produces instead of inside it (e.g. a Dropbox folder-download zip, whose members carry no wrapping directory of their own). type: object required: - filename - hash title: BatchAddDocumentItem description: Single document in a batch add-documents request. ExportStatusResponse: properties: status: type: string title: Status description: 'Workflow status: ''running'', ''completed'', or ''failed''.' url: anyOf: - type: string - type: 'null' title: Url description: Download URL when status is 'completed'. expires_at: anyOf: - type: string format: date-time - type: 'null' title: Expires At description: URL expiry when status is 'completed'. document_count: anyOf: - type: integer - type: 'null' title: Document Count description: Number of documents in the zip. skipped_count: anyOf: - type: integer - type: 'null' title: Skipped Count description: Number of documents that could not be included. error: anyOf: - type: string - type: 'null' title: Error description: Error message when status is 'failed'. type: object required: - status title: ExportStatusResponse description: Polling response for an export-documents workflow. DocumentLinkResponse: properties: success: type: boolean title: Success type: object required: - success title: DocumentLinkResponse description: Shared response for add/remove document-to-matter and document-to-task operations. CreateAliasRequest: properties: hash: type: string title: Hash description: Content hash of the file (must match an existing canonical's checksum). filename: type: string maxLength: 4096 minLength: 1 title: Filename description: Display name for the alias record. relative_path: anyOf: - type: string - type: 'null' title: Relative Path description: Same relative_path you'd send to /add-document. target_directory_id: anyOf: - type: string format: uuid - type: 'null' title: Target Directory Id description: Same target_directory_id you'd send to /add-document. task_id: anyOf: - type: string - type: 'null' title: Task Id description: Optional task (Conversation) ID to link the alias to. lr: type: boolean title: Lr default: false matter_id: anyOf: - type: string - type: 'null' title: Matter Id description: Optional matter ID to link the alias to. matter_directory_id: anyOf: - type: string format: uuid - type: 'null' title: Matter Directory Id description: Same matter_directory_id you'd send to /add-document. source: anyOf: - $ref: '#/components/schemas/DocumentSource' - type: 'null' file_content_type: anyOf: - $ref: '#/components/schemas/DocumentType' - type: 'null' type: object required: - hash - filename title: CreateAliasRequest description: 'Hardwire a symlink alias for content already in DocHub — no blob upload (ENG-17767). Send this instead of uploading + calling /add-document when /check-duplicates returned action=''alias''. Mirrors the linking/placement fields of AddDocumentRequest but carries no blob ''filename'' (there is nothing to upload — the alias points at the existing canonical).' AdminIngestHealthResponse: properties: evaluated_at: type: string format: date-time title: Evaluated At window_minutes: type: integer title: Window Minutes completed: $ref: '#/components/schemas/AdminIngestHealthCompleted' failures_by_class: additionalProperties: type: integer type: object title: Failures By Class throughput_per_hour: type: number title: Throughput Per Hour default: 0.0 queue: $ref: '#/components/schemas/AdminIngestHealthQueue' type: object required: - evaluated_at - window_minutes - completed - queue title: AdminIngestHealthResponse description: Platform-wide Doc Hub ingestion health for the alerting monitor. AddDocumentsToTaskResponse: properties: success: type: boolean title: Success added: type: integer title: Added default: 0 already_linked: type: integer title: Already Linked default: 0 failed: type: integer title: Failed default: 0 type: object required: - success title: AddDocumentsToTaskResponse ListDocumentsResponse: properties: success: type: boolean title: Success documents: items: $ref: '#/components/schemas/DocumentMetadataSummary' type: array title: Documents total_count: anyOf: - type: integer - type: 'null' title: Total Count description: Total matching documents (set when pagination is used) type: object required: - success title: ListDocumentsResponse description: 'Response for get_documents_by_task and get_documents_by_matter: success and list of document summaries. When the caller passes ``limit``, ``total_count`` is populated with the unsliced row count so the frontend can render paging controls. When ``limit`` is omitted (legacy behaviour), ``total_count`` is ``None``.' CursorPaginationMetadata: properties: page_size: type: integer title: Page Size description: Items per page has_next: type: boolean title: Has Next description: Whether there are more items after this page has_previous: type: boolean title: Has Previous description: Whether there are items before this page (cursor was provided) next_cursor: anyOf: - type: string - type: 'null' title: Next Cursor description: Opaque cursor for the next page; null on last page type: object required: - page_size - has_next - has_previous title: CursorPaginationMetadata description: 'Cursor-based pagination metadata (ENG-22724). Replaces offset-based ``PaginationMetadata`` for the folder listing. No total count is computed — the expensive ``COUNT(*)`` over 1M+ rows is eliminated. The client navigates with opaque cursor strings instead of page numbers.' BatchAddDocumentsResponse: properties: documents: items: $ref: '#/components/schemas/BatchAddDocumentResult' type: array title: Documents type: object required: - documents title: BatchAddDocumentsResponse description: Response for POST /document/add-documents. Array order matches request order. CheckDuplicatesResponse: properties: files: items: $ref: '#/components/schemas/CheckDuplicateOne' type: array title: Files description: List of files with duplicate status. type: object required: - files title: CheckDuplicatesResponse SelectAllSharedCountRequest: properties: select_all_folder_id: anyOf: - type: string format: uuid - type: 'null' title: Select All Folder Id description: Folder the select-all was taken in; omit for the DocHub root. exclude_doc_ids: items: type: string format: uuid type: array maxItems: 5000 title: Exclude Doc Ids description: Doc IDs the user unchecked after select-all. type: object title: SelectAllSharedCountRequest description: 'Request for POST select-all-shared-count: a DocHub select-all about to be deleted (ENG-23079).' DocumentTokenEstimateRequest: properties: files: items: $ref: '#/components/schemas/DocumentTokenEstimateFileRequest' type: array maxItems: 10000 minItems: 1 title: Files type: object required: - files title: DocumentTokenEstimateRequest description: 'Request for POST /document/estimate/tokens: price locally counted token totals.' DocumentSortField: type: string enum: - date_added - name - size - category - type - added_by title: DocumentSortField description: 'Sortable fields for the document list. ``TYPE`` and ``ADDED_BY`` mirror the members of the same name on :class:`FolderSortField` and reuse its ordering expressions, so the flat list and the folder browser order the two columns identically — they render the same values on the same screen. Matters and Tasks are absent here for the same reason they are absent there: those names are encrypted at rest, so ordering on them would sort ciphertext.' AddDocumentsV2Request: properties: manifest_blob_path: type: string maxLength: 4096 minLength: 1 title: Manifest Blob Path description: Path to the manifest JSON blob in the user's Azure container. batch_id: anyOf: - type: string format: uuid - type: 'null' title: Batch Id description: Frontend-generated batch ID (from /batch-start). Created server-side if omitted. task_id: anyOf: - type: string - type: 'null' title: Task Id matter_id: anyOf: - type: string - type: 'null' title: Matter Id matter_directory_id: anyOf: - type: string format: uuid - type: 'null' title: Matter Directory Id lr: type: boolean title: Lr default: false type: object required: - manifest_blob_path title: AddDocumentsV2Request description: 'Request for POST /document/add-documents-v2: fire-and-forget manifest-based registration.' AdminFailedDocsUser: properties: id: type: string title: Id email: anyOf: - type: string - type: 'null' title: Email full_name: anyOf: - type: string - type: 'null' title: Full Name type: object required: - id title: AdminFailedDocsUser description: Customer whose FAILED_NO_RETRY docs are listed. DocumentEstimateRequest: properties: files: items: $ref: '#/components/schemas/DocumentEstimateFileRequest' type: array maxItems: 10000 minItems: 1 title: Files type: object required: - files title: DocumentEstimateRequest description: 'Request for POST /document/estimate: estimate processing credits before upload.' AdminFailedIngestSkip: properties: id: type: string format: uuid title: Id reason: type: string title: Reason type: object required: - id - reason title: AdminFailedIngestSkip DeleteFolderResponse: properties: success: type: boolean title: Success default: true removed_folder_count: type: integer title: Removed Folder Count description: Directory rows dropped (the deleted subtree). unlinked_doc_count: type: integer title: Unlinked Doc Count description: 'Matter scope: docs un-associated from the matter (still in DocHub).' default: 0 hard_deleted_doc_count: type: integer title: Hard Deleted Doc Count description: 'DocHub scope: docs hard-deleted (their only placement was inside the subtree).' default: 0 pruned_folder_count: anyOf: - type: integer - type: 'null' title: Pruned Folder Count description: 'When prune_empty_folders=true: folders pruned inline (matter scope, or DocHub with no async purge). None means pruning was deferred to the background drain (DocHub with files to purge) or wasn''t requested.' type: object required: - removed_folder_count title: DeleteFolderResponse GetDocumentResponse: properties: success: type: boolean title: Success document: anyOf: - $ref: '#/components/schemas/DocumentMetadataSummary' - type: 'null' type: object required: - success title: GetDocumentResponse description: 'Response for get_document: success and optional document summary.' SortOrder: type: string enum: - asc - desc title: SortOrder description: Sort direction. BatchDocumentsItem: properties: id: type: string title: Id name: type: string title: Name status: type: string title: Status location: type: string title: Location default: '' checksum: anyOf: - type: string - type: 'null' title: Checksum description: 'Content hash of the document. Match uploads to rows on THIS, not on ``location``: ``location`` encodes the id of whichever upload container first produced the file, so a de-duplicated re-upload keeps the earlier container''s path and a client that rebuilds ``extracted_/`` can never match it.' original_relative_path: anyOf: - type: string - type: 'null' title: Original Relative Path description: Folder-qualified path the file was uploaded under, when known. Not always set. failure_reason: anyOf: - type: string - type: 'null' title: Failure Reason description: Why the document failed (e.g. 'corrupted_file'). Only set on FAILED_NO_RETRY. Without it a bundled member that failed could only be reported as a generic 'Processing failed' (ENG-22515). retry_pending: type: boolean title: Retry Pending description: True when the document is FAILED_NO_RETRY but the transient-failure sweep will re-queue it on its own, so its failure is not final yet. default: false type: object required: - id - name - status title: BatchDocumentsItem description: Single document in a batch documents listing. PollDocumentsV2Request: properties: batch_id: type: string format: uuid title: Batch Id description: Batch ID from /add-documents-v2. type: object required: - batch_id title: PollDocumentsV2Request description: Request for POST /document/poll-documents-v2. BatchAddDocumentsRequest: properties: task_id: anyOf: - type: string - type: 'null' title: Task Id description: Optional task (Conversation) ID to link all documents to. lr: type: boolean title: Lr description: Whether task-document links are for legal research. default: false matter_id: anyOf: - type: string - type: 'null' title: Matter Id description: Optional matter ID to link all documents to (used when task_id is absent). batch_id: anyOf: - type: string format: uuid - type: 'null' title: Batch Id description: DocHubUploadBatch ID from batch-start. When set, docs are tracked for batch completion. matter_directory_id: anyOf: - type: string format: uuid - type: 'null' title: Matter Directory Id description: Optional folder in the MATTER's tree to file the doc into (requires matter_id). Distinct from target_directory_id, which is always a DocHub folder — folder ids do not cross scopes. When set, the doc is placed here explicitly and its DocHub folder ancestry is NOT mirrored into the matter, since the user picked the matter location directly (ENG-19239). documents: items: $ref: '#/components/schemas/BatchAddDocumentItem' type: array maxItems: 100 minItems: 1 title: Documents type: object required: - documents title: BatchAddDocumentsRequest description: 'Request for POST /document/add-documents: batch-register multiple uploaded documents.' SelectAllSharedCountResponse: properties: shared_count: type: integer title: Shared Count description: Selected files the caller did not upload. default: 0 type: object title: SelectAllSharedCountResponse description: 'Result for POST select-all-shared-count: read-only; mutates nothing. ``shared_count`` is how many files the select-all shows that a delete would skip: shared in via a matter, owned by someone else.' AddDocumentRequest: properties: filename: type: string maxLength: 4096 minLength: 1 title: Filename hash: type: string title: Hash original_filename: anyOf: - type: string - type: 'null' title: Original Filename description: Display name (e.g. user's filename). When provided, used instead of blob metadata so the client can send arbitrary Unicode in the request body instead of upload headers. task_id: anyOf: - type: string - type: 'null' title: Task Id description: Optional task (Conversation) ID to link the document to. lr: type: boolean title: Lr description: Whether this task-document link is for legal research. default: false matter_id: anyOf: - type: string - type: 'null' title: Matter Id description: Optional matter ID to link the document to. source: anyOf: - $ref: '#/components/schemas/DocumentSource' - type: 'null' description: 'Origin of the document: ''user'' (uploaded) or ''strongsuit'' (system-generated). Defaults to ''user'' when omitted.' chunking_strategy: anyOf: - type: string - type: 'null' title: Chunking Strategy description: 'Text splitting strategy for ingestion. When set, overrides automatic classification-based splitter selection. Values: ''financial'' (transaction-aware, zero overlap), ''contract'' (default sentence splitter).' file_content_type: anyOf: - $ref: '#/components/schemas/DocumentType' - type: 'null' description: Document classification (e.g. MATTER_MEMORY, TASK_MEMORY). When provided, bypasses LLM classification during ingestion. purpose: anyOf: - $ref: '#/components/schemas/DocumentPurpose' - type: 'null' description: Intended use of this upload. When set to 'template', the file is content-sniffed and rejected unless it's a genuine .docx (ENG-17640). Omit for ordinary document uploads — this never restricts those. archive_member_names_url_encoded: type: boolean title: Archive Member Names Url Encoded description: Set when this upload is an archive whose member names were percent-encoded by the producer (e.g. a Dropbox folder-download zip). Extraction decodes member names before registering the children. default: false archive_member_path_prefix: anyOf: - type: string maxLength: 255 - type: 'null' title: Archive Member Path Prefix description: Folder path to nest this archive's extracted members under, so the archive itself can sit beside the folder it produces instead of inside it (e.g. a Dropbox folder-download zip, whose members carry no wrapping directory of their own). relative_path: anyOf: - type: string - type: 'null' title: Relative Path description: Folder-relative path from a folder upload (e.g. 'Taxes/2024/w2.pdf'), typically the browser's webkitRelativePath. Its directory part builds the user's DocHub folder tree and the basename becomes the display name. If omitted but original_filename contains '/', it is split as a fallback. target_directory_id: anyOf: - type: string format: uuid - type: 'null' title: Target Directory Id description: Optional DocHub folder to upload into (the 'current folder'); defaults to root. Any relative_path is created beneath it. matter_directory_id: anyOf: - type: string format: uuid - type: 'null' title: Matter Directory Id description: Optional folder in the MATTER's tree to file the doc into (requires matter_id). Distinct from target_directory_id, which is always a DocHub folder — folder ids do not cross scopes. When set, the doc is placed here explicitly and its DocHub folder ancestry is NOT mirrored into the matter, since the user picked the matter location directly (ENG-19239). total_bytes: type: integer minimum: 0.0 title: Total Bytes description: File size in bytes for pre-registration credit estimation (0 = per-doc floor). default: 0 pages: type: integer minimum: 0.0 title: Pages description: Known page count for pre-registration credit estimation (0 if unknown). default: 0 type: object required: - filename - hash title: AddDocumentRequest ProcessingFileItem: properties: id: type: string format: uuid title: Id name: anyOf: - type: string - type: 'null' title: Name description: Filename; null for a client-authored upload container, which the UI labels by member count. is_upload_package: type: boolean title: Is Upload Package description: True for a hidden bulk-upload container whose members are still being extracted. default: false ingestion_status: $ref: '#/components/schemas/IngestionStatus' percent_complete: anyOf: - type: integer - type: 'null' title: Percent Complete archive_members_done: anyOf: - type: integer - type: 'null' title: Archive Members Done archive_members_total: anyOf: - type: integer - type: 'null' title: Archive Members Total folder_id: anyOf: - type: string format: uuid - type: 'null' title: Folder Id description: Leaf folder for deep-linking; null at the scope root. folder_path: anyOf: - type: string - type: 'null' title: Folder Path description: Folder breadcrumb from the scope root (e.g. 'DocHub/Discovery/2024'), no filename. type: object required: - id - ingestion_status title: ProcessingFileItem description: One document still ingesting, with where it lives, for the banner's file list. CreateFolderRequest: properties: name: type: string maxLength: 250 minLength: 1 title: Name description: Folder display name parent_id: anyOf: - type: string format: uuid - type: 'null' title: Parent Id description: Parent folder; omit for a top-level folder matter_id: anyOf: - type: string - type: 'null' title: Matter Id description: Matter scope; omit to target the caller's DocHub tree type: object required: - name title: CreateFolderRequest DeletionImpactRequest: properties: folder_ids: items: type: string format: uuid type: array title: Folder Ids description: Folders to delete; each resolved recursively (whole subtree). document_ids: items: type: string format: uuid type: array title: Document Ids description: Loose files to delete. matter_id: anyOf: - type: string - type: 'null' title: Matter Id description: 'Scope: matter id for matter-scoped folders/files; omit for DocHub scope.' type: object title: DeletionImpactRequest description: 'Request for POST deletion-impact: read-only preview of what a delete would affect.' PollDocumentsResponse: properties: success: type: boolean title: Success documents: items: $ref: '#/components/schemas/DocumentPollItem' type: array title: Documents description: Document id, status, size, and percent_complete for documents the user can access. type: object required: - success title: PollDocumentsResponse description: 'Response for POST poll-documents: id, status, size, and percent_complete for each document.' AdminIngestHealthCompleted: properties: succeeded: type: integer title: Succeeded failed: type: integer title: Failed total: type: integer title: Total success_rate_pct: anyOf: - type: number - type: 'null' title: Success Rate Pct customers: type: integer title: Customers default: 0 type: object required: - succeeded - failed - total title: AdminIngestHealthCompleted description: INGEST jobs that reached a terminal state inside the window. AddDocumentsToMatterRequest: properties: doc_ids: items: type: string format: uuid type: array minItems: 1 title: Doc Ids description: UUIDs of the documents to add matter_id: type: string minLength: 1 title: Matter Id description: CUID of the matter to add the documents to type: object required: - doc_ids - matter_id title: AddDocumentsToMatterRequest FolderSortField: type: string enum: - name - date_added - category - added_by - type title: FolderSortField description: "Sortable fields for the folder listing (ENG-19278).\n\nDeliberately not the same set as ``DocumentSortField``: ``size`` isn't a column in the\nfolder browser, while ``added_by`` and ``type`` are. Matters/Tasks are absent on purpose —\nthose names are encrypted at rest, so ordering on them would sort ciphertext.\n\nFolders are sorted together with files, never pinned above them. How a folder places depends\non whether it has a value for the field:\n\n- ``NAME``, ``DATE_ADDED`` — a folder has its own name and ``created_at``, so it interleaves\n with files on equal footing.\n- ``TYPE`` — a folder sorts as the literal ``\"folder\"``, so it interleaves alphabetically\n among file extensions (``docx`` < ``folder`` < ``pdf``).\n- ``CATEGORY``, ``ADDED_BY`` — a folder has neither, so it carries NULL and pins to the top\n in *both* directions (see ``_merged_order_by``)." AdminFailedIngestRequeueResponse: properties: requeued: items: type: string format: uuid type: array title: Requeued skipped: items: $ref: '#/components/schemas/AdminFailedIngestSkip' type: array title: Skipped type: object title: AdminFailedIngestRequeueResponse RenameFolderRequest: properties: name: type: string maxLength: 250 minLength: 1 title: Name description: New folder display name matter_id: anyOf: - type: string - type: 'null' title: Matter Id description: Matter scope; omit for DocHub type: object required: - name title: RenameFolderRequest RemoveDocumentFromTaskRequest: properties: doc_id: type: string format: uuid title: Doc Id description: UUID of the document to remove task_id: type: string minLength: 1 title: Task Id description: CUID of the task (Conversation) to remove the document from type: object required: - doc_id - task_id title: RemoveDocumentFromTaskRequest DocumentType: type: string enum: - COMPLAINT - STATEMENT_OF_FACTS - ANSWER - PRIOR_MOTION - CONTRACT - BRIEF - DEMAND_LETTER - EXHIBITS - OTHER - VARIOUS - FINANCIAL_DOCUMENT - POLICY_DOCUMENT - PERSONNEL_RECORD - MEETING_MINUTES - TESTIMONY_STATEMENT - TECHNICAL_DOCUMENT - MEDIA_CONTENT - EMAIL - MEDICAL_RECORD - MATTER_MEMORY - TASK_MEMORY - MATTER_FORM_CACHE - MATTER_PREFERENCES - PRELIMINARY_ANALYSIS - EARLY_INTAKE_MEMORY title: DocumentType description: Document type classification for matters. AdminUploadSummaryResponse: properties: user: $ref: '#/components/schemas/AdminFailedDocsUser' since: type: string format: date-time title: Since until: type: string format: date-time title: Until total: type: integer title: Total by_status: additionalProperties: type: integer type: object title: By Status description: DocMetadata.status -> row count inside the window. first_upload: anyOf: - type: string format: date-time - type: 'null' title: First Upload last_upload: anyOf: - type: string format: date-time - type: 'null' title: Last Upload type: object required: - user - since - until - total title: AdminUploadSummaryResponse description: Upload outcomes for one customer over a time window (Doc Hub alert triage). CancelUploadResponse: properties: cancelled_ids: items: type: string format: uuid type: array title: Cancelled Ids description: Documents that were cancelled. type: object title: CancelUploadResponse BatchStartRequest: properties: task_id: type: string minLength: 1 title: Task Id description: Task (Conversation) ID backing the dataset. expected_doc_count: anyOf: - type: integer minimum: 0.0 - type: 'null' title: Expected Doc Count description: Number of files in this upload session. When set, batch completion fires only after that many docs reach terminal — prevents premature completion when a fast doc drains the batch before slow docs enroll (ENG-16159). Reconcile the true count via /batch-finalize. type: object required: - task_id title: BatchStartRequest description: 'Request for POST /document/batch-start: declare an upload batch for a dataset task.' UploadStateQuery: properties: blob_path: type: string maxLength: 1024 title: Blob Path description: Blob name within the caller's own container, as it was uploaded. total_bytes: type: integer minimum: 0.0 title: Total Bytes description: Size the finished blob should be. hash: type: string maxLength: 256 title: Hash description: Type-prefixed content hash (e.g. 'sha1:...'), as written to blob metadata. type: object required: - blob_path - total_bytes - hash title: UploadStateQuery description: One blob a client is about to send, or re-send. PaginationMetadata: properties: page: type: integer title: Page description: Current page number page_size: type: integer title: Page Size description: Number of items per page total_count: type: integer title: Total Count description: Total number of items total_pages: type: integer title: Total Pages description: Total number of pages has_next: type: boolean title: Has Next description: Whether there is a next page has_previous: type: boolean title: Has Previous description: Whether there is a previous page type: object required: - page - page_size - total_count - total_pages - has_next - has_previous title: PaginationMetadata description: Pagination metadata for list responses. PollDocumentsRequest: properties: document_ids: items: type: string format: uuid type: array maxItems: 2000 minItems: 1 title: Document Ids description: Document UUIDs to poll for progress. type: object required: - document_ids title: PollDocumentsRequest description: 'Request for POST poll-documents: list of document IDs to poll.' CheckDuplicatesRequest: properties: files: items: type: string type: array title: Files description: Legacy hash-only duplicate check. Prefer 'entries' for path-aware detection — with 'files', a byte-identical upload under a different name/folder is reported as a duplicate even though it would now become an independent alias record. entries: anyOf: - items: $ref: '#/components/schemas/CheckDuplicateEntry' type: array - type: 'null' title: Entries description: 'Path-aware duplicate check (ENG-17767): hash + relative_path per file. When set, ''files'' is ignored.' type: object title: CheckDuplicatesRequest AddDocumentsToTaskRequest: properties: doc_ids: items: type: string format: uuid type: array minItems: 1 title: Doc Ids description: UUIDs of the documents to add task_id: type: string minLength: 1 title: Task Id description: CUID of the task (Conversation) to add the documents to batch_id: anyOf: - type: string format: uuid - type: 'null' title: Batch Id description: DocHubUploadBatch ID from batch-start. When set, docs are tracked for batch completion. type: object required: - doc_ids - task_id title: AddDocumentsToTaskRequest ViewDocumentResponse: properties: success: type: boolean title: Success url: anyOf: - type: string - type: 'null' title: Url expires_at: anyOf: - type: string format: date-time - type: 'null' title: Expires At type: object required: - success title: ViewDocumentResponse DocumentFilterOptionsResponse: properties: success: type: boolean title: Success categories: items: $ref: '#/components/schemas/FilterOption' type: array title: Categories types: items: $ref: '#/components/schemas/FilterOption' type: array title: Types matters: items: $ref: '#/components/schemas/FilterOption' type: array title: Matters tasks: items: $ref: '#/components/schemas/FilterOption' type: array title: Tasks added_by_users: items: $ref: '#/components/schemas/FilterOption' type: array title: Added By Users type: object required: - success title: DocumentFilterOptionsResponse description: Available filter values with counts for faceted search. AddFoldersToTaskRequest: properties: task_id: type: string minLength: 1 title: Task Id description: CUID of the task (Conversation) to add the documents to folder_ids: items: type: string format: uuid type: array title: Folder Ids description: Folders to expand server-side. Scope is body.matter_id (matter tree) or omit for the caller's DocHub — same as delete-documents / listing. Not inferred from the task. doc_ids: items: type: string format: uuid type: array title: Doc Ids description: Individually-selected loose files to link alongside the folders. matter_id: anyOf: - type: string - type: 'null' title: Matter Id description: 'Scope for folder expansion: matter id for matter-scoped folders; omit for DocHub.' batch_id: anyOf: - type: string format: uuid - type: 'null' title: Batch Id description: DocHubUploadBatch ID from batch-start. When set, expanded docs are tracked for batch completion. include_subfolders: type: boolean title: Include Subfolders description: Recurse into subfolders (default true). default: true return_doc_ids: type: boolean title: Return Doc Ids description: When true, include resolved_doc_ids in the response. Opt-in so callers that only need the link (Doc Review, Timeline, Files tab) do not download the expanded list. default: false type: object required: - task_id title: AddFoldersToTaskRequest description: Expand folders server-side and link the resulting docs to a task (ENG-22527). FolderResponse: properties: id: type: string format: uuid title: Id name: type: string title: Name parent_id: anyOf: - type: string format: uuid - type: 'null' title: Parent Id type: object required: - id - name title: FolderResponse IngestionStatus: type: string enum: - queued - processing - done - failed - cancelled - stranded - unknown title: IngestionStatus description: 'Derived per-doc ingestion status for API responses. Projected from (DocMetadata.status, latest INGEST DocHubJob.status, job age). Response-only: not persisted. See `_derive_ingestion_status` in `app/modules/document/routes.py`.' UserInfo: properties: user_id: type: string title: User Id fullname: anyOf: - type: string - type: 'null' title: Fullname email: anyOf: - type: string - type: 'null' title: Email profile_url: anyOf: - type: string - type: 'null' title: Profile Url type: object required: - user_id title: UserInfo description: Lightweight user info embedded in responses. RemoveFoldersFromMatterRequest: properties: matter_id: type: string title: Matter Id description: Target matter. folder_ids: items: type: string format: uuid type: array title: Folder Ids description: MATTER folders to remove (un-associate all docs within, recursively). doc_ids: items: type: string format: uuid type: array title: Doc Ids description: Individual files to un-associate from the matter. select_all: type: boolean title: Select All description: Remove all documents in the scope from the matter. When select_all_folder_id is also set, only docs under that folder subtree are removed; otherwise all docs in the matter. folder_ids and doc_ids are ignored. default: false select_all_folder_id: anyOf: - type: string format: uuid - type: 'null' title: Select All Folder Id description: Scope select_all to a specific matter folder subtree. exclude_doc_ids: items: type: string format: uuid type: array maxItems: 5000 title: Exclude Doc Ids description: 'Doc IDs to exclude from select_all. Used for the mode+delta selection model: the user selected all, then unchecked a few items. Bounded by user clicks (max 5000). Only effective when select_all is true.' exclude_folder_ids: items: type: string format: uuid type: array maxItems: 500 title: Exclude Folder Ids description: Folder IDs to exclude from select_all. The server resolves each folder's subtree and excludes all contained docs. Bounded by user clicks (max 500). Only effective when select_all is true. include_subfolders: type: boolean title: Include Subfolders description: Recurse into subfolders (default true). default: true delete_empty_folders: type: boolean title: Delete Empty Folders description: Drop the now-empty matter folder nodes so the tree stays clean (default true). default: true type: object required: - matter_id title: RemoveFoldersFromMatterRequest PaginatedDocumentListResponse: properties: success: type: boolean title: Success documents: items: $ref: '#/components/schemas/DocumentMetadataSummary' type: array title: Documents pagination: $ref: '#/components/schemas/PaginationMetadata' type: object required: - success - documents - pagination title: PaginatedDocumentListResponse description: Paginated response for GET /document/list. AddDocumentToTaskRequest: properties: doc_id: type: string format: uuid title: Doc Id description: UUID of the document to add task_id: type: string minLength: 1 title: Task Id description: CUID of the task (Conversation) to add the document to type: object required: - doc_id - task_id title: AddDocumentToTaskRequest DeleteDocumentsRequest: properties: document_ids: items: type: string format: uuid type: array maxItems: 2000 title: Document Ids description: Loose file UUIDs to delete. Use select_all for larger deletes. folder_ids: items: type: string format: uuid type: array title: Folder Ids description: Folders to delete; each resolved recursively (whole subtree) on the server. matter_id: anyOf: - type: string - type: 'null' title: Matter Id description: 'Scope for folder resolution: matter id for matter-scoped folders; omit for DocHub scope.' select_all: type: boolean title: Select All description: 'Delete all documents in the scope. With matter_id: all docs in the matter owned by the caller. Without matter_id: all visible user-owned docs (DocHub scope). When select_all_folder_id is also set, only docs under that folder subtree are deleted. document_ids and folder_ids are ignored.' default: false select_all_folder_id: anyOf: - type: string format: uuid - type: 'null' title: Select All Folder Id description: Scope select_all to a specific folder subtree. Only effective when select_all is true. exclude_doc_ids: items: type: string format: uuid type: array maxItems: 5000 title: Exclude Doc Ids description: 'Doc IDs to exclude from select_all. Used for the mode+delta selection model: the user selected all, then unchecked a few items. Bounded by user clicks (max 5000). Only effective when select_all is true.' exclude_folder_ids: items: type: string format: uuid type: array maxItems: 500 title: Exclude Folder Ids description: Folder IDs to exclude from select_all. The server resolves each folder's subtree and excludes all contained docs. Bounded by user clicks (max 500). Only effective when select_all is true. prune_empty_folders: type: boolean title: Prune Empty Folders description: If true, once the background purge finishes, delete the folders these documents vacated (and their ancestors) if they are left empty. Runs at the tail of the delete job, so it can't race the async purge, and never touches unrelated empty folders. default: false type: object title: DeleteDocumentsRequest description: 'Request for POST delete-documents: hard-delete a batch of documents owned by the caller. Accepts ``folder_ids`` (resolved server-side to all files in the subtree) and/or ``document_ids`` (loose files). At least one must be non-empty. When ``folder_ids`` is provided, ``matter_id`` scopes the resolution; omit it for DocHub scope. Backward-compatible: the old ``document_ids``-only shape still works unchanged.' RemoveDocumentFromMatterRequest: properties: doc_id: type: string format: uuid title: Doc Id description: UUID of the document to remove matter_id: type: string minLength: 1 title: Matter Id description: CUID of the matter to remove the document from prune_empty_folders: type: boolean title: Prune Empty Folders description: If true, delete the folder this file vacated (and its ancestors) if now empty. default: false type: object required: - doc_id - matter_id title: RemoveDocumentFromMatterRequest AddFoldersToMatterRequest: properties: matter_id: type: string title: Matter Id description: Target matter. folder_ids: items: type: string format: uuid type: array title: Folder Ids description: Source DocHub folders to copy (subtree mirrored into the matter). doc_ids: items: type: string format: uuid type: array title: Doc Ids description: Individually-selected loose files to add. target_directory_id: anyOf: - type: string format: uuid - type: 'null' title: Target Directory Id description: Matter folder to nest the copied subtree under (the matter cwd); null = matter root. include_subfolders: type: boolean title: Include Subfolders description: Recurse into subfolders (default true). default: true type: object required: - matter_id title: AddFoldersToMatterRequest CheckDuplicateOne: properties: hash: type: string title: Hash exists: type: boolean title: Exists action: anyOf: - type: string enum: - upload - skip - alias - type: 'null' title: Action description: 'Path-aware mode only (set when the request used ''entries''): what the client should do. ''upload'' = content not present, upload the bytes via /add-document. ''skip'' = a byte-identical file already exists at this exact path, do nothing. ''alias'' = the bytes exist elsewhere; do NOT upload — call /create-alias to hardwire a symlink record instantly (no Azure transfer, no ingest).' id: anyOf: - type: string - type: 'null' title: Id name: anyOf: - type: string - type: 'null' title: Name azure_path: anyOf: - type: string - type: 'null' title: Azure Path archived: anyOf: - type: boolean - type: 'null' title: Archived failed: anyOf: - type: boolean - type: 'null' title: Failed failure_reason: anyOf: - type: string - type: 'null' title: Failure Reason description: Why the document failed (e.g. 'password_protected'). Only set on FAILED_NO_RETRY. type: object required: - hash - exists title: CheckDuplicateOne AddFoldersToTaskResponse: properties: success: type: boolean title: Success added: type: integer title: Added default: 0 already_linked: type: integer title: Already Linked default: 0 resolved_doc_count: type: integer title: Resolved Doc Count default: 0 resolved_doc_ids: items: type: string format: uuid type: array title: Resolved Doc Ids description: Expanded file ids (folders + loose extras). Empty unless return_doc_ids was set. type: object required: - success title: AddFoldersToTaskResponse PollDocumentsV2Item: properties: id: type: string title: Id name: type: string title: Name filename: type: string title: Filename default: '' size_bytes: type: integer title: Size Bytes default: 0 percent_complete: type: integer title: Percent Complete default: 0 failure_reason: anyOf: - type: string - type: 'null' title: Failure Reason type: object required: - id - name title: PollDocumentsV2Item description: Per-document detail for display (up to 3 per category). ClearDocsRequest: properties: document_names: items: type: string type: array minItems: 1 title: Document Names description: File names to match against doc_metadata.name. type: object required: - document_names title: ClearDocsRequest description: 'Request for POST clear-docs: hard-delete documents by name.' ProcessingStatusResponse: properties: processing: type: integer title: Processing description: Files still ingesting anywhere in the scope. A hidden upload container counts as the members it has yet to register, not as one file, so this is a count of the customer's own files rather than of rows. default: 0 failed: type: integer title: Failed description: Documents whose ingestion ended failed, stranded or cancelled. default: 0 archives_extracting: type: integer title: Archives Extracting description: Customer-uploaded archives still extracting members. Hidden upload containers are excluded, so a non-zero value means the customer's own zip is being extracted. default: 0 archive_members_done: anyOf: - type: integer - type: 'null' title: Archive Members Done description: Members registered so far across extracting customer archives; null when none report counts. archive_members_total: anyOf: - type: integer - type: 'null' title: Archive Members Total description: Members planned across extracting customer archives; null when none report counts. files: anyOf: - items: $ref: '#/components/schemas/ProcessingFileItem' type: array - type: 'null' title: Files description: In-flight documents, newest first, capped; null unless include_files was requested. files_truncated: type: boolean title: Files Truncated description: True when more documents were in flight than the list carries. default: false type: object title: ProcessingStatusResponse description: 'Result for GET processing-status: scope-wide in-flight ingestion counts for the Doc Hub banner, plus the in-flight rows when ``include_files`` was requested.' DocumentPollItem: properties: id: type: string format: uuid title: Id description: Document id. status: type: string title: Status description: Document processing status (e.g. UNPROCESSED, PROCESSED, FAILED_NO_RETRY). size: anyOf: - type: integer - type: 'null' title: Size description: Document size in bytes. percent_complete: anyOf: - type: integer - type: 'null' title: Percent Complete description: Processing progress 0-100. failure_reason: anyOf: - type: string - type: 'null' title: Failure Reason description: Why the document failed (e.g. 'password_protected'). Only set on FAILED_NO_RETRY. retry_pending: type: boolean title: Retry Pending description: True when the document is FAILED_NO_RETRY but the transient-failure sweep will re-queue it on its own. Clients should keep polling instead of reporting it failed. default: false type: object required: - id - status title: DocumentPollItem description: 'Single document polling result: id, status, size, and percent_complete.' AdminFailedIngestRequeueRequest: properties: target_user_id: type: string minLength: 1 title: Target User Id document_ids: items: type: string format: uuid type: array minItems: 1 title: Document Ids type: object required: - target_user_id - document_ids title: AdminFailedIngestRequeueRequest RenameDocumentRequest: properties: document_id: type: string format: uuid title: Document Id description: UUID of the document to rename new_name: type: string maxLength: 250 minLength: 1 title: New Name description: New name for the document type: object required: - document_id - new_name title: RenameDocumentRequest FolderListingOrderEntry: properties: kind: type: string enum: - folder - file title: Kind id: type: string format: uuid title: Id type: object required: - kind - id title: FolderListingOrderEntry description: One position in the merged folder+file render order (ENG-19278). MoveDocumentsResponse: properties: success: type: boolean title: Success default: true moved_count: type: integer title: Moved Count description: Documents whose placement was updated. skipped_doc_ids: items: type: string format: uuid type: array title: Skipped Doc Ids description: Docs skipped because an identical file (same contents + name) already exists in the target folder. type: object required: - moved_count title: MoveDocumentsResponse DocumentEstimateResponse: properties: total_credits: type: integer title: Total Credits description: Total estimated credits for all files, rounded up once for the batch. total_tokens: type: integer title: Total Tokens description: Total estimated tokens across all files. estimate_min_seconds: type: integer title: Estimate Min Seconds description: Lower bound of estimated total processing time in seconds. estimate_max_seconds: type: integer title: Estimate Max Seconds description: Upper bound of estimated total processing time in seconds. empirical: type: boolean title: Empirical description: True when time estimates are based on historical processing data; False when using default constants. documents: items: $ref: '#/components/schemas/DocumentEstimateItem' type: array title: Documents description: Per-document breakdown. credits_pending: type: integer title: Credits Pending description: Credits already reserved by the caller's in-flight uploads this month. default: 0 credits_remaining: type: integer title: Credits Remaining description: Credits left in the caller's monthly budget. default: 0 credit_limit: type: integer title: Credit Limit description: The caller's monthly credit limit. default: 0 would_exceed_budget: type: boolean title: Would Exceed Budget description: True when total_credits + credits_pending exceeds credits_remaining. Computed the same way the registration gate computes it, so a False here means the upload will be accepted. Clients must block the upload when this is True. default: false type: object required: - total_credits - total_tokens - estimate_min_seconds - estimate_max_seconds - empirical title: DocumentEstimateResponse description: 'Response for POST /document/estimate: per-document and aggregate credit estimates.' FolderTreeResponse: properties: folders: items: $ref: '#/components/schemas/FolderNodeSchema' type: array title: Folders type: object title: FolderTreeResponse description: 'Lightweight folder-only tree for the folder-picker dialog (ENG-22636). Returns every folder in the scope as a flat list; the client rebuilds the tree from parent_id pointers. No files, no counts, no pagination — just the skeleton needed to render a destination picker.' FilterOption: properties: value: type: string title: Value label: type: string title: Label count: type: integer title: Count type: object required: - value - label - count title: FilterOption description: Single option in a faceted filter (value, display label, count). DocumentEstimateFileRequest: properties: name: type: string title: Name description: File name including extension (e.g. 'report.pdf'). total_bytes: type: integer exclusiveMinimum: 0.0 title: Total Bytes description: File size in bytes. pages: type: integer minimum: 0.0 title: Pages description: Known page count (0 if unknown; bytes-based estimate is used). default: 0 type: object required: - name - total_bytes title: DocumentEstimateFileRequest description: Single file descriptor for cost estimation (mirrors discovery's FileRequest). AddDocumentResponse: properties: success: type: boolean title: Success document_id: type: string format: uuid title: Document Id task_linked: anyOf: - type: boolean - type: 'null' title: Task Linked description: True if document was linked to the requested task; False if link was attempted and failed; None if no task_id was provided. matter_linked: anyOf: - type: boolean - type: 'null' title: Matter Linked description: True if document was linked to the requested matter; False if link was attempted and failed; None if no matter_id was provided. type: object required: - success - document_id title: AddDocumentResponse FolderListingResponse: properties: folder_id: anyOf: - type: string format: uuid - type: 'null' title: Folder Id root_label: type: string title: Root Label breadcrumb: items: $ref: '#/components/schemas/FolderNodeSchema' type: array title: Breadcrumb folders: items: $ref: '#/components/schemas/FolderNodeSchema' type: array title: Folders files: items: $ref: '#/components/schemas/DocumentMetadataSummary' type: array title: Files description: Files placed at this level, in the same enriched shape as GET /document/list items. total_file_count: anyOf: - type: integer - type: 'null' title: Total File Count description: 'Recursive count of visible files in this folder and all descendants (at root: all files). Null in cursor-paginated search/filter mode (count not computed).' default: 0 folder_count: type: integer title: Folder Count description: Total child folders at this level (before paging). default: 0 file_count: anyOf: - type: integer - type: 'null' title: File Count description: Total files at this level (before paging); not recursive. Null in cursor pagination mode (count not computed). default: 0 pagination: anyOf: - $ref: '#/components/schemas/PaginationMetadata' - type: 'null' description: 'Page window over the merged folder+file ordering. total_count = folder_count + file_count. DEPRECATED: use cursor_pagination instead for new code (ENG-22724).' cursor_pagination: anyOf: - $ref: '#/components/schemas/CursorPaginationMetadata' - type: 'null' description: Cursor-based pagination (ENG-22724). Present when the caller passes a cursor or page_size. order: items: $ref: '#/components/schemas/FolderListingOrderEntry' type: array title: Order description: Render sequence for this page. Folders and files are sorted together and interleave, so neither folders[] nor files[] alone expresses the order — walk this and look each id up in the matching array. Folders are NOT pinned first. type: object required: - root_label title: FolderListingResponse DocumentEstimateItem: properties: name: type: string title: Name description: File name. estimated_tokens: type: integer title: Estimated Tokens description: Estimated token count for ingestion + summarization. estimated_credits: type: number title: Estimated Credits description: 'Estimated credits for processing this document. Fractional: most documents cost well under one credit.' estimated_seconds: type: number title: Estimated Seconds description: Estimated processing time in seconds for this document. type: object required: - name - estimated_tokens - estimated_credits - estimated_seconds title: DocumentEstimateItem description: Per-document credit estimate returned by the estimation endpoint. PollDocumentsV2Response: properties: registration_status: type: string title: Registration Status description: 'Temporal workflow status: running, completed, failed, unknown.' default: unknown summary: $ref: '#/components/schemas/PollDocumentsV2Summary' registering: items: $ref: '#/components/schemas/PollDocumentsV2Item' type: array maxItems: 3 title: Registering in_progress: items: $ref: '#/components/schemas/PollDocumentsV2Item' type: array maxItems: 3 title: In Progress completed: items: $ref: '#/components/schemas/PollDocumentsV2Item' type: array maxItems: 3 title: Completed failed: items: $ref: '#/components/schemas/PollDocumentsV2Item' type: array maxItems: 3 title: Failed type: object required: - summary title: PollDocumentsV2Response description: Response for POST /document/poll-documents-v2. AffectedMatter: properties: id: type: string title: Id name: type: string title: Name description: Matter name; may be encrypted (the FE proxy decrypts it). type: object required: - id - name title: AffectedMatter description: A matter that at least one about-to-be-deleted file is linked to. BatchFinalizeResponse: properties: sealed: type: boolean title: Sealed description: True if the batch was found and sealed with the given count. type: object required: - sealed title: BatchFinalizeResponse description: Response for POST /document/batch-finalize. MoveSkipReason: type: string enum: - name_conflict - batch_name_conflict - redundant_descendant - too_deep - cycle - already_there - not_at_source title: MoveSkipReason description: 'Why one selected item did not move (ENG-19224). Collisions are refused, never resolved: nothing is overwritten, merged, deleted, or unlinked by a move. Every obstruction is one of these, so a caller renders them from a single flat list.' GeneratedDocsByTasksResponse: properties: result: additionalProperties: type: string type: object title: Result type: object required: - result title: GeneratedDocsByTasksResponse description: Map of task/conversation id → newest generated ``.docx`` document id. DeleteDocumentsResponse: properties: accepted: type: integer title: Accepted description: Documents tombstoned and enrolled in the background purge. default: 0 workflow_id: anyOf: - type: string - type: 'null' title: Workflow Id description: Id of the drain workflow (None if nothing accepted). failed: items: $ref: '#/components/schemas/FailedDocDelete' type: array title: Failed description: Documents rejected before tombstoning (not found or not the owner). Capped at 100 entries. failed_count: type: integer title: Failed Count description: Total rejected documents, including any not listed in failed. default: 0 type: object title: DeleteDocumentsResponse description: 'Result for POST delete-documents (async, ENG-17809). The selected docs are tombstoned synchronously (they vanish from listings at once) and purged in the background by a Temporal workflow. ``failed`` holds only docs rejected before tombstoning (not found / not the owner / an archive still being extracted).' UploadStateResponse: properties: blobs: items: $ref: '#/components/schemas/UploadStateItem' type: array title: Blobs type: object required: - blobs title: UploadStateResponse AddDocumentToMatterResponse: properties: success: type: boolean title: Success already_linked: type: boolean title: Already Linked default: false type: object required: - success title: AddDocumentToMatterResponse description: Response for add-document-to-matter. Includes whether the link already existed. BatchDocumentsResponse: properties: documents: items: $ref: '#/components/schemas/BatchDocumentsItem' type: array title: Documents total: type: integer title: Total page: type: integer title: Page page_size: type: integer title: Page Size has_more: type: boolean title: Has More archives_pending: type: integer title: Archives Pending description: Upload containers in this batch that have not finished extracting. Silence in the document list means 'not written yet' while this is > 0 and 'never going to be written' once it is 0 — without it a client cannot tell the two apart and can only guess with a stall timer. default: 0 extraction_complete: type: boolean title: Extraction Complete description: True when no container in this batch is still extracting (``archives_pending == 0``). default: true type: object required: - documents - total - page - page_size - has_more title: BatchDocumentsResponse description: Paginated response for GET /document/batch/{batch_id}/documents. AddFoldersToMatterResponse: properties: added_doc_count: type: integer title: Added Doc Count description: Docs newly associated with the matter. folder_count: type: integer title: Folder Count description: Matter folders created for the mirrored subtree. skipped_count: type: integer title: Skipped Count description: Docs already associated with the matter (re-filed, not re-added). type: object required: - added_doc_count - folder_count - skipped_count title: AddFoldersToMatterResponse DocumentSource: type: string enum: - user - strongsuit title: DocumentSource description: 'Origin of a document: user-uploaded or system-generated (strongsuit).' CancelUploadV2Response: properties: cancelled_count: type: integer title: Cancelled Count description: Number of documents archived. type: object required: - cancelled_count title: CancelUploadV2Response description: Response for POST /document/cancel-upload-v2. AdminIngestHealthQueue: properties: queued: type: integer title: Queued processing: type: integer title: Processing customers: type: integer title: Customers default: 0 oldest_queued_minutes: anyOf: - type: number - type: 'null' title: Oldest Queued Minutes starved_jobs: type: integer title: Starved Jobs default: 0 high_retry_jobs: type: integer title: High Retry Jobs default: 0 top_user_id: anyOf: - type: string - type: 'null' title: Top User Id top_user_processing: type: integer title: Top User Processing default: 0 top_user_processing_share_pct: anyOf: - type: number - type: 'null' title: Top User Processing Share Pct type: object required: - queued - processing title: AdminIngestHealthQueue description: Current INGEST queue shape — depth, wait, concentration and stall signals. AddDocumentToTaskResponse: properties: success: type: boolean title: Success already_linked: type: boolean title: Already Linked default: false type: object required: - success title: AddDocumentToTaskResponse description: Response for add-document-to-task. Includes whether the link already existed. CancelUploadV2Request: properties: batch_id: type: string format: uuid title: Batch Id description: Batch ID from /add-documents-v2. task_id: anyOf: - type: string - type: 'null' title: Task Id matter_id: anyOf: - type: string - type: 'null' title: Matter Id type: object required: - batch_id title: CancelUploadV2Request description: Request for POST /document/cancel-upload-v2. AdminFailedIngestDownloadRequest: properties: target_user_id: type: string minLength: 1 title: Target User Id document_ids: items: type: string format: uuid type: array minItems: 1 title: Document Ids type: object required: - target_user_id - document_ids title: AdminFailedIngestDownloadRequest DeleteStatusResponse: properties: pending: type: integer title: Pending description: Documents still being purged (delete_state='deleting', or 'purging' once the drain claims them). default: 0 failed: type: integer title: Failed description: Documents that couldn't be deleted (delete_state='delete_failed'). default: 0 type: object title: DeleteStatusResponse description: 'Result for GET delete-status: counts sourced from delete_state (no Temporal query).' SearchScope: type: string enum: - subtree - current title: SearchScope description: "How deep a folder-listing query reaches (ENG-23085).\n\nQuery mode (any ``search`` or file filter) flattens the listing into a match set. This\nchooses what that set spans:\n\n- ``SUBTREE`` — matches at and below ``folder_id`` (the whole scope at root). The default,\n and the only behaviour before this flag existed, so an absent param is a no-op.\n- ``CURRENT`` — matches placed directly at ``folder_id``: its immediate child folders and\n the files at that level, nothing deeper.\n\nThe endpoint holds no policy about which affordance maps to which value — the frontend\nsends ``CURRENT`` for filter chips and ``SUBTREE`` for search (ENG-23088). Keeping the\nmapping there means a scope control, if one is ever wanted, overrides this param without\na backend change.\n\nThe restriction is applied in the query, never after paging: a page filtered post-hoc\nwould render short or empty and make ``has_next`` describe rows the caller never sees." MoveDocumentRequest: properties: doc_id: type: string format: uuid title: Doc Id description: Document to move target_folder_id: anyOf: - type: string format: uuid - type: 'null' title: Target Folder Id description: Destination folder; null/omit for root source_folder_id: anyOf: - type: string format: uuid - type: 'null' title: Source Folder Id description: Folder the doc is currently filed in (null = root); the placement being moved matter_id: anyOf: - type: string - type: 'null' title: Matter Id description: Matter scope; omit for DocHub type: object required: - doc_id title: MoveDocumentRequest BatchAddDocumentResult: properties: document_id: anyOf: - type: string - type: 'null' title: Document Id description: Document ID on success. error: anyOf: - type: string - type: 'null' title: Error description: Error message on per-item failure. task_linked: anyOf: - type: boolean - type: 'null' title: Task Linked description: True if document was linked to the requested task; False if link was attempted and failed; None if no task_id was provided. matter_linked: anyOf: - type: boolean - type: 'null' title: Matter Linked description: True if document was linked to the requested matter; False if link was attempted and failed; None if no matter_id was provided. type: object title: BatchAddDocumentResult description: Per-document result in a batch add-documents response. AddDocumentToMatterRequest: properties: doc_id: type: string format: uuid title: Doc Id description: UUID of the document to add matter_id: type: string minLength: 1 title: Matter Id description: CUID of the matter to add the document to type: object required: - doc_id - matter_id title: AddDocumentToMatterRequest DocumentCreditsResponse: properties: credits: type: integer title: Credits description: Total credits used for document processing in the requested window. type: object required: - credits title: DocumentCreditsResponse description: 'Response for GET /document/credits: Doc Hub processing credits for a month or ``since`` window.' DocumentListView: type: string enum: - all - matter_files - strongsuit - unassigned title: DocumentListView description: Tab scope for the document list. TaskSummaryWithUser: properties: id: type: string title: Id description: Task (Conversation) id. matter_id: anyOf: - type: string - type: 'null' title: Matter Id description: Matter the task belongs to. title: type: string title: Title description: Task title. module_number: anyOf: - type: integer - type: string - type: 'null' title: Module Number description: Module numeric identifier. user: anyOf: - $ref: '#/components/schemas/UserInfo' - type: 'null' description: Task owner. type: object required: - id - title title: TaskSummaryWithUser description: Task reference with owner user info for document metadata. MoveDocumentsRequest: properties: doc_ids: items: type: string format: uuid type: array maxItems: 1000 title: Doc Ids description: Documents to move (bulk, one transaction). target_folder_id: anyOf: - type: string format: uuid - type: 'null' title: Target Folder Id description: Destination folder; null/omit for root source_folder_id: anyOf: - type: string format: uuid - type: 'null' title: Source Folder Id description: Folder the docs are currently filed in (null = root); the placement being moved (DocHub only). matter_id: anyOf: - type: string - type: 'null' title: Matter Id description: Matter scope; omit for DocHub type: object required: - doc_ids title: MoveDocumentsRequest AddDocumentsToMatterResponse: properties: success: type: boolean title: Success added: type: integer title: Added default: 0 already_linked: type: integer title: Already Linked default: 0 type: object required: - success title: AddDocumentsToMatterResponse CheckDuplicateEntry: properties: hash: type: string title: Hash description: File hash, prefixed with its type (e.g. 'sha1:...'). filename: anyOf: - type: string - type: 'null' title: Filename description: 'The file''s display name (the SAME name you will send to /add-document, e.g. ''05_Affidavit.pdf''). REQUIRED for reliable same-name duplicate detection: ''skip'' vs ''alias'' turns on whether a file with this exact name already lives at the target folder. Falls back to the last segment of relative_path when omitted — but send it explicitly for bare-file/root uploads where relative_path is null, or a byte-identical re-upload to the same place is misdetected as an alias instead of a skip (ENG-17767).' relative_path: anyOf: - type: string - type: 'null' title: Relative Path description: 'The SAME relative_path you will send to /add-document: the folder-upload path incl. filename (e.g. ''dir01/test.txt''), or null for a bare file (send the name in ''filename''). Combined with target_directory_id to resolve where the file will live. Enables path-aware duplicate detection (ENG-17767): byte-identical content at a DIFFERENT path is a distinct record (a symlink alias), not a duplicate, so ''skip'' is returned only for a true no-op (same bytes+name at the same current path).' target_directory_id: anyOf: - type: string - type: 'null' title: Target Directory Id description: The SAME target_directory_id (current folder) you will send to /add-document. None = DocHub root. type: object required: - hash title: CheckDuplicateEntry CancelUploadRequest: properties: doc_ids: items: type: string format: uuid type: array minItems: 1 title: Doc Ids description: UUIDs of the documents whose uploads should be cancelled. task_id: anyOf: - type: string - type: 'null' title: Task Id description: If provided, only unlink docs from this specific task instead of all tasks. matter_id: anyOf: - type: string - type: 'null' title: Matter Id description: If provided, also unlink docs from this specific matter. type: object required: - doc_ids title: CancelUploadRequest GetDownloadURLResponse: properties: url: anyOf: - type: string - type: 'null' title: Url expires_at: anyOf: - type: string format: date-time - type: 'null' title: Expires At type: object title: GetDownloadURLResponse DocumentPurpose: type: string enum: - template title: DocumentPurpose description: 'What an uploaded document will be used for, on shared upload endpoints that serve multiple callers. Lets a route apply purpose-specific validation (e.g. TEMPLATE enforces .docx, ENG-17640) without affecting uploads that omit it.' MoveItemsResponse: properties: success: type: boolean title: Success default: true moved_folder_count: type: integer title: Moved Folder Count description: Folders relocated. moved_file_count: type: integer title: Moved File Count description: Files relocated. skipped: items: $ref: '#/components/schemas/MoveItemsSkipped' type: array title: Skipped description: Items that did not move, capped at 200. skipped_total: type: integer title: Skipped Total description: Total skipped, including any beyond the cap. default: 0 skipped_truncated: type: boolean title: Skipped Truncated description: True when ``skipped`` omits some of ``skipped_total``. default: false checked_at: anyOf: - type: string format: date-time - type: 'null' title: Checked At description: 'Preflight only: when the check ran. Advisory — the destination can change before the move, so the move re-validates independently rather than trusting this result.' type: object required: - moved_folder_count - moved_file_count title: MoveItemsResponse BatchFinalizeRequest: properties: batch_id: type: string format: uuid title: Batch Id description: UUID of the DocHubUploadBatch to seal. expected_doc_count: type: integer minimum: 0.0 title: Expected Doc Count description: Actual number of docs successfully registered this session (discounts failed/cancelled uploads). type: object required: - batch_id - expected_doc_count title: BatchFinalizeRequest description: 'Request for POST /document/batch-finalize: seal an upload batch with its true size.' EmailProvenance: properties: subject: anyOf: - type: string - type: 'null' title: Subject description: The email's Subject header. sender: anyOf: - type: string - type: 'null' title: Sender description: From header, as 'Display Name
' when the message carried both. to: items: type: string type: array title: To description: To recipients, as 'Display Name
'. Capped at 25; a longer list is truncated. cc: items: type: string type: array title: Cc description: Cc recipients, same shape and cap as `to`. sent_at: anyOf: - type: string - type: 'null' title: Sent At description: The Date header, as an ISO 8601 string. A string rather than a timestamp because a sender whose client wrote a malformed date is passed through verbatim rather than dropped — parse it if you can, otherwise render it as text. message_id: anyOf: - type: string - type: 'null' title: Message Id description: RFC 5322 Message-ID, angle brackets included. The same value in every mailbox holding a copy. type: object title: EmailProvenance description: 'The message an attachment arrived on (ENG-22885). Recorded on the email document when its attachments were extracted, and read here through ``parent_id``. Every field is optional because it mirrors the headers the message actually carried: an email with no ``Cc`` has none, and a message whose headers could not be decoded has nothing at all. Absent entirely for a file that is not an email attachment, and for one whose email was ingested before the extractor recorded provenance — re-ingesting that email fills it in.' DocumentMetadataSummary: properties: id: type: string format: uuid title: Id description: Document id. date_added: anyOf: - type: string format: date-time - type: 'null' title: Date Added description: When the document was added. size: anyOf: - type: integer - type: 'null' title: Size description: Size in bytes. kind: anyOf: - type: string - type: 'null' title: Kind description: Mime type (e.g. application/pdf). type_label: type: string title: Type Label description: Short display type, e.g. 'pdf'. Derived from the mime type first and the filename extension only as a fallback, so a file uploaded without an extension still shows its real type. Render this rather than parsing the name — the folder listing's type sort uses the same derivation, and parsing the name yourself puts the label out of step with the ordering. Empty only when neither signal is available. default: '' category: anyOf: - type: string - type: 'null' title: Category description: Document type / classification (e.g. COMPLAINT, BRIEF, EMAIL). From file_content_type. associated_matters: items: $ref: '#/components/schemas/MatterSummaryWithUser' type: array title: Associated Matters description: Matters this document is linked to (id, name, owner user). associated_tasks: items: $ref: '#/components/schemas/TaskSummaryWithUser' type: array title: Associated Tasks description: Tasks this document is linked to (id, title, module number, owner user). name: type: string title: Name description: Original file name (basename). original_relative_path: anyOf: - type: string - type: 'null' title: Original Relative Path description: Folder path the document was uploaded under (e.g. 'bank accounts/2024/statement.pdf'); null if uploaded flat. folder_path: anyOf: - type: string - type: 'null' title: Folder Path description: Current DocHub folder placement path ending in the filename (e.g. 'bank accounts/statement.pdf'); null when at root. Reflects moves/direct-into-folder uploads, unlike original_relative_path. parent_id: anyOf: - type: string format: uuid - type: 'null' title: Parent Id description: 'Document this one was extracted from: an archive member''s archive, or an email attachment''s email. Null for a file added on its own.' parent_name: anyOf: - type: string - type: 'null' title: Parent Name description: Display name of the parent_id document, when the listing could resolve it. Null when parent_id is null or the parent is not visible to this listing. email_provenance: anyOf: - $ref: '#/components/schemas/EmailProvenance' - type: 'null' description: 'The email this document was extracted from, as a message rather than a file: sender, recipients, sent date, subject, Message-ID. Populated by the single-document metadata endpoint only — listings omit it to keep the page payload down. Null when the document is not an email attachment, or when its email predates provenance being recorded. Equal to `email_sources[0].provenance` when `email_sources` is non-empty; kept as its own field for clients that only need the one message.' email_sources: items: $ref: '#/components/schemas/EmailSource' type: array title: Email Sources description: 'Every email this document arrived on that the caller may see, not just the first (ENG-22887). A deduplicated attachment is stored once but can have been delivered by several messages. Ordered: the document''s own parent email first — so the head is the message the ''Extracted from'' label names — then oldest *ingested* first, which is send order only for a mailbox synced in order; sort on `provenance.sent_at` if you need true chronology. More than one entry means the file was received more than once. Empty for a document that is not an email attachment, and on listing endpoints, which omit it.' email_sources_truncated: type: boolean title: Email Sources Truncated description: True when more emails carried this document than `email_sources` lists (the cap is 25). The count of the remainder is deliberately not reported — it would cost a second query for a number the panel does not need. Always false on listing endpoints. default: false processed_tokens: anyOf: - type: integer - type: 'null' title: Processed Tokens description: Tokens ingestion actually produced for this document (the OCR/parse output), from the usage ledger. Null until processing has recorded usage. Lets a client compare its own pre-upload count with what was billed. credits_charged: anyOf: - type: number - type: 'null' title: Credits Charged description: Credits charged for this document across ingestion and summarization, from the usage ledger. Null until recorded. user_id: type: string title: User Id description: ID of the user who uploaded the document. user: anyOf: - $ref: '#/components/schemas/UserInfo' - type: 'null' description: Full user info of the uploader (None if account deleted). location: anyOf: - type: string - type: 'null' title: Location description: Storage path. checksum: anyOf: - type: string - type: 'null' title: Checksum description: Content checksum. percent_complete: anyOf: - type: integer - type: 'null' title: Percent Complete description: Processing progress 0-100. source: anyOf: - $ref: '#/components/schemas/DocumentSource' - type: 'null' description: 'Origin of the document: ''user'' (uploaded) or ''strongsuit'' (system-generated).' can_edit: type: boolean title: Can Edit description: Whether the requesting user can edit (rename, re-categorise, …) this document. default: false ingestion_status: $ref: '#/components/schemas/IngestionStatus' description: 'Derived per-doc ingestion status. Projected from DocMetadata.status and the latest INGEST DocHubJob. Values: queued, processing, done, failed, stranded, unknown.' default: unknown failure_reason: anyOf: - type: string - type: 'null' title: Failure Reason description: Populated when ingestion_status is 'failed'; short machine-readable reason (e.g. 'password_protected'). archive_members_total: anyOf: - type: integer - type: 'null' title: Archive Members Total description: 'Archives only: how many files the archive holds, known once extraction has planned its members. Null for ordinary documents and for archives that have not started extracting. NOT cleared when extraction finishes, so a fully processed archive keeps its final total; read it only alongside ingestion_status.' archive_members_done: anyOf: - type: integer - type: 'null' title: Archive Members Done description: 'Archives only: how many members have been registered as documents so far. Climbs while ingestion_status is ''processing''; on ''failed'' it is how many files did land. NOT cleared when extraction finishes, so a processed archive keeps its final n of N — do not read it as ''still extracting'' without checking ingestion_status.' already_linked_to_task: anyOf: - type: boolean - type: 'null' title: Already Linked To Task description: True if this document is already linked to the specified task_id. Only populated when linked_task_id is provided in the request; null otherwise. type: object required: - id - name - user_id title: DocumentMetadataSummary description: Abbreviated document metadata for API responses (subset of DocMetadata). PollDocumentsV2Summary: properties: total: type: integer title: Total default: 0 registering: type: integer title: Registering default: 0 unprocessed: type: integer title: Unprocessed default: 0 processed: type: integer title: Processed default: 0 failed: type: integer title: Failed default: 0 type: object title: PollDocumentsV2Summary description: Aggregate status counts for a batch. DocumentTokenEstimateFileRequest: properties: name: type: string title: Name description: File name including extension. tokens: type: integer minimum: 0.0 title: Tokens description: Text tokens counted locally (o200k_base). ocr_pages: type: integer minimum: 0.0 title: Ocr Pages description: Pages the backend will OCR (no text layer). default: 0 pages: type: integer minimum: 0.0 title: Pages description: Total page count when known; used for the time estimate. default: 0 total_bytes: type: integer minimum: 0.0 title: Total Bytes description: File size in bytes; used for the time estimate. default: 0 type: object required: - name - tokens title: DocumentTokenEstimateFileRequest description: 'One file the desktop uploader has already read and counted. ``tokens`` is the text the backend will process, tokenized locally with the same encoder ingestion uses. ``ocr_pages`` are pages with no usable text layer (scans, photos); the server prices those from its own per-page figure so the constant lives in one place. A container (zip, email) is sent as one entry carrying the sum of its members.' AdminFailedIngestListResponse: properties: user: $ref: '#/components/schemas/AdminFailedDocsUser' documents: items: $ref: '#/components/schemas/AdminFailedDocItem' type: array title: Documents total_failed: type: integer title: Total Failed retryable_count: type: integer title: Retryable Count permanent_count: type: integer title: Permanent Count empty_blob_count: type: integer title: Empty Blob Count alias_count: type: integer title: Alias Count default: 0 truncated: type: boolean title: Truncated default: false type: object required: - user - total_failed - retryable_count - permanent_count - empty_blob_count title: AdminFailedIngestListResponse RenameDocumentResponse: properties: previous_name: type: string title: Previous Name new_name: type: string title: New Name error: anyOf: - type: string - type: 'null' title: Error type: object required: - previous_name - new_name title: RenameDocumentResponse AdminFailedDocItem: properties: id: type: string format: uuid title: Id name: type: string title: Name mime_type: anyOf: - type: string - type: 'null' title: Mime Type size_bytes: anyOf: - type: integer - type: 'null' title: Size Bytes upload_datetime: anyOf: - type: string format: date-time - type: 'null' title: Upload Datetime location: anyOf: - type: string - type: 'null' title: Location failure_reason: anyOf: - type: string - type: 'null' title: Failure Reason failure_detail: anyOf: - type: string - type: 'null' title: Failure Detail description: Human-readable why this row is FAILED_NO_RETRY and whether retry can help. last_transient_failure: anyOf: - type: string - type: 'null' title: Last Transient Failure job_error: anyOf: - type: string - type: 'null' title: Job Error description: Latest DocHubJob.error_message for this document, if any. percent_complete: anyOf: - type: integer - type: 'null' title: Percent Complete retryable: type: boolean title: Retryable skip_reason: anyOf: - type: string - type: 'null' title: Skip Reason description: 'Why this row cannot be re-queued: permanent, empty_blob, alias.' has_location: type: boolean title: Has Location default: false type: object required: - id - name - retryable title: AdminFailedDocItem description: One FAILED_NO_RETRY DocHub file for the admin failed-ingest tool. RemoveFoldersFromMatterResponse: properties: removed_doc_count: type: integer title: Removed Doc Count description: Docs un-associated from the matter (still in DocHub). removed_folder_count: type: integer title: Removed Folder Count description: Matter folder nodes dropped. skipped_count: type: integer title: Skipped Count description: Requested loose doc_ids that weren't associated (no-op). type: object required: - removed_doc_count - removed_folder_count - skipped_count title: RemoveFoldersFromMatterResponse MoveFolderRequest: properties: new_parent_id: anyOf: - type: string format: uuid - type: 'null' title: New Parent Id description: Destination parent; omit/null to move to root matter_id: anyOf: - type: string - type: 'null' title: Matter Id description: Matter scope; omit for DocHub type: object title: MoveFolderRequest DeleteDocumentRequest: properties: document_id: type: string format: uuid title: Document Id description: UUID of the document to delete. type: object required: - document_id title: DeleteDocumentRequest CreateUploadUrlResponse: properties: upload_url: type: string title: Upload Url expires_at: type: string format: date-time title: Expires At type: object required: - upload_url - expires_at title: CreateUploadUrlResponse UploadStateItem: properties: blob_path: type: string title: Blob Path complete: type: boolean title: Complete description: Storage already holds this exact file, finished. Do not send it again. staged_blocks: items: type: string type: array title: Staged Blocks description: Block ids staged against this blob but not committed. A resumed upload sends only the blocks missing from this list. Empty when the blob is absent, complete, or was not staged in blocks. type: object required: - blob_path - complete title: UploadStateItem FailedDocDelete: properties: id: type: string format: uuid title: Id reason: type: string title: Reason type: object required: - id - reason title: FailedDocDelete description: One per-doc failure entry for bulk delete responses. UploadStateRequest: properties: blobs: items: $ref: '#/components/schemas/UploadStateQuery' type: array maxItems: 1000 title: Blobs type: object required: - blobs title: UploadStateRequest MatterSummaryWithUser: properties: id: type: string title: Id description: Matter id. name: type: string title: Name description: Matter name/title. user: anyOf: - $ref: '#/components/schemas/UserInfo' - type: 'null' description: Matter owner. type: object required: - id - name title: MatterSummaryWithUser description: Matter reference with owner user info for document metadata. MoveItemsRequest: properties: folder_ids: items: type: string format: uuid type: array maxItems: 1000 title: Folder Ids description: Folders to move. doc_ids: items: type: string format: uuid type: array maxItems: 1000 title: Doc Ids description: Files to move. target_folder_id: anyOf: - type: string format: uuid - type: 'null' title: Target Folder Id description: Destination folder; null/omit for root. source_folder_id: anyOf: - type: string format: uuid - type: 'null' title: Source Folder Id description: The level being moved out of (null = root). Every selected item must currently live here. move_all_at_source: type: boolean title: Move All At Source description: Move everything at ``source_folder_id`` instead of an explicit selection, resolved server-side. Required for levels larger than one page — a paged client only holds the ids it has rendered. When true, ``folder_ids``/``doc_ids`` are ignored. default: false exclude_doc_ids: items: type: string format: uuid type: array maxItems: 5000 title: Exclude Doc Ids description: 'Doc IDs to exclude from move_all_at_source. Used for the mode+delta selection model: the user selected all, then unchecked a few files. Only effective when move_all_at_source is true.' exclude_folder_ids: items: type: string format: uuid type: array maxItems: 500 title: Exclude Folder Ids description: Folder IDs to exclude from move_all_at_source. Only effective when move_all_at_source is true. matter_id: anyOf: - type: string - type: 'null' title: Matter Id description: Matter scope; omit for DocHub. type: object title: MoveItemsRequest AdminFailedIngestDownloadResponse: properties: items: items: $ref: '#/components/schemas/AdminFailedIngestDownloadItem' type: array title: Items skipped: items: $ref: '#/components/schemas/AdminFailedIngestSkip' type: array title: Skipped type: object title: AdminFailedIngestDownloadResponse FolderNodeSchema: properties: id: type: string format: uuid title: Id name: type: string title: Name parent_id: anyOf: - type: string format: uuid - type: 'null' title: Parent Id file_count: anyOf: - type: integer - type: 'null' title: File Count description: Files placed directly in this folder subfolder_count: anyOf: - type: integer - type: 'null' title: Subfolder Count description: Direct child folders path: anyOf: - type: string - type: 'null' title: Path description: Scope-relative ancestry path (root→leaf, e.g. 'Bank/2024/drafts'); set on name-search hits so a flat result folder is navigable/disambiguated, null on normal level listings. created_at: anyOf: - type: string format: date-time - type: 'null' title: Created At description: Folder creation time — the folder-side analogue of a file's upload_datetime, and what sort_by=date_added orders folders by. Render this in a 'Date Added' column so the sort is visible. type: object required: - id - name title: FolderNodeSchema ExportDocumentsResponse: properties: workflow_id: type: string title: Workflow Id type: object required: - workflow_id title: ExportDocumentsResponse EmailSource: properties: document_id: type: string format: uuid title: Document Id description: Doc Hub id of the email document itself. name: type: string title: Name description: The email document's display name (its stored .eml filename). provenance: $ref: '#/components/schemas/EmailProvenance' description: That email's own headers. Fields the message did not carry are null/empty. type: object required: - document_id - name - provenance title: EmailSource description: 'One email a document arrived on, as the details panel lists it (ENG-22887). A deduplicated attachment is stored once but can have arrived on several emails; each of them recorded the document id it resolved to, and that is the only record the file came more than once. Listing them is what lets a matter trace the file back to every message that delivered it, rather than to whichever one happened to be resolved first. ``document_id`` is the email''s own Doc Hub document, so a client can open it.' AdminFailedIngestDownloadItem: properties: id: type: string format: uuid title: Id name: type: string title: Name url: type: string title: Url expires_at: anyOf: - type: string format: date-time - type: 'null' title: Expires At type: object required: - id - name - url title: AdminFailedIngestDownloadItem MoveItemsSkipped: properties: kind: type: string enum: - folder - file title: Kind id: type: string format: uuid title: Id reason: $ref: '#/components/schemas/MoveSkipReason' type: object required: - kind - id - reason title: MoveItemsSkipped ClearDocsResponse: properties: success: type: boolean title: Success description: False when some documents were left behind — an archive still being extracted is refused rather than purged (ENG-22114). Compare deleted_count with the names requested to see how many. deleted_count: type: integer title: Deleted Count description: Number of doc_metadata rows deleted. type: object required: - success - deleted_count title: ClearDocsResponse description: 'Response for POST clear-docs: hard-deletes matching documents owned by the user.' AddDocumentsV2Response: properties: batch_id: type: string title: Batch Id description: Batch ID for polling via /poll-documents-v2. workflow_id: type: string title: Workflow Id description: Temporal workflow ID. doc_count: type: integer title: Doc Count description: Number of documents in the manifest. type: object required: - batch_id - workflow_id - doc_count title: AddDocumentsV2Response description: Response for POST /document/add-documents-v2. BatchStartResponse: properties: batch_id: anyOf: - type: string format: uuid - type: 'null' title: Batch Id description: UUID of the created DocHubUploadBatch row. None for non-dataset uploads. type: object title: BatchStartResponse description: 'Response for POST /document/batch-start: returns the batch_id to pass on each upload.'