Files
Jacob Mathison e3d9047143 Merged in jmathison/DEVOPS-722 (pull request #226)
DEVOPS-722 enforce team management visibility

* DEVOPS-722 enforce team management visibility

* DEVOPS-722 reduce admin user list complexity

* DEVOPS-722 cover admin access helpers

* DEVOPS-722 address team management PR feedback

* DEVOPS-722 fix admin access tests in CI

* DEVOPS-722 fix remaining admin PR feedback
2026-05-12 16:49:12 +00:00

7304 lines
221 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
openapi: 3.0.3
info:
title: Query Orchestration API
description: API documentation for the Query Orchestration services.
version: 0.0.1
contact:
email: piragavarapu@aarete.com
name: Aarete Inc.
url: https://aarete.com
license:
name: Aarete Inc.internal use
url: https://aarete.com
servers:
- url: https://doczy.com/v1
description: Production server
tags:
- name: ClientService
description: Operations related to clients
- name: CollectorService
description: Operations related to collectors
- name: DocumentsService
description: Operations related to documents
- name: FolderService
description: Operations related to document folders and organization
- name: LabelService
description: Operations related to document labels and workflow tracking
- name: FieldExtractionService
description: Operations related to document field extractions
- name: ExportService
description: Operations related to exports
- name: AuthService
description: Operations related to authentication
- name: AdminService
description: Operations related to user management and administration
- name: EulaService
description: Operations related to End User License Agreement management and tracking
- name: UISettingsService
description: Generic UI key-value settings (e.g. demo-dashboard:{userId}, feature-flags:global, saved-filters:{clientId})
- name: SuperAdminSchemaService
description: |
Super-admin-only endpoints for managing client-scoped JSON Schemas
used to validate custom document metadata. All routes under this tag
require the super_admin Permit.io role; user_admin and below are
denied by the resource-action gate on the super-admin resource.
- name: CustomMetadataService
description: |
Read/write operations for a document's mutable custom metadata
payload. Available to client_user, user_admin, and super_admin
(auditor is read-only). Requires the owning document to first be
bound to a client_metadata_schemas row via PATCH
/super-admin/documents/{id}/schema.
- name: BotService
description: |
Owner-scoped chatbot session/scope/turn endpoints for client_user.
Sessions are visible only to their creator within a client.
Routes use the singular `/client/{clientId}/...` form per plan §3.
- name: SuperAdminBotService
description: |
Super-admin-only chatbot session endpoints. Lists, reads, and
soft-deletes bot sessions across all users within a client.
Restricted to the super_admin Permit.io role.
paths:
/client:
post:
operationId: createClient
tags:
- ClientService
summary: Create a new client
description: Creates a new client with the provided details.
security:
- jwtAuth: []
requestBody:
description: The details required to create a client
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ClientCreate"
responses:
"201":
description: Client created successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ClientIDBody"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/clients:
get:
operationId: listClients
tags:
- ClientService
summary: List all clients
description: Returns a list of all clients in the system.
security:
- jwtAuth: []
responses:
"200":
description: List of clients retrieved successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ClientListResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{id}:
parameters:
- $ref: "#/components/parameters/ClientID"
get:
operationId: getClient
tags:
- ClientService
summary: Get a client by ID
description: Retrieves a specific client by its ID.
security:
- jwtAuth: []
responses:
"200":
description: Client details.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/DocClient"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
patch:
operationId: updateClient
tags:
- ClientService
summary: Update a client
description: Updates an existing client with new details.
security:
- jwtAuth: []
requestBody:
description: The details to update
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ClientUpdate"
responses:
"200":
description: Client updated successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
delete:
operationId: deleteClient
tags:
- ClientService
summary: Hard-delete a client and all its data
description: >-
Permanently deletes a client and all associated data including documents,
folders, collectors, batch uploads, and sync records. Source documents in
S3 are NOT deleted but their paths are logged. This operation is
irreversible. Requires confirm=true query parameter.
security:
- jwtAuth: []
parameters:
- name: confirm
in: query
description: Must be set to true to confirm deletion
required: true
schema:
type: boolean
- name: verbose
in: query
required: false
description: When true, returns S3 paths of orphaned source documents in the response body
schema:
type: boolean
default: false
responses:
"200":
description: Client deleted successfully (verbose mode).
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/DeleteResponse"
"204":
description: Client deleted successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
# Query paths have been removed - see remove_query_plan.md
/client/{id}/status:
parameters:
- $ref: "#/components/parameters/ClientID"
get:
operationId: getStatusByClientId
tags:
- ClientService
summary: Get client sync status
description: Retrieves the sync status by its client ID.
security:
- jwtAuth: []
responses:
"200":
description: Client status details.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ClientStatusBody"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{id}/collector:
parameters:
- $ref: "#/components/parameters/ClientID"
get:
operationId: getCollectorByClientId
tags:
- CollectorService
summary: Get a collector by client ID
description: Retrieves a specific collector by its client ID.
security:
- jwtAuth: []
responses:
"200":
description: Collector details.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/Collector"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
patch:
operationId: setCollectorByClientId
tags:
- CollectorService
summary: Set a collector
description: Set client collector with new details.
security:
- jwtAuth: []
requestBody:
description: The details to be set for the collector.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CollectorSet"
responses:
"204":
description: Collector set successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{id}/folders:
parameters:
- $ref: "#/components/parameters/ClientID"
get:
operationId: listClientFolders
tags:
- FolderService
summary: List folders for a client
description: |
Returns all folders belonging to a client. The response includes each folder's
ID, path, and parent folder ID, allowing clients to reconstruct the folder hierarchy.
Root-level folders will have a null parentId.
When metrics=true is specified, each folder will include processing metrics
(document counts and label breakdown). This adds overhead so should only be
used when metrics are needed.
security:
- jwtAuth: []
parameters:
- name: metrics
in: query
required: false
description: |
When true, include processing metrics for each folder (document counts by label).
Defaults to false for performance reasons.
schema:
type: boolean
default: false
responses:
"200":
description: List of folders for the client.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/FolderList"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{id}/document:
parameters:
- $ref: "#/components/parameters/ClientID"
get:
operationId: listDocumentsByClientId
tags:
- DocumentsService
summary: List the documents for a client
description: Retrieves the list of documents by the client ID.
security:
- jwtAuth: []
responses:
"200":
description: Client documents list.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ListDocuments"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
post:
operationId: uploadDocument
tags:
- DocumentsService
summary: Upload a file
description: Upload a single file to the server with optional metadata
security:
- jwtAuth: []
requestBody:
required: true
description: upload file body
content:
multipart/form-data:
schema:
type: object
required:
- file
properties:
file:
type: string
format: binary
maxLength: 107374182400
description: The file to upload
filename:
type: string
pattern: ".+"
maxLength: 4096
description: Optional custom filename
example: "document.pdf"
encoding:
file:
contentType: application/pdf
style: form
explode: false
responses:
"200":
description: Document uploaded.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{id}/document/batch:
parameters:
- $ref: "#/components/parameters/ClientID"
post:
operationId: uploadDocumentBatch
tags:
- DocumentsService
summary: Upload multiple PDF documents as ZIP archive
description: Upload a ZIP archive containing multiple PDF documents for async batch processing
security:
- jwtAuth: []
requestBody:
required: true
description: ZIP archive containing PDF documents
content:
multipart/form-data:
schema:
type: object
required:
- archive
properties:
archive:
type: string
format: binary
maxLength: 1073741824 # 1GB limit for ZIP files
description: The file to be uploaded as a ZIP archive
encoding:
archive:
contentType: application/zip
style: form
explode: false
responses:
"202":
description: Batch upload accepted for processing
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/BatchUploadResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
get:
operationId: listDocumentBatches
tags:
- DocumentsService
summary: List batch uploads for a client
description: Retrieves a list of batch uploads for the specified client
security:
- jwtAuth: []
parameters:
- in: query
name: limit
schema:
type: integer
format: int32
minimum: 1
maximum: 100
default: 20
description: Maximum number of items to return
- in: query
name: offset
schema:
type: integer
format: int32
minimum: 0
maximum: 2147483647
default: 0
description: Number of items to skip
responses:
"200":
description: List of batch uploads
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/BatchUploadList"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{id}/document/batch/{batch_id}:
parameters:
- $ref: "#/components/parameters/ClientID"
- $ref: "#/components/parameters/BatchID"
get:
operationId: getDocumentBatch
tags:
- DocumentsService
summary: Get batch upload status
description: Retrieves detailed status information for a specific batch upload
security:
- jwtAuth: []
responses:
"200":
description: Batch upload details
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/BatchUploadDetails"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/document/{id}:
parameters:
- $ref: "#/components/parameters/DocumentID"
get:
operationId: getDocument
tags:
- DocumentsService
summary: Get document details by its id
description: |
Retrieves the details of a document by its id, including metadata such as
folder, filename, labels, and optionally the full text extraction record.
security:
- jwtAuth: []
parameters:
- name: textRecord
in: query
required: false
description: When true, includes the full text extraction record in the response
schema:
type: boolean
default: false
responses:
"200":
description: Document details.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/DocumentEnriched"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
delete:
operationId: deleteDocument
tags:
- DocumentsService
summary: Hard-delete a document
description: >-
Permanently deletes a document and all dependent data including entries,
cleans, text extractions, field extractions, labels, and results. Source
documents in S3 are NOT deleted but their paths are logged.
security:
- jwtAuth: []
parameters:
- name: verbose
in: query
required: false
description: When true, returns S3 paths of orphaned source documents in the response body
schema:
type: boolean
default: false
responses:
"200":
description: Document deleted successfully (verbose mode).
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/DeleteResponse"
"204":
description: Document deleted successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/document/{id}/download:
parameters:
- $ref: "#/components/parameters/DocumentID"
get:
operationId: downloadDocument
tags:
- DocumentsService
summary: Download the original document file
description: |
Streams the original uploaded document file. The response Content-Type
is auto-detected from the stored filename extension. No query parameters
are required; the system resolves the file type automatically.
security:
- jwtAuth: []
responses:
"200":
description: Document file bytes.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
Content-Disposition:
schema:
type: string
maxLength: 4096
description: 'Attachment header with original filename, e.g. attachment; filename="report.pdf"'
content:
application/octet-stream:
schema:
type: string
format: binary
maxLength: 107374182400
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/folders:
post:
operationId: createFolder
tags:
- FolderService
summary: Create a new folder
description: Creates a new folder for organizing documents.
security:
- jwtAuth: []
requestBody:
description: The details required to create a folder
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/FolderCreate"
responses:
"201":
description: Folder created successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/Folder"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/folders/{folderId}:
parameters:
- name: folderId
in: path
required: true
description: The folder ID
schema:
type: string
format: uuid
maxLength: 50
patch:
operationId: renameFolder
tags:
- FolderService
summary: Rename a folder
description: Updates the folder path/name.
security:
- jwtAuth: []
requestBody:
description: The new folder path
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/FolderRename"
responses:
"200":
description: Folder renamed successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/Folder"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
delete:
operationId: deleteFolder
tags:
- FolderService
summary: Hard-delete a folder tree
description: >-
Permanently deletes a folder and all its child folders recursively. The
root folder (path '/') cannot be deleted. If the folder tree contains
documents, include_documents=true is required or a 409 Conflict is
returned. When include_documents=true, all documents in the tree are
also permanently deleted. Source documents in S3 are NOT deleted but
their paths are logged.
security:
- jwtAuth: []
parameters:
- name: include_documents
in: query
required: false
description: When true, also deletes all documents in the folder tree
schema:
type: boolean
default: false
- name: verbose
in: query
required: false
description: When true, returns S3 paths of orphaned source documents in the response body
schema:
type: boolean
default: false
responses:
"200":
description: Folder tree deleted successfully (verbose mode).
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/DeleteResponse"
"204":
description: Folder tree deleted successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Conflict"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/folders/{folderId}/documents:
parameters:
- name: folderId
in: path
required: true
description: The folder ID
schema:
type: string
format: uuid
maxLength: 50
get:
operationId: getFolderDocuments
tags:
- FolderService
summary: Get documents in a folder
description: |
Retrieves all documents within a specific folder, including filename and labels.
Optionally includes the full text extraction record for each document.
Returns a lighter-weight format than GET /document/{id} (excludes client_id and computed fields).
security:
- jwtAuth: []
parameters:
- name: textRecord
in: query
required: false
description: When true, includes the full text extraction record for each document
schema:
type: boolean
default: false
responses:
"200":
description: List of documents in folder.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
type: object
properties:
documents:
type: array
maxItems: 10000
items:
$ref: "#/components/schemas/DocumentInFolder"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/folders/{folderId}/metrics:
parameters:
- name: folderId
in: path
required: true
description: The folder ID
schema:
type: string
format: uuid
maxLength: 50
get:
operationId: getFolderMetrics
tags:
- FolderService
summary: Get folder processing metrics
description: Retrieves processing progress metrics for documents in a folder.
security:
- jwtAuth: []
responses:
"200":
description: Folder metrics.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/FolderMetrics"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/documents/{documentId}/labels:
parameters:
- name: documentId
in: path
required: true
description: The document ID
schema:
type: string
format: uuid
maxLength: 50
post:
operationId: applyLabel
tags:
- LabelService
summary: Apply a label to a document
description: Applies a workflow label to a document for tracking processing state.
security:
- jwtAuth: []
requestBody:
description: The label to apply
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/LabelApplication"
responses:
"201":
description: Label applied successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/LabelRecord"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
get:
operationId: getDocumentLabels
tags:
- LabelService
summary: Get all labels for a document
description: Retrieves all labels that have been applied to a document, ordered by most recent first.
security:
- jwtAuth: []
responses:
"200":
description: List of labels.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
type: object
properties:
labels:
type: array
maxItems: 1000
items:
$ref: "#/components/schemas/LabelRecord"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/labels/{labelName}/documents:
parameters:
- name: labelName
in: path
required: true
description: The label name
schema:
type: string
maxLength: 100
pattern: "^[A-Za-z0-9_]+$"
- name: clientId
in: query
required: true
description: The client ID to filter documents
schema:
$ref: "#/components/schemas/ClientID"
get:
operationId: getDocumentsByLabel
tags:
- LabelService
summary: Get all documents with a specific label
description: Retrieves all documents that have been tagged with a specific label.
security:
- jwtAuth: []
responses:
"200":
description: List of documents with this label.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
type: object
properties:
documents:
type: array
maxItems: 10000
items:
$ref: "#/components/schemas/DocumentSummary"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{id}/export:
parameters:
- $ref: "#/components/parameters/ClientID"
post:
operationId: triggerExport
tags:
- ExportService
summary: Trigger an export
description: Initiates the export process.
security:
- jwtAuth: []
requestBody:
description: The export requirements.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ExportTrigger"
responses:
"201":
description: Export triggered successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/IdMessage"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/export/{id}:
parameters:
- $ref: "#/components/parameters/ExportID"
get:
operationId: exportState
tags:
- ExportService
summary: Check export state.
description: Checks the current state of an export.
security:
- jwtAuth: []
responses:
"200":
description: Export has been completed.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ExportDetails"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/field-extractions:
post:
operationId: createFieldExtraction
tags:
- FieldExtractionService
summary: Create a new field extraction
description: Creates a new field extraction with single-value and array fields for a document.
security:
- jwtAuth: []
requestBody:
description: The field extraction data
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/FieldExtractionRequest"
responses:
"201":
description: Field extraction created successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/FieldExtractionResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
get:
operationId: getCurrentFieldExtraction
tags:
- FieldExtractionService
summary: Get current field extraction
description: Retrieves the most recent field extraction for a document.
security:
- jwtAuth: []
parameters:
- name: documentId
in: query
required: true
description: The document ID
schema:
type: string
format: uuid
maxLength: 50
responses:
"200":
description: Current field extraction.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/FieldExtractionResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/field-extractions/version:
get:
operationId: getFieldExtractionByVersion
tags:
- FieldExtractionService
summary: Get field extraction by version
description: Retrieves a specific version of field extraction for a document.
security:
- jwtAuth: []
parameters:
- name: documentId
in: query
required: true
description: The document ID
schema:
type: string
format: uuid
maxLength: 50
- name: version
in: query
required: true
description: The version number to retrieve
schema:
type: integer
format: int64
minimum: 1
maximum: 9223372036854775807
responses:
"200":
description: Field extraction for the specified version.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/FieldExtractionResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/field-extractions/history:
get:
operationId: getFieldExtractionHistory
tags:
- FieldExtractionService
summary: Get field extraction version history
description: Retrieves all versions of field extractions for a document, ordered by most recent first.
security:
- jwtAuth: []
parameters:
- name: documentId
in: query
required: true
description: The document ID
schema:
type: string
format: uuid
maxLength: 50
responses:
"200":
description: Field extraction history.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
type: object
properties:
versions:
type: array
maxItems: 1000
items:
$ref: "#/components/schemas/FieldExtractionVersion"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/login:
get:
operationId: login
tags:
- AuthService
summary: Login to the application
description: >-
Initiates the login flow by redirecting to Cognito IDP login page.
security:
- {}
- cognitoAuth: [openid, email, profile]
responses:
"302":
description: Redirect to Cognito login page
headers:
Location:
schema:
type: string
format: uri
maxLength: 2048
pattern: "^https://.*"
description: URL to the Cognito login page
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/login-callback:
get:
operationId: loginCallback
tags:
- AuthService
summary: OAuth2 callback endpoint
description: >-
Handles the OAuth2 callback during the login process. Receives the
authorization code from Cognito IDP and exchanges it for tokens.
security:
- {}
parameters:
- name: code
in: query
description: Authorization code from Cognito
required: true
schema:
type: string
maxLength: 2048
pattern: "^[A-Za-z0-9\\-_]+$"
- name: state
in: query
description: State parameter for CSRF protection
required: true
schema:
type: string
maxLength: 1024
pattern: "^[A-Za-z0-9\\-_]+$"
responses:
"302":
description: Redirect to application after successful login
headers:
Location:
schema:
type: string
format: uri
maxLength: 2048
pattern: "^https?://.*"
description: URL to redirect after successful login
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/logout:
get:
operationId: logout
tags:
- AuthService
summary: Logout from the application
description: >-
Logs the user out by invalidating the session and redirecting to
Cognito logout endpoint.
security:
- jwtAuth: []
responses:
"302":
description: Redirect to Cognito logout page or application home page
headers:
Location:
schema:
type: string
format: uri
maxLength: 2048
pattern: "^https?://.*"
description: URL to redirect after logout
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/ui-settings:
post:
operationId: createUISetting
tags:
- UISettingsService
summary: Create a UI setting
description: >
Creates a new UI setting (namespace, key, value).
Use namespace to scope data (e.g. demo-dashboard:{userId}, feature-flags:global).
Returns 201 with the created resource.
security:
- jwtAuth: []
requestBody:
description: UI setting payload.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UISettingCreate"
responses:
"201":
description: Setting created successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/UISetting"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
get:
operationId: listUISettings
tags:
- UISettingsService
summary: List UI settings
description: Returns settings where isDeleted is false. Optional query param namespace filters by namespace (e.g. demo-dashboard:user123).
security:
- jwtAuth: []
parameters:
- name: namespace
in: query
required: false
schema:
type: string
maxLength: 255
description: Filter by namespace (omit to list all).
responses:
"200":
description: List of settings.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/UISettingListResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/ui-settings/{id}:
parameters:
- $ref: "#/components/parameters/UISettingID"
get:
operationId: getUISetting
tags:
- UISettingsService
summary: Get a UI setting by ID
description: Returns a single setting by id. Returns 404 if not found or soft-deleted.
security:
- jwtAuth: []
responses:
"200":
description: Setting details.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/UISetting"
"400":
$ref: "#/components/responses/InvalidRequest"
"404":
$ref: "#/components/responses/NotFound"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
patch:
operationId: updateUISetting
tags:
- UISettingsService
summary: Update a UI setting
description: Updates the value of an existing setting. Returns 404 if not found or soft-deleted.
security:
- jwtAuth: []
requestBody:
description: Updated UI setting value payload.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UISettingUpdate"
responses:
"200":
description: Setting updated successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/UISetting"
"404":
$ref: "#/components/responses/NotFound"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
delete:
operationId: deleteUISetting
tags:
- UISettingsService
summary: Soft-delete a UI setting
description: Sets isDeleted to true. Returns 204 on success, 404 if not found.
security:
- jwtAuth: []
responses:
"204":
description: Setting soft-deleted.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"404":
$ref: "#/components/responses/NotFound"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/identity:
get:
operationId: getIdentity
tags:
- AuthService
summary: Get current user identity and roles
description: >-
Returns the authenticated user's assigned roles from Permit.io,
including the permissions granted by each role.
Any authenticated user can call this endpoint to discover their own roles.
security:
- jwtAuth: []
responses:
"200":
description: User roles and permissions retrieved successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/IdentityResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
"502":
description: Failed to retrieve roles from Permit.io
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
/home:
get:
operationId: getHomePage
tags:
- AuthService
summary: Get the home page menu
description: >-
Returns the HTML menu page for authenticated users.
security:
- jwtAuth: []
responses:
"200":
description: Home page HTML
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
text/html:
schema:
type: string
description: HTML content for the home page menu
maxLength: 1048576
pattern: "^.*$"
format: html
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/admin/users:
post:
operationId: createAdminUser
tags:
- AdminService
summary: Create a new user
description: >-
Creates a new user in both AWS Cognito and Permit.io systems with optional role assignments.
Idempotent - returns 200 OK if user already exists with identical attributes.
Team Management permissions are enforced before user creation: Super Admin can
create any user, User Admin and Client Admin can create only non-AArete users
with client_user/user_admin roles, and Auditor cannot create users.
**Creation Flow:**
1. User is created in AWS Cognito (primary authentication system)
2. If Cognito creation fails, operation fails with HTTP 502 (no user created)
3. User is created in Permit.io (authorization/role system)
4. If Permit.io creation fails, user still exists in Cognito but permit_synced=false
5. Roles are assigned in Permit.io (best-effort, continues on failures)
**Role Assignment Behavior:**
- Roles must exist in your Permit.io environment (e.g., super_admin, user_admin, auditor, client_user)
- Invalid/non-existent roles fail silently and are logged server-side
- Only successfully assigned roles appear in the roles_assigned response field
- The roles_assigned array may be a subset of the requested roles array
- If all roles fail, roles_assigned will be null or empty (user has no permissions)
**Partial Success Scenarios:**
- Returns HTTP 201 even if Permit.io creation or some role assignments fail
- Check permit_synced field: false indicates user was not created in Permit.io
- Compare roles_assigned vs requested roles to detect role assignment failures
- User can authenticate (Cognito) but may lack authorization (Permit.io) if sync fails
security:
- jwtAuth: []
requestBody:
description: The user details required to create a user
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserCreate"
responses:
"201":
description: User created successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserCreateResponse"
"200":
description: User already exists with matching attributes (idempotent).
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserCreateResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"409":
$ref: "#/components/responses/Conflict"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
"502":
$ref: "#/components/responses/BadGateway"
get:
operationId: listAdminUsers
tags:
- AdminService
summary: List users
description: >-
Lists users from AWS Cognito with pagination, filtering, and sorting support.
Results are filtered according to the viewer's Team Management role. User
Admin and Client Admin viewers only receive non-AArete users that do not have
auditor or super_admin roles, while Super Admin and Auditor viewers receive all
environment-visible users.
The roles field is populated from Permit.io so clients can enforce the same
visibility and action rules locally.
security:
- jwtAuth: []
parameters:
- name: page
in: query
description: Page number for pagination
schema:
type: integer
format: int32
minimum: 1
default: 1
maximum: 10000
- name: page_size
in: query
description: Number of results per page
schema:
type: integer
format: int32
minimum: 1
maximum: 60
default: 50
- name: search
in: query
description: Search term for email/name filtering
schema:
type: string
maxLength: 256
pattern: "^.+$"
- name: status
in: query
description: Filter by user status
schema:
type: string
enum: [enabled, disabled, all]
default: all
- name: sort_by
in: query
description: Field to sort by
schema:
type: string
enum: [email, created_at, last_name]
default: email
- name: sort_order
in: query
description: Sort direction
schema:
type: string
enum: [asc, desc]
default: asc
responses:
"200":
description: List of users.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserList"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/admin/users/{email}:
parameters:
- $ref: "#/components/parameters/UserEmail"
get:
operationId: getAdminUser
tags:
- AdminService
summary: Get user by email
description: >-
Retrieves user details from both AWS Cognito and Permit.io by email address.
Team Management visibility is enforced. Hidden users return 404 so User Admin
and Client Admin callers cannot enumerate AArete, Auditor, or Super Admin users.
security:
- jwtAuth: []
responses:
"200":
description: User details.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserDetails"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
head:
operationId: checkAdminUserExists
tags:
- AdminService
summary: Check if user exists
description: >-
Checks if a user exists in Cognito and/or Permit.io without returning full details.
Team Management visibility is enforced. Hidden users return 404 so User Admin
and Client Admin callers cannot enumerate AArete, Auditor, or Super Admin users.
security:
- jwtAuth: []
responses:
"200":
description: User exists.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
X-User-Exists-Cognito:
schema:
type: boolean
description: Whether user exists in Cognito
X-User-Exists-PermitIO:
schema:
type: boolean
description: Whether user exists in Permit.io
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
description: User does not exist in either system
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
patch:
operationId: updateAdminUser
tags:
- AdminService
summary: Update user attributes and roles
description: >-
Updates user attributes (first_name, last_name) in Cognito and manages role assignments in Permit.io.
Email address cannot be changed (use email path parameter to identify user).
Team Management mutation rules are enforced: Super Admin can update any
environment-visible user, User Admin and Client Admin can update only non-AArete
client-level users and can assign only client_user/user_admin roles, and Auditor
is read-only.
**Attribute Updates:**
- first_name and last_name are updated in AWS Cognito
- Omit fields you don't want to change (e.g., send only roles to change roles)
**Role Management (REPLACE Strategy):**
- Providing a roles array REPLACES all existing roles (not additive)
- To add a role: include ALL current roles PLUS the new role
- To remove a role: include only the roles you want to keep
- To remove all roles: send an empty array []
- Omitting the roles field leaves role assignments unchanged
**Role Assignment Behavior:**
- Roles must exist in your Permit.io environment
- Invalid/non-existent roles fail silently and are logged server-side
- Response.roles field shows the final state after successful assignments
- Compare response.roles vs requested roles to detect failures
**Example - Add a Role:**
Current roles: ["client_user"]
To add "auditor": send roles: ["client_user", "auditor"]
Result: ["client_user", "auditor"]
**Example - Replace All Roles:**
Current roles: ["auditor", "client_user"]
To change to just "super_admin": send roles: ["super_admin"]
Result: ["super_admin"] (auditor and client_user removed)
security:
- jwtAuth: []
requestBody:
description: The user attributes to update
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserUpdate"
responses:
"200":
description: User updated successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserDetails"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
delete:
operationId: deleteAdminUser
tags:
- AdminService
summary: Delete user permanently
description: >-
Permanently deletes a user from both AWS Cognito and Permit.io.
This operation is irreversible. Requires confirm=true query parameter.
Team Management mutation rules are enforced: Super Admin can delete any
environment-visible user, User Admin and Client Admin can delete only non-AArete
client-level users, and Auditor is read-only.
security:
- jwtAuth: []
parameters:
- name: confirm
in: query
description: Must be set to true to confirm deletion
required: true
schema:
type: boolean
responses:
"200":
description: User deleted successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserDeleteResponse"
"207":
description: User partially deleted (multi-status).
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserDeleteResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/admin/users/{email}/disable:
parameters:
- $ref: "#/components/parameters/UserEmail"
post:
operationId: disableAdminUser
tags:
- AdminService
summary: Disable user
description: >-
Disables a user in AWS Cognito, preventing authentication.
User data and roles are preserved. Idempotent.
Team Management mutation rules are enforced: Super Admin can disable any
environment-visible user, User Admin and Client Admin can disable only non-AArete
client-level users, and Auditor is read-only.
security:
- jwtAuth: []
responses:
"200":
description: User disabled successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserActionResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/admin/users/{email}/enable:
parameters:
- $ref: "#/components/parameters/UserEmail"
post:
operationId: enableAdminUser
tags:
- AdminService
summary: Enable user
description: >-
Re-enables a previously disabled user in AWS Cognito.
Restores authentication capability. Idempotent.
Team Management mutation rules are enforced: Super Admin can enable any
environment-visible user, User Admin and Client Admin can enable only non-AArete
client-level users, and Auditor is read-only.
security:
- jwtAuth: []
responses:
"200":
description: User enabled successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/AdminUserActionResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
# EULA Public Endpoints
/eula:
get:
operationId: getCurrentEula
tags:
- EulaService
summary: Get current EULA version
description: Returns the current active End User License Agreement version. This endpoint is public and does not require authentication.
security: []
responses:
"200":
description: Current EULA version retrieved successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/EulaPublicResponse"
example:
id: "019580df-ef65-7676-8de9-94435a93337a"
version: "1.0"
title: "Terms of Service v1.0"
content: "# Terms of Service\n\n## Section 1: Acceptance of Terms\n\nBy using this service, you agree to these terms..."
effectiveDate: "2026-01-01T00:00:00Z"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/eula/status:
get:
operationId: getEulaStatus
tags:
- EulaService
summary: Check user's EULA agreement status
description: |
Returns the current user's agreement status for the current EULA version.
Designed for the frontend to quickly determine if the user needs to be prompted to agree.
security:
- jwtAuth: []
responses:
"200":
description: EULA status retrieved successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/EulaStatusResponse"
examples:
agreed:
summary: User has agreed to current EULA
value:
hasAgreed: true
currentVersion: "1.0"
currentVersionId: "019580df-ef65-7676-8de9-94435a93337a"
agreedAt: "2026-01-15T10:30:00Z"
agreedVersion: "1.0"
notAgreed:
summary: User has not agreed to current EULA
value:
hasAgreed: false
currentVersion: "2.0"
currentVersionId: "019580df-ef65-7676-8de9-94435a93337b"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/eula/agree:
post:
operationId: agreeToEula
tags:
- EulaService
summary: Record user agreement to current EULA
description: |
Records the user's agreement to the current EULA version.
Returns 201 for first agreement, 200 if user already agreed (idempotent).
The IP address is automatically captured from the request.
security:
- jwtAuth: []
responses:
"201":
description: Agreement recorded successfully (first agreement).
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/EulaAgreementResponse"
example:
id: "019580df-ef65-7676-8de9-94435a93337c"
eulaVersionId: "019580df-ef65-7676-8de9-94435a93337a"
eulaVersion: "1.0"
agreedAt: "2026-01-22T14:30:00Z"
"200":
description: User already agreed to current version (returns existing agreement).
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/EulaAgreementResponse"
example:
id: "019580df-ef65-7676-8de9-94435a93337c"
eulaVersionId: "019580df-ef65-7676-8de9-94435a93337a"
eulaVersion: "1.0"
agreedAt: "2026-01-15T10:30:00Z"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
# EULA Admin Endpoints
/admin/eula:
get:
operationId: listEulaVersions
tags:
- EulaService
summary: List all EULA versions
description: Returns a paginated list of all EULA versions.
security:
- jwtAuth: []
parameters:
- name: page
in: query
description: Page number for pagination
schema:
type: integer
format: int32
minimum: 1
maximum: 10000
default: 1
- name: page_size
in: query
description: Number of items per page
schema:
type: integer
format: int32
minimum: 1
maximum: 100
default: 20
responses:
"200":
description: List of EULA versions retrieved successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/EulaVersionList"
example:
versions:
- id: "019580df-ef65-7676-8de9-94435a93337a"
version: "1.0"
title: "Terms of Service v1.0"
content: "# Terms of Service\n\n## Section 1\n\nBy using this service..."
effectiveDate: "2026-01-01T00:00:00Z"
createdAt: "2025-12-15T10:30:00Z"
createdBy: "admin@example.com"
isCurrent: true
activatedAt: "2026-01-01T00:00:00Z"
activatedBy: "admin@example.com"
- id: "019580df-ef65-7676-8de9-94435a93337b"
version: "0.9-beta"
title: "Terms of Service (Beta)"
content: "# Terms of Service (Beta)\n\n## Section 1\n\nThis is a beta version..."
effectiveDate: "2025-11-01T00:00:00Z"
createdAt: "2025-10-15T10:30:00Z"
createdBy: "admin@example.com"
isCurrent: false
total: 2
page: 1
page_size: 20
has_more: false
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
post:
operationId: createEulaVersion
tags:
- EulaService
summary: Create a new EULA version
description: Creates a new EULA version. The content should be in Markdown format.
security:
- jwtAuth: []
requestBody:
description: EULA version details
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/EulaVersionCreate"
example:
version: "2.0"
title: "Terms of Service v2.0"
content: "# Terms of Service v2.0\n\n## Section 1\n\nBy using this service..."
effectiveDate: "2026-02-01T00:00:00Z"
responses:
"201":
description: EULA version created successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/EulaVersion"
example:
id: "019580df-ef65-7676-8de9-94435a93337d"
version: "2.0"
title: "Terms of Service v2.0"
content: "# Terms of Service v2.0\n\n## Section 1\n\nBy using this service..."
effectiveDate: "2026-02-01T00:00:00Z"
createdAt: "2026-01-22T14:30:00Z"
createdBy: "admin@example.com"
isCurrent: false
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"409":
$ref: "#/components/responses/Conflict"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/admin/eula/{version_id}:
parameters:
- $ref: "#/components/parameters/EulaVersionID"
get:
operationId: getEulaVersion
tags:
- EulaService
summary: Get a specific EULA version
description: Retrieves a specific EULA version by its ID.
security:
- jwtAuth: []
responses:
"200":
description: EULA version retrieved successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/EulaVersion"
example:
id: "019580df-ef65-7676-8de9-94435a93337a"
version: "1.0"
title: "Terms of Service v1.0"
content: "# Terms of Service\n\n## Section 1: Acceptance of Terms\n\nBy using this service, you agree to these terms..."
effectiveDate: "2026-01-01T00:00:00Z"
createdAt: "2025-12-15T10:30:00Z"
createdBy: "admin@example.com"
isCurrent: true
activatedAt: "2026-01-01T00:00:00Z"
activatedBy: "admin@example.com"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
patch:
operationId: updateEulaVersion
tags:
- EulaService
summary: Update EULA version metadata
description: Updates only the metadata (title and effective date) of an EULA version. Content cannot be modified.
security:
- jwtAuth: []
requestBody:
description: Fields to update
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/EulaVersionUpdate"
example:
title: "Terms of Service v1.0 (Revised)"
effectiveDate: "2026-01-15T00:00:00Z"
responses:
"200":
description: EULA version updated successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/EulaVersion"
example:
id: "019580df-ef65-7676-8de9-94435a93337a"
version: "1.0"
title: "Terms of Service v1.0 (Revised)"
content: "# Terms of Service\n\n## Section 1: Acceptance of Terms\n\nBy using this service, you agree to these terms..."
effectiveDate: "2026-01-15T00:00:00Z"
createdAt: "2025-12-15T10:30:00Z"
createdBy: "admin@example.com"
isCurrent: true
activatedAt: "2026-01-01T00:00:00Z"
activatedBy: "admin@example.com"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/admin/eula/{version_id}/activate:
parameters:
- $ref: "#/components/parameters/EulaVersionID"
post:
operationId: activateEulaVersion
tags:
- EulaService
summary: Activate an EULA version
description: |
Sets this version as the current active EULA. Uses a database transaction to atomically
clear the previous current flag and set the new one. Returns 409 if another admin
activated a different version concurrently.
security:
- jwtAuth: []
responses:
"200":
description: EULA version activated successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/EulaVersion"
example:
id: "019580df-ef65-7676-8de9-94435a93337d"
version: "2.0"
title: "Terms of Service v2.0"
content: "# Terms of Service v2.0\n\n## Section 1: Acceptance of Terms\n\nBy accessing or using our services..."
effectiveDate: "2026-02-01T00:00:00Z"
createdAt: "2026-01-22T14:30:00Z"
createdBy: "admin@example.com"
isCurrent: true
activatedAt: "2026-01-22T15:00:00Z"
activatedBy: "admin@example.com"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Conflict"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/admin/eula/agreements:
get:
operationId: listEulaAgreements
tags:
- EulaService
summary: List EULA agreements
description: |
Returns a paginated list of user agreements. Use version_id to filter by
a specific EULA version. Use user_id to view a specific user's complete
EULA agreement history.
security:
- jwtAuth: []
parameters:
- name: page
in: query
description: Page number for pagination
schema:
type: integer
format: int32
minimum: 1
maximum: 10000
default: 1
- name: page_size
in: query
description: Number of items per page
schema:
type: integer
format: int32
minimum: 1
maximum: 100
default: 20
- name: version_id
in: query
description: Filter by specific EULA version ID
schema:
type: string
format: uuid
maxLength: 36
- name: user_id
in: query
description: Filter by Cognito subject ID to see all EULAs a specific user agreed to
schema:
type: string
maxLength: 256
responses:
"200":
description: List of agreements retrieved successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/EulaAgreementList"
example:
agreements:
- id: "019580df-ef65-7676-8de9-94435a93337c"
cognitoSubjectId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
userEmail: "user1@example.com"
eulaVersionId: "019580df-ef65-7676-8de9-94435a93337a"
eulaVersion: "1.0"
eulaVersionTitle: "Terms of Service v1.0"
agreedAt: "2026-01-15T10:30:00Z"
agreedFromIp: "192.168.1.100"
- id: "019580df-ef65-7676-8de9-94435a93337e"
cognitoSubjectId: "b2c3d4e5-f6a7-8901-bcde-f12345678901"
userEmail: "user2@example.com"
eulaVersionId: "019580df-ef65-7676-8de9-94435a93337a"
eulaVersion: "1.0"
eulaVersionTitle: "Terms of Service v1.0"
agreedAt: "2026-01-16T09:15:00Z"
agreedFromIp: "10.0.0.50"
total: 150
page: 1
page_size: 20
has_more: true
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/admin/eula/compliance:
get:
operationId: getEulaCompliance
tags:
- EulaService
summary: Get EULA compliance report
description: |
Returns a comprehensive compliance report showing which users have and have not
agreed to a specific EULA version. Defaults to the current active version if
no version_id is provided. User data is fetched from Cognito for accuracy.
security:
- jwtAuth: []
parameters:
- name: page
in: query
description: Page number for pagination
schema:
type: integer
format: int32
minimum: 1
maximum: 10000
default: 1
- name: page_size
in: query
description: Number of items per page
schema:
type: integer
format: int32
minimum: 1
maximum: 100
default: 50
- name: version_id
in: query
description: Specific EULA version to report on. If omitted, uses current active version.
schema:
type: string
format: uuid
maxLength: 36
- name: agreed
in: query
description: Filter by agreement status. True for agreed only, false for not-agreed only.
schema:
type: boolean
responses:
"200":
description: Compliance report generated successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/EulaComplianceReport"
example:
eulaVersion:
id: "019580df-ef65-7676-8de9-94435a93337a"
version: "1.0"
title: "Terms of Service v1.0"
effectiveDate: "2026-01-01T00:00:00Z"
isCurrent: true
summary:
totalUsers: 150
agreedCount: 120
notAgreedCount: 30
compliancePercentage: 80.0
users:
- cognitoSubjectId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
email: "user1@example.com"
currentEmail: "user1@example.com"
agreed: true
agreedAt: "2026-01-15T10:30:00Z"
agreedFromIp: "192.168.1.100"
- cognitoSubjectId: "b2c3d4e5-f6a7-8901-bcde-f12345678901"
currentEmail: "user2@example.com"
agreed: false
- cognitoSubjectId: "c3d4e5f6-a7b8-9012-cdef-123456789012"
email: "user3-old@example.com"
currentEmail: "user3-new@example.com"
agreed: true
agreedAt: "2026-01-16T14:45:00Z"
agreedFromIp: "10.0.0.25"
pagination:
page: 1
pageSize: 50
totalPages: 3
totalItems: 150
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/super-admin/custom-schemas:
post:
operationId: createCustomSchema
tags:
- SuperAdminSchemaService
summary: Create a custom metadata schema
description: >-
Creates a new client-scoped JSON Schema used to validate custom
document metadata. Restricted to the super_admin role.
security:
- jwtAuth: []
requestBody:
description: The schema to create
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CustomSchemaRequest"
responses:
"201":
description: Schema created successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/CustomSchemaResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"409":
$ref: "#/components/responses/Conflict"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
get:
operationId: listCustomSchemas
tags:
- SuperAdminSchemaService
summary: List custom metadata schemas for a client
description: >-
Lists client-scoped JSON Schemas. Supports filtering by name, status
and optional inclusion of all historical versions. Restricted to the
super_admin role.
security:
- jwtAuth: []
parameters:
- name: clientId
in: query
description: The client whose schemas to list.
required: true
schema:
type: string
maxLength: 36
- name: name
in: query
description: Filter by schema name (exact match).
required: false
schema:
type: string
maxLength: 255
- name: status
in: query
description: >-
Filter by lifecycle status. The sentinel `any` returns rows in
all statuses. Defaults to `active` when omitted.
required: false
schema:
type: string
enum:
- active
- superseded
- retired
- any
- name: includeAllVersions
in: query
description: >-
When false, return only the latest version per (clientId, name)
lineage. When true, return every version that matches the other
filters.
required: false
schema:
type: boolean
default: false
- name: limit
in: query
description: Maximum number of results to return.
required: false
schema:
type: integer
format: int32
minimum: 1
maximum: 200
default: 50
- name: offset
in: query
description: Number of results to skip for pagination.
required: false
schema:
type: integer
format: int32
minimum: 0
maximum: 2147483647
default: 0
responses:
"200":
description: Schema list retrieved successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/CustomSchemaListResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/super-admin/custom-schemas/{schemaId}:
parameters:
- name: schemaId
in: path
required: true
schema:
type: string
format: uuid
maxLength: 36
description: The custom metadata schema ID.
get:
operationId: getCustomSchema
tags:
- SuperAdminSchemaService
summary: Get a custom metadata schema by ID
description: >-
Returns the full JSON Schema document plus lifecycle metadata for
the specified schema row. Restricted to the super_admin role.
security:
- jwtAuth: []
responses:
"200":
description: Schema retrieved successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/CustomSchemaResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
delete:
operationId: deleteCustomSchema
tags:
- SuperAdminSchemaService
summary: Retire a custom metadata schema
description: >-
Marks the schema as retired. Fails with 409 Conflict if any document
still references the schema. Restricted to the super_admin role.
security:
- jwtAuth: []
responses:
"204":
description: Schema retired successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Conflict"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/super-admin/custom-schemas/{schemaId}/versions:
parameters:
- name: schemaId
in: path
required: true
schema:
type: string
format: uuid
maxLength: 36
description: The parent custom metadata schema ID whose lineage is being extended.
post:
operationId: createCustomSchemaVersion
tags:
- SuperAdminSchemaService
summary: Create a new version of a custom metadata schema
description: >-
Creates a new schema row with a new ID that inherits the parent
schema's clientId and name. The parent row must currently have
status=active; it is marked superseded in the same transaction.
Restricted to the super_admin role.
security:
- jwtAuth: []
requestBody:
description: The new schema version payload.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CustomSchemaVersionRequest"
responses:
"201":
description: Schema version created successfully.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/CustomSchemaResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Conflict"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/super-admin/documents/{id}/schema:
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
maxLength: 36
description: The document ID whose schema binding is being mutated.
patch:
operationId: assignDocumentSchema
tags:
- SuperAdminSchemaService
summary: Assign (or clear) a custom schema for a document
description: >-
Binds a document to a client_metadata_schemas row, or clears the
binding when customSchemaId is null. The service layer enforces
every invariant from plan Section 7.3 before the UPDATE: document
must have no existing custom metadata, no legacy field extractions,
and the schema must belong to the same client. Restricted to the
super_admin role.
security:
- jwtAuth: []
requestBody:
description: The new schema binding.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/DocumentSchemaAssignRequest"
responses:
"200":
description: Binding updated.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/DocumentSchemaAssignResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Conflict"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/super-admin/documents/{id}/reset-metadata:
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
maxLength: 36
description: The document ID whose custom metadata is being reset.
post:
operationId: resetDocumentMetadata
tags:
- SuperAdminSchemaService
summary: Reset a document's custom metadata and schema binding
description: >-
Atomically deletes every document_custom_metadata row for the
document and nullifies documents.custom_schema_id in a single
transaction. Returns previous schema binding details and the
count of deleted metadata versions. Idempotent: already-clean
documents return 200 with metadataVersionsDeleted set to 0.
Rejects documents carrying legacy field extractions with 409.
Restricted to the super_admin role.
security:
- jwtAuth: []
responses:
"200":
description: Reset completed.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/DocumentMetadataResetResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Conflict"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/custom-metadata:
get:
operationId: getCurrentCustomMetadata
tags:
- CustomMetadataService
summary: Get the current custom metadata row for a document
description: >-
Returns the most recent document_custom_metadata row for the
specified document, decorated with the bound schema id, name, and
version.
security:
- jwtAuth: []
parameters:
- name: documentId
in: query
required: true
description: The document whose current metadata is being requested.
schema:
type: string
format: uuid
maxLength: 36
responses:
"200":
description: Latest metadata row.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/CustomMetadataResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
post:
operationId: setCustomMetadata
tags:
- CustomMetadataService
summary: Write a new custom metadata version for a document
description: >-
Validates the supplied metadata payload against the document's
bound schema and appends a new version row. The actor is derived
from the JWT sub claim; the request body has no createdBy field.
security:
- jwtAuth: []
requestBody:
description: Metadata payload + the target document id.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CustomMetadataRequest"
responses:
"201":
description: Metadata version written.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/CustomMetadataResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Conflict"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/custom-metadata/version:
get:
operationId: getCustomMetadataByVersion
tags:
- CustomMetadataService
summary: Get a specific historical metadata version
description: >-
Returns the metadata row whose version matches the query parameter,
decorated with schema id/name/version. Returns 404 when the row
does not exist and 400 when version is less than 1.
security:
- jwtAuth: []
parameters:
- name: documentId
in: query
required: true
description: The document whose historical metadata version is being requested.
schema:
type: string
format: uuid
maxLength: 36
- name: version
in: query
required: true
description: The metadata version number (>= 1) to return.
schema:
type: integer
format: int32
minimum: 1
maximum: 2147483647
responses:
"200":
description: Metadata row at the requested version.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/CustomMetadataResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/custom-metadata/history:
get:
operationId: getCustomMetadataHistory
tags:
- CustomMetadataService
summary: List version summaries for a document's metadata
description: >-
Returns a paged list of (version, createdAt, createdBy) tuples in
descending version order. limit must be in [1, 200]; values above
200 are clamped. offset must be >= 0.
security:
- jwtAuth: []
parameters:
- name: documentId
in: query
required: true
description: The document whose metadata history is being requested.
schema:
type: string
format: uuid
maxLength: 36
- name: limit
in: query
required: false
description: Maximum number of version summaries to return per page (1-200, default 50).
schema:
type: integer
format: int32
minimum: 1
maximum: 200
default: 50
- name: offset
in: query
required: false
description: Number of version summaries to skip before the page starts (default 0).
schema:
type: integer
format: int32
minimum: 0
maximum: 2147483647
default: 0
responses:
"200":
description: Version summaries in descending version order.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/CustomMetadataHistoryResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{clientId}/bot/sessions:
parameters:
- $ref: "#/components/parameters/BotClientID"
post:
operationId: createBotSession
tags:
- BotService
summary: Create a new chatbot session
description: >-
Creates an owner-scoped chatbot session for the authenticated
client_user. The Cognito subject (JWT sub) becomes createdBy.
Title defaults to empty until the first turn arrives.
security:
- jwtAuth: []
requestBody:
description: Empty body — accepted for forward compatibility.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateBotSessionRequest"
responses:
"201":
description: Session created.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/BotSessionResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
get:
operationId: listBotSessions
tags:
- BotService
summary: List the caller's chatbot sessions for a client
description: >-
Returns sessions owned by the authenticated user under this
clientId, newest-updated first. Each session carries a recentTurns
preview whose length is min(request.limit, cfg.RecentTurns)
per plan §3. Plan §3 bounds: limit in [1, 200] and offset >= 0.
security:
- jwtAuth: []
parameters:
- name: limit
in: query
required: false
description: Maximum number of sessions to return (1-200, default 20).
schema:
type: integer
format: int32
minimum: 1
maximum: 200
default: 20
- name: offset
in: query
required: false
description: Number of sessions to skip for pagination (default 0).
schema:
type: integer
format: int32
minimum: 0
maximum: 2147483647
default: 0
responses:
"200":
description: Session list with embedded recent-turn previews.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/BotSessionListResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{clientId}/bot/sessions/{sessionId}:
parameters:
- $ref: "#/components/parameters/BotClientID"
- $ref: "#/components/parameters/BotSessionID"
get:
operationId: getBotSession
tags:
- BotService
summary: Get one chatbot session by id
description: >-
Owner-scoped read. Returns 404 when the session belongs to a
different client, a different user, or has been soft-deleted.
security:
- jwtAuth: []
responses:
"200":
description: Session details.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/BotSessionResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{clientId}/bot/sessions/{sessionId}/turns:
parameters:
- $ref: "#/components/parameters/BotClientID"
- $ref: "#/components/parameters/BotSessionID"
post:
operationId: createBotTurn
tags:
- BotService
summary: Submit a new chatbot turn
description: >-
Posts a new turn to the chatbot session. Plan §6 algorithm: tx1
locks the session, abandons grace-expired in_flight rows, and
either inserts a fresh in_flight row at the next ordinal or
resets a terminal-failure row for retry. The FastAPI agent is
called outside any DB transaction, then tx2 records the
outcome via compare-and-set on attempt_id. Returns 201 on
success with the persisted turn body. FastAPI failures persist
an errored row and return 502 with the error body.
security:
- jwtAuth: []
requestBody:
description: Prompt to submit.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateBotTurnRequest"
responses:
"201":
description: Turn completed.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/BotTurnResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"409":
$ref: "#/components/responses/Conflict"
"410":
description: Session was deleted while the agent call was in flight.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
"502":
description: FastAPI agent failed; persisted errored row in body.
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
get:
operationId: listBotTurns
tags:
- BotService
summary: List all turns for a chatbot session
description: >-
Returns every persisted turn for the owner-scoped session,
ordered ASC by ordinal. Plan §11.
security:
- jwtAuth: []
responses:
"200":
description: Ordered list of turns.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/BotTurnListResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{clientId}/bot/sessions/{sessionId}/scope:
parameters:
- $ref: "#/components/parameters/BotClientID"
- $ref: "#/components/parameters/BotSessionID"
patch:
operationId: patchBotSessionScope
tags:
- BotService
summary: Patch a session's document/folder scope
description: >-
Adds or removes documents and folders from a session's scope.
Duplicate ids inside add/remove are deduplicated. An id appearing
in both add and remove returns 400 add_remove_conflict. A document
or folder belonging to a different client returns 400
document_cross_client / folder_cross_client. The persisted scope
is the union of (existing - remove) add.
security:
- jwtAuth: []
requestBody:
description: Add/remove sets for documents and folders.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/BotSessionScopePatchRequest"
responses:
"200":
description: Updated session, including the new scope.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/BotSessionResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{clientId}/documents/{documentId}/schema:
parameters:
- $ref: "#/components/parameters/BotClientID"
- $ref: "#/components/parameters/M5DocumentID"
get:
operationId: getDocumentSchema
tags:
- BotService
summary: Get the bound custom schema for a document
description: >-
Returns the JSON Schema body bound to the document via
documents.custom_schema_id. The composite FK in migration 128
guarantees the schema row's client_id matches the document's
clientId, so the M1 GetDocumentEnrichedForClient query is
sufficient for cross-client rejection. When the document has no
schema bound, the endpoint returns 200 with `schema: null`. Plan
§3 + §10 M5.
security:
- jwtAuth: []
responses:
"200":
description: Schema body or null when unbound.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/DocumentSchemaResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/client/{clientId}/documents/{documentId}/all-metadata:
parameters:
- $ref: "#/components/parameters/BotClientID"
- $ref: "#/components/parameters/M5DocumentID"
get:
operationId: getDocumentAllMetadata
tags:
- BotService
summary: Get document metadata bundle (document + labels + customMetadata)
description: >-
Composes three M1 client-scoped reads
(GetDocumentEnrichedForClient, GetDocumentLabelsForClient,
GetCurrentDocumentCustomMetadataForClient) into a single bundle
for the chatbot UI. labels is always a non-null array; when the
document has no schema bound or no metadata rows, customMetadata
is null. Plan §3 + §10 M5.
security:
- jwtAuth: []
responses:
"200":
description: Document, labels, and customMetadata.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/DocumentAllMetadataResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/super-admin/bot/sessions:
get:
operationId: listBotSessionsAsSuperAdmin
tags:
- SuperAdminBotService
summary: List chatbot sessions for a client (super-admin)
description: >-
Super-admin client-scoped list. Filters on clientId and
is_deleted=false; no created_by predicate. limit in [1, 200],
offset >= 0.
security:
- jwtAuth: []
parameters:
- name: clientId
in: query
required: true
description: The client whose sessions to list.
schema:
type: string
maxLength: 255
- name: limit
in: query
required: false
description: Maximum number of sessions to return (1-200, default 20).
schema:
type: integer
format: int32
minimum: 1
maximum: 200
default: 20
- name: offset
in: query
required: false
description: Number of sessions to skip for pagination (default 0).
schema:
type: integer
format: int32
minimum: 0
maximum: 2147483647
default: 0
responses:
"200":
description: Session list across all users in the client.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/BotSessionListResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
/super-admin/bot/sessions/{sessionId}:
parameters:
- $ref: "#/components/parameters/BotSessionID"
get:
operationId: getBotSessionAsSuperAdmin
tags:
- SuperAdminBotService
summary: Get one chatbot session by id (super-admin)
description: >-
Super-admin read. Filters on clientId (query param) and
is_deleted=false. Returns 404 when the session does not match.
security:
- jwtAuth: []
parameters:
- name: clientId
in: query
required: true
description: The client that owns the session.
schema:
type: string
maxLength: 255
responses:
"200":
description: Session details.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/BotSessionResponse"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
delete:
operationId: deleteBotSessionAsSuperAdmin
tags:
- SuperAdminBotService
summary: Soft-delete a chatbot session (super-admin)
description: >-
Sets is_deleted=true on the session. Any in-flight turns on the
session transition to status='session_deleted' so the M4 AddTurn
tx2 callback finds a terminal row.
security:
- jwtAuth: []
parameters:
- name: clientId
in: query
required: true
description: The client that owns the session.
schema:
type: string
maxLength: 255
responses:
"204":
description: Session soft-deleted.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
"400":
$ref: "#/components/responses/InvalidRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"403":
$ref: "#/components/responses/Forbidden"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
"500":
$ref: "#/components/responses/InternalError"
components:
parameters:
ClientID:
in: path
name: id
required: true
schema:
$ref: "#/components/schemas/ClientID"
description: The client ID.
ExportID:
in: path
name: id
required: true
schema:
$ref: "#/components/schemas/ExportID"
description: The export ID.
# QueryID parameter has been removed - see remove_query_plan.md
DocumentID:
in: path
name: id
required: true
schema:
$ref: "#/components/schemas/DocumentID"
description: The document ID.
BatchID:
in: path
name: batch_id
required: true
schema:
$ref: "#/components/schemas/BatchID"
description: The batch upload ID.
UserEmail:
in: path
name: email
required: true
schema:
type: string
format: email
maxLength: 320
description: URL-encoded user email address.
EulaVersionID:
in: path
name: version_id
required: true
schema:
type: string
format: uuid
maxLength: 36
description: The EULA version ID.
UISettingID:
in: path
name: id
required: true
schema:
type: string
format: uuid
maxLength: 36
description: The UI setting ID.
BotClientID:
in: path
name: clientId
required: true
schema:
type: string
maxLength: 255
description: The owning client ID for chatbot routes.
BotSessionID:
in: path
name: sessionId
required: true
schema:
type: string
format: uuid
maxLength: 36
description: The chatbot session ID.
M5DocumentID:
in: path
name: documentId
required: true
schema:
type: string
format: uuid
maxLength: 36
description: The document ID for the M5 schema/all-metadata routes.
headers:
RateLimit:
schema:
type: string
pattern: "^[0-9]+;window=[0-9]+$"
maxLength: 32
example: 100;window=60
description: Rate limit information in format "limit;window=time-window"
example: "100;window=10"
securitySchemes:
jwtAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: >-
JWT token obtained after Cognito authentication. Implements RFC8725 JWT
best practices for security.
cognitoAuth:
type: oauth2
description: >-
Authentication using Amazon Cognito IDP. Implements RFC8725 JWT best
practices for security.
flows:
authorizationCode:
authorizationUrl: >-
https://doczy.auth.us-east-1.amazoncognito.com/oauth2/authorize
tokenUrl: >-
https://doczy.auth.us-east-1.amazoncognito.com/oauth2/token
scopes:
openid: Get OIDC token
email: Access to user's email
profile: Access to user's profile
responses:
InvalidRequest:
description: Invalid request body.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
InternalError:
description: Internal server error.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
TooManyRequests:
description: Response upon too many requests.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
Retry-After:
schema:
type: integer
format: int32
minimum: 0
maximum: 86400
description: Number of seconds before trying again.
example: 120
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
Unauthorized:
description: Response when unauthorized.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
NotFound:
description: Resource not found.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
Forbidden:
description: Insufficient permissions to perform this action.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
Conflict:
description: Resource already exists or state conflict.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
BadGateway:
description: External service error.
headers:
RateLimit:
$ref: "#/components/headers/RateLimit"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
schemas:
# Query API schemas
ClientID:
type: string
description: The client external id
example: AAA
maxLength: 36
pattern: "^.+$"
DocumentID:
type: string
format: uuid
description: The document id.
example: 019580df-b3f8-7348-9ab1-1e55b3f18ed7
maxLength: 36
ExportID:
type: string
format: uuid
description: The export id.
example: 019580de-4d51-713c-98ee-464e83811f13
maxLength: 36
BatchID:
type: string
format: uuid
description: The batch upload id.
example: 019580df-ef65-7676-8de9-94435a93337a
maxLength: 36
BatchStatus:
type: string
enum:
- processing
- completed
- failed
- cancelled
description: The status of a batch upload
BatchUploadResponse:
type: object
description: Response returned when a batch upload is accepted for processing
required:
- batch_id
- status
- status_url
properties:
batch_id:
$ref: "#/components/schemas/BatchID"
status:
$ref: "#/components/schemas/BatchStatus"
status_url:
type: string
format: uri-reference
maxLength: 512
description: URL to check batch status
example: "/client/AAA/document/batch/019580df-ef65-7676-8de9-94435a93337a"
BatchUploadSummary:
type: object
description: Summary information about a batch upload
required:
- batch_id
- client_id
- original_filename
- status
- total_documents
- processed_documents
- failed_documents
- invalid_type_documents
- progress_percent
- created_at
properties:
batch_id:
$ref: "#/components/schemas/BatchID"
client_id:
$ref: "#/components/schemas/ClientID"
original_filename:
type: string
maxLength: 4096
pattern: "^.+$"
description: Original filename of the uploaded ZIP archive
example: "documents.zip"
status:
$ref: "#/components/schemas/BatchStatus"
total_documents:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Total number of documents in the batch
example: 100
processed_documents:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Number of documents processed so far
example: 42
failed_documents:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Number of documents that failed processing
example: 2
invalid_type_documents:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Number of non-PDF files found in archive
example: 1
progress_percent:
type: integer
format: int32
minimum: 0
maximum: 100
description: Processing progress percentage
example: 42
created_at:
type: string
format: date-time
maxLength: 50
description: When the batch upload was created
completed_at:
type: string
format: date-time
maxLength: 50
nullable: true
description: When the batch upload completed processing
BatchDocumentOutcome:
type: object
description: Per-file outcome from batch extraction and pipeline processing
required: [filename, outcome]
properties:
filename:
type: string
maxLength: 4096
description: Original filename from the ZIP archive
outcome:
type: string
enum:
[
submitted,
duplicate,
failed_open,
failed_read,
failed_s3_upload,
failed_upload,
invalid_type,
init_complete,
init_duplicate,
sync_complete,
sync_skipped,
clean_passed,
clean_failed,
]
description: Current processing status
error_detail:
type: string
maxLength: 2048
nullable: true
description: Human-readable error message for failure outcomes
document_id:
type: string
format: uuid
maxLength: 36
nullable: true
description: Assigned document ID (null for files that never became documents)
clean_fail_reason:
type: string
maxLength: 2048
nullable: true
description: >
Specific clean validation failure reason when outcome is clean_failed.
Null otherwise.
created_at:
type: string
format: date-time
maxLength: 50
description: When the file was first extracted from the ZIP
updated_at:
type: string
format: date-time
maxLength: 50
description: When the outcome was last updated by a pipeline stage
BatchUploadDetails:
description: Detailed information about a batch upload including failed filenames and per-file outcomes
allOf:
- $ref: "#/components/schemas/BatchUploadSummary"
- type: object
properties:
failed_filenames:
type: array
maxItems: 10000
items:
type: string
maxLength: 4096
pattern: "^.+$"
description: List of filenames that failed processing
example: ["doc3.pdf", "doc17.pdf"]
document_outcomes:
type: array
maxItems: 10000
items:
$ref: "#/components/schemas/BatchDocumentOutcome"
description: Per-file outcome tracking for all files in the batch
BatchUploadList:
type: object
description: List of batch uploads for a client
required:
- batches
- total_count
properties:
batches:
type: array
maxItems: 100
items:
$ref: "#/components/schemas/BatchUploadSummary"
total_count:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Total number of batches for this client
example: 25
ClientName:
type: string
description: The client name
example: AArete
maxLength: 256
pattern: "^.+$"
ClientCanSync:
type: boolean
description: If the client is allowing active syncs
DocClient:
description: The properties of a client.
type: object
properties:
id:
$ref: "#/components/schemas/ClientID"
name:
$ref: "#/components/schemas/ClientName"
can_sync:
$ref: "#/components/schemas/ClientCanSync"
required:
- id
- name
- can_sync
ClientStatus:
type: string
enum:
- IN_SYNC
- NOT_SYNCED
- NOT_SYNCING
description: Specifies the status of a client.
ClientStatusBody:
description: A client status information object.
type: object
properties:
status:
$ref: "#/components/schemas/ClientStatus"
required:
- status
ClientIDBody:
description: The client id.
type: object
properties:
id:
$ref: "#/components/schemas/ClientID"
required:
- id
ClientListResponse:
description: Response containing a list of all clients.
type: object
properties:
clients:
type: array
description: List of clients in the system.
maxItems: 10000
items:
$ref: "#/components/schemas/DocClient"
totalCount:
type: integer
format: int32
description: Total number of clients.
minimum: 0
maximum: 2147483647
required:
- clients
- totalCount
UISettingCreate:
type: object
description: Request body for creating a UI setting
required:
- namespace
- key
- value
properties:
namespace:
type: string
maxLength: 255
description: Scope for the setting (e.g. demo-dashboard:{userId}, feature-flags:global, saved-filters:{clientId})
key:
type: string
maxLength: 255
description: Setting key within the namespace
value:
type: object
description: JSON value (object) for the setting
UISetting:
type: object
description: A UI setting record
required:
- id
- namespace
- key
- value
- isDeleted
- createdAt
- updatedAt
properties:
id:
type: string
format: uuid
maxLength: 36
namespace:
type: string
maxLength: 255
key:
type: string
maxLength: 255
value:
type: object
isDeleted:
type: boolean
createdAt:
type: string
format: date-time
maxLength: 32
updatedAt:
type: string
format: date-time
maxLength: 32
UISettingUpdate:
type: object
description: Request body for updating a UI setting
required:
- value
properties:
value:
type: object
description: New JSON value for the setting
UISettingListResponse:
type: object
description: List of UI settings
required:
- settings
- totalCount
properties:
settings:
type: array
maxItems: 10000
items:
$ref: "#/components/schemas/UISetting"
totalCount:
type: integer
format: int32
minimum: 0
maximum: 10000
ListDocuments:
type: array
description: The documents in the client.
maxItems: 256
items:
$ref: "#/components/schemas/DocumentSummary"
Hash:
type: string
description: The document hash
maxLength: 2048
pattern: "^.+$"
DocumentSummary:
description: The document summary properties.
type: object
properties:
id:
$ref: "#/components/schemas/DocumentID"
hash:
$ref: "#/components/schemas/Hash"
required:
- id
- hash
DocumentEnriched:
description: Enriched document details with additional metadata
type: object
required:
- id
- client_id
- hash
- hasTextRecord
- labels
properties:
id:
$ref: "#/components/schemas/DocumentID"
client_id:
$ref: "#/components/schemas/ClientID"
hash:
$ref: "#/components/schemas/Hash"
hasTextRecord:
type: boolean
description: "Whether a text extraction (field extraction) record exists for this document"
folderId:
type: string
format: uuid
maxLength: 50
description: "Parent folder ID, null if document is not in a folder"
filename:
type: string
maxLength: 4096
description: "Original filename of the document"
originalPath:
type: string
maxLength: 4096
description: "Original path provided during upload (immutable)"
labels:
type: array
maxItems: 1000
items:
$ref: "#/components/schemas/LabelRecord"
description: "All labels applied to this document"
textRecord:
$ref: "#/components/schemas/FieldExtractionResponse"
fileSizeBytes:
type: integer
format: int64
minimum: 0
maximum: 4294967295
description: "File size in bytes (null for legacy documents)"
customSchemaId:
type: string
format: uuid
maxLength: 36
description: >-
Mutable-metadata feature: the client_metadata_schemas row id
this document is currently bound to, or null when the document
has not been opted in to the custom schema system. A document
with a non-null customSchemaId rejects legacy field extraction
writes.
hasCustomMetadata:
type: boolean
description: >-
True iff at least one document_custom_metadata row exists for
this document. A document can have customSchemaId set but
hasCustomMetadata false (schema bound, no metadata written
yet).
DocumentInFolder:
description: Document within a folder with enriched metadata (lighter format, excludes client_id and fields)
type: object
required:
- id
- hash
- hasTextRecord
- labels
properties:
id:
$ref: "#/components/schemas/DocumentID"
hash:
$ref: "#/components/schemas/Hash"
hasTextRecord:
type: boolean
description: "Whether a text extraction record exists for this document"
folderId:
type: string
format: uuid
maxLength: 50
description: "Parent folder ID"
filename:
type: string
maxLength: 4096
description: "Original filename of the document"
originalPath:
type: string
maxLength: 4096
description: "Original path provided during upload (immutable)"
labels:
type: array
maxItems: 1000
items:
$ref: "#/components/schemas/LabelRecord"
description: "All labels applied to this document"
textRecord:
$ref: "#/components/schemas/FieldExtractionResponse"
fileSizeBytes:
type: integer
format: int64
minimum: 0
maximum: 4294967295
description: "File size in bytes (null for legacy documents)"
SchemaStatus:
type: string
enum:
- active
- superseded
- retired
description: |
Lifecycle state of a client_metadata_schemas row. `active` is
the version currently assignable to new documents. `superseded`
is automatically set when a newer version of the same (clientId,
name) lineage is created via POST /versions. `retired` is set
when a super_admin explicitly deletes an unused schema.
CustomSchemaRequest:
description: >-
Request body for creating a new custom metadata schema. Does not
include a createdBy field; the handler derives the actor from the
authenticated JWT subject.
type: object
required:
- clientId
- name
- schema
properties:
clientId:
type: string
minLength: 1
maxLength: 36
description: The client that owns this schema.
name:
type: string
minLength: 1
maxLength: 255
description: Unique schema name within the client lineage.
description:
type: string
maxLength: 1024
description: Optional human-readable description of the schema.
schema:
type: object
additionalProperties: true
maxProperties: 1024
description: >-
The full JSON Schema document (Draft 2020-12) used to validate
custom document metadata. Must declare root type=object and
must explicitly set additionalProperties. The maxProperties cap
is a defense-in-depth limit against malformed schema payloads;
the byte-level cap (65 536) lives in the customschema validator.
CustomSchemaVersionRequest:
description: >-
Request body for creating a new version of an existing custom
metadata schema. The parent schema row supplies clientId and name;
the actor is derived from the authenticated JWT subject.
type: object
required:
- schema
properties:
description:
type: string
maxLength: 1024
description: Optional human-readable description of this new version.
schema:
type: object
additionalProperties: true
maxProperties: 1024
description: >-
The full JSON Schema document (Draft 2020-12) for the new
version. Same validation rules as CustomSchemaRequest.schema.
CustomSchemaResponse:
description: >-
Full custom metadata schema row including the JSON Schema document
and lifecycle metadata.
type: object
required:
- id
- clientId
- name
- schema
- version
- status
- documentCount
- canDelete
- createdAt
- createdBy
properties:
id:
type: string
format: uuid
maxLength: 36
description: The schema row ID.
clientId:
type: string
minLength: 1
maxLength: 36
description: The client that owns this schema.
name:
type: string
minLength: 1
maxLength: 255
description: The schema name (shared across versions in a lineage).
description:
type: string
maxLength: 1024
description: Optional human-readable description of the schema.
schema:
type: object
additionalProperties: true
maxProperties: 1024
description: The full JSON Schema document (Draft 2020-12).
version:
type: integer
format: int32
minimum: 1
maximum: 2147483647
description: Monotonic version number within the (clientId, name) lineage.
status:
$ref: "#/components/schemas/SchemaStatus"
documentCount:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Number of documents currently referencing this schema version.
canDelete:
type: boolean
description: True when documentCount is zero and the schema can be retired.
createdAt:
type: string
format: date-time
maxLength: 64
description: Timestamp when this schema row was created.
createdBy:
type: string
minLength: 1
maxLength: 255
description: >-
Cognito subject ID (JWT sub claim) of the caller. Opaque UUID,
not an email.
example: "b7a4c1d2-8e3f-4a5b-9c6d-0e1f2a3b4c5d"
CustomSchemaListResponse:
description: >-
List of custom metadata schemas for a client. Each row omits the
full JSON Schema document; use GET /super-admin/custom-schemas/
{schemaId} to retrieve it.
type: object
required:
- schemas
properties:
schemas:
type: array
maxItems: 200
description: The schema rows matching the query filters.
items:
type: object
required:
- id
- clientId
- name
- version
- status
- documentCount
- canDelete
- createdAt
- createdBy
properties:
id:
type: string
format: uuid
maxLength: 36
description: The schema row ID.
clientId:
type: string
minLength: 1
maxLength: 36
description: The client that owns this schema.
name:
type: string
minLength: 1
maxLength: 255
description: The schema name (shared across versions in a lineage).
description:
type: string
maxLength: 1024
description: Optional human-readable description of the schema.
version:
type: integer
format: int32
minimum: 1
maximum: 2147483647
description: Monotonic version number within the lineage.
status:
$ref: "#/components/schemas/SchemaStatus"
documentCount:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Number of documents referencing this schema version.
canDelete:
type: boolean
description: True when documentCount is zero.
createdAt:
type: string
format: date-time
maxLength: 64
description: Timestamp when this schema row was created.
createdBy:
type: string
minLength: 1
maxLength: 255
description: >-
Cognito subject ID (JWT sub claim) of the caller. Opaque
UUID, not an email.
example: "b7a4c1d2-8e3f-4a5b-9c6d-0e1f2a3b4c5d"
DocumentSchemaAssignRequest:
description: >-
Request body for PATCH /super-admin/documents/{id}/schema. The
actor is derived from the JWT sub claim; the body has no createdBy
field. A null customSchemaId clears the binding.
type: object
properties:
customSchemaId:
type: string
format: uuid
maxLength: 36
nullable: true
description: The client_metadata_schemas row id to bind, or null to clear.
DocumentSchemaAssignResponse:
description: >-
Result of a schema binding mutation. Returns the bound schema
metadata (or nulls when cleared).
type: object
required:
- documentId
properties:
documentId:
type: string
format: uuid
maxLength: 36
customSchemaId:
type: string
format: uuid
maxLength: 36
nullable: true
schemaName:
type: string
maxLength: 255
nullable: true
schemaVersion:
type: integer
format: int32
minimum: 1
maximum: 2147483647
nullable: true
DocumentMetadataResetResponse:
description: >-
Result of a reset-metadata operation. The previous* fields
describe the document's schema binding before the reset ran so
the caller can log or display what was wiped. Fields are null
when the document had no schema bound at reset time (the
idempotent no-op case, returned alongside
metadataVersionsDeleted set to 0).
type: object
required:
- documentId
- previousSchemaId
- previousSchemaName
- previousSchemaVersion
- metadataVersionsDeleted
- resetAt
- resetBy
properties:
documentId:
type: string
format: uuid
maxLength: 36
description: The document whose metadata was reset.
previousSchemaId:
type: string
format: uuid
maxLength: 36
nullable: true
description: >-
The document's custom_schema_id before the reset ran.
Null when no schema was bound.
previousSchemaName:
type: string
maxLength: 255
nullable: true
description: >-
Name of the previously bound schema, or null when no schema
was bound.
previousSchemaVersion:
type: integer
format: int32
minimum: 1
maximum: 2147483647
nullable: true
description: >-
Version of the previously bound schema row, or null when no
schema was bound.
metadataVersionsDeleted:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: >-
Number of document_custom_metadata rows that existed (and
were deleted) at reset time. Zero is valid: the reset
endpoint is idempotent on already-clean documents.
resetAt:
type: string
format: date-time
maxLength: 64
description: UTC timestamp when the reset completed.
resetBy:
type: string
minLength: 1
maxLength: 255
description: >-
Cognito subject ID (JWT sub claim) of the caller. Opaque
UUID, not an email.
example: "b7a4c1d2-8e3f-4a5b-9c6d-0e1f2a3b4c5d"
CustomMetadataRequest:
description: >-
POST /custom-metadata body. No createdBy field — the actor is
derived from the JWT sub claim.
type: object
required:
- documentId
- metadata
properties:
documentId:
type: string
format: uuid
maxLength: 36
metadata:
type: object
additionalProperties: true
maxProperties: 1024
description: >-
Arbitrary JSON object that must conform to the document's
bound schema_def. The byte-level cap (1 048 576) lives in the
service layer constant MaxMetadataPayloadBytes.
CustomMetadataResponse:
description: >-
Full metadata row decorated with the document's bound schema id,
name, and version.
type: object
required:
- id
- documentId
- metadata
- version
- createdAt
- createdBy
properties:
id:
type: string
format: uuid
maxLength: 36
documentId:
type: string
format: uuid
maxLength: 36
metadata:
type: object
additionalProperties: true
maxProperties: 1024
version:
type: integer
format: int32
minimum: 1
maximum: 2147483647
schemaId:
type: string
format: uuid
maxLength: 36
nullable: true
schemaName:
type: string
maxLength: 255
nullable: true
schemaVersion:
type: integer
format: int32
minimum: 1
maximum: 2147483647
nullable: true
createdAt:
type: string
format: date-time
maxLength: 64
createdBy:
type: string
minLength: 1
maxLength: 255
description: Cognito subject ID (JWT sub claim) of the writer.
example: "b7a4c1d2-8e3f-4a5b-9c6d-0e1f2a3b4c5d"
CustomMetadataHistoryResponse:
description: Paged list of version summaries, newest first.
type: object
required:
- versions
properties:
versions:
type: array
maxItems: 200
items:
type: object
required:
- version
- createdAt
- createdBy
properties:
version:
type: integer
format: int32
minimum: 1
maximum: 2147483647
createdAt:
type: string
format: date-time
maxLength: 64
createdBy:
type: string
minLength: 1
maxLength: 255
example: "b7a4c1d2-8e3f-4a5b-9c6d-0e1f2a3b4c5d"
ClientCreate:
description: The properties for creation.
type: object
properties:
id:
$ref: "#/components/schemas/ClientID"
name:
$ref: "#/components/schemas/ClientName"
required:
- id
- name
ClientUpdate:
description: The properties that may be updated.
type: object
properties:
name:
$ref: "#/components/schemas/ClientName"
can_sync:
$ref: "#/components/schemas/ClientCanSync"
IdMessage:
description: A single uuid.
type: object
properties:
id:
type: string
format: uuid
description: Unique identifier for entity.
maxLength: 36
required:
- id
CodeVersion:
type: integer
format: int64
minimum: 1
maximum: 9223372036854775808
description: The desired code version.
Version:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: The desired version.
Collector:
type: object
properties:
client_id:
$ref: "#/components/schemas/ClientID"
active_version:
$ref: "#/components/schemas/Version"
latest_version:
$ref: "#/components/schemas/Version"
minimum_cleaner_version:
$ref: "#/components/schemas/CodeVersion"
description: Collector model. Note - minimum_text_version has been removed since text extraction is deprecated.
required:
- client_id
- minimum_cleaner_version
- latest_version
- active_version
CollectorSet:
type: object
properties:
minimum_cleaner_version:
$ref: "#/components/schemas/CodeVersion"
active_version:
$ref: "#/components/schemas/Version"
description: Payload for updating a Collector. Note - minimum_text_version has been removed.
CollectorFieldName:
type: string
pattern: "^.+$"
maxLength: 256
description: The output field name.
ExportTrigger:
type: object
properties:
ingestion_filters:
type: object
description: Filter the scope based on ingestion parameters.
properties:
start_date:
type: string
format: date-time
maxLength: 32
description: This first date of ingestion.
end_date:
type: string
format: date-time
maxLength: 32
description: The last date of ingestion.
field_filters:
type: array
maxItems: 256
description: Filter the scope based on field output values.
items:
$ref: "#/components/schemas/FieldFilter"
description: Payload for triggering an export.
FieldFilter:
type: object
properties:
field_name:
$ref: "#/components/schemas/CollectorFieldName"
condition:
$ref: "#/components/schemas/FieldFilterCondition"
values:
type: array
description: The values useful to the filter.
maxItems: 100
items:
type: string
pattern: "^.+$"
maxLength: 256
description: Filtering a column
required:
- field_name
- condition
- values
FieldFilterCondition:
type: string
enum:
- less_than
- greater_than
- closed_interval
- open_interval
- left_closed_interval
- right_closed_interval
- include
- exclude
description: The possible field filtering conditions.
ExportStatus:
type: string
enum:
- completed
- in_progress
- failed
description: The possible export states.
ExportDetails:
type: object
properties:
client_id:
$ref: "#/components/schemas/ClientID"
status:
$ref: "#/components/schemas/ExportStatus"
output_location:
type: string
description: The location in which the export zip file will be found.
example: s3://a/A/export/20250213/uuid.csv
maxLength: 2048
pattern: '^s3://.+/.+/export/[0-9]{8}/.+\.csv$'
description: Payload for export trigger response.
required:
- client_id
- status
ErrorMessage:
description: Description of error
type: object
properties:
message:
type: string
pattern: "^.+$"
description: Message describing the cause.
maxLength: 256
example: "you must give me good information"
error_type:
type: string
description: Machine-readable error classification for programmatic handling.
maxLength: 64
example: "UserNotFound"
details:
type: string
description: Additional error details for debugging (sanitized).
maxLength: 512
example: "The specified user does not exist in Cognito"
required:
- message
example:
message: you must include a message
error_type: InvalidParameter
details: The email format is invalid
# Identity API schemas
IdentityRole:
type: object
description: A role assigned to the user with its permissions
required:
- key
- name
- permissions
properties:
key:
type: string
description: The role key/identifier
maxLength: 128
pattern: "^[a-z0-9_-]+$"
example: "auditor"
name:
type: string
description: Human-readable role name
maxLength: 256
pattern: "^.+$"
example: "Auditor"
description:
type: string
description: Optional description of the role
maxLength: 1024
example: "Read-only access to view documents and exports"
permissions:
type: array
description: List of permissions granted by this role
maxItems: 500
items:
type: string
maxLength: 128
pattern: "^[a-z0-9_-]+:[a-z0-9_-]+$"
example: ["document:read", "document:list", "export:read"]
IdentityResponse:
type: object
description: Response containing the user's roles and their permissions
required:
- roles
properties:
roles:
type: array
description: List of roles assigned to the user with their permissions
maxItems: 100
items:
$ref: "#/components/schemas/IdentityRole"
# Admin API schemas
AdminUserCreate:
description: Request body for creating a new user with email, name, and role assignments
type: object
required:
- email
- first_name
- last_name
- roles
properties:
email:
type: string
format: email
maxLength: 320
pattern: '^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$'
description: User email address (used as Cognito username)
example: john.doe@example.com
first_name:
type: string
minLength: 1
maxLength: 100
pattern: "^.+$"
description: User's given name for account creation
example: John
last_name:
type: string
minLength: 1
maxLength: 100
pattern: "^.+$"
description: User's family name for account creation
example: Doe
roles:
type: array
minItems: 1
maxItems: 50
items:
type: string
pattern: "^.+$"
maxLength: 100
description: >-
List of role keys to assign in Permit.io (e.g., super_admin, user_admin, auditor, client_user).
Roles must exist in your Permit.io environment. Invalid roles fail silently - check roles_assigned in response.
example: ["user_admin", "auditor"]
AdminUserCreateResponse:
description: Response after creating a user, including Cognito subject ID and sync status
type: object
required:
- cognito_subject_id
- email
- status
- permit_synced
properties:
cognito_subject_id:
type: string
maxLength: 256
pattern: "^.+$"
description: Created user's Cognito unique subject identifier
example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
email:
type: string
format: email
maxLength: 320
description: User email address
example: john.doe@example.com
first_name:
type: string
maxLength: 100
pattern: "^.+$"
description: Created user's given name
example: John
last_name:
type: string
maxLength: 100
pattern: "^.+$"
description: Created user's family name
example: Doe
status:
type: string
maxLength: 50
pattern: "^.+$"
description: Cognito user status
example: FORCE_CHANGE_PASSWORD
enabled:
type: boolean
description: Whether the created user is enabled in Cognito
example: true
permit_synced:
type: boolean
description: >-
Whether user was successfully created in Permit.io authorization system.
If false, user exists in Cognito (can authenticate) but not in Permit.io (has no authorization/permissions).
Manual sync or retry may be required.
example: true
roles_assigned:
type: array
maxItems: 50
items:
type: string
maxLength: 100
pattern: "^.+$"
description: >-
Roles that were successfully assigned in Permit.io. May be a subset of requested roles if some failed.
Compare with requested roles array to detect assignment failures. If null or empty, no roles were assigned
(user has no permissions). Only present if permit_synced is true.
example: ["user_admin", "auditor"]
created_at:
type: string
format: date-time
maxLength: 50
description: Timestamp when the user was created in the system
example: "2025-10-16T14:23:45Z"
AdminUserDetails:
description: Complete user information from Cognito and Permit.io including roles and timestamps
type: object
required:
- cognito_subject_id
- email
- status
- enabled
properties:
cognito_subject_id:
type: string
maxLength: 256
pattern: "^.+$"
description: User's Cognito unique subject identifier from authentication system
example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
email:
type: string
format: email
maxLength: 320
description: Email address of the user account
example: john.doe@example.com
first_name:
type: string
maxLength: 100
pattern: "^.+$"
description: User's given name retrieved from Cognito
example: John
last_name:
type: string
maxLength: 100
pattern: "^.+$"
description: User's family name retrieved from Cognito
example: Doe
status:
type: string
maxLength: 50
pattern: "^.+$"
description: Current Cognito user account status
example: CONFIRMED
enabled:
type: boolean
description: Current enabled status of the user in Cognito
example: true
roles:
type: array
maxItems: 50
items:
type: string
maxLength: 100
pattern: "^.+$"
description: >-
Roles assigned in Permit.io. Populated by GET /admin/users and
GET /admin/users/{email} so Team Management clients can enforce
role-based visibility and action rules.
example: ["admin", "viewer"]
created_at:
type: string
format: date-time
maxLength: 50
description: Timestamp when the user account was created
example: "2025-10-15T09:15:30Z"
updated_at:
type: string
format: date-time
maxLength: 50
description: Timestamp of last update
example: "2025-10-16T14:20:10Z"
AdminUserUpdate:
description: Request body for updating user attributes (first name, last name, and roles)
type: object
properties:
first_name:
type: string
minLength: 1
maxLength: 100
pattern: "^.+$"
description: Updated given name for the user
example: Jonathan
last_name:
type: string
minLength: 1
maxLength: 100
pattern: "^.+$"
description: Updated family name for the user
example: Doe-Smith
roles:
type: array
maxItems: 50
items:
type: string
pattern: "^.+$"
maxLength: 100
description: >-
Complete list of role keys to assign in Permit.io - REPLACES all existing roles (not additive).
To add a role, include all current roles plus the new one. To remove a role, omit it from the array.
Roles must exist in Permit.io environment. Invalid roles fail silently - check response.roles for final state.
Omit this field entirely to leave roles unchanged.
example: ["user_admin", "auditor"]
AdminUserList:
description: Paginated list of users with total count and pagination metadata
type: object
required:
- users
- total
- page
- page_size
properties:
users:
type: array
maxItems: 100
items:
$ref: '#/components/schemas/AdminUserDetails'
description: List of users for current page
total:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Total number of users matching filter
example: 147
page:
type: integer
format: int32
minimum: 1
maximum: 10000
description: Current page number
example: 1
page_size:
type: integer
format: int32
minimum: 1
maximum: 100
description: Number of users per page
example: 20
has_more:
type: boolean
description: Whether more pages are available
example: true
AdminUserActionResponse:
description: Response for user enable/disable actions with success status and timestamp
type: object
required:
- success
- email
- action
properties:
success:
type: boolean
description: Whether the action succeeded
example: true
email:
type: string
format: email
maxLength: 320
description: Email of the user acted upon
example: john.doe@example.com
action:
type: string
enum: [disable, enable]
description: Action performed
example: disable
cognito_subject_id:
type: string
maxLength: 256
pattern: "^.+$"
description: Cognito subject identifier for the action response
example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
timestamp:
type: string
format: date-time
maxLength: 50
description: Timestamp of the action
example: "2025-10-16T14:25:33Z"
AdminUserDeleteResponse:
description: Response for user deletion with status from each system (Cognito and Permit.io)
type: object
required:
- success
- email
- deleted_from
properties:
success:
type: boolean
description: Whether the deletion succeeded
example: true
email:
type: string
format: email
maxLength: 320
description: Email of the deleted user
example: john.doe@example.com
cognito_subject_id:
type: string
maxLength: 256
pattern: "^.+$"
description: Cognito subject identifier of the deleted user
example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
deleted_from:
type: object
required:
- cognito
- permit
properties:
cognito:
type: boolean
description: Whether user was deleted from Cognito
example: true
permit:
type: boolean
description: Whether user was deleted from Permit.io
example: true
description: Deletion status from each system
timestamp:
type: string
format: date-time
maxLength: 50
description: Timestamp of the deletion
example: "2025-10-16T14:27:15Z"
# Folder schemas
FolderCreate:
description: Request to create a new folder for organizing documents
type: object
required:
- path
- clientId
- createdBy
properties:
path:
type: string
maxLength: 1000
pattern: "^/.*$"
description: Folder path (must start with /). Use "/" for root folder.
example: "/documents/2024"
parentId:
type: string
format: uuid
maxLength: 50
description: Optional parent folder ID
example: "019580df-ef65-7676-8de9-94435a93337a"
clientId:
$ref: "#/components/schemas/ClientID"
createdBy:
type: string
format: email
maxLength: 320
description: Email of user who created the folder
example: user@example.com
FolderRename:
description: Request to rename an existing folder
type: object
required:
- path
properties:
path:
type: string
maxLength: 1000
pattern: "^/.*$"
description: New folder path (must start with /). Use "/" for root folder.
example: "/documents/2024-renamed"
Folder:
description: Folder information for organizing documents
type: object
required:
- id
- path
- clientId
- createdAt
- createdBy
properties:
id:
type: string
format: uuid
maxLength: 50
description: Folder ID
example: "019580df-ef65-7676-8de9-94435a93337a"
path:
type: string
maxLength: 1000
pattern: "^/.*$"
description: Folder path (must start with /). Root folder has path "/".
example: "/documents/2024"
parentId:
type: string
format: uuid
maxLength: 50
nullable: true
description: Parent folder ID
example: "019580df-ef65-7676-8de9-94435a93337b"
clientId:
$ref: "#/components/schemas/ClientID"
createdAt:
type: string
format: date-time
maxLength: 50
description: Creation timestamp
example: "2025-10-16T14:27:15Z"
createdBy:
type: string
format: email
maxLength: 320
description: Email of the user who created this folder
example: user@example.com
metrics:
allOf:
- $ref: "#/components/schemas/FolderMetricsInline"
nullable: true
description: |
Processing metrics for this folder. Only populated when metrics=true
is specified in the request. Null otherwise.
FolderList:
description: List of folders for a client
type: object
required:
- folders
properties:
folders:
type: array
maxItems: 10000
description: |
List of folders. Each folder includes its ID, path, and parentId.
Root-level folders have parentId set to null. Clients can use
parentId to reconstruct the folder hierarchy/tree structure.
items:
$ref: "#/components/schemas/Folder"
FolderMetrics:
description: Processing metrics for a folder including document counts
type: object
required:
- folderId
- totalDocuments
- byLabel
properties:
folderId:
type: string
format: uuid
maxLength: 50
description: Unique identifier for the folder
example: "019580df-ef65-7676-8de9-94435a93337a"
totalDocuments:
type: integer
format: int32
minimum: 0
maximum: 1000000
description: Total number of documents in folder
example: 150
byLabel:
type: object
maxProperties: 100
additionalProperties:
type: integer
format: int32
minimum: 0
maximum: 1000000
description: Document counts by label
example:
Ingested: 150
OCR_Processed: 120
Dashboard_Ready: 100
FolderMetricsInline:
description: Inline processing metrics for a folder (excludes folderId since it's on parent)
type: object
required:
- totalDocuments
- byLabel
properties:
totalDocuments:
type: integer
format: int32
minimum: 0
maximum: 1000000
description: Total number of documents in folder
example: 150
byLabel:
type: object
maxProperties: 100
additionalProperties:
type: integer
format: int32
minimum: 0
maximum: 1000000
description: Document counts by label
example:
Ingested: 150
OCR_Processed: 120
Dashboard_Ready: 100
# Label schemas
LabelApplication:
description: Request to apply a workflow label to a document
type: object
required:
- label
- appliedBy
properties:
label:
type: string
maxLength: 100
pattern: "^[A-Za-z0-9_]+$"
description: Label name (alphanumeric and underscore only)
example: "OCR_Processed"
appliedBy:
type: string
format: email
maxLength: 320
description: Email of user applying the label
example: user@example.com
LabelRecord:
description: Record of a label applied to a document
type: object
required:
- id
- documentId
- label
- appliedBy
- appliedAt
properties:
id:
type: string
format: uuid
maxLength: 50
description: Label record ID
example: "019580df-ef65-7676-8de9-94435a93337a"
documentId:
$ref: "#/components/schemas/DocumentID"
label:
type: string
maxLength: 100
pattern: "^[A-Za-z0-9_]+$"
description: Workflow label name (alphanumeric and underscore only)
example: "OCR_Processed"
appliedBy:
type: string
format: email
maxLength: 320
description: Email of the user who applied this label
example: user@example.com
appliedAt:
type: string
format: date-time
maxLength: 50
description: Timestamp when label was applied
example: "2025-10-16T14:27:15Z"
# Field Extraction schemas
FieldExtractionRequest:
description: Request to create a new field extraction with single and array fields
type: object
required:
- documentId
- singleFields
- arrayFields
- createdBy
properties:
documentId:
$ref: "#/components/schemas/DocumentID"
singleFields:
$ref: "#/components/schemas/SingleFields"
arrayFields:
type: array
maxItems: 10000
items:
$ref: "#/components/schemas/ArrayFieldItem"
description: Array of field extraction items (all must have consistent structure)
createdBy:
type: string
format: email
maxLength: 320
description: Email of user creating the extraction
example: user@example.com
SingleFields:
description: Single-value fields for a document extraction (1:1 relationship)
type: object
properties:
fileName:
type: string
maxLength: 500
description: Original file name
example: "contract_2024.pdf"
contractTitle:
type: string
maxLength: 500
description: Title of the contract
aareteDerivedAmendmentNum:
type: integer
format: int32
minimum: 0
maximum: 999
description: Amendment number derived by Aarete
clientName:
type: string
maxLength: 500
description: Name of the client
payerName:
type: string
maxLength: 500
description: Name of the payer
payerState:
type: string
maxLength: 2
pattern: "^[A-Z]{2}$"
description: Two-letter state code for payer
example: "CA"
providerState:
type: string
maxLength: 2
pattern: "^[A-Z]{2}$"
description: Two-letter state code for provider
example: "NY"
filenameTin:
type: string
maxLength: 20
description: Tax Identification Number from filename
provGroupTin:
type: string
maxLength: 20
description: Provider group TIN
provGroupNpi:
type: string
maxLength: 20
description: Provider group NPI
provGroupNameFull:
type: string
maxLength: 500
description: Full name of provider group
provOtherTin:
type: string
maxLength: 20
description: Other provider TIN
provOtherNpi:
type: string
maxLength: 20
description: Other provider NPI
provOtherNameFull:
type: string
maxLength: 500
description: Full name of other provider
aareteDerivedEffectiveDt:
type: string
format: date
maxLength: 50
description: Contract effective date
example: "2024-01-01"
aareteDerivedTerminationDt:
type: string
format: date
maxLength: 50
description: Contract termination date
example: "2025-12-31"
autoRenewalInd:
type: boolean
description: Auto-renewal indicator
autoRenewalTerm:
type: string
maxLength: 200
description: Auto-renewal terms
ArrayFieldItem:
description: Single row of array field data (112 fields forming one row)
type: object
properties:
exhibitTitle:
type: string
maxLength: 500
exhibitPage:
type: string
maxLength: 100
reimbProvTin:
type: string
maxLength: 20
reimbProvNpi:
type: string
maxLength: 20
reimbProvName:
type: string
maxLength: 500
reimbEffectiveDt:
type: string
format: date
maxLength: 50
reimbTerminationDt:
type: string
format: date
maxLength: 50
aareteDerivedClaimTypeCd:
type: string
maxLength: 100
aareteDerivedProduct:
type: string
maxLength: 200
aareteDerivedLob:
type: string
maxLength: 200
aareteDerivedProgram:
type: string
maxLength: 200
aareteDerivedNetwork:
type: string
maxLength: 200
aareteDerivedProvType:
type: string
maxLength: 200
provTaxonomyCd:
type: string
maxLength: 100
provTaxonomyCdDesc:
type: string
maxLength: 500
provSpecialtyCd:
type: string
maxLength: 100
provSpecialtyCdDesc:
type: string
maxLength: 500
placeOfServiceCd:
type: string
maxLength: 100
placeOfServiceCdDesc:
type: string
maxLength: 500
billTypeCd:
type: string
maxLength: 100
billTypeCdDesc:
type: string
maxLength: 500
patientAgeMin:
type: string
maxLength: 50
patientAgeMax:
type: string
maxLength: 50
reimbTerm:
type: string
maxLength: 500
lobProgramRelationship:
type: string
maxLength: 200
lobProductRelationship:
type: string
maxLength: 200
carveoutInd:
type: boolean
carveoutCd:
type: string
maxLength: 100
lesserOfInd:
type: boolean
greaterOfInd:
type: boolean
aareteDerivedReimbMethod:
type: string
maxLength: 200
unitOfMeasure:
type: string
maxLength: 100
reimbPctRate:
type: number
format: double
minimum: 0
maximum: 999.9999
reimbFeeRate:
type: number
format: double
minimum: 0
maximum: 9999999999.99
reimbConversionFactor:
type: number
format: double
minimum: 0
maximum: 99999999.9999
triggerCapThresholdAmt:
type: number
format: double
minimum: 0
maximum: 9999999999.99
triggerBaseThreshold:
type: number
format: double
minimum: 0
maximum: 9999999999.99
defaultInd:
type: boolean
additionDesc:
type: string
maxLength: 1000
additionMaxFeeRateInc:
type: number
format: double
minimum: 0
maximum: 9999999999.99
additionMaxPctRateInc:
type: number
format: double
minimum: 0
maximum: 999.9999
aareteDerivedAdditionRateChangeTimeline:
type: string
maxLength: 200
aareteDerivedFeeSchedule:
type: string
maxLength: 200
aareteDerivedFeeScheduleVersion:
type: string
maxLength: 100
serviceTerm:
type: string
maxLength: 500
cpt4ProcCd:
type: string
maxLength: 100
cpt4ProcCdDesc:
type: string
maxLength: 500
cpt4ProcMod:
type: string
maxLength: 100
cpt4ProcModDesc:
type: string
maxLength: 500
revenueCd:
type: string
maxLength: 100
revenueCdDesc:
type: string
maxLength: 500
diagCd:
type: string
maxLength: 100
diagCdDesc:
type: string
maxLength: 500
ndcCd:
type: string
maxLength: 100
ndcCdDesc:
type: string
maxLength: 500
claimAdmitTypeCd:
type: string
maxLength: 100
authAdmitTypeDesc:
type: string
maxLength: 500
claimStatusCd:
type: string
maxLength: 100
claimStatusCdDesc:
type: string
maxLength: 500
grouperType:
type: string
maxLength: 100
grouperCd:
type: string
maxLength: 100
grouperCdDesc:
type: string
maxLength: 500
grouperPctRate:
type: number
format: double
minimum: 0
maximum: 999.9999
grouperBaseRate:
type: number
format: double
minimum: 0
maximum: 9999999999.99
# Grouper Extended Fields
aareteDerivedGrouperVersion:
type: string
maxLength: 200
grouperAlternativeLevelOfCare:
type: string
maxLength: 200
grouperSeverityInd:
type: boolean
grouperSeverity:
type: string
maxLength: 100
grouperRiskOfMortalitySubclass:
type: string
maxLength: 100
grouperTransferInd:
type: boolean
grouperReadmissionsInd:
type: boolean
grouperHacInd:
type: boolean
# Outlier Fields
outlierTerm:
type: string
maxLength: 500
outlierFirstDollarInd:
type: boolean
rangeNbrDays:
type: string
maxLength: 100
outlierFixedLossNbrDaysThreshold:
type: number
format: double
minimum: 0
maximum: 99999999.99
outlierFixedLossThreshold:
type: number
format: double
minimum: 0
maximum: 9999999999.99
outlierMaximum:
type: number
format: double
minimum: 0
maximum: 9999999999.99
outlierMaximumFrequency:
type: number
format: double
minimum: 0
maximum: 99999999.99
outlierPctRate:
type: number
format: double
minimum: 0
maximum: 999.9999
outlierExclusionCd:
type: string
maxLength: 100
outlierExclusionCdDesc:
type: string
maxLength: 500
# Facility Adjustment Fields
facilityAdjustmentTerm:
type: string
maxLength: 500
dshInd:
type: boolean
dshPctRate:
type: number
format: double
minimum: 0
maximum: 999.9999
dshFeeRate:
type: number
format: double
minimum: 0
maximum: 9999999999.99
imeInd:
type: boolean
imePctRate:
type: number
format: double
minimum: 0
maximum: 999.9999
imeFeeRate:
type: number
format: double
minimum: 0
maximum: 9999999999.99
ntapInd:
type: boolean
ntapPctRate:
type: number
format: double
minimum: 0
maximum: 999.9999
ntapFeeRate:
type: number
format: double
minimum: 0
maximum: 9999999999.99
ucInd:
type: boolean
ucPctRate:
type: number
format: double
minimum: 0
maximum: 999.9999
ucFeeRate:
type: number
format: double
minimum: 0
maximum: 9999999999.99
gmeInd:
type: boolean
gmePctRate:
type: number
format: double
minimum: 0
maximum: 999.9999
gmeFeeRate:
type: number
format: double
minimum: 0
maximum: 9999999999.99
# Rate Escalator Fields
rateEscalatorInd:
type: boolean
rateEscalatorDesc:
type: string
maxLength: 500
rateEscalatorMaxRateIncPct:
type: number
format: double
minimum: 0
maximum: 999.9999
rateEscalatorRateChangeTimeline:
type: number
format: double
minimum: 0
maximum: 99999999.99
# Stop Loss Fields
stopLossTerm:
type: string
maxLength: 500
stopLossFirstDollarInd:
type: boolean
stopLossRangeNbrDays:
type: number
format: double
minimum: 0
maximum: 99999999.99
stopLossFixedLossThreshold:
type: number
format: double
minimum: 0
maximum: 9999999999.99
stopLossMaximum:
type: number
format: double
minimum: 0
maximum: 9999999999.99
stopLossMaximumFrequency:
type: number
format: double
minimum: 0
maximum: 99999999.99
stopLossDailyMaxRate:
type: number
format: double
minimum: 0
maximum: 9999999999.99
stopLossPctRateOnExcessCharges:
type: number
format: double
minimum: 0
maximum: 999.9999
stopLossExclusionCd:
type: string
maxLength: 100
stopLossExclusionDesc:
type: string
maxLength: 500
FieldExtractionResponse:
description: Field extraction with version information
type: object
required:
- id
- documentId
- version
- singleFields
- arrayFields
- createdAt
- createdBy
properties:
id:
type: string
format: uuid
maxLength: 50
description: Field extraction ID
example: "019580df-ef65-7676-8de9-94435a93337a"
documentId:
$ref: "#/components/schemas/DocumentID"
version:
type: integer
format: int32
minimum: 1
maximum: 9999
description: Version number (1-based)
example: 1
singleFields:
$ref: "#/components/schemas/SingleFields"
arrayFields:
type: array
maxItems: 10000
items:
$ref: "#/components/schemas/ArrayFieldItem"
description: Array of field extraction items
createdAt:
type: string
format: date-time
maxLength: 50
description: Creation timestamp
example: "2025-10-16T14:27:15Z"
createdBy:
type: string
format: email
maxLength: 320
description: Email of user who created this extraction
example: user@example.com
FieldExtractionVersion:
description: Field extraction version summary for history
type: object
required:
- id
- documentId
- version
- createdAt
- createdBy
properties:
id:
type: string
format: uuid
maxLength: 50
description: Field extraction ID
example: "019580df-ef65-7676-8de9-94435a93337a"
documentId:
$ref: "#/components/schemas/DocumentID"
version:
type: integer
format: int32
minimum: 1
maximum: 9999
description: Version number (1-based)
example: 1
createdAt:
type: string
format: date-time
maxLength: 50
description: Creation timestamp
example: "2025-10-16T14:27:15Z"
createdBy:
type: string
format: email
maxLength: 320
description: Email of user who created this version
example: user@example.com
# EULA Schemas
EulaVersion:
description: Full EULA version details
type: object
required:
- id
- version
- title
- content
- createdAt
- createdBy
- isCurrent
properties:
id:
type: string
format: uuid
maxLength: 36
description: EULA version ID
version:
type: string
maxLength: 50
pattern: "^.+$"
description: Version string (e.g., "1.0", "2024-01")
example: "1.0"
title:
type: string
maxLength: 500
pattern: "^.+$"
description: Human-readable title
example: "Terms of Service v1.0"
content:
type: string
maxLength: 1048576
description: Full EULA text in Markdown format
example: "# Terms of Service\n\n## Section 1\n\nBy using this service..."
effectiveDate:
type: string
format: date-time
maxLength: 50
nullable: true
description: When this version becomes effective (optional)
example: "2026-01-01T00:00:00Z"
createdAt:
type: string
format: date-time
maxLength: 50
description: Creation timestamp
example: "2025-12-15T10:30:00Z"
createdBy:
type: string
maxLength: 320
description: Identifier of admin who created this version (email, username, or subject ID)
example: admin@example.com
isCurrent:
type: boolean
description: Whether this is the current active version
example: true
activatedAt:
type: string
format: date-time
maxLength: 50
nullable: true
description: When this version was activated
example: "2026-01-01T00:00:00Z"
activatedBy:
type: string
maxLength: 320
nullable: true
description: Identifier of admin who activated this version (email, username, or subject ID)
example: admin@example.com
EulaVersionSummary:
description: Abbreviated EULA version for lists
type: object
required:
- id
- version
- title
- isCurrent
properties:
id:
type: string
format: uuid
maxLength: 36
description: EULA version ID
version:
type: string
maxLength: 50
pattern: "^.+$"
description: Version string
example: "1.0"
title:
type: string
maxLength: 500
pattern: "^.+$"
description: Human-readable title
example: "Terms of Service v1.0"
effectiveDate:
type: string
format: date-time
maxLength: 50
nullable: true
description: When this version becomes effective (optional)
example: "2026-01-01T00:00:00Z"
isCurrent:
type: boolean
description: Whether this is the current active version
example: true
EulaVersionCreate:
description: Request body for creating a new EULA version
type: object
required:
- version
- title
- content
properties:
version:
type: string
maxLength: 50
minLength: 1
pattern: "^.+$"
description: Version string (must be unique)
example: "1.0"
title:
type: string
maxLength: 500
minLength: 1
pattern: "^.+$"
description: Human-readable title
example: "Terms of Service v1.0"
content:
type: string
maxLength: 1048576
minLength: 1
description: Full EULA text in Markdown format
example: "# Terms of Service\n\n## Section 1\n\nBy using this service..."
effectiveDate:
type: string
format: date-time
maxLength: 50
nullable: true
description: When this version becomes effective (optional)
example: "2026-01-01T00:00:00Z"
EulaVersionUpdate:
description: Request body for updating EULA version metadata
type: object
properties:
title:
type: string
maxLength: 500
minLength: 1
pattern: "^.+$"
description: Human-readable title
example: "Terms of Service v1.0 (Updated)"
effectiveDate:
type: string
format: date-time
maxLength: 50
description: When this version becomes effective
example: "2026-01-15T00:00:00Z"
EulaVersionList:
description: Paginated list of EULA versions
type: object
required:
- versions
- total
- page
- page_size
properties:
versions:
type: array
maxItems: 100
items:
$ref: "#/components/schemas/EulaVersion"
description: List of EULA versions
total:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Total number of EULA versions
example: 5
page:
type: integer
format: int32
minimum: 1
maximum: 10000
description: Current page number
example: 1
page_size:
type: integer
format: int32
minimum: 1
maximum: 100
description: Number of items per page
example: 20
has_more:
type: boolean
description: Whether more pages are available
example: false
EulaPublicResponse:
description: Public response for current EULA version
type: object
required:
- id
- version
- title
- content
properties:
id:
type: string
format: uuid
maxLength: 36
description: EULA version ID
version:
type: string
maxLength: 50
pattern: "^.+$"
description: Version string
example: "1.0"
title:
type: string
maxLength: 500
pattern: "^.+$"
description: Human-readable title
example: "Terms of Service v1.0"
content:
type: string
maxLength: 1048576
description: Full EULA text in Markdown format
example: "# Terms of Service\n\n## Section 1\n\nBy using this service..."
effectiveDate:
type: string
format: date-time
maxLength: 50
nullable: true
description: When this version became effective (optional)
example: "2026-01-01T00:00:00Z"
EulaStatusResponse:
description: User's EULA agreement status
type: object
required:
- hasAgreed
- currentVersion
- currentVersionId
properties:
hasAgreed:
type: boolean
description: Whether the user has agreed to the current EULA
example: true
currentVersion:
type: string
maxLength: 50
pattern: "^.+$"
description: Current EULA version string
example: "2.0"
currentVersionId:
type: string
format: uuid
maxLength: 36
description: EULA version ID
agreedAt:
type: string
format: date-time
maxLength: 50
nullable: true
description: When the user agreed (null if not agreed)
example: "2026-01-15T10:30:00Z"
agreedVersion:
type: string
maxLength: 50
nullable: true
description: Version the user agreed to (null if not agreed)
example: "2.0"
EulaAgreementResponse:
description: Response after recording an agreement
type: object
required:
- id
- eulaVersionId
- eulaVersion
- agreedAt
properties:
id:
type: string
format: uuid
maxLength: 36
description: Agreement record ID
example: "019580df-ef65-7676-8de9-94435a93337a"
eulaVersionId:
type: string
format: uuid
maxLength: 36
description: EULA version ID
eulaVersion:
type: string
maxLength: 50
pattern: "^.+$"
description: EULA version string
example: "1.0"
agreedAt:
type: string
format: date-time
maxLength: 50
description: When the agreement was recorded
example: "2026-01-15T10:30:00Z"
EulaAgreement:
description: EULA agreement record
type: object
required:
- id
- cognitoSubjectId
- userEmail
- eulaVersionId
- eulaVersion
- agreedAt
- agreedFromIp
properties:
id:
type: string
format: uuid
maxLength: 36
description: Agreement record ID
example: "019580df-ef65-7676-8de9-94435a93337a"
cognitoSubjectId:
type: string
maxLength: 256
pattern: "^.+$"
description: User's Cognito subject ID
example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
userEmail:
type: string
maxLength: 320
description: User identifier at time of agreement (email, username, or subject ID)
example: user@example.com
eulaVersionId:
type: string
format: uuid
maxLength: 36
description: EULA version ID
eulaVersion:
type: string
maxLength: 50
pattern: "^.+$"
description: EULA version string
example: "1.0"
eulaVersionTitle:
type: string
maxLength: 500
description: EULA version title (for user history view)
example: "Terms of Service v1.0"
agreedAt:
type: string
format: date-time
maxLength: 50
description: When the agreement was recorded
example: "2026-01-15T10:30:00Z"
agreedFromIp:
type: string
maxLength: 45
description: IP address from which the user agreed
example: "192.168.1.100"
EulaAgreementList:
description: Paginated list of EULA agreements
type: object
required:
- agreements
- total
- page
- page_size
properties:
agreements:
type: array
maxItems: 100
items:
$ref: "#/components/schemas/EulaAgreement"
description: List of EULA agreements
total:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Total number of agreements matching filter
example: 150
page:
type: integer
format: int32
minimum: 1
maximum: 10000
description: Current page number
example: 1
page_size:
type: integer
format: int32
minimum: 1
maximum: 100
description: Number of items per page
example: 20
has_more:
type: boolean
description: Whether more pages are available
example: true
EulaComplianceReport:
description: EULA compliance report with user agreement status
type: object
required:
- eulaVersion
- summary
- users
- pagination
properties:
eulaVersion:
$ref: "#/components/schemas/EulaVersionSummary"
summary:
$ref: "#/components/schemas/EulaComplianceSummary"
users:
type: array
maxItems: 100
items:
$ref: "#/components/schemas/EulaComplianceUser"
description: Unified list of users with agreement status
pagination:
$ref: "#/components/schemas/EulaCompliancePagination"
EulaComplianceSummary:
description: Summary statistics for compliance report
type: object
required:
- totalUsers
- agreedCount
- notAgreedCount
- compliancePercentage
properties:
totalUsers:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Total number of users in the system
example: 150
agreedCount:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Number of users who have agreed
example: 120
notAgreedCount:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Number of users who have not agreed
example: 30
compliancePercentage:
type: number
format: float
minimum: 0
maximum: 100
description: Percentage of users who have agreed
example: 80.0
EulaComplianceUser:
description: User record in compliance report
type: object
required:
- cognitoSubjectId
- currentEmail
- agreed
properties:
cognitoSubjectId:
type: string
maxLength: 256
pattern: "^.+$"
description: User's Cognito subject ID
example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
email:
type: string
maxLength: 320
nullable: true
description: User identifier at time of agreement (email, username, or subject ID; null if not agreed)
example: user@example.com
currentEmail:
type: string
maxLength: 320
description: User's current email from Cognito (may be empty or a non-email identifier)
example: user-updated@example.com
agreed:
type: boolean
description: Whether the user has agreed to this EULA version
example: true
agreedAt:
type: string
format: date-time
maxLength: 50
nullable: true
description: When the user agreed (null if not agreed)
example: "2026-01-15T10:30:00Z"
agreedFromIp:
type: string
maxLength: 45
nullable: true
description: IP address from which the user agreed (null if not agreed)
example: "192.168.1.100"
EulaCompliancePagination:
description: Pagination information for compliance report
type: object
required:
- page
- pageSize
- totalPages
- totalItems
properties:
page:
type: integer
format: int32
minimum: 1
maximum: 10000
description: Current page number
example: 1
pageSize:
type: integer
format: int32
minimum: 1
maximum: 100
description: Number of items per page
example: 50
totalPages:
type: integer
format: int32
minimum: 0
maximum: 10000
description: Total number of pages
example: 3
totalItems:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: Total number of items
example: 150
DeleteResponse:
description: Response for hard-delete operations when verbose=true
type: object
required:
- deletedDocuments
properties:
deletedDocuments:
type: array
description: S3 paths of orphaned source documents (only populated when verbose=true)
maxItems: 100000
items:
type: object
required:
- documentId
- s3Path
properties:
documentId:
type: string
format: uuid
maxLength: 36
description: ID of the deleted document
s3Path:
type: string
maxLength: 1024
description: Full S3 path (s3://bucket/key) of the orphaned source file
# ---------- Bot (chatbot) M2 schemas ----------
BotSessionScope:
description: |
The persisted document/folder scope of a chatbot session.
Empty arrays mean "all documents for the client" per plan §4.
Folder ids are returned as-is; folder expansion to documents
happens only in the M3 FastAPI payload assembly path, not here.
type: object
required:
- documentIds
- folderIds
properties:
documentIds:
type: array
maxItems: 10000
items:
type: string
format: uuid
maxLength: 36
description: Document ids in the session scope.
folderIds:
type: array
maxItems: 10000
items:
type: string
format: uuid
maxLength: 36
description: Folder ids in the session scope.
BotTurnPreview:
description: |
A single turn surfaced inside a session list response. M2 returns
only the columns the UI needs to render preview cards: ordinal,
prompt, optional completion, status, createdAt. Plan §5
ListLastTurnsForSessions returns the full row column set; the
response trims it to the preview view here.
type: object
required:
- ordinal
- prompt
- status
- createdAt
properties:
ordinal:
type: integer
format: int32
minimum: 1
maximum: 2147483647
description: 1-based turn ordinal within the session.
prompt:
type: string
maxLength: 65536
description: User prompt text.
completion:
type: string
maxLength: 65536
nullable: true
description: Assistant completion (markdown) when status=completed.
status:
type: string
enum:
- in_flight
- completed
- errored
- abandoned
- session_deleted
description: Turn status per plan §4.
createdAt:
type: string
format: date-time
maxLength: 50
description: When the turn was inserted.
BotSessionResponse:
description: |
The canonical chatbot session entity. Used as the response body
for create / get / patch and as the element type of the list
response. lastTurn is the derived last_terminal_ordinal from
plan §4 — never the in-flight ordinal.
type: object
required:
- id
- clientId
- createdBy
- title
- state
- lastTurn
- createdAt
- updatedAt
- scope
- recentTurns
properties:
id:
type: string
format: uuid
maxLength: 36
clientId:
type: string
maxLength: 255
createdBy:
type: string
maxLength: 255
description: Cognito subject (JWT sub) of the creator.
title:
type: string
maxLength: 255
description: Empty until the first turn arrives (plan §6).
state:
type: object
additionalProperties: true
maxProperties: 1024
description: Session state object persisted as jsonb.
lastTurn:
type: integer
format: int32
minimum: 0
maximum: 2147483647
description: |
Derived last_terminal_ordinal per plan §4. 0 when the session
has no terminal turns yet.
createdAt:
type: string
format: date-time
maxLength: 50
updatedAt:
type: string
format: date-time
maxLength: 50
scope:
$ref: "#/components/schemas/BotSessionScope"
recentTurns:
type: array
maxItems: 5
description: |
Most recent terminal turns. Populated by the list endpoint
with min(request.limit, cfg.RecentTurns) entries per plan §3.
Single-session reads (GET / POST / PATCH) emit an empty array.
items:
$ref: "#/components/schemas/BotTurnPreview"
BotSessionListResponse:
description: Paged list of chatbot sessions.
type: object
required:
- sessions
properties:
sessions:
type: array
maxItems: 200
items:
$ref: "#/components/schemas/BotSessionResponse"
CreateBotSessionRequest:
description: |
Empty body for now — accepted as JSON object to leave room for
future fields (title hint, initial scope) without a breaking
change. M2 ignores any properties the caller supplies.
type: object
additionalProperties: true
maxProperties: 32
BotSessionScopePatchRequest:
description: |
Add/remove sets for documents and folders. Each array is
deduplicated server-side. An id appearing in both add and remove
sets is rejected with 400 add_remove_conflict. Cross-client ids
are rejected with 400 document_cross_client / folder_cross_client.
type: object
properties:
addDocuments:
type: array
maxItems: 10000
items:
type: string
format: uuid
maxLength: 36
removeDocuments:
type: array
maxItems: 10000
items:
type: string
format: uuid
maxLength: 36
addFolders:
type: array
maxItems: 10000
items:
type: string
format: uuid
maxLength: 36
removeFolders:
type: array
maxItems: 10000
items:
type: string
format: uuid
maxLength: 36
# ---------- M4: bot turn schemas ----------
CreateBotTurnRequest:
description: |
Body for POST /client/{clientId}/bot/sessions/{sessionId}/turns.
The handler computes the target ordinal from session state via
prompt-match semantics (a retry of an existing terminal-failure
or completed turn reuses that row's ordinal). The wire body
therefore carries only the prompt; plan §6.
type: object
required:
- prompt
properties:
prompt:
type: string
maxLength: 65536
description: User prompt. Plan §6 mandates 1 <= rune count <= MaxTurnChars.
BotTurnResponse:
description: |
One persisted bot_turns row exposed on the wire. Status enum
mirrors the bot_turns_status_values CHECK constraint from
migration 131. error is the persisted JSON when status is
errored / abandoned / session_deleted, omitted otherwise.
type: object
required:
- ordinal
- prompt
- status
- createdAt
properties:
ordinal:
type: integer
format: int32
minimum: 1
maximum: 2147483647
prompt:
type: string
maxLength: 65536
completion:
type: string
maxLength: 65536
status:
type: string
enum:
- completed
- errored
- abandoned
- session_deleted
- in_flight
latencyMs:
type: integer
format: int32
minimum: 0
maximum: 2147483647
tokensIn:
type: integer
format: int32
minimum: 0
maximum: 2147483647
tokensOut:
type: integer
format: int32
minimum: 0
maximum: 2147483647
error:
type: object
additionalProperties: true
maxProperties: 32
createdAt:
type: string
format: date-time
maxLength: 50
BotTurnListResponse:
description: |
GET turns response. Turns are ordered ASC by ordinal.
type: object
required:
- turns
properties:
turns:
type: array
maxItems: 10000
items:
$ref: "#/components/schemas/BotTurnResponse"
# ---------- M5: read-only document endpoints ----------
DocumentSchemaResponse:
description: |
Body returned by GET /client/{clientId}/documents/{documentId}/schema.
schema is the JSON Schema body bound to the document, or null
when the document has no custom_schema_id binding. The
clientId / documentId echo the URL parameters so the caller can
reuse the response without parsing the path.
type: object
required:
- documentId
- clientId
properties:
documentId:
type: string
format: uuid
maxLength: 36
clientId:
type: string
maxLength: 255
schema:
type: object
additionalProperties: true
maxProperties: 1024
description: |
JSON Schema body, or null when the document has no schema
bound. The body round-trips verbatim from
client_metadata_schemas.schema_def.
DocumentAllMetadataResponse:
description: |
Bundle returned by GET /client/{clientId}/documents/{documentId}/all-metadata.
document is the M1 enriched-document shape; labels is always a
non-null array (empty when no labels are applied); customMetadata
is null when no schema is bound or no metadata rows exist.
type: object
required:
- document
- labels
properties:
document:
$ref: "#/components/schemas/DocumentEnriched"
labels:
type: array
maxItems: 10000
items:
$ref: "#/components/schemas/BotLabelRecord"
customMetadata:
type: object
additionalProperties: true
maxProperties: 1024
description: |
Latest custom metadata payload for the document, or null
when no schema is bound / no metadata rows exist.
BotLabelRecord:
description: |
Label record exposed by the M5 all-metadata endpoint. Mirrors
LabelRecord but treats appliedBy as a plain string so the
bundle survives non-email AppliedBy values (the underlying
documentLabels.appliedBy is varchar(255), not email-validated
at the database layer).
type: object
required:
- id
- documentId
- label
- appliedBy
- appliedAt
properties:
id:
type: string
format: uuid
maxLength: 36
documentId:
type: string
format: uuid
maxLength: 36
label:
type: string
maxLength: 255
appliedBy:
type: string
maxLength: 320
appliedAt:
type: string
format: date-time
maxLength: 50