{
  "openapi": "3.0.1",
  "info": {
    "title": "AIVINOVA Document Service API",
    "description": "Developed by [AIVINOVA Technology](https://aivinova.com/en/), this Document Service provides enterprise-grade document management in your own cloud tenant. Store documents cost-effectively, integrate them in real-time with CRM and ERP systems (such as Salesforce, Dynamics 365, SAP) via APIs and apps, and share files securely with external customers through protected download links. Your documents, your cloud, your control.\n\n---\n\n**Quick Start**\n\n- [Configure Postman Environment](/openapi/postman-environment) — optionally enter your credentials and download a ready-to-import environment\n- [Download OpenAPI JSON](/openapi/v1.json) — raw OpenAPI 3.x specification",
    "version": "v1"
  },
  "servers": [
    {
      "url": "https://docservice-intern-dev.aivinova.com",
      "description": "Azure Development"
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "tags": [
          "System - Health"
        ],
        "summary": "Health Check",
        "description": "## Comprehensive Health Check\n\nPerforms a comprehensive health check of all system components including database, blob storage, and configuration.\n\n---\n\n## Response\n\n```json\n{\n  \"status\": \"Healthy\",\n  \"totalDuration\": \"PT0.234S\",\n  \"checks\": {\n    \"database\": {\n      \"status\": \"Healthy\",\n      \"duration\": \"PT0.123S\"\n    },\n    \"blobstorage\": {\n      \"status\": \"Healthy\",\n      \"duration\": \"PT0.089S\"\n    }\n  }\n}\n```\n\n### Status Values\n\n| Status | Description |\n|--------|-------------|\n| `Healthy` | All systems operational |\n| `Degraded` | System operational but with warnings |\n| `Unhealthy` | Critical system failures detected |\n\n---\n\n## Use Cases\n\n- Monitoring dashboards\n- Alerting systems\n- Load balancer health checks\n- Pre-deployment validation",
        "operationId": "HealthCheck",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthCheckResponse"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthCheckResponse"
                }
              }
            }
          }
        }
      }
    },
    "/health/live": {
      "get": {
        "tags": [
          "System - Health"
        ],
        "summary": "Liveness Probe",
        "description": "## Kubernetes Liveness Probe\n\nSimple liveness check for Kubernetes. Returns 200 if the application process is running.\n\n---\n\n## Response\n\nReturns `200 OK` with:\n\n```json\n{\n  \"status\": \"Healthy\",\n  \"message\": \"Service is alive\"\n}\n```\n\n---\n\n## Kubernetes Configuration\n\n```yaml\nlivenessProbe:\n  httpGet:\n    path: /health/live\n    port: 8080\n  initialDelaySeconds: 30\n  periodSeconds: 10\n  timeoutSeconds: 5\n  failureThreshold: 3\n```\n\n---\n\n## Notes\n\n- Does NOT check external dependencies\n- Returns success if the process is running\n- Failure indicates the container should be restarted",
        "operationId": "LivenessProbe",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LivenessResponse"
                }
              }
            }
          }
        }
      }
    },
    "/health/ready": {
      "get": {
        "tags": [
          "System - Health"
        ],
        "summary": "Readiness Probe",
        "description": "## Kubernetes Readiness Probe\n\nReadiness check for Kubernetes. Returns 200 only if the service is ready to accept traffic (database and storage accessible).\n\n---\n\n## Response\n\n**Ready:**\n```json\n{\n  \"status\": \"Healthy\",\n  \"message\": \"Service is ready\"\n}\n```\n\n**Not Ready:**\n```json\n{\n  \"status\": \"Unhealthy\",\n  \"message\": \"Database not accessible\"\n}\n```\n\n---\n\n## Kubernetes Configuration\n\n```yaml\nreadinessProbe:\n  httpGet:\n    path: /health/ready\n    port: 8080\n  initialDelaySeconds: 10\n  periodSeconds: 5\n  timeoutSeconds: 3\n  failureThreshold: 2\n```\n\n---\n\n## Checked Dependencies\n\n- Database connectivity\n- Blob storage accessibility\n- Critical configuration loaded\n\n---\n\n## Notes\n\n- Failure removes pod from load balancer rotation\n- Pod will not receive traffic until ready\n- Use for zero-downtime deployments",
        "operationId": "ReadinessProbe",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadinessResponse"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadinessResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admin/system/validate": {
      "post": {
        "tags": [
          "System - Health"
        ],
        "summary": "Validate System Configuration & Backup Status",
        "description": "## Validate System Configuration & Backup Status\n\nPerforms comprehensive validation of all cloud services (storage, secrets, backup) and retrieves cloud-native backup status in a single request.\n\n**Requires:** Admin OAuth2 authentication (Admin.Full permission)\n\n---\n\n## Request Body\n\nNo request body required.\n\n---\n\n## Response Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `isValid` | bool | Overall validation status |\n| `errors` | string[] | Validation errors |\n| `warnings` | string[] | Configuration warnings |\n| `validatedAt` | datetime | When validation was performed (UTC) |\n| `durationMs` | long | Validation duration in milliseconds |\n| `storage` | object | Storage connectivity validation |\n| `secrets` | object | Secrets service validation |\n| `secretReferences` | object | Secret references validation |\n| `backup` | object | Cloud backup status for all resources |\n\n---\n\n## HTTP Status Codes\n\n| Code | Description |\n|------|-------------|\n| 200 | Validation completed |\n| 401 | Not authenticated |\n| 403 | Missing Admin.Full permission |",
        "operationId": "ValidateSystem",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SystemValidationResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden"
          }
        }
      }
    },
    "/api/config/document-links": {
      "get": {
        "tags": [
          "System - Configuration"
        ],
        "summary": "Get Document Link Configuration",
        "description": "## Get Current Document Link Configuration\n\nRetrieve the current configuration for document download links including default expiration, limits, and security settings.\n\n---\n\n## Response\n\n```json\n{\n  \"success\": true,\n  \"config\": {\n    \"defaultExpirationDays\": 7,\n    \"maxExpirationDays\": 365,\n    \"allowPasswordProtection\": true,\n    \"allowIpRestriction\": true,\n    \"defaultMaxDownloads\": null,\n    \"maxDownloadsLimit\": 1000,\n    \"enableAnalytics\": true\n  }\n}\n```\n\n### Configuration Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `defaultExpirationDays` | int | Default link expiration in days |\n| `maxExpirationDays` | int | Maximum allowed expiration in days |\n| `allowPasswordProtection` | bool | Whether password protection is enabled |\n| `allowIpRestriction` | bool | Whether IP restriction is enabled |\n| `defaultMaxDownloads` | int? | Default download limit (null = unlimited) |\n| `maxDownloadsLimit` | int | Maximum allowed download limit |\n| `enableAnalytics` | bool | Whether download analytics are tracked |\n\n---\n\n## Notes\n\n- Configuration is system-wide\n- Contact administrator to change settings\n- Existing links are not affected by configuration changes",
        "operationId": "GetDocumentLinkConfig",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentLinkConfigResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/documents/{documentGuid}/thumbnail": {
      "get": {
        "tags": [
          "Documents"
        ],
        "summary": "Get Document Thumbnail",
        "description": "## Get Document Thumbnail or Icon\n\nRetrieve a generated thumbnail image for a document. If thumbnail generation is not supported, returns an appropriate file type icon.\n\n**Requires:** `documents:read` permission\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `documentGuid` | guid | Unique identifier (GUID) of the document |\n\n## Query Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `size` | enum | medium | Thumbnail size: small (64x64), medium (256x256), large (512x512) |\n\n---\n\n## Supported Formats\n\n### Thumbnail Generation\n- **Images**: JPEG, PNG, GIF, BMP, TIFF\n- **Documents**: PDF (first page)\n\n### Icon Fallback\nFor unsupported file types, returns an SVG icon based on the file extension.\n\n---\n\n## Response\n\n- **Content-Type**: `image/jpeg` (thumbnail) or `image/svg+xml` (icon)\n- **Cache-Control**: 7 days for thumbnails, 1 hour for icons\n- **Body**: Binary image data\n\n---\n\n## Example\n\n```\nGET /api/documents/550e8400-e29b-41d4-a716-446655440000/thumbnail?size=medium\n```\n\n---\n\n## HTTP Status Codes\n\n| Code | Description |\n|------|-------------|\n| 200 | Thumbnail retrieved successfully |\n| 400 | Invalid size parameter |\n| 403 | Missing documents:read permission |\n| 404 | Document not found |",
        "operationId": "GetDocumentThumbnail",
        "parameters": [
          {
            "name": "documentGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "size",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admin/clients/oauth2": {
      "get": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "List OAuth2 Clients",
        "description": "## List All OAuth2 Clients\n\nRetrieve all registered OAuth2 clients with pagination.\n\n**Requires:** `Admin.Full` permission\n\n---\n\n## Query Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `isActive` | bool | null | Filter by active status (true/false) |\n| `page` | int | 1 | Page number for pagination |\n| `pageSize` | int | 20 | Number of items per page |\n\n---\n\n## Response Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `clientId` | string | Unique OAuth2 client identifier |\n| `displayName` | string | Human-readable client name |\n| `clientType` | string | Client type (confidential/public) |\n| `isActive` | bool | Whether client is active |\n| `expiresAt` | datetime | Expiration timestamp (null = never) |\n| `createdAt` | datetime | Creation timestamp |\n| `apiClientGuid` | guid | Linked ApiClient GUID for permissions |\n| `apiClientName` | string | Linked ApiClient name |\n| `permissionCount` | int | Number of assigned permissions |",
        "operationId": "ListOAuth2Clients",
        "parameters": [
          {
            "name": "isActive",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListOAuth2ClientsResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/admin/diagnostics/azure-ad": {
      "get": {
        "tags": [
          "Administration - Diagnostics"
        ],
        "summary": "Azure AD Configuration Diagnostics",
        "description": "## Azure AD Configuration Diagnostics\n\nValidates the configured Azure AD Admin App Registration end-to-end by performing three checks:\n\n1. **OIDC Metadata** — Verifies the tenant exists and is reachable (`{Instance}/{TenantId}/v2.0/.well-known/openid-configuration`)\n2. **Token Exchange** — Executes a full `client_credentials` token exchange using `AdminClientId` + `AdminClientSecret`, confirming Azure AD accepts the credentials\n3. **Claim Validation** — Decodes the received JWT and verifies the `iss` (issuer) and `aud` (audience) claims match the service configuration\n\n**Requires:** `Admin.Full` permission\n\n---\n\n## Prerequisites\n\nThe diagnostics run only when `Authentication__AzureAd__AdminClientSecret` is set.\nThis environment variable is **exclusively for debugging** — remove it after the issue is resolved.\n\n| Environment Variable | Required | Description |\n|---|---|---|\n| `Authentication__AzureAd__AdminClientSecret` | Yes | Client secret of the Admin App Registration |\n| `Authentication__AzureAd__AdminScope` | No | Token scope — defaults to `{Audience}/.default` |\n\n---\n\n## Response (healthy)\n\n```json\n{\n  \"success\": true,\n  \"result\": {\n    \"tenantId\": \"c018...\",\n    \"clientId\": \"e4ea...\",\n    \"isHealthy\": true,\n    \"summary\": \"Azure AD app is correctly configured and working\",\n    \"oidcMetadata\": { \"success\": true, \"issuer\": \"https://sts.windows.net/...\", \"tokenEndpoint\": \"https://login...\"},\n    \"tokenExchange\": { \"success\": true, \"appId\": \"e4ea...\", \"tokenAudience\": \"api://...\"},\n    \"tokenValidation\": { \"success\": true, \"issuerMatch\": true, \"audienceMatch\": true }\n  }\n}\n```\n\n## Response (unhealthy) — returns HTTP 503\n\n```json\n{\n  \"success\": false,\n  \"result\": {\n    \"isHealthy\": false,\n    \"summary\": \"Azure AD rejected the token request [invalid_client]: AADSTS7000215...\",\n    \"oidcMetadata\": { \"success\": true },\n    \"tokenExchange\": { \"success\": false, \"azureErrorCode\": \"invalid_client\", \"error\": \"AADSTS7000215: ...\" }\n  }\n}\n```\n\n---\n\n## Common Error Codes\n\n| Azure Error Code | Meaning |\n|---|---|\n| `invalid_client` | Wrong secret or client ID |\n| `unauthorized_client` | Client not allowed client credentials flow — check App Registration permissions |\n| `invalid_tenant` | TenantId does not exist |\n| `invalid_scope` | Scope not registered in the App Registration — check API permissions |",
        "operationId": "AdminDiagnosticsAzureAd",
        "responses": {
          "200": {
            "description": "OK"
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/admin/diagnostics/environment": {
      "get": {
        "tags": [
          "Administration - Diagnostics"
        ],
        "summary": "Environment Variable Diagnostics",
        "description": "## Environment Variable Diagnostics\n\nReturns all DocumentService-relevant environment variables that are currently set on the host, with **secret values masked** (first 4 characters shown, remainder replaced with `****`).\n\n**Requires:** `Admin.Full` permission\n\n---\n\n## Included Variable Prefixes\n\n| Prefix | Examples |\n|---|---|\n| `Authentication__` | `Authentication__AzureAd__TenantId`, `Authentication__Mode` |\n| `BlobStorage__` | `BlobStorage__AccountName`, `BlobStorage__ConnectionString` |\n| `ConnectionStrings__` | `ConnectionStrings__DefaultConnection` |\n| `Database__` | `Database__Provider`, `Database__DisableMigration` |\n| `SelfHostedOAuth2__` | `SelfHostedOAuth2__Enabled`, `SelfHostedOAuth2__SigningKey` |\n| `KeyVault__` | `KeyVault__Uri` |\n| `Secrets__` | `Secrets__Provider` |\n| `Storage__` | `Storage__Provider` |\n| `Azure__` | `Azure__ManagedIdentityClientId` |\n| `Backup__` | Backup configuration |\n| `License__` | `License__Plan` |\n| `Branding__` | `Branding__ShowApiDocs` |\n| `ASPNETCORE_*` | `ASPNETCORE_ENVIRONMENT` |\n| `DOTNET_*` | `DOTNET_RUNNING_IN_CONTAINER` |\n\n---\n\n## Masking Rules\n\nVariables whose name contains any of the following keywords are **automatically masked**:\n`SECRET`, `PASSWORD`, `CONNECTIONSTRING`, `SIGNINGKEY`, `APIKEY`, `API_KEY`, `PRIVATE`, `TOKEN`, `ENCRYPTIONKEY`\n\n> ⚠️ Even with masking, treat the output of this endpoint as sensitive — it reveals which variables are configured and their approximate values.\n\n---\n\n## Example Response\n\n```json\n{\n  \"success\": true,\n  \"count\": 8,\n  \"variables\": [\n    { \"key\": \"Authentication__AzureAd__AdminClientId\", \"value\": \"e4ea40ad-947c-4a03-b283-88db67f14546\" },\n    { \"key\": \"Authentication__AzureAd__AdminClientSecret\", \"value\": \"Stx8****\" },\n    { \"key\": \"Authentication__AzureAd__TenantId\", \"value\": \"c018...\"},\n    { \"key\": \"Authentication__Mode\", \"value\": \"AzureAd\" },\n    { \"key\": \"ConnectionStrings__DefaultConnection\", \"value\": \"Serv****\" },\n    { \"key\": \"BlobStorage__AccountName\", \"value\": \"mysa****\" }\n  ]\n}\n```",
        "operationId": "AdminDiagnosticsEnvironment",
        "responses": {
          "200": {
            "description": "OK"
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/account/usage": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Get Account Usage & License Info",
        "description": "## Get Account Usage & License Information\n\nReturns the current license plan, usage statistics (documents, versions, storage), and remaining capacity.\n\n**Requires:** Any authenticated client.\n\n---\n\n## Response Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `license` | object | Current license plan and limits |\n| `usage` | object | Current resource usage |\n| `capacity` | object | Remaining capacity and percentages |\n\n### License Limits (by Plan)\n\n| Plan | Max Documents | Max Storage |\n|------|--------------|-------------|\n| Free | 10,000 | 100 GB |\n| Pro | 100,000 | 1 TB |\n| Premium | Unlimited | Unlimited |\n\n---\n\n## HTTP Status Codes\n\n| Code | Description |\n|------|-------------|\n| 200 | Usage retrieved successfully |\n| 401 | Not authenticated |",
        "operationId": "GetAccountUsage",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountUsageResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/api/documents/upload": {
      "post": {
        "tags": [
          "Documents"
        ],
        "summary": "Upload Document (Base64)",
        "description": "## Upload Document via JSON/Base64\n\nUpload a new document or create a new version of an existing document using Base64-encoded content.\n\n**Note:** For large files (>10 MB), use the `/upload-stream` endpoint instead.\n\n---\n\n## Request Body\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `fileName` | string | Yes | Original filename including extension (e.g., \"contract.pdf\") |\n| `contentBase64` | string | Yes | File content as Base64-encoded string |\n| `displayName` | string | No | User-friendly display name for the document |\n| `description` | string | No | Detailed description of the document content or purpose |\n| `tags` | string[] | No | List of tags for categorization and search |\n| `groupTag` | string | No | Group tag for logical document grouping (e.g., \"Project-2024-001\", \"Order-A12345\") |\n| `classification` | enum | No | Security classification: Public, Internal, Confidential, Restricted (default: Internal) |\n| `retentionPolicy` | string | No | Retention policy identifier (e.g., \"7years\", \"permanent\") |\n| `createdBy` | string | No | User or system creating the document |\n| `documentGuid` | guid | No | For creating a new version of an existing document |\n| `versionComment` | string | No | Optional comment describing this version |\n| `externalReferences` | array | Yes | At least one external reference is required |\n| `commonReferences` | array | No | Cross-system business identifiers (optional) |\n\n### External Reference\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `systemName` | string | Yes | External system name (e.g., \"Salesforce\", \"SAP\") |\n| `systemId` | string | Yes | System instance ID (e.g., Salesforce Org-ID) |\n| `referenceType` | string | Yes | Type of referenced object (e.g., \"Account\", \"Contract\") |\n| `externalId` | string | Yes | Unique ID in the external system |\n| `referenceUrl` | string | No | URL to the object in the external system |\n| `isPrimary` | bool | No | Marks the primary reference for the system (default: false) |\n| `autoVersioning` | bool | No | Auto-version onto an existing document with this reference instead of requiring a document GUID (default: false) — see below |\n\n### Auto-Versioning via External Reference\n\nInstead of passing `documentGuid` to create a new version, set `autoVersioning: true`\non **one** external reference. The service then looks for an existing document that\nalready carries that exact reference (same `systemName`, `systemId`, `referenceType`,\n`externalId`) and adds a new version to it.\n\nRules:\n\n- At most **one** reference per request may set `autoVersioning: true`.\n- These rules only apply when at least one reference opts into `autoVersioning`. When no\n  reference uses it, `isPrimary` behaves as before (no constraint).\n- When `autoVersioning` is used and a reference sets `isPrimary: true`, that same reference\n  **must** be the `autoVersioning` one.\n- `autoVersioning` and `documentGuid` are **mutually exclusive**.\n- Matching also requires the **same `fileName`** as the existing document. If the\n  reference matches but the file name differs, a **new document** is created (the\n  response `message` notes this).\n- If no document matches, a new document is created (upsert).\n- If the reference matches **multiple** documents with the same file name, the request\n  fails with `409 AMBIGUOUS_REFERENCE`.\n\n### Common Reference (Cross-System Identifier)\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `type` | string | Yes | Reference type (e.g., \"InvoiceNumber\", \"OrderNumber\", \"CustomerNumber\") |\n| `value` | string | Yes | The unique identifier value |\n| `label` | string | No | Human-readable label for display |\n| `metadata` | object | No | Additional key-value metadata |\n| `systems` | array | No | Restrict access to specific systems (null = all systems) |\n| `allowCrossClientSharing` | bool | No | If true, clients that reach the document only via this CommonReference may also manage public links (default false). Only relevant when access control is enabled. |\n\n> **Access control (when enabled):** A CommonReference lets clients of *other* systems\n> read and download the document (cross-system). Such clients may also create/manage public\n> links **only** when `allowCrossClientSharing` is true. Updating or deleting the document\n> always stays with the owning system (the one referenced via an ExternalReference); other\n> clients receive `403`. On upload, every `externalReferences` entry must belong to a system\n> the client holds `Documents.Write` for (otherwise `403 ACCESS_DENIED`). Access control is\n> **enabled by default** (`AccessControl:Enabled=false` to opt out); each client receives its\n> document permissions scoped as `SystemName|SystemId`, i.e. **one API client per system**.\n\n---\n\n## Example Request\n\n```json\n{\n  \"fileName\": \"contract.pdf\",\n  \"contentBase64\": \"JVBERi0xLjQK...\",\n  \"displayName\": \"Customer Contract 2024\",\n  \"description\": \"Annual service agreement\",\n  \"tags\": [\"contract\", \"2024\"],\n  \"classification\": \"Confidential\",\n  \"externalReferences\": [{\n    \"systemName\": \"Salesforce\",\n    \"systemId\": \"00D5g000004XXXX\",\n    \"referenceType\": \"Account\",\n    \"externalId\": \"001XXXXXXXXXXXXXXX\"\n  }],\n  \"commonReferences\": [{\n    \"type\": \"InvoiceNumber\",\n    \"value\": \"INV-2024-001234\",\n    \"label\": \"Invoice Number\"\n  }, {\n    \"type\": \"CustomerNumber\",\n    \"value\": \"CUST-12345\",\n    \"label\": \"Customer ID\",\n    \"metadata\": { \"customerName\": \"Acme Corp\" }\n  }]\n}\n```\n\n\n---\n\n## Encryption (optional, only when creating a document)\n\nThe `encryption` object stores the document **encrypted**. The key stays with the client — the\nservice never stores it and **cannot recover it**.\n\n```json\n\"encryption\": {\n  \"mode\": \"serverSide\",\n  \"key\": \"<passphrase or Base64 raw key>\",\n  \"keyType\": \"passphrase\",\n  \"keyLabel\": \"max.mustermann\",\n  \"acknowledgeNoRecovery\": true\n}\n```\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `mode` | string | No | Currently only `serverSide` (default) |\n| `key` | string | Yes | Passphrase (min. 12 characters) or a Base64-encoded 32-byte key |\n| `keyType` | string | No | `passphrase` (default) or `raw` |\n| `keyLabel` | string | No | Free-form label of the key slot (e.g. a user name), **not** a secret |\n| `acknowledgeNoRecovery` | bool | Yes | Must be `true` — confirms that losing the key means losing the data |\n\n**Consequences**\n\n- `classification` is ignored and locked to `Restricted`.\n- `description` is stored encrypted and is only readable with the key.\n- Public download links are blocked (`409 ENCRYPTED_DOCUMENT`), thumbnails return a neutral\n  lock icon, and there is no preview and no PDF conversion.\n- The mode is **immutable**: an `encryption` object for an existing document (including via\n  auto-versioning/upsert) is rejected with `400 ENCRYPTION_MODE_IMMUTABLE`.\n\n**New version of an encrypted document**\n\nThe key is passed in the **`X-Document-Key`** header (optionally\n`X-Document-Key-Type: passphrase|raw`), not in the body:\n\n```\nX-Document-Key: <passphrase>\n```\n\n**Error codes**\n\n| Code | Status | Meaning |\n|------|--------|---------|\n| `ENCRYPTION_ACK_REQUIRED` | 400 | `acknowledgeNoRecovery` missing or `false` |\n| `ENCRYPTION_KEY_TOO_WEAK` | 400 | Passphrase shorter than 12 characters |\n| `ENCRYPTION_KEY_INVALID_FORMAT` | 400 | Raw key is not a Base64-encoded 32-byte value |\n| `ENCRYPTION_MODE_IMMUTABLE` | 400 | Encryption cannot be switched on or off afterwards |\n| `ENCRYPTION_KEY_REQUIRED` | 403 | `X-Document-Key` header missing for an encrypted document |\n| `ENCRYPTION_KEY_INVALID` | 403 | The key does not match any key slot |\n| `ENCRYPTION_KEY_RATE_LIMITED` | 429 | Too many failed attempts, honour `Retry-After` |\n\nDetails: `docs/encryption-guide.md`.\n",
        "operationId": "UploadDocument",
        "parameters": [
          {
            "name": "X-Correlation-Id",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UploadDocumentRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadDocumentResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/documents/upload-stream": {
      "post": {
        "tags": [
          "Documents"
        ],
        "summary": "Upload Document (Streaming)",
        "description": "## Streaming Upload for Large Files\n\nAccepts files up to 500 MB without Base64 encoding. Ideal for:\n- Direct browser uploads\n- Salesforce LWC (bypasses 12MB callout limit)\n- Mobile apps\n- External systems\n\n---\n\n## Request Format\n\n**Content-Type:** `multipart/form-data`\n\n### Form Fields\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `file` | File | Yes | The file to upload |\n| `metadata` | JSON String | Yes | Metadata as JSON (see below) |\n\n---\n\n## Metadata JSON Schema\n\n```json\n{\n  \"displayName\": \"Contract_2024.pdf\",\n  \"description\": \"Customer contract for project XYZ\",\n  \"tags\": [\"contract\", \"customer-abc\", \"2024\"],\n  \"classification\": \"Internal\",\n  \"retentionPolicy\": \"7years\",\n  \"createdBy\": \"user@example.com\",\n  \"externalReferences\": [\n    {\n      \"systemName\": \"Salesforce\",\n      \"systemId\": \"00D5g000004XXXX\",\n      \"referenceType\": \"Account\",\n      \"externalId\": \"001XXXXXXXXXXXXXXX\",\n      \"isPrimary\": true,\n      \"referenceUrl\": \"https://example.my.salesforce.com/001XXXXXXXXXXXXXXX\"\n    }\n  ],\n  \"options\": {\n    \"generateChecksum\": true,\n    \"blobContainer\": \"private\"\n  }\n}\n```\n\n### Metadata Fields\n\n| Field | Type | Required | Default | Description |\n|-------|------|----------|---------|-------------|\n| `displayName` | string | No | filename | User-friendly display name for the document |\n| `description` | string | No | - | Detailed description of the document content or purpose |\n| `tags` | string[] | No | [] | List of tags for categorization and search |\n| `groupTag` | string | No | - | Group tag for logical document grouping (e.g., \"Project-2024-001\") |\n| `classification` | enum | No | \"Internal\" | Security classification: Public, Internal, Confidential, Restricted |\n| `retentionPolicy` | string | No | - | Retention policy identifier (e.g., \"7years\", \"permanent\") |\n| `createdBy` | string | No | auth user | User or system creating the document |\n| `externalReferences` | array | Yes | - | At least one external reference required |\n| `commonReferences` | array | No | - | Cross-system business identifiers (optional) |\n| `documentGuid` | guid | No | - | For creating a new version of an existing document |\n| `versionComment` | string | No | - | Optional comment describing this version |\n| `options` | object | No | - | Upload processing options |\n\n### External Reference\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `systemName` | string | Yes | External system name (e.g., \"Salesforce\", \"SAP\") |\n| `systemId` | string | Yes | System instance ID (e.g., Salesforce Org-ID) |\n| `referenceType` | string | Yes | Type of referenced object (e.g., \"Account\", \"Contract\") |\n| `externalId` | string | Yes | Unique ID in the external system |\n| `referenceUrl` | string | No | URL to the object in the external system |\n| `isPrimary` | bool | No | Marks the primary reference for the system (default: false) |\n| `autoVersioning` | bool | No | Auto-version onto an existing document with this reference instead of requiring a document GUID (default: false) |\n\n> **Auto-Versioning:** set `autoVersioning: true` on exactly one external reference to\n> add a new version to the existing document that already carries that reference (same\n> four reference fields **and** same file name) — no `documentGuid` needed. If a\n> reference is `isPrimary`, it must also be the `autoVersioning` one;\n> `autoVersioning` and `documentGuid` are mutually exclusive. No match → new document\n> (upsert); matching reference but different file name → new document; multiple matches →\n> `409 AMBIGUOUS_REFERENCE`.\n\n### Common Reference (Cross-System Identifier)\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `type` | string | Yes | Reference type (e.g., \"InvoiceNumber\", \"OrderNumber\") |\n| `value` | string | Yes | The unique identifier value |\n| `label` | string | No | Human-readable label for display |\n| `metadata` | object | No | Additional key-value metadata |\n| `systems` | array | No | Restrict access to specific systems (null = all systems) |\n\n### Upload Options\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `generateChecksum` | bool | true | Generate SHA-256 checksum for integrity verification |\n| `blobContainer` | string | \"private\" | Target blob container name |\n\n---\n\n## Example: cURL\n\n```bash\ncurl -X POST \"https://api.example.com/api/documents/upload-stream\" \\\n  -H \"Authorization: Bearer YOUR_TOKEN\" \\\n  -F \"file=@/path/to/document.pdf\" \\\n  -F 'metadata={\"displayName\":\"Contract.pdf\",\"externalReferences\":[{\"systemName\":\"Salesforce\",\"systemId\":\"00D5g000004XXXX\",\"referenceType\":\"Account\",\"externalId\":\"001XXXXXXXXXXXXXXX\"}]}'\n```\n\n## Example: JavaScript (Fetch)\n\n```javascript\nconst formData = new FormData();\nformData.append('file', fileInput.files[0]);\nformData.append('metadata', JSON.stringify({\n  displayName: 'Contract.pdf',\n  description: 'Customer contract',\n  tags: ['contract', '2024'],\n  classification: 'Internal',\n  externalReferences: [{\n    systemName: 'Salesforce',\n    systemId: '00D5g000004XXXX',\n    referenceType: 'Account',\n    externalId: '001XXXXXXXXXXXXXXX',\n    isPrimary: true\n  }]\n}));\n\nconst response = await fetch('/api/documents/upload-stream', {\n  method: 'POST',\n  headers: { 'Authorization': 'Bearer ' + token },\n  body: formData\n});\n```\n\n---\n\n## Response\n\nOn success, returns an `UploadDocumentResponse` envelope. The uploaded\ndocument's details — including its GUID — live under `document`:\n\n```json\n{\n  \"success\": true,\n  \"message\": \"Document uploaded successfully\",\n  \"document\": {\n    \"documentGuid\": \"8b2a7f12-…\",\n    \"fileName\": \"contract.pdf\",\n    \"fileSize\": 18234,\n    \"version\": { \"versionNumber\": 1, \"isNewDocument\": true, \"totalVersions\": 1 }\n  },\n  \"errorCode\": null\n}\n```\n\n**Note:** read the new document's GUID from `document.documentGuid`, not from a\ntop-level `documentGuid`. The version number is `document.version.versionNumber`.\n\n\n---\n\n## Encryption (optional, only when creating a document)\n\nThe `metadata` field accepts the same `encryption` object as the Base64 upload:\n\n```json\n{\n  \"externalReferences\": [ ... ],\n  \"encryption\": {\n    \"mode\": \"serverSide\",\n    \"key\": \"<passphrase>\",\n    \"keyType\": \"passphrase\",\n    \"acknowledgeNoRecovery\": true\n  }\n}\n```\n\nThe file is encrypted **while streaming** (constant memory, also for large files); the storage\nprovider never sees the plaintext. `fileSize` in the response is still the **plaintext** size,\n`checksum` is the SHA-256 of the encrypted blob.\n\nFor a **new version** of an already encrypted document the key goes into the `X-Document-Key`\nheader and an `encryption` object is not allowed (`400 ENCRYPTION_MODE_IMMUTABLE`). Error codes\nas for the Base64 upload, details in `docs/encryption-guide.md`.\n",
        "operationId": "UploadDocumentStream",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadDocumentResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/documents/{documentGuid}": {
      "get": {
        "tags": [
          "Documents"
        ],
        "summary": "Get Document",
        "description": "## Get Document by GUID\n\nRetrieve document metadata by its unique identifier (GUID).\n\n---\n\n## Response Envelope\n\nThe response is wrapped in an envelope. The document fields below live under\n`document`:\n\n```json\n{\n  \"success\": true,\n  \"message\": \"Document retrieved successfully\",\n  \"document\": { /* fields described below */ },\n  \"errorCode\": null\n}\n```\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `documentGuid` | guid | Unique identifier (GUID) of the document |\n\n## Query Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `includeVersions` | bool | true | Include version history in the response |\n| `includeStatistics` | bool | false | Include usage statistics (view count, download count) |\n\n---\n\n## Response Fields\n\n### Document\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `documentGuid` | guid | Unique identifier (GUID) of the document |\n| `displayName` | string | User-friendly display name for the document |\n| `description` | string | Detailed description of the document content or purpose |\n| `fileName` | string | Original filename including extension |\n| `contentType` | string | MIME type of the file (e.g., \"application/pdf\") |\n| `fileExtension` | string | File extension including dot (e.g., \".pdf\") |\n| `tags` | string[] | List of tags for categorization and search |\n| `groupTag` | string | Group tag for logical document grouping |\n| `classification` | enum | Security classification: Public, Internal, Confidential, Restricted |\n| `retentionPolicy` | string | Retention policy identifier |\n| `currentVersion` | object | Current (latest) version as a Version object (see below). Use `currentVersion.versionNumber` for the scalar number. |\n| `createdAt` | datetime | Timestamp when the document was created (UTC) |\n| `createdBy` | string | User or system that created the document |\n| `modifiedAt` | datetime | Timestamp of last modification (UTC) |\n| `externalReferences` | array | External system references |\n| `commonReferences` | array | Cross-system business identifiers |\n\n### Common Reference\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `type` | string | Reference type (e.g., \"InvoiceNumber\", \"OrderNumber\") |\n| `value` | string | The unique identifier value |\n| `label` | string | Human-readable label for display |\n| `metadata` | object | Additional key-value metadata |\n| `systems` | array | Systems allowed to access (null = all systems) |\n| `createdAt` | datetime | When the reference was created |\n| `createdBy` | string | Who created the reference |\n\n### Version (if includeVersions=true)\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `versionNumber` | int | Sequential version number (1, 2, 3, ...) |\n| `fileSize` | long | File size in bytes |\n| `checksum` | string | SHA-256 hash of the file content |\n| `comment` | string | Optional comment describing this version |\n| `isCurrent` | bool | Whether this is the current (latest) version |\n| `createdAt` | datetime | Timestamp when the version was created |\n| `createdBy` | string | User or system that created this version |\n\n### Statistics (if includeStatistics=true)\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `totalDownloads` | int | Authenticated downloads via `/api/documents/{guid}/download` |\n| `totalPublicDownloads` | int | Downloads via public share links (`/download/{token}`), tracked separately |\n| `totalVersions` | int | Total number of versions |\n| `totalShares` | int | Number of share links created for the document |\n| `lastDownloadAt` | datetime | Timestamp of last authenticated download (nullable) |\n| `lastPublicDownloadAt` | datetime | Timestamp of last public-link download (nullable) |\n\n\n---\n\n## Encrypted documents\n\nFor encrypted documents the response additionally contains:\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `isEncrypted` | bool | `true` when the content is stored encrypted |\n| `encryptionMode` | string | `none` or `serverSide` |\n| `hasEncryptedDescription` | bool | Whether an encrypted description is stored |\n| `keySlots` | array | Key slots with `slotId`, `label`, `slotType`, `createdAt` — **never** key material |\n\n`description` is always `null` **without** a key. With a valid `X-Document-Key` header\n(optionally `X-Document-Key-Type: passphrase|raw`) or a valid `X-Document-Dek` header (the\nBase64 data key unwrapped from a public-key slot) it is returned decrypted. A wrong key\nanswers `403 ENCRYPTION_KEY_INVALID` and counts as a failed attempt (`429\nENCRYPTION_KEY_RATE_LIMITED` with `Retry-After` after too many). All other metadata is visible\nwithout a key. `classification` is always `Restricted` for encrypted documents.\n",
        "operationId": "GetDocument",
        "parameters": [
          {
            "name": "documentGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "includeVersions",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": true
            }
          },
          {
            "name": "includeStatistics",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetDocumentResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Documents"
        ],
        "summary": "Update Document",
        "description": "## Update Document Metadata\n\nPartial update of document metadata. Only provided fields are updated; omitted fields remain unchanged.\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `documentGuid` | guid | Unique identifier (GUID) of the document |\n\n## Request Body Fields\n\nAll fields are optional. Only include fields you want to update.\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `displayName` | string | User-friendly display name for the document |\n| `description` | string | Detailed description of the document content or purpose |\n| `tags` | string[] | List of tags for categorization and search |\n| `groupTag` | string | Group tag for logical document grouping (set to empty string to clear) |\n| `classification` | enum | Security classification: Public, Internal, Confidential, Restricted |\n| `retentionPolicy` | string | Retention policy identifier (e.g., \"7years\", \"permanent\") |\n| `addExternalReferences` | array | New external references to add |\n| `removeExternalReferences` | array | External references to remove (by systemName + externalId) |\n| `addCommonReferences` | array | New common references to add |\n| `removeCommonReferences` | array | Common references to remove (by type + value) |\n\n### External Reference (for addExternalReferences)\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `systemName` | string | Yes | External system name (e.g., \"Salesforce\", \"SAP\") |\n| `systemId` | string | Yes | System instance ID (e.g., Salesforce Org-ID) |\n| `referenceType` | string | Yes | Type of referenced object (e.g., \"Account\", \"Contract\") |\n| `externalId` | string | Yes | Unique ID in the external system |\n| `isPrimary` | bool | No | Whether this is the primary reference (default: false) |\n| `referenceUrl` | string | No | URL to the object in the external system |\n\n### Common Reference (for addCommonReferences)\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `type` | string | Yes | Reference type (e.g., \"InvoiceNumber\", \"OrderNumber\") |\n| `value` | string | Yes | The unique identifier value |\n| `label` | string | No | Human-readable label |\n| `metadata` | object | No | Additional key-value metadata |\n| `systems` | array | No | Restrict access to specific systems |\n\n### Common Reference (for removeCommonReferences)\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `type` | string | Yes | Reference type to match |\n| `value` | string | Yes | Reference value to match |\n\n---\n\n## Example: Update Tags and Classification\n\n```json\n{\n  \"tags\": [\"contract\", \"2024\", \"approved\"],\n  \"classification\": \"Confidential\"\n}\n```\n\n## Example: Add External Reference\n\n```json\n{\n  \"addExternalReferences\": [{\n    \"systemName\": \"SAP\",\n    \"systemId\": \"PRD\",\n    \"referenceType\": \"SalesOrder\",\n    \"externalId\": \"4500012345\"\n  }]\n}\n```\n\n## Example: Add Common Reference\n\n```json\n{\n  \"addCommonReferences\": [{\n    \"type\": \"InvoiceNumber\",\n    \"value\": \"INV-2024-001234\",\n    \"label\": \"Invoice Number\"\n  }]\n}\n```\n\n## Example: Remove Common Reference\n\n```json\n{\n  \"removeCommonReferences\": [{\n    \"type\": \"InvoiceNumber\",\n    \"value\": \"INV-2024-001234\"\n  }]\n}\n```\n\n\n---\n\n## Encrypted documents\n\n- Changing `classification` → `400 CLASSIFICATION_LOCKED` (locked to `Restricted`).\n- Changing `description` requires the `X-Document-Key` (or `X-Document-Dek`) header; without a key\n  `403 ENCRYPTION_KEY_REQUIRED`, with a wrong one `403 ENCRYPTION_KEY_INVALID`.\n  The new description is stored encrypted.\n- Every other field (display name, tags, references, retention, archiving) is changed\n  **without** a key.\n",
        "operationId": "UpdateDocument",
        "parameters": [
          {
            "name": "documentGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "X-Correlation-Id",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateDocumentRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdateDocumentResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Documents"
        ],
        "summary": "Delete Document",
        "description": "## Delete Document\n\nDelete a document. By default, performs a soft delete (recoverable for 30 days).\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `documentGuid` | guid | Unique identifier (GUID) of the document |\n\n## Query Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `permanent` | bool | false | If true, permanently deletes the document immediately (not recoverable) |\n\n---\n\n## Soft Delete (Default)\n\n- Document is marked as deleted but retained for 30 days\n- Can be restored within the retention period\n- Blob storage content is preserved\n- External references remain intact\n\n## Permanent Delete\n\n- Document and all versions are immediately deleted\n- Blob storage content is removed\n- External references are deleted\n- **This action cannot be undone**\n\n---\n\n## Example: Soft Delete\n\n```\nDELETE /api/documents/550e8400-e29b-41d4-a716-446655440000\n```\n\n## Example: Permanent Delete\n\n```\nDELETE /api/documents/550e8400-e29b-41d4-a716-446655440000?permanent=true\n```",
        "operationId": "DeleteDocument",
        "parameters": [
          {
            "name": "documentGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "X-Correlation-Id",
            "in": "header",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "X-Deleted-By",
            "in": "header",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "permanent",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteDocumentResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/documents/by-reference/{systemName}/{systemId}": {
      "get": {
        "tags": [
          "Documents"
        ],
        "summary": "Find Documents by External Reference",
        "description": "## Search Documents by External System Reference\n\nFind all documents linked to a specific external system instance. Use filters to narrow down results.\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `systemName` | string | Yes | External system name (e.g., \"Salesforce\", \"SAP\") |\n| `systemId` | string | Yes | System instance ID (e.g., Salesforce Org-ID \"00D5g000004XXXX\") |\n\n## Query Parameters\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `referenceType` | string | No | Filter by reference type (e.g., \"Account\", \"Contract\") |\n| `externalId` | string | No | Filter by external ID |\n| `page` | int | No | Page number for pagination (1-based, default: 1) |\n| `pageSize` | int | No | Number of items per page (default: 20, max: 100) |\n\n---\n\n## Example Requests\n\n**Get all documents for a Salesforce org:**\n```\nGET /api/documents/by-reference/Salesforce/00D5g000004XXXX\n```\n\n**Get documents for a specific Account:**\n```\nGET /api/documents/by-reference/Salesforce/00D5g000004XXXX?referenceType=Account&externalId=001XXXXXXXXXXXXXXX\n```\n\n---\n\n## Response\n\nReturns a paginated list of documents with their external references and metadata.",
        "operationId": "GetDocumentsByReference",
        "parameters": [
          {
            "name": "systemName",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "systemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "referenceType",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "externalId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetDocumentsByReferenceResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/documents/by-common-reference/{type}/{value}": {
      "get": {
        "tags": [
          "Documents"
        ],
        "summary": "Find Documents by Common Reference",
        "description": "## Search Documents by Cross-System Identifier\n\nFind documents linked to a common business identifier (like invoice number, order number, or customer ID) that is shared across multiple systems.\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `type` | string | Yes | Common reference type (e.g., \"InvoiceNumber\", \"OrderNumber\", \"CustomerNumber\") |\n| `value` | string | Yes | The unique identifier value |\n\n## Query Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `page` | int | 1 | Page number for pagination (1-based) |\n| `pageSize` | int | 20 | Number of items per page (max: 100) |\n\n---\n\n## Example Requests\n\n**Find all documents for an invoice:**\n```\nGET /api/documents/by-common-reference/InvoiceNumber/INV-2024-001234\n```\n\n**Find all documents for a customer:**\n```\nGET /api/documents/by-common-reference/CustomerNumber/CUST-12345\n```\n\n---\n\n## Response\n\nReturns a paginated list of documents with their common references and metadata.\n\n---\n\n## Use Cases\n\n- Find all documents related to a specific invoice across Salesforce, SAP, and other systems\n- Retrieve all contracts and orders for a customer number\n- Link documents from different systems using a shared business identifier",
        "operationId": "GetDocumentsByCommonReference",
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "value",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetDocumentsByReferenceResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/documents/filter": {
      "post": {
        "tags": [
          "Documents"
        ],
        "summary": "Advanced Document Filter",
        "description": "## Advanced Document Filtering\n\nFilter documents using multiple criteria including external references, common references, tags, classification, dates, and more.\n\n---\n\n## Request Body\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `externalSystem` | string | No | Filter by external system name |\n| `externalId` | string | No | Filter by external ID |\n| `commonReferenceType` | string | No | Filter by common reference type |\n| `commonReferenceValue` | string | No | Filter by common reference value |\n| `tags` | string[] | No | Filter by tags (all tags must match) |\n| `groupTag` | string | No | Filter by group tag (exact match) |\n| `classification` | string | No | Filter by classification |\n| `contentType` | string | No | Filter by content type (partial match) |\n| `fileNamePattern` | string | No | Filter by filename (partial match) |\n| `displayNamePattern` | string | No | Filter by display name (partial match) |\n| `createdFrom` | datetime | No | Documents created on or after this date |\n| `createdTo` | datetime | No | Documents created on or before this date |\n| `isArchived` | bool | No | Filter by archive status |\n| `isDeleted` | bool | No | Include soft-deleted documents |\n| `sortBy` | string | No | Sort field: fileName, displayName, contentType, classification, createdAt, modifiedAt |\n| `sortDirection` | string | No | Sort direction: asc, desc (default: desc) |\n| `page` | int | No | Page number (default: 1) |\n| `pageSize` | int | No | Page size (default: 20, max: 1000) |\n\n---\n\n## Example: Filter by Common Reference\n\n```json\n{\n  \"commonReferenceType\": \"InvoiceNumber\",\n  \"commonReferenceValue\": \"INV-2024-001234\",\n  \"page\": 1,\n  \"pageSize\": 20\n}\n```\n\n## Example: Multi-Criteria Filter\n\n```json\n{\n  \"commonReferenceType\": \"CustomerNumber\",\n  \"commonReferenceValue\": \"CUST-12345\",\n  \"tags\": [\"invoice\", \"2024\"],\n  \"classification\": \"Internal\",\n  \"createdFrom\": \"2024-01-01T00:00:00Z\",\n  \"sortBy\": \"createdAt\",\n  \"sortDirection\": \"desc\"\n}\n```\n\n---\n\n## Response\n\n```json\n{\n  \"documents\": [...],\n  \"totalCount\": 42,\n  \"page\": 1,\n  \"pageSize\": 20\n}\n```",
        "operationId": "FilterDocuments",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentFilter"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentFilterResult"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/documents/{documentGuid}/download": {
      "get": {
        "tags": [
          "Documents"
        ],
        "summary": "Download Document",
        "description": "## Download Document Content\n\nDownload the binary content of a document. Returns the current version by default.\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `documentGuid` | guid | Unique identifier (GUID) of the document |\n\n## Query Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `versionNumber` | int | latest | Specific version to download (1, 2, 3, ...) |\n| `profile` | string | default | Header profile for response customization |\n\n---\n\n## Header Profiles\n\nThe `profile` parameter enables client-specific HTTP header customization:\n\n| Profile | Content-Disposition | X-Frame-Options | Content-Security-Policy |\n|---------|---------------------|-----------------|------------------------|\n| `default` | attachment | DENY | - |\n| `salesforce` | inline | (removed) | frame-ancestors 'self' *.salesforce.com *.force.com |\n| `preview` | inline | - | - |\n\n---\n\n## Response\n\n- **Content-Type:** The original MIME type of the file (e.g., \"application/pdf\")\n- **Content-Disposition:** Depends on profile (attachment or inline)\n- **Body:** Binary file content\n\n---\n\n## Examples\n\n**Standard Download (Attachment):**\n```\nGET /api/documents/550e8400-e29b-41d4-a716-446655440000/download\n```\n\n**Salesforce iFrame Embedding:**\n```\nGET /api/documents/550e8400-e29b-41d4-a716-446655440000/download?profile=salesforce\n```\n\n**Browser Preview:**\n```\nGET /api/documents/550e8400-e29b-41d4-a716-446655440000/download?profile=preview\n```\n\n**Specific Version with Profile:**\n```\nGET /api/documents/550e8400-e29b-41d4-a716-446655440000/download?versionNumber=2&profile=preview\n```\n\n---\n\n## Encrypted documents\n\nIf the document is encrypted, the client key must be supplied in the `X-Document-Key` header (optionally `X-Document-Key-Type: passphrase|raw`). The server checks in this order: permission → system access control → rate limit → key.\n\n| Situation | Response |\n|-----------|----------|\n| No header | `403 ENCRYPTION_KEY_REQUIRED` |\n| Wrong key | `403 ENCRYPTION_KEY_INVALID` (counted as a failed attempt) |\n| Too many failed attempts | `429 ENCRYPTION_KEY_RATE_LIMITED` with `Retry-After` (seconds) |\n| Valid key | `200` with the decrypted original content and original content type |\n\nThere is **no** recovery path: without the key the content is permanently unreadable. Public download links are not supported for encrypted documents. Details: `docs/encryption-guide.md`.",
        "operationId": "DownloadDocument",
        "parameters": [
          {
            "name": "documentGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "version",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "profile",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/documents/{documentGuid}/keys": {
      "get": {
        "tags": [
          "Documents - Keys"
        ],
        "summary": "List Key Slots",
        "description": "## List the Key Slots of an Encrypted Document\n\nLists the key slots of an encrypted document. Every slot holds the same data key (DEK), wrapped\nwith a different client secret — so each slot opens the whole document including all versions.\n\n**Requires:** `Documents.Read` permission and read access to the document.\n**No document key is needed** — the response never contains key material.\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `documentGuid` | guid | Unique identifier (GUID) of the document |\n\n---\n\n## Response\n\n```json\n{\n  \"success\": true,\n  \"message\": \"Key slots retrieved successfully\",\n  \"documentGuid\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"keySlots\": [\n    {\n      \"slotId\": \"6f1c...\",\n      \"label\": \"max.mustermann\",\n      \"slotType\": \"Passphrase\",\n      \"createdAt\": \"2026-09-22T10:15:00Z\",\n      \"lastUsedAt\": \"2026-09-22T11:02:13Z\",\n      \"keyFingerprint\": null,\n      \"keyAlgorithm\": null\n    },\n    {\n      \"slotId\": \"9b2f...\",\n      \"label\": \"erika.musterfrau (certificate)\",\n      \"slotType\": \"PublicKey\",\n      \"createdAt\": \"2026-09-22T12:00:00Z\",\n      \"lastUsedAt\": null,\n      \"keyFingerprint\": \"4f8c...\",\n      \"keyAlgorithm\": \"RSA-3072\"\n    }\n  ]\n}\n```\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `slotId` | guid | Public id of the slot (used by `DELETE .../keys/{slotId}`) |\n| `label` | string | Client-assigned label, e.g. a user name. **Not a secret** |\n| `slotType` | string | `Passphrase`, `RawKey` or `PublicKey` |\n| `createdAt` | datetime | When the slot was created |\n| `lastUsedAt` | datetime | Last successful use, `null` if never used. Always `null` for `PublicKey` slots — the server cannot know which slot a client unwrapped |\n| `keyFingerprint` | string | `PublicKey` only: lowercase hex SHA-256 over the DER certificate or DER SubjectPublicKeyInfo; `null` otherwise |\n| `keyAlgorithm` | string | `PublicKey` only: e.g. `RSA-3072` or `EC-P256`; `null` otherwise |\n\nFor a `PublicKey` slot, `GET .../keys/{slotId}/wrapped-dek` returns the wrapped data key for\nlocal unwrapping.\n\n---\n\n## HTTP Status Codes\n\n| Code | Description |\n|------|-------------|\n| 200 | Key slots retrieved |\n| 403 | Missing `Documents.Read` permission, or `ACCESS_DENIED` |\n| 404 | Document not found |\n| 409 | `NOT_ENCRYPTED` — the document is not encrypted and has no key slots |\n\nDetails: `docs/encryption-guide.md`.\n",
        "operationId": "ListDocumentKeySlots",
        "parameters": [
          {
            "name": "documentGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetKeySlotsResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Documents - Keys"
        ],
        "summary": "Add Key Slot",
        "description": "## Add Another Key Slot\n\nAdds an **additional** key to an already encrypted document. The server unwraps the data key\n(DEK) with the existing key from the `X-Document-Key` (or `X-Document-Dek`) header and wraps it\nagain for the new key. Afterwards **both** keys open the document and all of its versions.\n\nThe new key is either a passphrase, a raw key or a **public key**\n(`newKeyType: \"publicKey\"`) — in the latter case the private key stays with the client, which\nfetches the wrapped DEK via `GET .../keys/{slotId}/wrapped-dek` and unwraps it locally.\n\n**Requires:** `Documents.Write` permission, full access (owning system) and a valid existing\ndocument key. Content, version and encryption mode stay unchanged.\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `documentGuid` | guid | Unique identifier (GUID) of the document |\n\n## Headers\n\n| Header | Required | Description |\n|--------|----------|-------------|\n| `X-Document-Key` | Yes* | An **existing**, valid key of the document |\n| `X-Document-Key-Type` | No | `passphrase` (default) or `raw`, for the existing key |\n| `X-Document-Dek` | Yes* | Alternative: the already unwrapped DEK (Base64, 32 bytes) |\n\n\\* Exactly one of the two key headers is required; sending both is\n`400 ENCRYPTION_KEY_CONFLICT`.\n\n## Request Body\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `newKey` | string | Yes¹ | The **new** key: passphrase (min. 12 characters) or Base64 raw key (exactly 32 bytes) |\n| `newKeyType` | string | No | `passphrase` (default), `raw` or `publicKey` |\n| `publicKey` | string | Yes² | X.509 certificate or SubjectPublicKeyInfo, PEM or Base64 DER |\n| `label` | string | No | Label for the new slot, e.g. a user name. **Not a secret** |\n\n¹ for `passphrase`/`raw`  ² for `publicKey`\n\n```json\n{\n  \"newKey\": \"second secure passphrase\",\n  \"newKeyType\": \"passphrase\",\n  \"label\": \"erika.musterfrau\"\n}\n```\n\n```json\n{\n  \"newKeyType\": \"publicKey\",\n  \"publicKey\": \"-----BEGIN CERTIFICATE-----\\nMIIC…\\n-----END CERTIFICATE-----\",\n  \"label\": \"erika.musterfrau (certificate)\"\n}\n```\n\n**Supported `publicKey` algorithms**\n\n| Key | Construction (`algorithm`) |\n|-----|----------------------------|\n| RSA, at least 2048 bit (3072 recommended) | `rsa-oaep-sha256` |\n| EC P-256 (`nistP256`) | `ecies-p256-hkdf-sha256-aesgcm` |\n\nAnything else (smaller RSA keys, other curves, Ed25519, DSA) is\n`400 PUBLIC_KEY_UNSUPPORTED`; unparseable input is `400 PUBLIC_KEY_INVALID_FORMAT`.\n\n> For certificates the service validates **neither the chain nor expiry nor revocation** — the\n> certificate is only a transport format for the public key here. Trust decisions are up to the\n> client.\n\n---\n\n## Response (201 Created)\n\n```json\n{\n  \"success\": true,\n  \"message\": \"Key slot added successfully\",\n  \"documentGuid\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"keySlot\": {\n    \"slotId\": \"9b2f...\",\n    \"label\": \"erika.musterfrau\",\n    \"slotType\": \"Passphrase\",\n    \"createdAt\": \"2026-09-22T12:00:00Z\",\n    \"lastUsedAt\": null,\n    \"keyFingerprint\": null,\n    \"keyAlgorithm\": null\n  },\n  \"totalKeySlots\": 2\n}\n```\n\n---\n\n## HTTP Status Codes\n\n| Code | Description |\n|------|-------------|\n| 201 | Key slot created |\n| 400 | `ENCRYPTION_KEY_TOO_WEAK`, `ENCRYPTION_KEY_INVALID_FORMAT`, `ENCRYPTION_KEY_CONFLICT`, `PUBLIC_KEY_INVALID_FORMAT`, `PUBLIC_KEY_UNSUPPORTED` or a missing `newKey`/`publicKey` |\n| 403 | Missing permission, `ACCESS_DENIED`, `ENCRYPTION_KEY_REQUIRED` or `ENCRYPTION_KEY_INVALID` |\n| 404 | Document not found |\n| 409 | `NOT_ENCRYPTED` — a document cannot be encrypted after creation; `KEY_SLOT_DUPLICATE` — that public key already has a slot |\n| 429 | `ENCRYPTION_KEY_RATE_LIMITED` — too many failed attempts, honour `Retry-After` |\n\nThe check order is permission → system access control → rate limit → key. A wrong existing key\ncounts as a failed attempt. Key material is never stored, logged or returned.\nDetails: `docs/encryption-guide.md`.\n",
        "operationId": "AddDocumentKeySlot",
        "parameters": [
          {
            "name": "documentGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "X-Correlation-Id",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddKeySlotRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddKeySlotResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/documents/{documentGuid}/keys/{slotId}/wrapped-dek": {
      "get": {
        "tags": [
          "Documents - Keys"
        ],
        "summary": "Get Wrapped Data Key",
        "description": "## Get the wrapped data key of a public-key slot\n\nReturns the data key (DEK) of a key slot **wrapped for a public key** — everything a client\nneeds to unwrap the DEK **locally with its private key**. The unwrapped DEK is then sent in the\n`X-Document-Dek` header to every endpoint that otherwise expects `X-Document-Key`.\n\n**Requires:** `Documents.Read` and read access to the document.\n**No document key is needed.** The response is worthless without the matching private key and is\ntherefore **not** rate limited either.\n\nOnly slots of type `PublicKey` are exportable. Passphrase and raw-key slots answer\n`409 KEY_SLOT_NOT_EXPORTABLE` — their wrapped DEK would be attackable offline.\n\n---\n\n## Path parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `documentGuid` | guid | Document GUID |\n| `slotId` | guid | Public id of the key slot (from `GET .../keys`) |\n\n---\n\n## Response (200 OK)\n\n```json\n{\n  \"success\": true,\n  \"message\": \"Wrapped data key retrieved successfully\",\n  \"documentGuid\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"slotId\": \"9b2f1c64-1f2e-4a3b-9c0d-2b7f5e1a4c88\",\n  \"keyFingerprint\": \"4f8c…\",\n  \"keyAlgorithm\": \"RSA-3072\",\n  \"algorithm\": \"rsa-oaep-sha256\",\n  \"wrappedDek\": \"<Base64>\",\n  \"nonce\": \"\",\n  \"ephemeralPublicKey\": null,\n  \"aad\": \"550e8400-e29b-41d4-a716-446655440000|9b2f1c64-1f2e-4a3b-9c0d-2b7f5e1a4c88\"\n}\n```\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `algorithm` | string | `rsa-oaep-sha256` or `ecies-p256-hkdf-sha256-aesgcm` |\n| `keyAlgorithm` | string | Recipient key, e.g. `RSA-3072` or `EC-P256` |\n| `keyFingerprint` | string | Lowercase hex SHA-256 over the DER certificate or DER SubjectPublicKeyInfo |\n| `wrappedDek` | string | The wrapped DEK, Base64 |\n| `nonce` | string | AES-GCM nonce, Base64; **empty** for `rsa-oaep-sha256` |\n| `ephemeralPublicKey` | string | Uncompressed ephemeral P-256 point (65 bytes), Base64; `null` for RSA |\n| `aad` | string | Additional authenticated data of the AES-GCM step: `\"{documentGuid}|{slotId}\"` |\n\n### Unwrapping\n\n- **`rsa-oaep-sha256`** — RSA-OAEP with SHA-256 (MGF1-SHA256, empty label) over `wrappedDek`\n  yields the 32 DEK bytes directly.\n- **`ecies-p256-hkdf-sha256-aesgcm`** — ECDH(private key, `ephemeralPublicKey`) → raw X\n  coordinate → HKDF-SHA256(empty salt, info `\"docsvc-ecies-v1|{documentGuid}|{slotId}\"`,\n  32 bytes) → AES-256-GCM decryption of `wrappedDek` with `nonce` and `aad`.\n\nThe full definition with sample code is in `docs/encryption-guide.md`.\n\n---\n\n## HTTP status codes\n\n| Code | Meaning |\n|------|---------|\n| 200 | Material retrieved |\n| 403 | Missing permission (`Documents.Read`) or `ACCESS_DENIED` |\n| 404 | `DOCUMENT_NOT_FOUND` or `KEY_SLOT_NOT_FOUND` |\n| 409 | `NOT_ENCRYPTED` or `KEY_SLOT_NOT_EXPORTABLE` (not a public-key slot) |\n\n> Removing a public-key slot does **not** revoke a DEK that was already unwrapped.\n",
        "operationId": "GetDocumentKeySlotWrappedDek",
        "parameters": [
          {
            "name": "documentGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "slotId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WrappedDekResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/documents/{documentGuid}/keys/{slotId}": {
      "delete": {
        "tags": [
          "Documents - Keys"
        ],
        "summary": "Remove Key Slot",
        "description": "## Remove a Key Slot\n\nRemoves one key slot of an encrypted document. Its key no longer opens the document; every\nother slot keeps working.\n\n**Requires:** `Documents.Write` permission, full access (owning system) and a **valid**\ndocument key in the `X-Document-Key` header — it may be the key of the slot being removed.\n\n> ⚠️ Removing a slot does **not** protect against someone who already knows the data key or\n> holds a copy of the content. Real revocation requires re-encryption (a new document with new\n> keys) and is not part of this operation.\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `documentGuid` | guid | Unique identifier (GUID) of the document |\n| `slotId` | guid | Public id of the slot (from `GET .../keys`) |\n\n## Headers\n\n| Header | Required | Description |\n|--------|----------|-------------|\n| `X-Document-Key` | Yes* | Any valid key of the document |\n| `X-Document-Key-Type` | No | `passphrase` (default) or `raw` |\n| `X-Document-Dek` | Yes* | Alternative: the already unwrapped DEK (Base64, 32 bytes). Sending both headers is `400 ENCRYPTION_KEY_CONFLICT` |\n\n\\* Exactly one of the two key headers is required.\n\n---\n\n## Response (200 OK)\n\n```json\n{\n  \"success\": true,\n  \"message\": \"Key slot removed successfully\",\n  \"documentGuid\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"slotId\": \"9b2f...\",\n  \"remainingKeySlots\": 1\n}\n```\n\n---\n\n## HTTP Status Codes\n\n| Code | Description |\n|------|-------------|\n| 200 | Key slot removed |\n| 403 | Missing permission, `ACCESS_DENIED`, `ENCRYPTION_KEY_REQUIRED` or `ENCRYPTION_KEY_INVALID` |\n| 404 | Document not found, or `KEY_SLOT_NOT_FOUND` |\n| 409 | `NOT_ENCRYPTED`, or `LAST_KEY_SLOT` — the last slot cannot be removed |\n| 429 | `ENCRYPTION_KEY_RATE_LIMITED` — too many failed attempts, honour `Retry-After` |\n\nThe key is evaluated **before** the slot is looked up: only a caller that already proved a valid\nkey learns about `KEY_SLOT_NOT_FOUND` or `LAST_KEY_SLOT`. Details: `docs/encryption-guide.md`.\n",
        "operationId": "RemoveDocumentKeySlot",
        "parameters": [
          {
            "name": "documentGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "slotId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "X-Correlation-Id",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteKeySlotResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/documents/{documentGuid}/links": {
      "post": {
        "tags": [
          "Documents - Links"
        ],
        "summary": "Create Download Link",
        "description": "## Create Shareable Download Link\n\nCreate a public download link for a document. The link can be shared with external users who don't have API access.\n\n---\n\n## Request Body\n\n| Field | Type | Required | Default | Description |\n|-------|------|----------|---------|-------------|\n| `documentGuid` | guid | Yes | - | Unique identifier (GUID) of the document |\n| `expiresAt` | datetime | No | 7 days | Expiration timestamp (UTC) - link becomes invalid after this time |\n| `maxDownloads` | int | No | unlimited | Maximum number of downloads allowed |\n| `password` | string | No | none | Optional password to protect the download link |\n| `allowedIps` | string[] | No | any | List of allowed IP addresses or CIDR ranges |\n| `versionNumber` | int | No | latest | Specific version to link to |\n\n---\n\n## Example: Simple Link (7 days, unlimited downloads)\n\n```json\n{\n  \"documentGuid\": \"550e8400-e29b-41d4-a716-446655440000\"\n}\n```\n\n## Example: Protected Link\n\n```json\n{\n  \"documentGuid\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"expiresAt\": \"2025-01-15T23:59:59Z\",\n  \"maxDownloads\": 5,\n  \"password\": \"SecurePassword123\"\n}\n```\n\n## Example: IP-Restricted Link\n\n```json\n{\n  \"documentGuid\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"allowedIps\": [\"192.168.1.0/24\", \"10.0.0.50\"]\n}\n```\n\n---\n\n## Response\n\nReturns the generated link token and full download URL.",
        "operationId": "CreateDocumentLink",
        "parameters": [
          {
            "name": "documentGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "X-Correlation-Id",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLinkApiRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateDocumentLinkResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Documents - Links"
        ],
        "summary": "Get Document Links",
        "description": "## Get All Download Links for a Document\n\nRetrieve all download links created for a specific document.\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `documentGuid` | guid | Unique identifier (GUID) of the document |\n\n## Query Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `includeExpired` | bool | false | Include expired/inactive links in the response |\n\n---\n\n## Response Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `token` | string | Unique link token for public download access |\n| `downloadUrl` | string | Full URL for public download access |\n| `expiresAt` | datetime | Expiration timestamp (UTC) - link becomes invalid after this time |\n| `maxDownloads` | int | Maximum number of downloads allowed (null = unlimited) |\n| `downloadCount` | int | Current number of times the link has been used |\n| `isPasswordProtected` | bool | Whether the link requires a password to download |\n| `allowedIps` | string[] | List of allowed IP addresses or CIDR ranges (null = no restriction) |\n| `isActive` | bool | Whether the link is currently active and usable |\n| `createdAt` | datetime | Timestamp when the link was created |\n| `createdBy` | string | User or system that created the link |",
        "operationId": "GetDocumentLinks",
        "parameters": [
          {
            "name": "documentGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "includeExpired",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetDocumentLinksResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/documents/links/{linkId}": {
      "delete": {
        "tags": [
          "Documents - Links"
        ],
        "summary": "Deactivate Link",
        "description": "## Deactivate Download Link\n\nDeactivate a specific download link. Once deactivated, the link can no longer be used for downloads.\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `documentGuid` | guid | Unique identifier (GUID) of the document |\n| `token` | string | Unique link token for public download access |\n\n---\n\n## Notes\n\n- Deactivation is immediate and cannot be reversed\n- The link will return 404 when accessed\n- Download statistics are preserved\n- Consider creating a new link if needed again",
        "operationId": "DeactivateLink",
        "parameters": [
          {
            "name": "linkId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "X-Deleted-By",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeactivateLinkResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/download/{token}": {
      "get": {
        "tags": [
          "Download - Public"
        ],
        "summary": "Download by Link Token",
        "description": "## Public Download via Link Token\n\nDownload a document using a shareable link token. **No authentication required.**\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `token` | string | Unique link token for public download access |\n\n## Query Parameters\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `password` | string | If protected | Password if the link is password-protected |\n| `profile` | string | No | Header profile for response customization (default: default) |\n\n---\n\n## Header Profiles\n\nThe `profile` parameter enables client-specific HTTP header customization:\n\n| Profile | Content-Disposition | X-Frame-Options | Content-Security-Policy |\n|---------|---------------------|-----------------|------------------------|\n| `default` | attachment | DENY | - |\n| `salesforce` | inline | (removed) | frame-ancestors 'self' *.salesforce.com *.force.com |\n| `preview` | inline | - | - |\n\n---\n\n## Validation\n\nThe link is validated for:\n- Token existence and validity\n- Expiration date\n- Download count limit\n- Password (if protected)\n- IP address (if restricted)\n\n---\n\n## Response\n\n- **Content-Type:** The original MIME type of the file\n- **Content-Disposition:** Depends on profile (attachment or inline)\n- **Body:** Binary file content\n\n---\n\n## Examples\n\n**Standard Download:**\n```\nGET /download/{token}\n```\n\n**Salesforce iFrame Embedding:**\n```\nGET /download/{token}?profile=salesforce\n```\n\n**With Password:**\n```\nGET /download/{token}?password=secret&profile=preview\n```\n\n---\n\n## Error Codes\n\n| Code | Description |\n|------|-------------|\n| 404 | Link not found or invalid |\n| 401 | Password required or incorrect |\n| 403 | IP address not allowed |\n| 410 | Link expired or download limit reached |",
        "operationId": "DownloadByToken",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "version",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "password",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "profile",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forwarded-For",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "410": {
            "description": "Gone",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/download/{token}/info": {
      "get": {
        "tags": [
          "Download - Public"
        ],
        "summary": "Validate Link Token",
        "description": "## Validate Link Token\n\nValidate a link token and retrieve download information without triggering a download. Useful for:\n- Previewing link details before download\n- Checking if password is required\n- Verifying link validity\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `token` | string | Unique link token for public download access |\n\n---\n\n## Response Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `isValid` | bool | Whether the link is valid and usable |\n| `fileName` | string | Original filename including extension |\n| `fileSize` | long | File size in bytes |\n| `contentType` | string | MIME type of the file (e.g., \"application/pdf\") |\n| `isPasswordProtected` | bool | Whether the link requires a password to download |\n| `expiresAt` | datetime | Expiration timestamp (UTC) - link becomes invalid after this time |\n| `remainingDownloads` | int | How many downloads are left (null = unlimited) |",
        "operationId": "ValidateLinkToken",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forwarded-For",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidateLinkResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admin/clients": {
      "get": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "List API Clients",
        "description": "## List All API Clients\n\nRetrieve a list of all registered API clients.\n\n**Requires:** `admin:read` permission\n\n---\n\n## Response Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `clientGuid` | guid | Unique identifier (GUID) of the API client |\n| `clientName` | string | Human-readable name of the API client |\n| `description` | string | Description of the client's purpose or system integration |\n| `apiKeyPrefix` | string | First 8 characters of the API key for identification |\n| `isActive` | bool | Whether the client is currently active and can authenticate |\n| `permissions` | string[] | List of granted permissions |\n| `rateLimitPerMinute` | int | Maximum requests per minute (null = unlimited) |\n| `allowedIpRanges` | string[] | List of allowed IP addresses or CIDR ranges (null = any) |\n| `lastUsedAt` | datetime | Timestamp of last API request using this client |\n| `expiresAt` | datetime | Expiration timestamp - client becomes invalid after this time (null = never) |\n| `createdAt` | datetime | Timestamp when the client was created |\n| `createdBy` | string | User or system that created the client |",
        "operationId": "ListApiClients",
        "parameters": [
          {
            "name": "isActive",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListApiClientsResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "Create API Client",
        "description": "## Create New API Client\n\nCreate a new API client with the specified permissions.\n\n**Requires:** `Admin.Full` permission\n\n**Important:** The API key is only shown once in the response. Store it securely!\n\n---\n\n## Request Body\n\n| Field | Type | Required | Default | Description |\n|-------|------|----------|---------|-------------|\n| `name` | string | Yes | - | Human-readable name of the API client |\n| `description` | string | No | - | Description of the client's purpose or system integration |\n| `generateApiKey` | bool | No | true | Whether to generate an API key for this client |\n| `azureAdClientId` | string | No | - | Azure AD / Entra ID App Registration Client ID to link to this client |\n| `azureAdClientSecret` | string | No | - | **Ephemeral — never stored.** Client secret of the Azure AD App Registration. When provided together with `azureAdClientId`, a client credentials token exchange is performed against Azure AD before saving. If validation fails, the client is not created. Remove after successful validation. |\n| `azureAdScope` | string | No | auto | **Ephemeral — never stored.** Scope for the validation token exchange. Defaults to `{Audience}/.default` from service configuration if omitted. |\n| `certificateThumbprint` | string | No | - | mTLS client certificate thumbprint |\n| `isActive` | bool | No | true | Whether the client is immediately active |\n| `expiresAt` | datetime | No | never | Expiration timestamp for the client |\n| `permissions` | array | No | [] | Initial permissions to grant |\n| `keyVaultStorage` | object | No | - | Optional Azure Key Vault configuration for the API key |\n\n---\n\n## Azure AD Validation (optional)\n\nIf you provide `azureAdClientId` **and** `azureAdClientSecret`, the service performs a full client credentials token exchange against Microsoft Entra ID before creating the client. This confirms the App Registration is correctly configured.\n\n> ⚠️ `azureAdClientSecret` and `azureAdScope` are **not stored** — they are used exclusively for this one-time validation. Remove them from your request after a successful creation.\n\nIf validation fails, the response returns `400 AZURE_AD_VALIDATION_FAILED` with the Azure AD error details.\n\n---\n\n## Example: Create with Azure AD validation\n\n```json\n{\n  \"name\": \"Salesforce Integration\",\n  \"description\": \"API client for Salesforce CRM integration\",\n  \"azureAdClientId\": \"e4ea40ad-947c-4a03-b283-88db67f14546\",\n  \"azureAdClientSecret\": \"Stx8Q~...\",\n  \"permissions\": [\"Documents.Read\", \"Documents.Write\"]\n}\n```\n\n---\n\n## Response\n\nReturns the created client details including the **API key** (shown only once).",
        "operationId": "CreateApiClient",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateClientRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateApiClientResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/admin/clients/{clientGuid}": {
      "get": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "Get API Client",
        "description": "## Get API Client by GUID\n\nRetrieve details of a specific API client.\n\n**Requires:** `admin:read` permission\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `clientGuid` | guid | Unique identifier (GUID) of the API client |\n\n---\n\n## Response Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `clientGuid` | guid | Unique identifier (GUID) of the API client |\n| `clientName` | string | Human-readable name of the API client |\n| `description` | string | Description of the client's purpose or system integration |\n| `apiKeyPrefix` | string | First 8 characters of the API key for identification |\n| `isActive` | bool | Whether the client is currently active and can authenticate |\n| `permissions` | string[] | List of granted permissions |\n| `rateLimitPerMinute` | int | Maximum requests per minute (null = unlimited) |\n| `allowedIpRanges` | string[] | List of allowed IP addresses or CIDR ranges (null = any) |\n| `lastUsedAt` | datetime | Timestamp of last API request using this client |\n| `expiresAt` | datetime | Expiration timestamp - client becomes invalid after this time (null = never) |\n| `createdAt` | datetime | Timestamp when the client was created |\n| `createdBy` | string | User or system that created the client |",
        "operationId": "GetApiClient",
        "parameters": [
          {
            "name": "clientGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetApiClientResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      },
      "patch": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "Update API Client",
        "description": "## Update API Client\n\nPartial update of API client properties. Only provided fields are updated.\n\n**Requires:** `Admin.Full` permission\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `clientGuid` | guid | Unique identifier (GUID) of the API client |\n\n## Request Body\n\nAll fields are optional. Only include fields you want to update.\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `name` | string | Human-readable name of the API client |\n| `description` | string | Description of the client's purpose or system integration |\n| `azureAdClientId` | string | Azure AD / Entra ID App Registration Client ID to link to this client |\n| `azureAdClientSecret` | string | **Ephemeral — never stored.** Client secret of the Azure AD App Registration. When provided together with `azureAdClientId`, a validation token exchange is run against Azure AD before saving. If validation fails, the update is not applied. Remove after use. |\n| `azureAdScope` | string | **Ephemeral — never stored.** Scope for the validation token exchange. Defaults to `{Audience}/.default` if omitted. |\n| `certificateThumbprint` | string | mTLS client certificate thumbprint |\n| `expiresAt` | datetime | Expiration timestamp — client becomes invalid after this time (null = never) |\n\n---\n\n## Azure AD Validation (optional)\n\nSupply `azureAdClientId` and `azureAdClientSecret` to automatically validate the Entra ID App Registration before the update is saved. The secret is never persisted.\n\nIf validation fails, the response returns `400 AZURE_AD_VALIDATION_FAILED` with the Azure AD error details.\n\n---\n\n## Example: Link an Azure AD app with validation\n\n```json\n{\n  \"azureAdClientId\": \"e4ea40ad-947c-4a03-b283-88db67f14546\",\n  \"azureAdClientSecret\": \"Stx8Q~...\"\n}\n```",
        "operationId": "UpdateApiClient",
        "parameters": [
          {
            "name": "clientGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateClientRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiClientOperationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "Delete API Client",
        "description": "## Delete API Client\n\nPermanently delete an API client. This action cannot be undone.\n\n**Requires:** `admin:delete` permission\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `clientGuid` | guid | Unique identifier (GUID) of the API client |\n\n---\n\n## Notes\n\n- Deletion is immediate and permanent\n- The API key will no longer authenticate\n- Consider deactivating instead of deleting for audit purposes",
        "operationId": "DeleteApiClient",
        "parameters": [
          {
            "name": "clientGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiClientOperationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/admin/clients/{clientGuid}/status": {
      "post": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "Set Client Status",
        "description": "## Activate or Deactivate API Client\n\nEnable or disable an API client without deleting it.\n\n**Requires:** `admin:write` permission\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `clientGuid` | guid | Unique identifier (GUID) of the API client |\n\n## Request Body\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `isActive` | bool | Yes | Whether the client is currently active and can authenticate |\n\n---\n\n## Example: Deactivate Client\n\n```json\n{\n  \"isActive\": false\n}\n```",
        "operationId": "SetApiClientStatus",
        "parameters": [
          {
            "name": "clientGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetClientStatusRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiClientOperationResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/admin/clients/{clientGuid}/rotate-key": {
      "post": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "Rotate API Key",
        "description": "## Rotate API Key\n\nGenerate a new API key for the client. The old key is immediately invalidated.\n\n**Requires:** `admin:write` permission\n\n**Important:** The new API key is only shown once in the response. Store it securely!\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `clientGuid` | guid | Unique identifier (GUID) of the API client |\n\n---\n\n## Response\n\nReturns the new API key (shown only once).\n\n---\n\n## Notes\n\n- The old API key is immediately invalidated\n- All existing sessions using the old key will fail\n- Store the new key securely before closing the response",
        "operationId": "RotateApiKey",
        "parameters": [
          {
            "name": "clientGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RotateApiKeyResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/admin/clients/{clientGuid}/key": {
      "get": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "Get API Key Info",
        "description": "## Get API Key Information\n\nRetrieve API key information for a client (prefix only, not the full key).\n\n**Requires:** `admin:read` permission\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `clientGuid` | guid | Unique identifier (GUID) of the API client |\n\n---\n\n## Response Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `apiKeyPrefix` | string | First 8 characters of the API key for identification |\n| `createdAt` | datetime | Timestamp when the current key was generated |\n| `lastUsedAt` | datetime | Timestamp of last API request using this key |\n\n---\n\n## Notes\n\n- The full API key cannot be retrieved after creation\n- Use `rotateKey` to generate a new key if the current one is lost",
        "operationId": "GetApiKeyInfo",
        "parameters": [
          {
            "name": "clientGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetApiKeyResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/admin/clients/{clientGuid}/permissions": {
      "post": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "Add Permissions",
        "description": "## Add Permissions to API Client\n\nGrant additional permissions to an existing API client.\n\n**Requires:** `admin:write` permission\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `clientGuid` | guid | Unique identifier (GUID) of the API client |\n\n## Request Body\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `permissions` | string[] | Yes | List of permissions to add |\n\n---\n\n## Available Permissions\n\n| Permission | Description |\n|------------|-------------|\n| `documents:read` | Read document metadata and download files |\n| `documents:write` | Upload new documents and create versions |\n| `documents:delete` | Delete documents (soft and permanent) |\n| `links:read` | View download links for documents |\n| `links:write` | Create and manage download links |\n| `links:delete` | Deactivate download links |\n| `admin:read` | View API clients and system settings |\n| `admin:write` | Create and modify API clients |\n| `admin:delete` | Delete API clients |\n\n---\n\n## Example\n\n```json\n{\n  \"permissions\": [\"documents:delete\", \"links:delete\"]\n}\n```",
        "operationId": "AddApiClientPermissions",
        "parameters": [
          {
            "name": "clientGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GrantPermissionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GrantPermissionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/admin/clients/{clientGuid}/permissions/{permissionGuid}": {
      "delete": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "Remove Permissions",
        "description": "## Remove Permissions from API Client\n\nRevoke permissions from an existing API client.\n\n**Requires:** `admin:write` permission\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `clientGuid` | guid | Unique identifier (GUID) of the API client |\n\n## Request Body\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `permissions` | string[] | Yes | List of permissions to remove |\n\n---\n\n## Example\n\n```json\n{\n  \"permissions\": [\"admin:write\", \"admin:delete\"]\n}\n```",
        "operationId": "RemoveApiClientPermissions",
        "parameters": [
          {
            "name": "clientGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "permissionGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevokePermissionResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/admin/clients/permissions/available": {
      "get": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "List Available Permissions",
        "description": "## List All Available Permissions\n\nRetrieve a list of all permissions that can be assigned to API clients.\n\n**Requires:** `admin:read` permission\n\n---\n\n## Response Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `name` | string | Permission identifier (e.g., \"documents:read\") |\n| `description` | string | Human-readable description of what the permission allows |\n| `category` | string | Permission category grouping (e.g., \"Documents\", \"Admin\") |\n\n---\n\n## Available Permission Categories\n\n- **Documents**: `documents:read`, `documents:write`, `documents:delete`\n- **Links**: `links:read`, `links:write`, `links:delete`\n- **Admin**: `admin:read`, `admin:write`, `admin:delete`",
        "operationId": "ListAvailablePermissions",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AvailablePermissionsResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/admin/clients/{clientGuid}/oauth2": {
      "get": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "Get OAuth2 Client",
        "description": "## Get OAuth2 Client Details\n\nRetrieve detailed information about a specific OAuth2 client including linked ApiClient and permissions.\n\n**Requires:** `Admin.Full` permission\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `clientGuid` | guid | OAuth2 client GUID (unique identifier) |\n\n---\n\n## Response Fields\n\n### OAuth2 Client\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `guid` | guid | Unique OAuth2 client GUID |\n| `clientId` | string | OAuth2 protocol client identifier |\n| `displayName` | string | Human-readable client name |\n| `description` | string | Client description |\n| `clientType` | string | Client type (confidential/public) |\n| `grantTypes` | string[] | Allowed OAuth2 grant types |\n| `scopes` | string[] | Allowed scopes |\n| `isActive` | bool | Whether client is active |\n| `expiresAt` | datetime | Expiration timestamp (null = never) |\n| `createdAt` | datetime | Creation timestamp |\n| `createdBy` | string | Creator user/system |\n\n### Linked ApiClient (if exists)\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `guid` | guid | ApiClient GUID |\n| `name` | string | ApiClient name |\n| `permissions` | array | Granted permissions with systemFilter |",
        "operationId": "GetOAuth2Client",
        "parameters": [
          {
            "name": "clientGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetOAuth2ClientResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "Create OAuth2 Client",
        "description": "## Create New OAuth2 Client\n\nCreate a new OAuth2 client for JWT-based authentication. The client_secret is **only returned once** - store it securely!\n\n**Requires:** `Admin.Full` permission\n\n---\n\n## Request Body\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `clientId` | string | Yes | Unique OAuth2 client ID (e.g., \"sf_abc123\") |\n| `displayName` | string | Yes | Human-readable client name |\n| `description` | string | No | Client description |\n| `clientSecret` | string | No | Custom secret (auto-generated if omitted) |\n| `grantTypes` | string[] | No | Default: [\"client_credentials\"] |\n| `scopes` | string[] | No | Default: [\"api\"] |\n| `expiresAt` | datetime | No | Expiration timestamp (null = never) |\n| `permissions` | string[] | No | Initial permissions to grant |\n\n---\n\n## Example Request\n\n```json\n{\n  \"clientId\": \"sf_prod_2024\",\n  \"displayName\": \"Salesforce Production\",\n  \"description\": \"OAuth2 client for Salesforce integration\",\n  \"grantTypes\": [\"client_credentials\"],\n  \"permissions\": [\"Documents.Read\", \"Documents.Write\"]\n}\n```\n\n---\n\n## Response\n\n```json\n{\n  \"success\": true,\n  \"clientId\": \"sf_prod_2024\",\n  \"clientSecret\": \"sWJ8Q~7xK...\",\n  \"displayName\": \"Salesforce Production\",\n  \"apiClientGuid\": \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n  \"warning\": \"⚠️ Store the client_secret securely - it cannot be retrieved again!\"\n}\n```\n\n**Important:** Save the `clientSecret` - it cannot be retrieved later!",
        "operationId": "CreateOAuth2Client",
        "parameters": [
          {
            "name": "clientGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateOAuth2ClientRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateOAuth2ClientResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      },
      "patch": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "Update OAuth2 Client",
        "description": "## Update OAuth2 Client\n\nPartial update of OAuth2 client metadata. Only provided fields are updated.\n\n**Requires:** `Admin.Full` permission\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `clientGuid` | guid | OAuth2 client GUID (unique identifier) |\n\n## Request Body\n\nAll fields are optional. Only include fields you want to update.\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `displayName` | string | Human-readable client name |\n| `description` | string | Client description |\n| `isActive` | bool | Whether client is active |\n| `expiresAt` | datetime | Expiration timestamp (null = never) |\n\n---\n\n## Example: Deactivate Client\n\n```json\n{\n  \"isActive\": false\n}\n```",
        "operationId": "UpdateOAuth2Client",
        "parameters": [
          {
            "name": "clientGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateOAuth2ClientRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdateOAuth2ClientResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "Delete OAuth2 Client",
        "description": "## Delete OAuth2 Client\n\nPermanently delete an OAuth2 client. This action **cannot be undone**.\n\n**Requires:** `Admin.Full` permission\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `clientGuid` | guid | OAuth2 client GUID (unique identifier) |\n\n---\n\n## Notes\n\n- Deletion is immediate and permanent\n- The client_id will no longer authenticate\n- Linked ApiClient is preserved (if it exists)\n- Consider deactivating instead of deleting for audit purposes",
        "operationId": "DeleteOAuth2Client",
        "parameters": [
          {
            "name": "clientGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteOAuth2ClientResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/admin/clients/{clientGuid}/oauth2/rotate-secret": {
      "post": {
        "tags": [
          "Administration - Clients"
        ],
        "summary": "Rotate Client Secret",
        "description": "## Rotate OAuth2 Client Secret\n\nGenerate a new client_secret. The old secret is **immediately invalidated**.\n\n**Requires:** `Admin.Full` permission\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `clientGuid` | guid | OAuth2 client GUID (unique identifier) |\n\n---\n\n## Response\n\n```json\n{\n  \"success\": true,\n  \"clientSecret\": \"new_sWJ8Q~7xK...\",\n  \"warning\": \"⚠️ Store the client_secret securely - it cannot be retrieved again!\"\n}\n```\n\n**Important:**\n- The old secret stops working immediately\n- The new secret is only shown once - save it securely!\n- Update all applications using the old secret",
        "operationId": "RotateOAuth2ClientSecret",
        "parameters": [
          {
            "name": "clientGuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RotateOAuth2ClientSecretRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RotateOAuth2ClientSecretResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/oauth2/token": {
      "post": {
        "tags": [
          "Authentication - OAuth2"
        ],
        "summary": "Generate OAuth2 Token",
        "description": "## OAuth2 Token Endpoint (Client Credentials Flow)\n\nGenerate a JWT access token using OAuth2 client credentials. **No authentication required** - use client_id and client_secret from your OAuth2 client registration.\n\n---\n\n## Request\n\n**Content-Type:** `application/x-www-form-urlencoded`\n\n### Form Parameters\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `grant_type` | string | Yes | Must be `client_credentials` or `refresh_token` |\n| `client_id` | string | Yes* | Your OAuth2 client ID (required for client_credentials) |\n| `client_secret` | string | Yes* | Your OAuth2 client secret (required for client_credentials) |\n| `refresh_token` | string | Yes* | Your refresh token (required for refresh_token grant) |\n| `scope` | string | No | Requested scopes (space-separated) |\n\n---\n\n## Example Request (Client Credentials)\n\n```bash\ncurl -X POST https://api.example.com/oauth2/token \\\n  -H \"Content-Type: application/x-www-form-urlencoded\" \\\n  -d \"grant_type=client_credentials\" \\\n  -d \"client_id=sf_abc123\" \\\n  -d \"client_secret=your_secret_here\" \\\n  -d \"scope=api\"\n```\n\n---\n\n## Response\n\n```json\n{\n  \"access_token\": \"eyJhbGciOiJIUzI1NiIs...\",\n  \"token_type\": \"Bearer\",\n  \"expires_in\": 3600,\n  \"refresh_token\": \"...\",\n  \"scope\": \"api\"\n}\n```\n\n### Response Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `access_token` | string | JWT token to use in Authorization header |\n| `token_type` | string | Always \"Bearer\" |\n| `expires_in` | int | Token lifetime in seconds (default: 3600 = 1 hour) |\n| `refresh_token` | string | Token for refreshing the access token (optional) |\n| `scope` | string | Granted scopes |\n\n---\n\n## Usage\n\nUse the access token in subsequent API requests:\n\n```bash\ncurl -X GET https://api.example.com/api/documents \\\n  -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIs...\"\n```",
        "operationId": "GetOAuth2Token",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "required": [
                  "grant_type"
                ],
                "type": "object",
                "allOf": [
                  {
                    "type": "object",
                    "properties": {
                      "grant_type": {
                        "type": "string"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "client_id": {
                        "type": "string"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "client_secret": {
                        "type": "string"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "refresh_token": {
                        "type": "string"
                      }
                    }
                  }
                ]
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "required": [
                  "grant_type"
                ],
                "type": "object",
                "allOf": [
                  {
                    "type": "object",
                    "properties": {
                      "grant_type": {
                        "type": "string"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "client_id": {
                        "type": "string"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "client_secret": {
                        "type": "string"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "refresh_token": {
                        "type": "string"
                      }
                    }
                  }
                ]
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuth2TokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuth2ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuth2ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/oauth2/introspect": {
      "post": {
        "tags": [
          "Authentication - OAuth2"
        ],
        "summary": "Token Introspection (RFC 7662)",
        "description": "## OAuth2 Token Introspection\n\nCheck if a token is active and retrieve its metadata according to RFC 7662.\n\n---\n\n## Request\n\n**Content-Type:** `application/x-www-form-urlencoded`\n\n### Form Parameters\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `token` | string | Yes | The token to introspect |\n| `client_id` | string | No | OAuth2 client ID (for authentication) |\n| `client_secret` | string | No | OAuth2 client secret (for authentication) |\n\n---\n\n## Response\n\n```json\n{\n  \"active\": true,\n  \"scope\": \"api documents:read\",\n  \"client_id\": \"sf_abc123\",\n  \"username\": \"service_account\",\n  \"exp\": 1735689600,\n  \"iat\": 1735686000\n}\n```\n\n### Response Fields\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `active` | bool | Whether the token is currently active |\n| `scope` | string | Space-separated list of scopes |\n| `client_id` | string | Client identifier for the token |\n| `username` | string | User identifier (if applicable) |\n| `exp` | int | Expiration timestamp (Unix time) |\n| `iat` | int | Issued at timestamp (Unix time) |",
        "operationId": "IntrospectOAuth2Token",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "required": [
                  "token"
                ],
                "type": "object",
                "allOf": [
                  {
                    "type": "object",
                    "properties": {
                      "token": {
                        "type": "string"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "client_id": {
                        "type": "string"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "client_secret": {
                        "type": "string"
                      }
                    }
                  }
                ]
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "required": [
                  "token"
                ],
                "type": "object",
                "allOf": [
                  {
                    "type": "object",
                    "properties": {
                      "token": {
                        "type": "string"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "client_id": {
                        "type": "string"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "client_secret": {
                        "type": "string"
                      }
                    }
                  }
                ]
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuth2IntrospectionResponse"
                }
              }
            }
          }
        }
      }
    },
    "/oauth2/revoke": {
      "post": {
        "tags": [
          "Authentication - OAuth2"
        ],
        "summary": "Token Revocation (RFC 7009)",
        "description": "## OAuth2 Token Revocation\n\nRevoke an access or refresh token according to RFC 7009. Once revoked, the token can no longer be used.\n\n---\n\n## Request\n\n**Content-Type:** `application/x-www-form-urlencoded`\n\n### Form Parameters\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `token` | string | Yes | The token to revoke (access or refresh token) |\n| `token_type_hint` | string | No | Hint about token type: \"access_token\" or \"refresh_token\" |\n\n---\n\n## Response\n\nReturns HTTP 200 on success (even if token was already invalid).\n\n---\n\n## Notes\n\n- Revocation is immediate\n- The endpoint always returns success for security reasons (RFC 7009)\n- After revocation, any API calls with this token will fail with 401",
        "operationId": "RevokeOAuth2Token",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "required": [
                  "token"
                ],
                "type": "object",
                "allOf": [
                  {
                    "type": "object",
                    "properties": {
                      "token": {
                        "type": "string"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "token_type_hint": {
                        "type": "string"
                      }
                    }
                  }
                ]
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "required": [
                  "token"
                ],
                "type": "object",
                "allOf": [
                  {
                    "type": "object",
                    "properties": {
                      "token": {
                        "type": "string"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "properties": {
                      "token_type_hint": {
                        "type": "string"
                      }
                    }
                  }
                ]
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "description": "Bad Request"
          }
        }
      }
    },
    "/api/upload-tokens": {
      "post": {
        "tags": [
          "Upload Tokens"
        ],
        "summary": "Generate Upload Token",
        "description": "## Generate One-Time Upload Token\n\nGenerate a secure, one-time token for frontend file uploads. The token allows a frontend (e.g., Salesforce LWC, browser app) to upload a file directly without exposing API credentials.\n\n**Requires:** `documents:write` permission\n\n---\n\n## Request Body\n\n| Field | Type | Required | Default | Description |\n|-------|------|----------|---------|-------------|\n| `userId` | string | Yes | - | User ID performing the upload (for audit) |\n| `systemName` | string | Yes | - | External system name (e.g., \"Salesforce\") |\n| `systemId` | string | Yes | - | System instance ID (e.g., Org ID) |\n| `referenceType` | string | Yes | - | Type of reference (e.g., \"AccountId\") |\n| `externalId` | string | Yes | - | ID in the external system |\n| `expirationMinutes` | int | No | 15 | Token validity in minutes (max: 30) |\n\n---\n\n## Example Request\n\n```json\n{\n  \"userId\": \"0051234567890ABC\",\n  \"systemName\": \"Salesforce\",\n  \"systemId\": \"00D5g00000Xyz123\",\n  \"referenceType\": \"AccountId\",\n  \"externalId\": \"001XXXXXXXXXXXXXXX\",\n  \"expirationMinutes\": 15\n}\n```\n\n## Response\n\n```json\n{\n  \"success\": true,\n  \"token\": \"a1b2c3d4e5f6...\",\n  \"expiresAt\": \"2025-01-15T14:30:00Z\",\n  \"expiresInSeconds\": 900\n}\n```\n\n---\n\n## Important Notes\n\n- **Token is shown only once** - store it securely!\n- **Single use** - token is consumed on successful upload\n- **Time limited** - maximum 30 minutes validity\n- **Pre-configured reference** - the external reference is embedded in the token\n\n---\n\n## Usage Flow\n\n1. Backend generates token (this endpoint)\n2. Backend passes token to frontend\n3. Frontend uploads file with `X-Upload-Token` header\n4. Token is consumed, document is created\n\n---\n\n## Error Codes\n\n| Code | Description |\n|------|-------------|\n| INVALID_EXPIRATION | Expiration time exceeds maximum (30 min) |\n| GENERATION_FAILED | Token generation failed |",
        "operationId": "GenerateUploadToken",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerateUploadTokenRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateUploadTokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Upload Tokens"
        ],
        "summary": "List Upload Tokens",
        "description": "## List Upload Tokens\n\nList all upload tokens created by the authenticated client.\n\n---\n\n## Query Parameters\n\n| Parameter | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `includeUsed` | bool | false | Include used tokens in the list |\n| `includeExpired` | bool | false | Include expired tokens in the list |\n\n---\n\n## Response\n\n```json\n{\n  \"tokens\": [\n    {\n      \"tokenPrefix\": \"a1b2c3d4\",\n      \"status\": \"valid\",\n      \"userId\": \"0051234567890ABC\",\n      \"reference\": \"Salesforce/AccountId/001XXX\",\n      \"createdAt\": \"2025-01-15T14:15:00Z\",\n      \"expiresAt\": \"2025-01-15T14:30:00Z\",\n      \"usedAt\": null,\n      \"resultDocumentGuid\": null\n    }\n  ],\n  \"count\": 1\n}\n```",
        "operationId": "ListUploadTokens",
        "parameters": [
          {
            "name": "includeUsed",
            "in": "query",
            "required": true,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "includeExpired",
            "in": "query",
            "required": true,
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListUploadTokensResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/upload-tokens/{token}/status": {
      "get": {
        "tags": [
          "Upload Tokens"
        ],
        "summary": "Get Upload Token Status",
        "description": "## Get Upload Token Status\n\nRetrieve the current status of an upload token. Only the client that created the token can view its status.\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `token` | string | The full upload token |\n\n---\n\n## Response\n\n```json\n{\n  \"tokenPrefix\": \"a1b2c3d4\",\n  \"status\": \"valid\",\n  \"userId\": \"0051234567890ABC\",\n  \"systemName\": \"Salesforce\",\n  \"systemId\": \"00D5g00000Xyz123\",\n  \"referenceType\": \"AccountId\",\n  \"externalId\": \"001XXXXXXXXXXXXXXX\",\n  \"createdAt\": \"2025-01-15T14:15:00Z\",\n  \"expiresAt\": \"2025-01-15T14:30:00Z\",\n  \"usedAt\": null,\n  \"resultDocumentGuid\": null\n}\n```\n\n---\n\n## Token Statuses\n\n| Status | Description |\n|--------|-------------|\n| `valid` | Token can be used for upload |\n| `used` | Token has been consumed for an upload |\n| `expired` | Token validity period has passed |\n| `revoked` | Token was manually revoked |",
        "operationId": "GetUploadTokenStatus",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadTokenStatusResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/upload-tokens/{token}": {
      "delete": {
        "tags": [
          "Upload Tokens"
        ],
        "summary": "Revoke Upload Token",
        "description": "## Revoke Upload Token\n\nRevoke an upload token before it expires or is used. Only the client that created the token can revoke it.\n\n---\n\n## Path Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `token` | string | The full upload token |\n\n---\n\n## Response (200 OK)\n\n```json\n{\n  \"message\": \"Token revoked successfully\"\n}\n```\n\n---\n\n## Notes\n\n- Revocation is immediate\n- Already used tokens cannot be revoked\n- Revoked tokens return 401 Unauthorized when used",
        "operationId": "RevokeUploadToken",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AccountUsageResponse": {
        "type": "object",
        "properties": {
          "license": {
            "$ref": "#/components/schemas/LicenseInfo"
          },
          "usage": {
            "$ref": "#/components/schemas/UsageInfo"
          },
          "capacity": {
            "$ref": "#/components/schemas/CapacityInfo"
          }
        }
      },
      "AddKeySlotRequest": {
        "type": "object",
        "properties": {
          "newKey": {
            "type": "string",
            "nullable": true
          },
          "newKeyType": {
            "type": "string",
            "nullable": true
          },
          "publicKey": {
            "type": "string",
            "nullable": true
          },
          "label": {
            "maxLength": 200,
            "type": "string",
            "nullable": true
          }
        }
      },
      "AddKeySlotResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "documentGuid": {
            "type": "string",
            "format": "uuid"
          },
          "keySlot": {
            "$ref": "#/components/schemas/DocumentKeySlotDetail2"
          },
          "totalKeySlots": {
            "type": "integer",
            "format": "int32"
          },
          "errorCode": {
            "type": "string",
            "nullable": true
          },
          "retryAfterSeconds": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          }
        }
      },
      "ApiClientDetail": {
        "type": "object",
        "properties": {
          "guid": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "isActive": {
            "type": "boolean"
          },
          "isMaster": {
            "type": "boolean"
          },
          "hasApiKey": {
            "type": "boolean"
          },
          "azureAdClientId": {
            "type": "string",
            "nullable": true
          },
          "certificateThumbprint": {
            "type": "string",
            "nullable": true
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdBy": {
            "type": "string",
            "nullable": true
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "modifiedBy": {
            "type": "string",
            "nullable": true
          },
          "lastAuthenticatedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "lastAuthenticatedFromIp": {
            "type": "string",
            "nullable": true
          },
          "permissions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClientPermissionInfo"
            }
          }
        },
        "nullable": true
      },
      "ApiClientOperationResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "ApiClientSummary": {
        "type": "object",
        "properties": {
          "guid": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "isActive": {
            "type": "boolean"
          },
          "isMaster": {
            "type": "boolean"
          },
          "hasApiKey": {
            "type": "boolean"
          },
          "hasAzureAd": {
            "type": "boolean"
          },
          "hasCertificate": {
            "type": "boolean"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastAuthenticatedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "permissionCount": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "ApiError": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "details": {
            "type": "string",
            "nullable": true
          },
          "validationErrors": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "nullable": true
          },
          "correlationId": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ApiErrorResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "default": false
          },
          "message": {
            "type": "string"
          },
          "error": {
            "$ref": "#/components/schemas/ApiError"
          }
        }
      },
      "AvailablePermissionsResponse": {
        "type": "object",
        "properties": {
          "permissions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PermissionDefinition"
            }
          }
        }
      },
      "BackupStatusResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "errorMessage": {
            "type": "string",
            "nullable": true
          },
          "storage": {
            "$ref": "#/components/schemas/StorageBackupStatus"
          },
          "database": {
            "$ref": "#/components/schemas/DatabaseBackupStatus"
          },
          "secrets": {
            "$ref": "#/components/schemas/SecretsBackupStatus"
          }
        },
        "nullable": true
      },
      "CapacityInfo": {
        "type": "object",
        "properties": {
          "documentsUsedPercent": {
            "type": "number",
            "format": "double"
          },
          "documentsRemaining": {
            "type": "integer",
            "format": "int32"
          },
          "storageUsedPercent": {
            "type": "number",
            "format": "double"
          },
          "storageRemainingBytes": {
            "type": "integer",
            "format": "int64"
          },
          "storageRemainingFormatted": {
            "type": "string"
          }
        }
      },
      "ChangesSummary": {
        "type": "object",
        "properties": {
          "updatedFields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FieldChange"
            }
          },
          "tagsAdded": {
            "type": "integer",
            "format": "int32"
          },
          "tagsRemoved": {
            "type": "integer",
            "format": "int32"
          },
          "referencesAdded": {
            "type": "integer",
            "format": "int32"
          },
          "referencesRemoved": {
            "type": "integer",
            "format": "int32"
          },
          "commonReferencesAdded": {
            "type": "integer",
            "format": "int32"
          },
          "commonReferencesRemoved": {
            "type": "integer",
            "format": "int32"
          },
          "primaryReferenceChanged": {
            "type": "boolean"
          },
          "totalChanges": {
            "type": "integer",
            "format": "int32"
          }
        },
        "nullable": true
      },
      "ClientPermissionInfo": {
        "type": "object",
        "properties": {
          "guid": {
            "type": "string",
            "format": "uuid"
          },
          "permission": {
            "type": "string"
          },
          "systemFilter": {
            "type": "string",
            "nullable": true
          },
          "grantedAt": {
            "type": "string",
            "format": "date-time"
          },
          "grantedBy": {
            "type": "string",
            "nullable": true
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "CommonReferenceDto": {
        "required": [
          "type",
          "value"
        ],
        "type": "object",
        "properties": {
          "type": {
            "maxLength": 100,
            "type": "string"
          },
          "value": {
            "maxLength": 500,
            "type": "string"
          },
          "label": {
            "maxLength": 500,
            "type": "string",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "nullable": true
          },
          "systems": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SystemReferenceDto"
            },
            "nullable": true
          },
          "allowCrossClientSharing": {
            "type": "boolean"
          }
        }
      },
      "CommonReferenceIdentifier": {
        "required": [
          "type",
          "value"
        ],
        "type": "object",
        "properties": {
          "type": {
            "maxLength": 100,
            "type": "string"
          },
          "value": {
            "maxLength": 500,
            "type": "string"
          }
        }
      },
      "CommonReferenceInfo": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string"
          },
          "value": {
            "type": "string"
          },
          "label": {
            "type": "string",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "nullable": true
          },
          "systems": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SystemReferenceInfo"
            },
            "nullable": true
          },
          "allowCrossClientSharing": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdBy": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ComponentHealth": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "responseTimeMs": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ConfigurationHealth": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "azureAdEnabled": {
            "type": "boolean"
          },
          "adminApiEnabled": {
            "type": "boolean"
          },
          "apiKeyEnabled": {
            "type": "boolean"
          }
        }
      },
      "ConversionInfo": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "convertedFileName": {
            "type": "string",
            "nullable": true
          },
          "convertedContentType": {
            "type": "string",
            "nullable": true
          },
          "convertedFileSize": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "errorMessage": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "CreateApiClientResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "clientGuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "apiKey": {
            "type": "string",
            "nullable": true
          },
          "keyVaultSecretName": {
            "type": "string",
            "nullable": true
          },
          "keyVaultUri": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "CreateClientRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "generateApiKey": {
            "type": "boolean"
          },
          "azureAdClientId": {
            "type": "string",
            "nullable": true
          },
          "certificateThumbprint": {
            "type": "string",
            "nullable": true
          },
          "isActive": {
            "type": "boolean"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "permissions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PermissionGrant"
            },
            "nullable": true
          },
          "keyVaultStorage": {
            "$ref": "#/components/schemas/KeyVaultStorageOption"
          },
          "azureAdClientSecret": {
            "type": "string",
            "nullable": true
          },
          "azureAdScope": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "CreateDocumentLinkResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "downloadUrl": {
            "type": "string",
            "nullable": true
          },
          "token": {
            "type": "string",
            "nullable": true
          },
          "link": {
            "$ref": "#/components/schemas/LinkInfo"
          },
          "availableVersions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VersionLinkInfo"
            },
            "nullable": true
          }
        }
      },
      "CreateLinkApiRequest": {
        "type": "object",
        "properties": {
          "versionNumber": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "expireUnit": {
            "type": "string",
            "nullable": true
          },
          "expireValue": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "isOneTimeLink": {
            "type": "boolean",
            "nullable": true
          },
          "maxDownloads": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "allowedIpRange": {
            "type": "string",
            "nullable": true
          },
          "password": {
            "type": "string",
            "nullable": true
          },
          "createdBy": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "CreateOAuth2ClientRequest": {
        "type": "object",
        "properties": {
          "clientId": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "clientSecret": {
            "type": "string",
            "nullable": true
          },
          "grantTypes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "permissions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "CreateOAuth2ClientResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "guid": {
            "type": "string",
            "format": "uuid"
          },
          "clientId": {
            "type": "string"
          },
          "clientSecret": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "grantTypes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "apiClientGuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "warning": {
            "type": "string"
          }
        }
      },
      "DatabaseBackupStatus": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "errorMessage": {
            "type": "string",
            "nullable": true
          },
          "automaticBackupsEnabled": {
            "type": "boolean"
          },
          "retentionDays": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "pointInTimeRestoreEnabled": {
            "type": "boolean"
          },
          "earliestRestorePoint": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "nullable": true
      },
      "DeactivateLinkResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "linkId": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          }
        }
      },
      "DeleteDocumentResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "deletion": {
            "$ref": "#/components/schemas/DeletionInfo"
          },
          "errorCode": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "DeleteKeySlotResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "documentGuid": {
            "type": "string",
            "format": "uuid"
          },
          "slotId": {
            "type": "string",
            "format": "uuid"
          },
          "remainingKeySlots": {
            "type": "integer",
            "format": "int32"
          },
          "errorCode": {
            "type": "string",
            "nullable": true
          },
          "retryAfterSeconds": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          }
        }
      },
      "DeleteOAuth2ClientResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "DeletionInfo": {
        "type": "object",
        "properties": {
          "documentGuid": {
            "type": "string",
            "format": "uuid"
          },
          "fileName": {
            "type": "string"
          },
          "isPermanent": {
            "type": "boolean"
          },
          "deletedAt": {
            "type": "string",
            "format": "date-time"
          },
          "deletedBy": {
            "type": "string"
          },
          "permanentDeletionAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "versionsAffected": {
            "type": "integer",
            "format": "int32"
          },
          "referencesAffected": {
            "type": "integer",
            "format": "int32"
          },
          "linksInvalidated": {
            "type": "integer",
            "format": "int32"
          }
        },
        "nullable": true
      },
      "DocumentDetailInfo": {
        "type": "object",
        "properties": {
          "documentGuid": {
            "type": "string",
            "format": "uuid"
          },
          "fileName": {
            "type": "string"
          },
          "displayName": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "contentType": {
            "type": "string"
          },
          "fileExtension": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "groupTag": {
            "type": "string",
            "nullable": true
          },
          "classification": {
            "type": "string"
          },
          "isEncrypted": {
            "type": "boolean"
          },
          "encryptionMode": {
            "type": "string"
          },
          "hasEncryptedDescription": {
            "type": "boolean"
          },
          "keySlots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DocumentKeySlotInfo"
            }
          },
          "retentionPolicy": {
            "type": "string",
            "nullable": true
          },
          "retentionUntil": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "isArchived": {
            "type": "boolean"
          },
          "isDeleted": {
            "type": "boolean"
          },
          "currentVersion": {
            "$ref": "#/components/schemas/DocumentVersionDetail"
          },
          "versions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DocumentVersionDetail"
            }
          },
          "externalReferences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExternalReferenceInfo"
            }
          },
          "commonReferences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CommonReferenceInfo"
            }
          },
          "statistics": {
            "$ref": "#/components/schemas/DocumentStatisticsInfo"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdBy": {
            "type": "string",
            "nullable": true
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedBy": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "DocumentDetailInfo2": {
        "type": "object",
        "properties": {
          "documentGuid": {
            "type": "string",
            "format": "uuid"
          },
          "fileName": {
            "type": "string"
          },
          "displayName": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "contentType": {
            "type": "string"
          },
          "fileExtension": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "groupTag": {
            "type": "string",
            "nullable": true
          },
          "classification": {
            "type": "string"
          },
          "isEncrypted": {
            "type": "boolean"
          },
          "encryptionMode": {
            "type": "string"
          },
          "hasEncryptedDescription": {
            "type": "boolean"
          },
          "keySlots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DocumentKeySlotInfo"
            }
          },
          "retentionPolicy": {
            "type": "string",
            "nullable": true
          },
          "retentionUntil": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "isArchived": {
            "type": "boolean"
          },
          "isDeleted": {
            "type": "boolean"
          },
          "currentVersion": {
            "$ref": "#/components/schemas/DocumentVersionDetail"
          },
          "versions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DocumentVersionDetail"
            }
          },
          "externalReferences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExternalReferenceInfo"
            }
          },
          "commonReferences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CommonReferenceInfo"
            }
          },
          "statistics": {
            "$ref": "#/components/schemas/DocumentStatisticsInfo"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdBy": {
            "type": "string",
            "nullable": true
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedBy": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "DocumentEncryptionRequest": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "nullable": true
          },
          "key": {
            "type": "string",
            "nullable": true
          },
          "keyType": {
            "type": "string",
            "nullable": true
          },
          "keyLabel": {
            "maxLength": 200,
            "type": "string",
            "nullable": true
          },
          "acknowledgeNoRecovery": {
            "type": "boolean"
          }
        },
        "nullable": true
      },
      "DocumentFilter": {
        "type": "object",
        "properties": {
          "externalSystem": {
            "type": "string",
            "nullable": true
          },
          "externalId": {
            "type": "string",
            "nullable": true
          },
          "commonReferenceType": {
            "type": "string",
            "nullable": true
          },
          "commonReferenceValue": {
            "type": "string",
            "nullable": true
          },
          "classification": {
            "type": "string",
            "nullable": true
          },
          "isArchived": {
            "type": "boolean",
            "nullable": true
          },
          "isDeleted": {
            "type": "boolean",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "groupTag": {
            "type": "string",
            "nullable": true
          },
          "contentType": {
            "type": "string",
            "nullable": true
          },
          "fileNamePattern": {
            "type": "string",
            "nullable": true
          },
          "displayNamePattern": {
            "type": "string",
            "nullable": true
          },
          "createdFrom": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "createdTo": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "sortBy": {
            "type": "string",
            "nullable": true
          },
          "sortDirection": {
            "type": "string"
          }
        }
      },
      "DocumentFilterResult": {
        "type": "object",
        "properties": {
          "documents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DocumentDetailInfo2"
            }
          },
          "totalCount": {
            "type": "integer",
            "format": "int32"
          },
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "format": "int32"
          },
          "hasNextPage": {
            "type": "boolean"
          },
          "hasPreviousPage": {
            "type": "boolean"
          }
        }
      },
      "DocumentInfo": {
        "type": "object",
        "properties": {
          "documentGuid": {
            "type": "string",
            "format": "uuid"
          },
          "fileName": {
            "type": "string"
          },
          "displayName": {
            "type": "string",
            "nullable": true
          },
          "groupTag": {
            "type": "string",
            "nullable": true
          },
          "contentType": {
            "type": "string"
          },
          "fileSize": {
            "type": "integer",
            "format": "int64"
          },
          "checksum": {
            "type": "string",
            "nullable": true
          },
          "version": {
            "$ref": "#/components/schemas/VersionInfo"
          },
          "externalReferences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExternalReferenceInfo"
            }
          },
          "commonReferences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CommonReferenceInfo"
            }
          },
          "conversion": {
            "$ref": "#/components/schemas/ConversionInfo"
          },
          "isEncrypted": {
            "type": "boolean"
          },
          "encryptionMode": {
            "type": "string"
          },
          "keySlots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DocumentKeySlotInfo"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdBy": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "DocumentKeySlotDetail": {
        "type": "object",
        "properties": {
          "lastUsedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "keyFingerprint": {
            "type": "string",
            "nullable": true
          },
          "keyAlgorithm": {
            "type": "string",
            "nullable": true
          },
          "slotId": {
            "type": "string",
            "format": "uuid"
          },
          "label": {
            "type": "string",
            "nullable": true
          },
          "slotType": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "DocumentKeySlotDetail2": {
        "type": "object",
        "properties": {
          "lastUsedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "keyFingerprint": {
            "type": "string",
            "nullable": true
          },
          "keyAlgorithm": {
            "type": "string",
            "nullable": true
          },
          "slotId": {
            "type": "string",
            "format": "uuid"
          },
          "label": {
            "type": "string",
            "nullable": true
          },
          "slotType": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "nullable": true
      },
      "DocumentKeySlotInfo": {
        "type": "object",
        "properties": {
          "slotId": {
            "type": "string",
            "format": "uuid"
          },
          "label": {
            "type": "string",
            "nullable": true
          },
          "slotType": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "DocumentLinkConfigResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "baseDownloadUrl": {
            "type": "string"
          },
          "defaultExpirationDays": {
            "type": "integer",
            "format": "int32"
          },
          "maxExpirationDays": {
            "type": "integer",
            "format": "int32"
          },
          "maxUploadSize": {
            "type": "integer",
            "format": "int64"
          },
          "maxStreamUploadSize": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "DocumentStatisticsInfo": {
        "type": "object",
        "properties": {
          "totalDownloads": {
            "type": "integer",
            "format": "int32"
          },
          "totalPublicDownloads": {
            "type": "integer",
            "format": "int32"
          },
          "totalVersions": {
            "type": "integer",
            "format": "int32"
          },
          "totalShares": {
            "type": "integer",
            "format": "int32"
          },
          "lastDownloadAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "lastPublicDownloadAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "nullable": true
      },
      "DocumentSummaryInfo": {
        "type": "object",
        "properties": {
          "documentGuid": {
            "type": "string",
            "format": "uuid"
          },
          "fileName": {
            "type": "string"
          },
          "displayName": {
            "type": "string",
            "nullable": true
          },
          "contentType": {
            "type": "string"
          },
          "fileExtension": {
            "type": "string"
          },
          "classification": {
            "type": "string"
          },
          "currentVersionNumber": {
            "type": "integer",
            "format": "int32"
          },
          "fileSize": {
            "type": "integer",
            "format": "int64"
          },
          "isArchived": {
            "type": "boolean"
          },
          "matchingReferences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExternalReferenceInfo"
            }
          },
          "totalReferences": {
            "type": "integer",
            "format": "int32"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "DocumentVersionDetail": {
        "type": "object",
        "properties": {
          "versionNumber": {
            "type": "integer",
            "format": "int32"
          },
          "isCurrent": {
            "type": "boolean"
          },
          "fileSize": {
            "type": "integer",
            "format": "int64"
          },
          "checksum": {
            "type": "string",
            "nullable": true
          },
          "comment": {
            "type": "string",
            "nullable": true
          },
          "hasConvertedVersion": {
            "type": "boolean"
          },
          "convertedContentType": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdBy": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ExternalReferenceIdentifier": {
        "required": [
          "systemName",
          "systemId",
          "referenceType",
          "externalId"
        ],
        "type": "object",
        "properties": {
          "systemName": {
            "maxLength": 50,
            "type": "string"
          },
          "systemId": {
            "maxLength": 200,
            "type": "string"
          },
          "referenceType": {
            "maxLength": 50,
            "type": "string"
          },
          "externalId": {
            "maxLength": 200,
            "type": "string"
          }
        }
      },
      "ExternalReferenceInfo": {
        "type": "object",
        "properties": {
          "systemName": {
            "type": "string"
          },
          "systemId": {
            "type": "string"
          },
          "referenceType": {
            "type": "string"
          },
          "externalId": {
            "type": "string"
          },
          "isPrimary": {
            "type": "boolean"
          }
        }
      },
      "ExternalReferenceRequest": {
        "required": [
          "systemName",
          "systemId",
          "referenceType",
          "externalId"
        ],
        "type": "object",
        "properties": {
          "systemName": {
            "maxLength": 50,
            "type": "string"
          },
          "systemId": {
            "maxLength": 200,
            "type": "string"
          },
          "referenceType": {
            "maxLength": 50,
            "type": "string"
          },
          "externalId": {
            "maxLength": 200,
            "type": "string"
          },
          "isPrimary": {
            "type": "boolean"
          },
          "autoVersioning": {
            "type": "boolean"
          },
          "metadata": {
            "type": "object",
            "nullable": true
          }
        }
      },
      "FieldChange": {
        "type": "object",
        "properties": {
          "fieldName": {
            "type": "string"
          },
          "oldValue": {
            "type": "string",
            "nullable": true
          },
          "newValue": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "GenerateUploadTokenRequest": {
        "required": [
          "userId",
          "systemName",
          "systemId",
          "referenceType",
          "externalId"
        ],
        "type": "object",
        "properties": {
          "userId": {
            "maxLength": 255,
            "type": "string"
          },
          "systemName": {
            "maxLength": 100,
            "type": "string"
          },
          "systemId": {
            "maxLength": 100,
            "type": "string"
          },
          "referenceType": {
            "maxLength": 100,
            "type": "string"
          },
          "externalId": {
            "maxLength": 255,
            "type": "string"
          },
          "expirationMinutes": {
            "maximum": 30,
            "minimum": 1,
            "type": "integer",
            "format": "int32",
            "nullable": true
          }
        }
      },
      "GenerateUploadTokenResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "token": {
            "type": "string",
            "nullable": true
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "expiresInSeconds": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "errorCode": {
            "type": "string",
            "nullable": true
          },
          "errorMessage": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "GetApiClientResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "client": {
            "$ref": "#/components/schemas/ApiClientDetail"
          }
        }
      },
      "GetApiKeyResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "clientGuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "clientName": {
            "type": "string",
            "nullable": true
          },
          "apiKey": {
            "type": "string",
            "nullable": true
          },
          "keyVaultSecretName": {
            "type": "string",
            "nullable": true
          },
          "keyVaultUri": {
            "type": "string",
            "nullable": true
          },
          "warning": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "GetDocumentLinksResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "documentGuid": {
            "type": "string",
            "format": "uuid"
          },
          "fileName": {
            "type": "string",
            "nullable": true
          },
          "totalCount": {
            "type": "integer",
            "format": "int32"
          },
          "activeCount": {
            "type": "integer",
            "format": "int32"
          },
          "links": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LinkInfo2"
            }
          }
        }
      },
      "GetDocumentResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "document": {
            "$ref": "#/components/schemas/DocumentDetailInfo"
          },
          "errorCode": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "GetDocumentsByReferenceResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "searchParams": {
            "$ref": "#/components/schemas/ReferenceSearchParams"
          },
          "documents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DocumentSummaryInfo"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationInfo"
          },
          "errorCode": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "GetKeySlotsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "documentGuid": {
            "type": "string",
            "format": "uuid"
          },
          "keySlots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DocumentKeySlotDetail"
            }
          },
          "errorCode": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "GetOAuth2ClientResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "client": {
            "$ref": "#/components/schemas/OAuth2ClientSummary"
          }
        }
      },
      "GrantPermissionRequest": {
        "type": "object",
        "properties": {
          "permission": {
            "type": "string"
          },
          "systemFilter": {
            "type": "string",
            "nullable": true
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "GrantPermissionResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "permission": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "HealthCheckResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "totalResponseTimeMs": {
            "type": "number",
            "format": "double"
          },
          "checks": {
            "$ref": "#/components/schemas/HealthChecks"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          }
        }
      },
      "HealthChecks": {
        "type": "object",
        "properties": {
          "database": {
            "$ref": "#/components/schemas/ComponentHealth"
          },
          "storage": {
            "$ref": "#/components/schemas/ComponentHealth"
          },
          "configuration": {
            "$ref": "#/components/schemas/ConfigurationHealth"
          }
        }
      },
      "KeyVaultStorageOption": {
        "type": "object",
        "properties": {
          "storeInKeyVault": {
            "type": "boolean"
          },
          "secretName": {
            "type": "string",
            "nullable": true
          },
          "keyVaultUri": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "LicenseInfo": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string"
          },
          "limits": {
            "$ref": "#/components/schemas/LicenseLimits"
          }
        }
      },
      "LicenseLimits": {
        "type": "object",
        "properties": {
          "maxDocuments": {
            "type": "integer",
            "format": "int32"
          },
          "maxStorageBytes": {
            "type": "integer",
            "format": "int64"
          },
          "maxStorageFormatted": {
            "type": "string"
          }
        }
      },
      "LinkInfo": {
        "type": "object",
        "properties": {
          "linkId": {
            "type": "integer",
            "format": "int32"
          },
          "documentGuid": {
            "type": "string",
            "format": "uuid"
          },
          "fileName": {
            "type": "string"
          },
          "versionNumber": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "expireAt": {
            "type": "string",
            "format": "date-time"
          },
          "isOneTimeLink": {
            "type": "boolean"
          },
          "maxDownloads": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "downloadCount": {
            "type": "integer",
            "format": "int32"
          },
          "hasPassword": {
            "type": "boolean"
          },
          "allowedIpRange": {
            "type": "string",
            "nullable": true
          },
          "isActive": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdBy": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "LinkInfo2": {
        "type": "object",
        "properties": {
          "linkId": {
            "type": "integer",
            "format": "int32"
          },
          "documentGuid": {
            "type": "string",
            "format": "uuid"
          },
          "fileName": {
            "type": "string"
          },
          "versionNumber": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "expireAt": {
            "type": "string",
            "format": "date-time"
          },
          "isOneTimeLink": {
            "type": "boolean"
          },
          "maxDownloads": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "downloadCount": {
            "type": "integer",
            "format": "int32"
          },
          "hasPassword": {
            "type": "boolean"
          },
          "allowedIpRange": {
            "type": "string",
            "nullable": true
          },
          "isActive": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdBy": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ListApiClientsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "clients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiClientSummary"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/PaginationInfo"
          }
        }
      },
      "ListOAuth2ClientsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "clients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OAuth2ClientSummary"
            }
          },
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "totalCount": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "ListUploadTokensResponse": {
        "type": "object",
        "properties": {
          "tokens": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UploadTokenListItem"
            }
          },
          "count": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "LivenessResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "OAuth2ClientSummary": {
        "type": "object",
        "properties": {
          "guid": {
            "type": "string",
            "format": "uuid"
          },
          "clientId": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "isActive": {
            "type": "boolean"
          },
          "grantTypes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "apiClientGuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdBy": {
            "type": "string"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "modifiedBy": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "OAuth2ErrorResponse": {
        "required": [
          "error"
        ],
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "errorDescription": {
            "type": "string",
            "nullable": true
          },
          "errorUri": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "OAuth2IntrospectionResponse": {
        "type": "object",
        "properties": {
          "active": {
            "type": "boolean"
          },
          "scope": {
            "type": "string",
            "nullable": true
          },
          "clientId": {
            "type": "string",
            "nullable": true
          },
          "username": {
            "type": "string",
            "nullable": true
          },
          "tokenType": {
            "type": "string",
            "nullable": true
          },
          "exp": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "iat": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "nbf": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "sub": {
            "type": "string",
            "nullable": true
          },
          "aud": {
            "type": "string",
            "nullable": true
          },
          "iss": {
            "type": "string",
            "nullable": true
          },
          "jti": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "OAuth2TokenResponse": {
        "required": [
          "accessToken"
        ],
        "type": "object",
        "properties": {
          "accessToken": {
            "type": "string"
          },
          "tokenType": {
            "type": "string"
          },
          "expiresIn": {
            "type": "integer",
            "format": "int32"
          },
          "refreshToken": {
            "type": "string",
            "nullable": true
          },
          "scope": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "PaginationInfo": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "totalCount": {
            "type": "integer",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "format": "int32"
          },
          "hasNextPage": {
            "type": "boolean"
          },
          "hasPreviousPage": {
            "type": "boolean"
          }
        }
      },
      "PermissionDefinition": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "category": {
            "type": "string"
          }
        }
      },
      "PermissionGrant": {
        "type": "object",
        "properties": {
          "permission": {
            "type": "string"
          },
          "systemFilter": {
            "type": "string",
            "nullable": true
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "ReadinessResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "reason": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ReferenceSearchParams": {
        "type": "object",
        "properties": {
          "systemName": {
            "type": "string"
          },
          "systemId": {
            "type": "string"
          },
          "referenceType": {
            "type": "string",
            "nullable": true
          },
          "externalId": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "RevokePermissionResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "RotateApiKeyResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "newApiKey": {
            "type": "string",
            "nullable": true
          },
          "keyVaultSecretName": {
            "type": "string",
            "nullable": true
          },
          "keyVaultUri": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "RotateOAuth2ClientSecretRequest": {
        "type": "object",
        "properties": {
          "newClientSecret": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "RotateOAuth2ClientSecretResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "clientSecret": {
            "type": "string"
          },
          "warning": {
            "type": "string"
          }
        }
      },
      "RuntimeComponentValidation": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "tested": {
            "type": "boolean"
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "providerName": {
            "type": "string",
            "nullable": true
          },
          "details": {
            "type": "object",
            "nullable": true
          }
        },
        "nullable": true
      },
      "RuntimeComponentValidation2": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "tested": {
            "type": "boolean"
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "providerName": {
            "type": "string",
            "nullable": true
          },
          "details": {
            "$ref": "#/components/schemas/#/properties/storage/properties/details"
          }
        },
        "nullable": true
      },
      "SecretReferencesValidation": {
        "type": "object",
        "properties": {
          "allSecretsExist": {
            "type": "boolean"
          },
          "totalReferences": {
            "type": "integer",
            "format": "int32"
          },
          "existingSecrets": {
            "type": "integer",
            "format": "int32"
          },
          "missingSecrets": {
            "type": "integer",
            "format": "int32"
          },
          "missingSecretNames": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "nullable": true
      },
      "SecretsBackupStatus": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "errorMessage": {
            "type": "string",
            "nullable": true
          },
          "softDeleteEnabled": {
            "type": "boolean"
          },
          "softDeleteRetentionDays": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "purgeProtectionEnabled": {
            "type": "boolean"
          }
        },
        "nullable": true
      },
      "SetClientStatusRequest": {
        "type": "object",
        "properties": {
          "isActive": {
            "type": "boolean"
          }
        }
      },
      "SetPrimaryReferenceRequest": {
        "required": [
          "systemName",
          "systemId",
          "referenceType",
          "externalId"
        ],
        "type": "object",
        "properties": {
          "systemName": {
            "maxLength": 50,
            "type": "string"
          },
          "systemId": {
            "maxLength": 200,
            "type": "string"
          },
          "referenceType": {
            "maxLength": 50,
            "type": "string"
          },
          "externalId": {
            "maxLength": 200,
            "type": "string"
          }
        },
        "nullable": true
      },
      "StorageBackupStatus": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "errorMessage": {
            "type": "string",
            "nullable": true
          },
          "pointInTimeRestoreEnabled": {
            "type": "boolean"
          },
          "retentionDays": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "softDeleteEnabled": {
            "type": "boolean"
          },
          "softDeleteRetentionDays": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "versioningEnabled": {
            "type": "boolean"
          }
        },
        "nullable": true
      },
      "SystemReferenceDto": {
        "required": [
          "systemName",
          "systemId"
        ],
        "type": "object",
        "properties": {
          "systemName": {
            "maxLength": 50,
            "type": "string"
          },
          "systemId": {
            "maxLength": 200,
            "type": "string"
          }
        }
      },
      "SystemReferenceInfo": {
        "type": "object",
        "properties": {
          "systemName": {
            "type": "string"
          },
          "systemId": {
            "type": "string"
          }
        }
      },
      "SystemValidationResponse": {
        "type": "object",
        "properties": {
          "isValid": {
            "type": "boolean"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "validatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "durationMs": {
            "type": "integer",
            "format": "int64"
          },
          "storage": {
            "$ref": "#/components/schemas/RuntimeComponentValidation"
          },
          "secrets": {
            "$ref": "#/components/schemas/RuntimeComponentValidation2"
          },
          "secretReferences": {
            "$ref": "#/components/schemas/SecretReferencesValidation"
          },
          "backup": {
            "$ref": "#/components/schemas/BackupStatusResponse"
          }
        }
      },
      "UpdateClientRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "azureAdClientId": {
            "type": "string",
            "nullable": true
          },
          "certificateThumbprint": {
            "type": "string",
            "nullable": true
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "azureAdClientSecret": {
            "type": "string",
            "nullable": true
          },
          "azureAdScope": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "UpdatedDocumentInfo": {
        "type": "object",
        "properties": {
          "documentGuid": {
            "type": "string",
            "format": "uuid"
          },
          "isEncrypted": {
            "type": "boolean"
          },
          "encryptionMode": {
            "type": "string"
          },
          "fileName": {
            "type": "string"
          },
          "displayName": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "groupTag": {
            "type": "string",
            "nullable": true
          },
          "classification": {
            "type": "string"
          },
          "externalReferences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExternalReferenceInfo"
            }
          },
          "commonReferences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CommonReferenceInfo"
            }
          },
          "retentionPolicy": {
            "type": "string",
            "nullable": true
          },
          "retentionUntil": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "isArchived": {
            "type": "boolean"
          },
          "modifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedBy": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "UpdateDocumentRequest": {
        "type": "object",
        "properties": {
          "fileName": {
            "maxLength": 500,
            "type": "string",
            "nullable": true
          },
          "displayName": {
            "maxLength": 500,
            "type": "string",
            "nullable": true
          },
          "description": {
            "maxLength": 2000,
            "type": "string",
            "nullable": true
          },
          "addTags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "removeTags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "replaceTags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "groupTag": {
            "maxLength": 200,
            "type": "string",
            "nullable": true
          },
          "classification": {
            "type": "string",
            "nullable": true
          },
          "addExternalReferences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExternalReferenceRequest"
            },
            "nullable": true
          },
          "removeExternalReferences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExternalReferenceIdentifier"
            },
            "nullable": true
          },
          "setPrimaryReference": {
            "$ref": "#/components/schemas/SetPrimaryReferenceRequest"
          },
          "addCommonReferences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CommonReferenceDto"
            },
            "nullable": true
          },
          "removeCommonReferences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CommonReferenceIdentifier"
            },
            "nullable": true
          },
          "retentionPolicy": {
            "maxLength": 50,
            "type": "string",
            "nullable": true
          },
          "retentionUntil": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "isArchived": {
            "type": "boolean",
            "nullable": true
          },
          "modifiedBy": {
            "maxLength": 200,
            "type": "string",
            "nullable": true
          },
          "updateReason": {
            "maxLength": 500,
            "type": "string",
            "nullable": true
          }
        }
      },
      "UpdateDocumentResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "document": {
            "$ref": "#/components/schemas/UpdatedDocumentInfo"
          },
          "changes": {
            "$ref": "#/components/schemas/ChangesSummary"
          },
          "errorCode": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "UpdateOAuth2ClientRequest": {
        "type": "object",
        "properties": {
          "displayName": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "isActive": {
            "type": "boolean",
            "nullable": true
          },
          "grantTypes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "UpdateOAuth2ClientResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "UploadDocumentRequest": {
        "required": [
          "fileContentBase64",
          "fileName",
          "externalReferences"
        ],
        "type": "object",
        "properties": {
          "fileContentBase64": {
            "type": "string"
          },
          "fileName": {
            "maxLength": 500,
            "type": "string"
          },
          "documentGuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "versionComment": {
            "maxLength": 500,
            "type": "string",
            "nullable": true
          },
          "displayName": {
            "maxLength": 500,
            "type": "string",
            "nullable": true
          },
          "description": {
            "maxLength": 2000,
            "type": "string",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "groupTag": {
            "maxLength": 200,
            "type": "string",
            "nullable": true
          },
          "classification": {
            "type": "string",
            "nullable": true
          },
          "externalReferences": {
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExternalReferenceRequest"
            }
          },
          "commonReferences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CommonReferenceDto"
            },
            "nullable": true
          },
          "options": {
            "$ref": "#/components/schemas/UploadOptionsRequest"
          },
          "encryption": {
            "$ref": "#/components/schemas/DocumentEncryptionRequest"
          },
          "retentionPolicy": {
            "maxLength": 50,
            "type": "string",
            "nullable": true
          },
          "createdBy": {
            "maxLength": 200,
            "type": "string",
            "nullable": true
          }
        }
      },
      "UploadDocumentResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "document": {
            "$ref": "#/components/schemas/DocumentInfo"
          },
          "errorCode": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "UploadOptionsRequest": {
        "type": "object",
        "properties": {
          "convertToPdf": {
            "type": "boolean"
          },
          "generateChecksum": {
            "type": "boolean"
          },
          "blobContainer": {
            "maxLength": 100,
            "type": "string"
          },
          "contentType": {
            "maxLength": 100,
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "UploadTokenListItem": {
        "type": "object",
        "properties": {
          "tokenPrefix": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "userId": {
            "type": "string"
          },
          "reference": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "usedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "resultDocumentGuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          }
        }
      },
      "UploadTokenStatusResponse": {
        "type": "object",
        "properties": {
          "tokenPrefix": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "userId": {
            "type": "string"
          },
          "systemName": {
            "type": "string"
          },
          "systemId": {
            "type": "string"
          },
          "referenceType": {
            "type": "string"
          },
          "externalId": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "usedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "resultDocumentGuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          }
        }
      },
      "UsageInfo": {
        "type": "object",
        "properties": {
          "totalDocuments": {
            "type": "integer",
            "format": "int32"
          },
          "totalVersions": {
            "type": "integer",
            "format": "int32"
          },
          "totalStorageBytes": {
            "type": "integer",
            "format": "int64"
          },
          "totalStorageFormatted": {
            "type": "string"
          }
        }
      },
      "ValidateLinkResponse": {
        "type": "object",
        "properties": {
          "isValid": {
            "type": "boolean"
          },
          "documentGuid": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "fileName": {
            "type": "string",
            "nullable": true
          },
          "versionNumber": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "requiresPassword": {
            "type": "boolean"
          },
          "expireAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "remainingDownloads": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "message": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "VersionInfo": {
        "type": "object",
        "properties": {
          "versionNumber": {
            "type": "integer",
            "format": "int32"
          },
          "isNewDocument": {
            "type": "boolean"
          },
          "totalVersions": {
            "type": "integer",
            "format": "int32"
          },
          "comment": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "VersionLinkInfo": {
        "type": "object",
        "properties": {
          "versionNumber": {
            "type": "integer",
            "format": "int32"
          },
          "downloadUrl": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "comment": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WrappedDekResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "documentGuid": {
            "type": "string",
            "format": "uuid"
          },
          "slotId": {
            "type": "string",
            "format": "uuid"
          },
          "keyFingerprint": {
            "type": "string",
            "nullable": true
          },
          "keyAlgorithm": {
            "type": "string",
            "nullable": true
          },
          "algorithm": {
            "type": "string"
          },
          "wrappedDek": {
            "type": "string"
          },
          "nonce": {
            "type": "string"
          },
          "ephemeralPublicKey": {
            "type": "string",
            "nullable": true
          },
          "aad": {
            "type": "string"
          },
          "errorCode": {
            "type": "string",
            "nullable": true
          }
        }
      }
    },
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "description": "API Key authentication. Provide your API key in the 'X-API-Key' header.",
        "name": "X-API-Key",
        "in": "header"
      },
      "Bearer": {
        "type": "http",
        "description": "Azure AD / Entra ID Bearer Token. Format: 'Bearer {token}'",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    }
  },
  "security": [
    {
      "ApiKey": [ ]
    },
    {
      "Bearer": [ ]
    }
  ],
  "tags": [
    {
      "name": "System - Health"
    },
    {
      "name": "System - Configuration"
    },
    {
      "name": "Documents"
    },
    {
      "name": "Administration - Clients"
    },
    {
      "name": "Administration - Diagnostics"
    },
    {
      "name": "Account"
    },
    {
      "name": "Documents - Keys"
    },
    {
      "name": "Documents - Links"
    },
    {
      "name": "Download - Public"
    },
    {
      "name": "Authentication - OAuth2"
    },
    {
      "name": "Upload Tokens"
    }
  ]
}