retrieve document by id and tests * working * missing files
67 KiB
API Documentation
API Overview
The DoczyAI Query Orchestration Platform exposes a comprehensive REST API following OpenAPI 3.0.3 specification. The API is automatically generated from the specification file serviceAPIs/queryAPI.yaml using oapi-codegen.
also see query api summary
Base Configuration
- Base URL:
https://doczy.com/v1(production),http://localhost:8080(development) - API Version: 0.0.1
- Content Type:
application/json - Documentation: Auto-generated Swagger UI at
/swagger/index.html
API Services
The API is organized into the following service groups:
| Service | Description |
|---|---|
| ClientService | Operations related to clients |
| CollectorService | Operations related to collectors |
| DocumentsService | Operations related to documents |
| FolderService | Operations related to document folders and organization |
| LabelService | Operations related to document labels and workflow tracking |
| FieldExtractionService | Operations related to document field extractions |
| ExportService | Operations related to exports |
| AuthService | Operations related to authentication |
| AdminService | Operations related to user management and administration |
| EulaService | Operations related to End User License Agreement management and tracking |
| UISettingsService | Operations related to UI-scoped key-value settings (per user, client, or global) |
Authentication and Authorization
Security Schemes
JWT Authentication
- Type: Bearer token authentication
- Header:
Authorization: Bearer <token> - Token Source: JWT cookie set via OAuth flow
OAuth2 Flow
- Type: OAuth2 Authorization Code Flow
- Provider: AWS Cognito
- Scopes:
openid,email,profile
Authentication Endpoints
GET /login
Initiates OAuth2 authentication flow with AWS Cognito.
Security: Public (no authentication required)
Response: 302 Redirect to Cognito login page
GET /login-callback
OAuth2 callback handler that processes authentication response.
Security: Public Parameters:
code(query, required): Authorization code from Cognito (max 2048 chars)state(query, required): CSRF protection parameter (max 1024 chars)
Response: 302 Sets JWT cookie and redirects to application
GET /logout
Terminates user session and clears authentication cookies.
Security: Public (no authentication required)
Response: 302 Redirect to Cognito logout page or application home
GET /home
Returns the HTML menu page.
Security: Public (no authentication required)
Response: 200 HTML content
GET /identity
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. This endpoint requires JWT authentication but does not require specific Permit.io permissions.
Security: Requires JWT authentication (auth-only, no Permit.io check)
Response (IdentityResponse):
{
"roles": [
{
"key": "auditor",
"name": "Auditor",
"description": "Read-only access to view documents and exports",
"permissions": ["document:read", "document:list", "export:read"]
}
]
}
Responses:
200: User roles and permissions retrieved successfully401: Authentication required429: Rate limit exceeded502: Failed to retrieve roles from Permit.io
Rate Limiting
The queryAPI service implements dual-layer rate limiting to protect against DDoS attacks and ensure fair resource allocation.
Rate Limit Architecture
Dual-Layer Protection:
- Layer 1: Global/Aggregate Rate Limiting - Protects total system capacity across all IP addresses
- Layer 2: Per-IP Rate Limiting - Prevents individual client abuse
Both layers must pass for a request to proceed. The global limiter checks first for faster failure paths under DDoS conditions.
Default Rate Limits
By default, all endpoints are limited to:
- Global: 500 requests per second total (1000 burst)
- Per-IP: 5 requests per second per IP (10 burst)
- Cleanup Interval: 3 minutes for inactive IP limiters
Important: No endpoints are exempt from rate limiting. This is a security requirement to prevent DDoS attacks.
Configuration
Rate limits are configured via environment variables:
# Global/Aggregate rate limiting (protects total system capacity)
RATE_LIMIT_GLOBAL_RATE=500 # total req/s across ALL IPs
RATE_LIMIT_GLOBAL_BURST=1000 # total burst capacity across ALL IPs
# Per-IP rate limiting (protects against individual abusers)
RATE_LIMIT_DEFAULT_RATE=5 # req/s per IP
RATE_LIMIT_DEFAULT_BURST=10 # burst per IP
RATE_LIMIT_EXPIRES_IN=180 # seconds (3 minutes)
# Per-endpoint overrides (JSON format)
RATE_LIMIT_ENDPOINT_OVERRIDES={}
Rate Limit Headers
All API responses include a RateLimit header indicating the current limit:
RateLimit: 20;window=2
Format: {burst};window={seconds}
Rate Limit Exceeded Response
HTTP Status: 429 Too Many Requests
Headers:
Retry-After: {seconds}- Number of seconds before retryingRateLimit: {burst};window={seconds}- Current rate limit
Response Body:
{
"message": "rate limit exceeded"
}
Client Management (ClientService)
GET /clients
Lists all clients in the system.
Security: Requires JWT authentication
Response (ClientListResponse):
{
"clients": [
{
"id": "AAA",
"name": "ACME Corporation",
"can_sync": true
}
],
"totalCount": 1
}
POST /client
Creates a new client in the system.
Security: Requires JWT authentication
Request Body (ClientCreate):
{
"id": "string (max 36 chars, required)",
"name": "string (max 256 chars, required)"
}
Responses:
201: Client created successfully{ "id": "AAA" }400: Invalid request data401: Authentication required429: Rate limit exceeded500: Internal server error
GET /client/{id}
Retrieves client details by ID.
Security: Requires JWT authentication
Path Parameters:
id: Client identifier (string, max 36 chars)
Response (DocClient):
{
"id": "AAA",
"name": "ACME Corporation",
"can_sync": true
}
PATCH /client/{id}
Updates client information.
Security: Requires JWT authentication
Request Body (ClientUpdate):
{
"name": "string (max 256 chars, optional)",
"can_sync": "boolean (optional)"
}
Response: 200 Client updated successfully
DELETE /client/{id}
Permanently deletes a client and all associated data: documents (with all dependent rows), folders, collector configurations, batch uploads, and clientCanSync records. Source documents in S3 are NOT deleted; their paths are logged and optionally returned. This operation is irreversible.
Security: Requires JWT authentication. Restricted to super_admin role only.
Query Parameters:
confirm(required, boolean): Must betrueto proceed. Returns400 Bad Requestif absent or false.verbose(optional, boolean, default: false): Whentrue, returns S3 paths of orphaned source documents.
Response:
204: Client deleted successfully (whenverbose=false)200: Client deleted successfully with S3 paths (whenverbose=true):
{
"deletedDocuments": [
{
"documentId": "019580df-b3f8-7348-9ab1-1e55b3f18ed7",
"s3Path": "s3://bucket-name/key/path/to/file"
}
]
}
400: Missingconfirm=truequery parameter404: Client not found
GET /client/{id}/status
Returns client synchronization status.
Security: Requires JWT authentication
Response (ClientStatusBody):
{
"status": "IN_SYNC"
}
Status Values: IN_SYNC, NOT_SYNCED, NOT_SYNCING
Document Operations (DocumentsService)
POST /client/{id}/document
Uploads a document for a specific client.
Security: Requires JWT authentication
Content Type: multipart/form-data
Max File Size: 100GB
Form Parameters:
file(required): Document file (PDF)filename(optional): Custom filename (max 4096 chars)
Response: 200 Document uploaded
GET /client/{id}/document
Lists documents for a client.
Security: Requires JWT authentication
Response (ListDocuments):
[
{
"id": "019580df-b3f8-7348-9ab1-1e55b3f18ed7",
"hash": "sha256:abc123..."
}
]
GET /document/{id}
Retrieves enriched document details by ID, including metadata such as folder, filename, labels, and optionally the full text extraction record.
Security: Requires JWT authentication
Path Parameters:
id: Document UUID (max 36 chars)
Query Parameters:
textRecord(optional, default: false): When true, includes the full text extraction record in the response
Response (DocumentEnriched):
{
"id": "019580df-b3f8-7348-9ab1-1e55b3f18ed7",
"client_id": "AAA",
"hash": "sha256:abc123...",
"hasTextRecord": true,
"folderId": "019580df-ef65-7676-8de9-94435a93337a",
"filename": "contract_2024.pdf",
"originalPath": "/documents/2024/contract_2024.pdf",
"labels": [
{
"id": "019580df-ef65-7676-8de9-94435a93337b",
"documentId": "019580df-b3f8-7348-9ab1-1e55b3f18ed7",
"label": "OCR_Processed",
"appliedBy": "user@example.com",
"appliedAt": "2025-10-16T14:27:15Z"
}
],
"fileSizeBytes": 1048576
}
GET /document/{id}/download
Streams the original uploaded document file directly from S3. The response Content-Type is auto-detected from the stored filename extension.
Security: Requires JWT authentication
Path Parameters:
id: Document UUID (max 36 chars)
Response (200): Raw file bytes (streamed)
Content-Type: Auto-detected from filename (e.g.,application/pdf,image/png,application/vnd.openxmlformats-officedocument.wordprocessingml.document)Content-Disposition:attachment; filename="<original_filename>"Content-Length: File size in bytes
Error Responses:
400: Invalid document ID format401: Missing or invalid JWT token404: Document not found or no S3 entry for the document500: S3 retrieval failure
Example:
curl -H "Authorization: Bearer <token>" \
-o report.pdf \
http://localhost:8080/document/019580df-ef65-7676-8de9-94435a93337a/download
Notes:
- No query parameters needed -- file type is automatically determined from the stored filename
- Response streams directly from S3, suitable for large files
- Returns 404 if the document has no stored file (e.g., legacy documents without S3 entries)
- Supports any file type without code changes (PDF, PNG, DOCX, CSV, etc.)
DELETE /document/{id}
Permanently deletes a document and all dependent data: document entries, cleans (and their entries), text extractions (and their entries), field extractions (versions and array fields), labels, results, and result dependencies. Source documents in S3 are NOT deleted; their paths are logged and optionally returned.
Security: Requires JWT authentication. Restricted to super_admin role only.
Path Parameters:
id: Document UUID (max 36 chars)
Query Parameters:
verbose(optional, boolean, default: false): Whentrue, returns S3 paths of orphaned source documents.
Response:
204: Document deleted successfully (whenverbose=false)200: Document deleted successfully with S3 paths (whenverbose=true):
{
"deletedDocuments": [
{
"documentId": "019580df-b3f8-7348-9ab1-1e55b3f18ed7",
"s3Path": "s3://bucket-name/key/path/to/file"
}
]
}
404: Document not found
Batch Document Operations (DocumentsService)
POST /client/{id}/document/batch
Uploads a ZIP archive containing multiple PDF documents for asynchronous batch processing.
Security: Requires JWT authentication
Content Type: multipart/form-data
Max Archive Size: 1GB
Supported Archive Type: ZIP only
Form Parameters:
archive(required): ZIP file containing PDF documents
Response (202 Accepted):
{
"batch_id": "019580df-ef65-7676-8de9-94435a93337a",
"status": "processing",
"status_url": "/client/AAA/document/batch/019580df-ef65-7676-8de9-94435a93337a"
}
GET /client/{id}/document/batch
Lists batch uploads for a client with pagination support.
Security: Requires JWT authentication
Query Parameters:
limit: Maximum results (integer, 1-100, default: 20)offset: Pagination offset (integer, default: 0)
Response (BatchUploadList):
{
"batches": [
{
"batch_id": "019580df-ef65-7676-8de9-94435a93337a",
"client_id": "AAA",
"original_filename": "documents.zip",
"status": "completed",
"total_documents": 100,
"processed_documents": 100,
"failed_documents": 2,
"invalid_type_documents": 1,
"progress_percent": 100,
"created_at": "2024-01-01T00:00:00Z",
"completed_at": "2024-01-01T00:05:00Z"
}
],
"total_count": 25
}
Batch Status Values: processing, completed, failed, cancelled
GET /client/{id}/document/batch/{batch_id}
Retrieves detailed status information for a specific batch upload, including per-file outcome tracking through the document processing pipeline.
Security: Requires JWT authentication
Path Parameters:
batch_id: Batch upload identifier (UUID)
Response (BatchUploadDetails):
{
"batch_id": "019580df-ef65-7676-8de9-94435a93337a",
"client_id": "AAA",
"original_filename": "documents.zip",
"status": "completed",
"total_documents": 5,
"processed_documents": 3,
"failed_documents": 1,
"invalid_type_documents": 1,
"progress_percent": 100,
"created_at": "2024-01-01T00:00:00Z",
"completed_at": "2024-01-01T00:05:00Z",
"failed_filenames": ["corrupt.pdf"],
"document_outcomes": [
{
"filename": "invoice.pdf",
"outcome": "clean_passed",
"document_id": "019580e0-1111-7676-8de9-000000000001",
"created_at": "2024-01-01T00:00:01Z",
"updated_at": "2024-01-01T00:04:50Z"
},
{
"filename": "receipt.pdf",
"outcome": "clean_passed",
"document_id": "019580e0-2222-7676-8de9-000000000002",
"created_at": "2024-01-01T00:00:01Z",
"updated_at": "2024-01-01T00:04:52Z"
},
{
"filename": "duplicate_invoice.pdf",
"outcome": "duplicate",
"document_id": "019580e0-1111-7676-8de9-000000000001",
"created_at": "2024-01-01T00:00:01Z",
"updated_at": "2024-01-01T00:00:01Z"
},
{
"filename": "corrupt.pdf",
"outcome": "clean_failed",
"error_detail": "PDF validation failed",
"document_id": "019580e0-3333-7676-8de9-000000000003",
"clean_fail_reason": "invalid PDF structure: missing xref table",
"created_at": "2024-01-01T00:00:01Z",
"updated_at": "2024-01-01T00:04:55Z"
},
{
"filename": "spreadsheet.xlsx",
"outcome": "invalid_type",
"error_detail": null,
"document_id": null,
"created_at": "2024-01-01T00:00:01Z",
"updated_at": "2024-01-01T00:00:01Z"
}
]
}
The document_outcomes array provides per-file tracking through the entire processing pipeline. Each file in the ZIP archive gets one outcome entry, starting at extraction time and updating as the file progresses through the document runners (init, sync, clean). When all outcomes reach a terminal state, the batch is fully processed.
Document Outcome Values:
| Outcome | Meaning | Terminal? |
|---|---|---|
submitted |
File extracted and uploaded, waiting for processing | No |
duplicate |
File hash matches an existing document for this client | Yes |
failed_open |
Could not open file from ZIP archive | Yes |
failed_read |
Could not read file content from ZIP archive | Yes |
failed_s3_upload |
Could not upload extracted file to S3 | Yes |
failed_upload |
Upload handler returned an error | Yes |
invalid_type |
File is not a PDF | Yes |
init_complete |
Document record created, forwarded to sync | No |
init_duplicate |
Duplicate detected during init processing | Yes |
sync_complete |
Sync check passed, forwarded to clean | No |
sync_skipped |
Client sync is disabled | Yes |
clean_passed |
Document passed all validation checks | Yes |
clean_failed |
Document failed validation (see clean_fail_reason) |
Yes |
Outcome Fields:
| Field | Type | Description |
|---|---|---|
filename |
string | Original filename from the ZIP archive |
outcome |
string | Current processing status (see table above) |
error_detail |
string or null | Human-readable error message for failure outcomes |
document_id |
uuid or null | Assigned document ID (null for files that never became documents) |
clean_fail_reason |
string or null | Specific validation failure reason when outcome is clean_failed |
created_at |
datetime | When the file was first extracted from the ZIP |
updated_at |
datetime | When the outcome was last updated by a pipeline stage |
Folder Operations (FolderService)
Folder Path Constraints
All folder paths must comply with the following constraints when creating or renaming folders:
- Must start with
/: All paths must begin with a forward slash - Maximum path length: 1000 characters
- Maximum segment length: 255 characters per path segment
- Maximum depth: 20 levels of nesting
- Valid characters only: Alphanumeric (
a-z,A-Z,0-9), hyphen (-), underscore (_), period (.), and space () - Segment must start with alphanumeric: Each path segment must begin with a letter or number
- No empty segments: Double slashes (
//) or trailing slashes are not allowed - No path traversal: Sequences like
..or./are blocked - No hidden folders: Segments cannot start with a period (e.g.,
/.hidden) - No leading/trailing whitespace: Spaces within segment names are allowed, but not at the start or end
- No control characters: ASCII control characters (0x00-0x1F, 0x7F) are blocked
- No Windows reserved names: Names like
CON,PRN,AUX,NUL,COM1-COM9,LPT1-LPT9are blocked - Root folder restrictions: The root path
/can only exist once per client and cannot be renamed - Path uniqueness: Each path must be unique within a client (enforced by database)
- Unicode normalization: Paths are normalized to NFC form
Valid path examples:
/documents/documents/2024/Q1/client-data/reports_2024/My Documents/Archive
Invalid path examples:
documents(missing leading/)/documents/(trailing slash)/foo//bar(empty segment)/foo/../bar(path traversal)/.hidden(dot prefix)/foo@bar(invalid character)/CON(Windows reserved name)
GET /clients/{clientId}/folders
Lists all folders for a specific client, including the folder hierarchy.
Security: Requires JWT authentication
Path Parameters:
clientId: Client external ID (string, max 36 chars)
Query Parameters:
metrics(optional, default: false): When true, includes processing metrics for each folder (document counts by label). Adds overhead so should only be used when metrics are needed.
Response (200 OK):
{
"folders": [
{
"id": "019580df-ef65-7676-8de9-94435a93337a",
"path": "/",
"parentId": null,
"clientId": "AAA",
"createdAt": "2025-10-16T14:27:15Z",
"createdBy": "system"
},
{
"id": "019580df-ef65-7676-8de9-94435a93337b",
"path": "/documents",
"parentId": "019580df-ef65-7676-8de9-94435a93337a",
"clientId": "AAA",
"createdAt": "2025-10-16T14:30:00Z",
"createdBy": "user@example.com"
},
{
"id": "019580df-ef65-7676-8de9-94435a93337c",
"path": "/documents/2024",
"parentId": "019580df-ef65-7676-8de9-94435a93337b",
"clientId": "AAA",
"createdAt": "2025-10-16T14:35:00Z",
"createdBy": "user@example.com"
}
]
}
Notes:
- Returns all folders for the client, including nested folders
- Folders are returned in a flat list; use
parentIdto reconstruct the hierarchy - The root folder (path="/") is included if it exists
POST /folders
Creates a new folder for organizing documents.
Security: Requires JWT authentication
Request Body (FolderCreate):
{
"path": "/documents/2024",
"clientId": "AAA",
"createdBy": "user@example.com",
"parentId": "019580df-ef65-7676-8de9-94435a93337a"
}
| Field | Type | Required | Description |
|---|---|---|---|
| path | string | Yes | Folder path, must start with "/" (max 1000 chars) |
| clientId | string | Yes | Client external ID |
| createdBy | string | Yes | Email of user creating the folder |
| parentId | uuid | No | Parent folder ID for nested folders |
Response (201 Created):
{
"id": "019580df-ef65-7676-8de9-94435a93337a",
"path": "/documents/2024",
"parentId": null,
"clientId": "AAA",
"createdAt": "2025-10-16T14:27:15Z",
"createdBy": "user@example.com"
}
PATCH /folders/{folderId}
Renames an existing folder.
Security: Requires JWT authentication
Path Parameters:
folderId: Folder UUID
Request Body (FolderRename):
{
"path": "/documents/2024-renamed"
}
Response (200 OK): Updated folder object
DELETE /folders/{folderId}
Permanently deletes a folder and all child folders recursively. The root folder (/) cannot be deleted. If the folder tree contains documents, the caller must either delete the documents first or pass include_documents=true.
Security: Requires JWT authentication. Restricted to super_admin role only.
Path Parameters:
folderId: Folder UUID
Query Parameters:
include_documents(optional, boolean, default: false): Whentrue, deletes all documents in the folder tree along with the folders. Whenfalseand the folder tree contains documents, returns409 Conflict.verbose(optional, boolean, default: false): Whentrue, returns S3 paths of orphaned source documents.
Response:
204: Folder tree deleted successfully (whenverbose=false)200: Folder tree deleted successfully with S3 paths (whenverbose=true):
{
"deletedDocuments": [
{
"documentId": "019580df-b3f8-7348-9ab1-1e55b3f18ed7",
"s3Path": "s3://bucket-name/key/path/to/file"
}
]
}
404: Folder not found409: Cannot delete root folder, or folder tree contains documents andinclude_documentsis nottrue
GET /folders/{folderId}/documents
Retrieves all documents within a specific folder, including filename and labels. Returns a lighter-weight format than GET /document/{id} (excludes client_id).
Security: Requires JWT authentication
Query Parameters:
textRecord(optional, default: false): When true, includes the full text extraction record for each document
Response:
{
"documents": [
{
"id": "019580df-b3f8-7348-9ab1-1e55b3f18ed7",
"hash": "sha256:abc123...",
"hasTextRecord": true,
"folderId": "019580df-ef65-7676-8de9-94435a93337a",
"filename": "contract_2024.pdf",
"originalPath": "/documents/2024/contract_2024.pdf",
"labels": [],
"fileSizeBytes": 1048576
}
]
}
GET /folders/{folderId}/metrics
Retrieves processing progress metrics for documents in a folder.
Security: Requires JWT authentication
Response (FolderMetrics):
{
"folderId": "019580df-ef65-7676-8de9-94435a93337a",
"totalDocuments": 150,
"byLabel": {
"Ingested": 150,
"OCR_Processed": 120,
"Dashboard_Ready": 100
}
}
Label Operations (LabelService)
POST /documents/{documentId}/labels
Applies a workflow label to a document for tracking processing state.
Security: Requires JWT authentication
Path Parameters:
documentId: Document UUID
Request Body (LabelApplication):
{
"label": "OCR_Processed",
"appliedBy": "user@example.com"
}
| Field | Type | Required | Description |
|---|---|---|---|
| label | string | Yes | Label name (alphanumeric and underscore only, max 100 chars) |
| appliedBy | string | Yes | Email of user applying the label |
Response (201 Created):
{
"id": "019580df-ef65-7676-8de9-94435a93337a",
"documentId": "019580df-b3f8-7348-9ab1-1e55b3f18ed7",
"label": "OCR_Processed",
"appliedBy": "user@example.com",
"appliedAt": "2025-10-16T14:27:15Z"
}
GET /documents/{documentId}/labels
Retrieves all labels that have been applied to a document, ordered by most recent first.
Security: Requires JWT authentication
Response:
{
"labels": [
{
"id": "019580df-ef65-7676-8de9-94435a93337a",
"documentId": "019580df-b3f8-7348-9ab1-1e55b3f18ed7",
"label": "OCR_Processed",
"appliedBy": "user@example.com",
"appliedAt": "2025-10-16T14:27:15Z"
}
]
}
GET /labels/{labelName}/documents
Retrieves all documents that have been tagged with a specific label.
Security: Requires JWT authentication
Path Parameters:
labelName: Label name (alphanumeric and underscore only, max 100 chars)
Query Parameters:
clientId(required): Client ID to filter documents (string, max 36 chars)
Response:
{
"documents": [
{
"id": "019580df-b3f8-7348-9ab1-1e55b3f18ed7",
"hash": "sha256:abc123..."
}
]
}
Field Extraction Operations (FieldExtractionService)
POST /field-extractions
Creates a new field extraction with single-value and array fields for a document.
Security: Requires JWT authentication
Request Body (FieldExtractionRequest):
{
"documentId": "019580df-b3f8-7348-9ab1-1e55b3f18ed7",
"singleFields": {
"fileName": "contract_2024.pdf",
"contractTitle": "Service Agreement",
"clientName": "ACME Corp",
"payerName": "Insurance Co",
"payerState": "CA",
"providerState": "NY",
"aareteDerivedEffectiveDt": "2024-01-01",
"aareteDerivedTerminationDt": "2025-12-31",
"autoRenewalInd": true
},
"arrayFields": [
{
"exhibitTitle": "Exhibit A",
"exhibitPage": "15",
"reimbProvTin": "123456789",
"reimbProvNpi": "1234567890",
"reimbProvName": "Provider Name",
"reimbEffectiveDt": "2024-01-01",
"aareteDerivedClaimTypeCd": "INPATIENT",
"aareteDerivedReimbMethod": "Per Diem",
"reimbPctRate": 85.5,
"reimbFeeRate": 150.0
}
],
"createdBy": "user@example.com"
}
Single Fields (1:1 relationship with document):
fileName,contractTitle,clientName,payerNamepayerState,providerState(2-letter state codes)filenameTin,provGroupTin,provGroupNpi,provGroupNameFullprovOtherTin,provOtherNpi,provOtherNameFullaareteDerivedEffectiveDt,aareteDerivedTerminationDt(dates)aareteDerivedAmendmentNum(integer)autoRenewalInd(boolean),autoRenewalTerm
Array Fields (1:N relationship - multiple rows per document):
- Provider info:
reimbProvTin,reimbProvNpi,reimbProvName - Dates:
reimbEffectiveDt,reimbTerminationDt - Classifications:
aareteDerivedClaimTypeCd,aareteDerivedProduct,aareteDerivedLob,aareteDerivedProgram,aareteDerivedNetwork,aareteDerivedProvType - Codes:
provTaxonomyCd,provSpecialtyCd,placeOfServiceCd,billTypeCd,cpt4ProcCd,revenueCd,diagCd,ndcCd - Rates:
reimbPctRate,reimbFeeRate,reimbConversionFactor,grouperPctRate,grouperBaseRate - Indicators:
carveoutInd,lesserOfInd,greaterOfInd,defaultInd
Response (201 Created):
{
"id": "019580df-ef65-7676-8de9-94435a93337a",
"documentId": "019580df-b3f8-7348-9ab1-1e55b3f18ed7",
"version": 1,
"singleFields": { ... },
"arrayFields": [ ... ],
"createdAt": "2025-10-16T14:27:15Z",
"createdBy": "user@example.com"
}
GET /field-extractions
Retrieves the most recent field extraction for a document.
Security: Requires JWT authentication
Query Parameters:
documentId(required): Document UUID
Response: FieldExtractionResponse (same as POST response)
GET /field-extractions/history
Retrieves all versions of field extractions for a document, ordered by most recent first.
Security: Requires JWT authentication
Query Parameters:
documentId(required): Document UUID
Response:
{
"versions": [
{
"id": "019580df-ef65-7676-8de9-94435a93337a",
"documentId": "019580df-b3f8-7348-9ab1-1e55b3f18ed7",
"version": 2,
"createdAt": "2025-10-17T10:00:00Z",
"createdBy": "user@example.com"
},
{
"id": "019580df-ef65-7676-8de9-94435a93337b",
"documentId": "019580df-b3f8-7348-9ab1-1e55b3f18ed7",
"version": 1,
"createdAt": "2025-10-16T14:27:15Z",
"createdBy": "user@example.com"
}
]
}
GET /field-extractions/version
Retrieves a specific version of a field extraction for a document by version number.
Security: Requires JWT authentication
Query Parameters:
documentId(required): Document UUIDversion(required): Version number (integer, minimum 1)
Response (200 OK):
{
"id": "019580df-ef65-7676-8de9-94435a93337a",
"documentId": "019580df-b3f8-7348-9ab1-1e55b3f18ed7",
"version": 1,
"singleFields": {
"fileName": "contract_2024.pdf",
"contractTitle": "Service Agreement",
"clientName": "ACME Corp"
},
"arrayFields": [],
"createdAt": "2025-10-16T14:27:15Z",
"createdBy": "user@example.com"
}
Error Responses:
400: Missing required query parameters404: Version not found for the specified document
Collector Configuration (CollectorService)
GET /client/{id}/collector
Retrieves collector configuration for a client.
Security: Requires JWT authentication
Response (Collector):
{
"client_id": "AAA",
"active_version": 1,
"latest_version": 2,
"minimum_cleaner_version": 1,
"minimum_text_version": 1,
"fields": [
{
"name": "contract_date",
"query_id": "019580df-ef65-7676-8de9-94435a93337a"
}
]
}
PATCH /client/{id}/collector
Updates collector configuration.
Security: Requires JWT authentication
Request Body (CollectorSet):
{
"minimum_cleaner_version": 2,
"minimum_text_version": 2,
"active_version": 1,
"fields": [
{
"name": "contract_date",
"query_id": "019580df-ef65-7676-8de9-94435a93337a"
}
]
}
Response: 204 Collector set successfully
Export Operations (ExportService)
POST /client/{id}/export
Triggers data export for a client.
Security: Requires JWT authentication
Request Body (ExportTrigger):
{
"ingestion_filters": {
"start_date": "2024-01-01T00:00:00Z",
"end_date": "2024-12-31T23:59:59Z"
},
"field_filters": [
{
"field_name": "contract_type",
"condition": "include",
"values": ["SERVICE", "PRODUCT"]
}
]
}
Filter Conditions: less_than, greater_than, closed_interval, open_interval, left_closed_interval, right_closed_interval, include, exclude
Response (201 Created):
{
"id": "019580de-4d51-713c-98ee-464e83811f13"
}
GET /export/{id}
Checks export status and retrieves download URL.
Security: Requires JWT authentication
Response (ExportDetails):
{
"client_id": "AAA",
"status": "completed",
"output_location": "s3://bucket/AAA/export/20250213/uuid.csv"
}
Export Status Values: completed, in_progress, failed
User Administration (AdminService)
POST /admin/users
Creates a new user in both AWS Cognito and Permit.io systems with optional role assignments.
Security: Requires JWT authentication
Environment Scoping: When COGNITO_ENVIRONMENT_ID is configured on the server, newly created users are automatically tagged with the custom:environment_id attribute matching the server's value. This ensures users are scoped to the correct environment.
Creation Flow:
- User is created in AWS Cognito (primary authentication system) with the server's environment ID (if configured)
- If Cognito creation fails, operation fails with HTTP 502
- User is created in Permit.io (authorization/role system) with the environment ID as an attribute
- If Permit.io creation fails, user still exists in Cognito but
permit_synced=false - Roles are assigned in Permit.io (best-effort, continues on failures)
Request Body (AdminUserCreate):
{
"email": "john.doe@example.com",
"first_name": "John",
"last_name": "Doe",
"roles": ["user_admin", "auditor"]
}
| Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | User email address (max 320 chars) | |
| first_name | string | Yes | User's given name (max 100 chars) |
| last_name | string | Yes | User's family name (max 100 chars) |
| roles | array | Yes | List of role keys to assign (1-50 roles) |
Response (201 Created or 200 OK if user exists):
{
"cognito_subject_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "john.doe@example.com",
"first_name": "John",
"last_name": "Doe",
"status": "FORCE_CHANGE_PASSWORD",
"enabled": true,
"permit_synced": true,
"roles_assigned": ["user_admin", "auditor"],
"created_at": "2025-10-16T14:23:45Z"
}
Error Responses:
400: Invalid request data401: Authentication required403: Insufficient permissions409: User already exists with different attributes429: Rate limit exceeded502: External service (Cognito) error
GET /admin/users
Lists users from AWS Cognito with pagination, filtering, and sorting support.
Security: Requires JWT authentication
Environment Filtering: When COGNITO_ENVIRONMENT_ID is configured, the response is filtered to include only users whose custom:environment_id matches the server's value or users with no environment tag (legacy/untagged users). Users belonging to other environments are excluded from the results.
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
| page | integer | 1 | Page number (1-10000) |
| page_size | integer | 50 | Results per page (1-100) |
| search | string | - | Search term for email/name filtering |
| status | string | all | Filter by status: enabled, disabled, all |
| sort_by | string | Sort field: email, created_at, last_name |
|
| sort_order | string | asc | Sort direction: asc, desc |
Response (AdminUserList):
{
"users": [
{
"cognito_subject_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "john.doe@example.com",
"first_name": "John",
"last_name": "Doe",
"status": "CONFIRMED",
"enabled": true,
"roles": ["admin", "viewer"],
"created_at": "2025-10-15T09:15:30Z",
"updated_at": "2025-10-16T14:20:10Z"
}
],
"total": 147,
"page": 1,
"page_size": 50,
"has_more": true
}
GET /admin/users/{email}
Retrieves user details from both AWS Cognito and Permit.io by email address.
Security: Requires JWT authentication
Environment Ownership: When COGNITO_ENVIRONMENT_ID is configured, returns 404 Not Found for users belonging to a different environment to prevent information leakage. Untagged users and users matching the server's environment are accessible.
Path Parameters:
email: URL-encoded user email address (max 320 chars)
Response (AdminUserDetails): Same structure as user list item
HEAD /admin/users/{email}
Checks if a user exists in Cognito and/or Permit.io without returning full details.
Security: Requires JWT authentication
Environment Ownership: When COGNITO_ENVIRONMENT_ID is configured, returns 404 for users belonging to a different environment.
Response Headers:
X-User-Exists-Cognito: booleanX-User-Exists-PermitIO: boolean
Response:
200: User exists (at least in one system)404: User does not exist in either system
PATCH /admin/users/{email}
Updates user attributes (first_name, last_name) in Cognito and manages role assignments in Permit.io.
Security: Requires JWT authentication
Environment Ownership: When COGNITO_ENVIRONMENT_ID is configured, returns 404 Not Found for users belonging to a different environment.
Role Management (REPLACE Strategy):
- Providing a
rolesarray 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
Request Body (AdminUserUpdate):
{
"first_name": "Jonathan",
"last_name": "Doe-Smith",
"roles": ["user_admin", "auditor"]
}
Response (200 OK): Updated AdminUserDetails
DELETE /admin/users/{email}
Permanently deletes a user from both AWS Cognito and Permit.io. This operation is irreversible.
Security: Requires JWT authentication
Environment Ownership: When COGNITO_ENVIRONMENT_ID is configured, returns 404 Not Found for users belonging to a different environment.
Query Parameters:
confirm(required): Must betrueto confirm deletion
Response (200 OK or 207 Multi-Status):
{
"success": true,
"email": "john.doe@example.com",
"cognito_subject_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"deleted_from": {
"cognito": true,
"permit": true
},
"timestamp": "2025-10-16T14:27:15Z"
}
POST /admin/users/{email}/disable
Disables a user in AWS Cognito, preventing authentication. User data and roles are preserved. Idempotent.
Security: Requires JWT authentication
Environment Ownership: When COGNITO_ENVIRONMENT_ID is configured, returns 404 Not Found for users belonging to a different environment.
Response (AdminUserActionResponse):
{
"success": true,
"email": "john.doe@example.com",
"action": "disable",
"cognito_subject_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": "2025-10-16T14:25:33Z"
}
POST /admin/users/{email}/enable
Re-enables a previously disabled user in AWS Cognito. Restores authentication capability. Idempotent.
Security: Requires JWT authentication
Environment Ownership: When COGNITO_ENVIRONMENT_ID is configured, returns 404 Not Found for users belonging to a different environment.
Response: Same as disable endpoint with "action": "enable"
EULA Operations (EulaService)
The EULA (End User License Agreement) service manages EULA versions and tracks user consent. It provides both public endpoints for retrieving and agreeing to EULAs, and administrative endpoints for managing EULA versions and viewing compliance reports.
Public Endpoints
GET /eula
Returns the current active EULA version. This endpoint is public and does not require authentication.
Security: Public (no authentication required)
Response (EulaPublicResponse):
{
"id": "019580df-ef65-7676-8de9-94435a93337a",
"version": "1.0",
"title": "Terms of Service",
"content": "# Terms of Service\n\nThis is the full EULA content in Markdown format...",
"effective_date": "2025-01-01T00:00:00Z"
}
Responses:
200: Current EULA version retrieved successfully404: No current EULA version configured500: Internal server error
GET /eula/status
Returns the current user's agreement status for the current EULA version. Used by the frontend to determine if the user needs to be prompted to agree.
Security: Requires JWT authentication
Response (EulaStatusResponse):
{
"has_agreed": true,
"current_version": "1.0",
"current_version_id": "019580df-ef65-7676-8de9-94435a93337a",
"agreed_at": "2025-01-15T10:30:00Z",
"agreed_version": "1.0"
}
Responses:
200: EULA status retrieved successfully401: Authentication required404: No current EULA version configured500: Internal server error
POST /eula/agree
Records the user's agreement to the current EULA version. This operation is idempotent - calling it multiple times will not create duplicate records. The IP address is automatically captured from the request.
Security: Requires JWT authentication
Response (EulaAgreementResponse):
{
"id": "019580df-ef65-7676-8de9-94435a93337b",
"eula_version_id": "019580df-ef65-7676-8de9-94435a93337a",
"eula_version": "1.0",
"agreed_at": "2025-01-15T10:30:00Z"
}
Responses:
201: Agreement recorded successfully (first agreement)200: User already agreed to current version (returns existing agreement)400: No current EULA version configured401: Authentication required500: Internal server error
Administrative Endpoints
GET /admin/eula
Returns a paginated list of all EULA versions.
Security: Requires JWT authentication
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
| page | integer | 1 | Page number (1-10000) |
| page_size | integer | 20 | Results per page (1-100) |
Response (EulaVersionList):
{
"versions": [
{
"id": "019580df-ef65-7676-8de9-94435a93337a",
"version": "1.0",
"title": "Terms of Service",
"content": "# Terms of Service...",
"effective_date": "2025-01-01T00:00:00Z",
"is_current": true,
"created_at": "2024-12-01T00:00:00Z",
"created_by": "admin@example.com",
"activated_at": "2025-01-01T00:00:00Z",
"activated_by": "admin@example.com"
}
],
"total": 3,
"has_more": false
}
POST /admin/eula
Creates a new EULA version. The content should be in Markdown format.
Security: Requires JWT authentication
Request Body (EulaVersionCreate):
{
"version": "2.0",
"title": "Updated Terms of Service",
"content": "# Updated Terms of Service\n\nThis is the new EULA content...",
"effective_date": "2025-06-01T00:00:00Z"
}
| Field | Type | Required | Description |
|---|---|---|---|
| version | string | Yes | Unique version identifier (max 50 chars) |
| title | string | Yes | Human-readable title |
| content | string | Yes | Full EULA text in Markdown format |
| effective_date | datetime | Yes | When this version becomes effective |
Response (201 Created): EulaVersion object
Error Responses:
400: Invalid request data401: Authentication required403: Insufficient permissions409: Version string already exists
GET /admin/eula/{version_id}
Retrieves a specific EULA version by its ID.
Security: Requires JWT authentication
Path Parameters:
version_id: EULA version UUID
Response (EulaVersion): Full EULA version object
PATCH /admin/eula/{version_id}
Updates only the metadata (title and effective date) of an EULA version. Content cannot be modified to maintain audit integrity.
Security: Requires JWT authentication
Request Body (EulaVersionUpdate):
{
"title": "Updated Title",
"effective_date": "2025-07-01T00:00:00Z"
}
Response (200 OK): Updated EulaVersion object
POST /admin/eula/{version_id}/activate
Sets this version as the current active EULA. Uses a database transaction to atomically clear the previous current flag and set the new one.
Security: Requires JWT authentication
Path Parameters:
version_id: EULA version UUID to activate
Response (200 OK): Activated EulaVersion object with is_current=true
Error Responses:
404: Version not found409: Concurrent activation conflict (another admin activated a different version)
GET /admin/eula/agreements
Returns a paginated list of user agreements. Use filters to view agreements for specific EULA versions or users.
Security: Requires JWT authentication
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
| page | integer | 1 | Page number (1-10000) |
| page_size | integer | 20 | Results per page (1-100) |
| version_id | uuid | - | Filter by specific EULA version |
| user_id | string | - | Filter by Cognito subject ID |
Response (EulaAgreementList):
{
"agreements": [
{
"id": "019580df-ef65-7676-8de9-94435a93337b",
"cognito_subject_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"user_email": "user@example.com",
"eula_version_id": "019580df-ef65-7676-8de9-94435a93337a",
"eula_version": "1.0",
"agreed_at": "2025-01-15T10:30:00Z",
"agreed_from_ip": "192.168.1.1"
}
],
"total": 150,
"has_more": true
}
GET /admin/eula/compliance
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.
Security: Requires JWT authentication
Environment Filtering: When COGNITO_ENVIRONMENT_ID is configured, the compliance report only includes users matching the server's environment or untagged legacy users. Users from other environments are excluded from the total counts and user list.
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
| page | integer | 1 | Page number (1-10000) |
| page_size | integer | 50 | Results per page (1-100) |
| version_id | uuid | - | Specific EULA version (defaults to current) |
| agreed | boolean | - | Filter by agreement status |
Response (EulaComplianceReport):
{
"version_id": "019580df-ef65-7676-8de9-94435a93337a",
"version": "1.0",
"total_users": 200,
"agreed_count": 150,
"not_agreed_count": 50,
"compliance_percentage": 75.0,
"users": [
{
"cognito_subject_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "user@example.com",
"first_name": "John",
"last_name": "Doe",
"has_agreed": true,
"agreed_at": "2025-01-15T10:30:00Z"
}
],
"page": 1,
"page_size": 50,
"has_more": true
}
UI Settings Operations (UISettingsService)
The UI Settings service provides a generic key-value store scoped by namespace. Use it for user preferences, feature flags, saved filters, or other UI state. Namespaces scope data (e.g. demo-dashboard:{userId}, feature-flags:global, saved-filters:{clientId}). Records use soft delete (isDeleted); list/get exclude soft-deleted rows.
Security: All UI settings endpoints require JWT authentication (auth-only, no Permit.io resource check).
GET /ui-settings
Returns settings where isDeleted is false. Optional query param namespace filters by namespace.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| namespace | string | No | Filter by namespace (omit to list all). Max 255 chars. |
Response (UISettingListResponse): { settings: UISetting[], totalCount: number }
Responses: 200 OK, 400 Bad Request, 401 Unauthorized, 429 Too Many Requests, 500 Internal Server Error
POST /ui-settings
Creates a new UI setting. Returns 201 with the created resource.
Request Body (UISettingCreate):
| Field | Type | Required | Description |
|---|---|---|---|
| namespace | string | Yes | Scope for the setting (e.g. demo-dashboard:{userId}, feature-flags:global). Max 255. |
| key | string | Yes | Setting key within the namespace. Max 255. |
| value | object | Yes | JSON value (object) for the setting. |
Response (UISetting): Created setting with id, namespace, key, value, isDeleted, createdAt, updatedAt
Responses: 201 Created, 400 Bad Request, 401 Unauthorized, 429 Too Many Requests, 500 Internal Server Error
GET /ui-settings/{id}
Returns a single setting by id. Returns 404 if not found or soft-deleted.
Path Parameters: id (uuid) – UI setting ID
Response (UISetting): Full setting object
Responses: 200 OK, 400 Bad Request, 401 Unauthorized, 404 Not Found, 429 Too Many Requests, 500 Internal Server Error
PATCH /ui-settings/{id}
Updates the value of an existing setting. Returns 404 if not found or soft-deleted.
Path Parameters: id (uuid) – UI setting ID
Request Body (UISettingUpdate): { value: object } – New JSON value for the setting
Response (UISetting): Updated setting object
Responses: 200 OK, 400 Bad Request, 401 Unauthorized, 404 Not Found, 429 Too Many Requests, 500 Internal Server Error
DELETE /ui-settings/{id}
Soft-deletes a UI setting (sets isDeleted to true). Record is retained. Returns 204 on success, 404 if not found.
Path Parameters: id (uuid) – UI setting ID
Responses: 204 No Content, 400 Bad Request, 401 Unauthorized, 404 Not Found, 429 Too Many Requests, 500 Internal Server Error
Request/Response Schemas
Standard Response Headers
All API responses include:
RateLimit: Current rate limit status (format:100;window=60)Content-Type:application/json(except file downloads and HTML pages)
Error Response Format
{
"message": "Error description (max 256 chars)"
}
Common HTTP Status Codes
| Code | Description |
|---|---|
| 200 | Success |
| 201 | Created |
| 202 | Accepted (async processing) |
| 204 | No Content (success with no body) |
| 207 | Multi-Status (partial success) |
| 302 | Redirect |
| 400 | Bad Request (validation errors) |
| 401 | Unauthorized (authentication required) |
| 403 | Forbidden (insufficient permissions) |
| 404 | Not Found |
| 409 | Conflict (resource exists or state conflict) |
| 429 | Too Many Requests (rate limited) |
| 500 | Internal Server Error |
| 502 | Bad Gateway (external service error) |
API Versioning
Current Strategy
- URL-based versioning:
/v1prefix - Backward Compatibility: Maintained within major versions
- OpenAPI Version: 0.0.1 (development phase)
Future Considerations
- Semantic versioning for production releases
- Deprecation notices for breaking changes
- Version sunset policies
Authorization Reference (Permit.io Integration)
The API uses Permit.io for fine-grained authorization. This section documents what data is sent to Permit.io for each endpoint, enabling system administrators to configure the correct resources, actions, and roles in Permit.io.
Authorization Flow
- Authentication: User authenticates via AWS Cognito, receiving a JWT token
- User Identification: The
sub(subject) claim from the JWT is extracted as the user identifier - Resource Mapping: The first path segment of the URL becomes the resource (e.g.,
/client/{id}/document→client) - Action Mapping: The HTTP method is converted to lowercase to become the action (e.g.,
GET→get) - Permission Check: Permit.io checks if the user has permission to perform the action on the resource
Permit.io Data Mapping Logic
Resource Extraction (from internal/cognitoauth/mapping.go):
- The resource is derived from the first segment of the URL path
- Leading slashes are removed
- Example:
/client/{id}/document/batch/{batch_id}→ resource:client
Action Extraction:
- HTTP method is converted to lowercase
GET→get,POST→post,PATCH→patch,DELETE→delete,HEAD→head
Endpoints Exempt from Authorization
The following endpoints skip authentication and Permit.io authorization entirely:
| Endpoint | Purpose |
|---|---|
GET /home |
Public home/menu page |
GET /logout |
Session termination |
GET /health |
Health check endpoint |
GET /swagger/* |
Swagger UI documentation |
GET /metrics |
Prometheus metrics |
GET /eula |
Public EULA version retrieval |
Special Authentication Endpoints
These endpoints handle authentication flows and bypass normal authorization:
| Endpoint | Purpose |
|---|---|
GET /login |
Initiates OAuth2/PKCE login flow with Cognito |
GET /login-callback |
Handles OAuth2 callback from Cognito |
Auth-Only Endpoints (JWT required, no Permit.io check)
The following endpoints require a valid JWT token but do not check Permit.io permissions. Any authenticated user can access them:
| Endpoint | Purpose |
|---|---|
GET /identity |
Users need to discover their roles |
GET /eula/status |
Users need to check their EULA agreement status |
POST /eula/agree |
Users need to be able to agree to the EULA |
GET /ui-settings |
List UI settings (optional namespace filter) |
POST /ui-settings |
Create UI setting |
GET /ui-settings/{id} |
Get UI setting by ID |
PATCH /ui-settings/{id} |
Update UI setting value |
DELETE /ui-settings/{id} |
Soft-delete UI setting |
Authorization Reference Table
The following table shows what data is passed to Permit.io for each protected endpoint:
| HTTP Method | Endpoint | Resource | Action | Notes |
|---|---|---|---|---|
| Client Management | ||||
POST |
/client |
client |
post |
Create new client |
GET |
/clients |
clients |
get |
List all clients |
GET |
/client/{id} |
client |
get |
Get client details |
PATCH |
/client/{id} |
client |
patch |
Update client |
DELETE |
/client/{id} |
client |
delete |
Hard-delete client (super_admin only) |
GET |
/client/{id}/status |
client |
get |
Get client sync status |
| Document Operations | ||||
POST |
/client/{id}/document |
client |
post |
Upload document |
GET |
/client/{id}/document |
client |
get |
List client documents |
GET |
/document/{id} |
document |
get |
Get document details |
GET |
/document/{id}/download |
document |
get |
Download document file |
DELETE |
/document/{id} |
document |
delete |
Hard-delete document (super_admin only) |
| Batch Document Operations | ||||
POST |
/client/{id}/document/batch |
client |
post |
Upload batch (ZIP) |
GET |
/client/{id}/document/batch |
client |
get |
List batch uploads |
GET |
/client/{id}/document/batch/{batch_id} |
client |
get |
Get batch status |
| Folder Operations | ||||
GET |
/client/{id}/folders |
client |
get |
List client folders |
POST |
/folders |
folders |
post |
Create folder |
PATCH |
/folders/{folderId} |
folders |
patch |
Rename folder |
DELETE |
/folders/{folderId} |
folders |
delete |
Hard-delete folder tree (super_admin only) |
GET |
/folders/{folderId}/documents |
folders |
get |
List folder documents |
GET |
/folders/{folderId}/metrics |
folders |
get |
Get folder metrics |
| Label Operations | ||||
POST |
/documents/{documentId}/labels |
documents |
post |
Apply label to document |
GET |
/documents/{documentId}/labels |
documents |
get |
Get document labels |
GET |
/labels/{labelName}/documents |
labels |
get |
Get documents by label |
| Field Extraction Operations | ||||
POST |
/field-extractions |
field-extractions |
post |
Create field extraction |
GET |
/field-extractions |
field-extractions |
get |
Get latest extraction |
GET |
/field-extractions/version |
field-extractions |
get |
Get specific version |
GET |
/field-extractions/history |
field-extractions |
get |
Get extraction history |
| Collector Configuration | ||||
GET |
/client/{id}/collector |
client |
get |
Get collector config |
PATCH |
/client/{id}/collector |
client |
patch |
Update collector config |
| Export Operations | ||||
POST |
/client/{id}/export |
client |
post |
Trigger export |
GET |
/export/{id} |
export |
get |
Get export status |
| User Administration | ||||
POST |
/admin/users |
admin |
post |
Create user |
GET |
/admin/users |
admin |
get |
List users |
GET |
/admin/users/{email} |
admin |
get |
Get user details |
HEAD |
/admin/users/{email} |
admin |
head |
Check user existence |
PATCH |
/admin/users/{email} |
admin |
patch |
Update user |
DELETE |
/admin/users/{email} |
admin |
delete |
Delete user |
POST |
/admin/users/{email}/disable |
admin |
post |
Disable user |
POST |
/admin/users/{email}/enable |
admin |
post |
Enable user |
| EULA Operations | ||||
GET |
/eula |
- | - | Public (no auth) |
GET |
/eula/status |
- | - | Auth-only (no Permit.io) |
POST |
/eula/agree |
- | - | Auth-only (no Permit.io) |
GET |
/admin/eula |
admin |
get |
List EULA versions |
POST |
/admin/eula |
admin |
post |
Create EULA version |
GET |
/admin/eula/{version_id} |
admin |
get |
Get EULA version |
PATCH |
/admin/eula/{version_id} |
admin |
patch |
Update EULA metadata |
POST |
/admin/eula/{version_id}/activate |
admin |
post |
Activate EULA version |
GET |
/admin/eula/agreements |
admin |
get |
List EULA agreements |
GET |
/admin/eula/compliance |
admin |
get |
Get compliance report |
| UI Settings Operations | ||||
GET |
/ui-settings |
- | - | Auth-only (no Permit.io) |
POST |
/ui-settings |
- | - | Auth-only (no Permit.io) |
GET |
/ui-settings/{id} |
- | - | Auth-only (no Permit.io) |
PATCH |
/ui-settings/{id} |
- | - | Auth-only (no Permit.io) |
DELETE |
/ui-settings/{id} |
- | - | Auth-only (no Permit.io) |
Permit.io Configuration Requirements
To configure Permit.io to work with this API, administrators must create:
Resources
| Resource Key | Description |
|---|---|
client |
Client management and client-scoped operations |
clients |
Client listing (plural form) |
document |
Individual document operations |
documents |
Document collection and label operations |
folders |
Folder management |
labels |
Label-based document queries |
field-extractions |
Field extraction operations |
export |
Export operations |
admin |
User administration and EULA admin operations |
Actions
| Action Key | HTTP Method | Description |
|---|---|---|
get |
GET | Read/retrieve resources |
post |
POST | Create resources |
patch |
PATCH | Update resources |
delete |
DELETE | Delete resources |
head |
HEAD | Check resource existence |
Role Configuration
The following roles are defined in the Permit.io configuration (cmd/auth_related/permit.setup/permit_policies.yaml):
| Role | Resources | Actions | Use Case |
|---|---|---|---|
super_admin |
All resources | All actions including delete |
Full administrative access |
user_admin |
admin, documents, field-extractions, folders |
get, post, patch, delete (admin only) |
User management |
auditor |
admin, client, clients, document, export, documents, field-extractions, folders, labels |
get (and head for admin) |
Read-only access for auditing |
client_user |
client, clients, document, export, documents, field-extractions, folders, labels |
get, post, patch (varies by resource) |
Client-specific access |
Delete permissions: Only super_admin has delete access to client, document, and folders resources. The client_user role does NOT have client:delete or any other delete permissions on these resources.
Authorization Error Responses
When authorization fails, the API returns:
HTTP 401 Unauthorized - No valid JWT token:
{
"error": "Authorization required",
"message": "This endpoint requires authentication. Please obtain a valid JWT token.",
"login_url": "/login"
}
HTTP 403 Forbidden - Insufficient permissions:
{
"error": "Insufficient permissions",
"message": "Access denied by authorization service",
"user": "<cognito-subject-id>",
"resource": "<resource-name>",
"action": "<action-name>"
}
Code Generation
OpenAPI Integration
The API is generated from the OpenAPI specification using:
oapi-codegen -generate "types,server" -o api.gen.go serviceAPIs/queryAPI.yaml
Generated Artifacts
- Type-safe Go structs for requests/responses
- Echo framework route handlers
- OpenAPI validation middleware
- Swagger documentation
Validation
- Automatic request validation against OpenAPI schema
- Response validation in development mode
- Parameter binding with type safety