{"openapi":"3.1.0","info":{"title":"doccape API","description":"Anonymize personal data in plain text and documents (PDF, DOC/DOCX, images).","contact":{"name":"Support","email":"doccape@scitlab.de"},"version":"1.0"},"servers":[{"url":"https://app.doccape.de/api","description":"Production / configured server"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Configuration","description":"Read upload/anonymization configuration and available text/image labels.\n\nUse these endpoints before uploading documents or calling the text API to discover valid label names and the active project configuration."},{"name":"Document Anonymization (Default Project)","description":"Upload, monitor, download, list, and delete documents under `/external/v1/documents/...`.\nUses the project resolved from the API key (project key → that project; user/org key → default project)."},{"name":"Document Anonymization (Project-scoped)","description":"Upload, monitor, download, list, and inspect documents under `/external/v1/projects/{projectId}/documents/...`.\nTargets an explicit project the credential is allowed to access."},{"name":"Projects","description":"Discover projects accessible with the current API key.\n\nUse project IDs from this list with the project-scoped document and configuration endpoints."},{"name":"Text","description":"Anonymize plain text in a single request.\n\nDiscover valid label names via `GET /external/v1/text-labels` before calling this endpoint."}],"paths":{"/external/v1/projects/{projectId}/documents":{"get":{"tags":["Document Anonymization (Project-scoped)"],"summary":"Find All Documents","description":"Returns a paginated list of documents in the project.\n\nAll filters are optional. Defaults: `page = 0`, `size = 20`.","operationId":"listProjectDocuments","parameters":[{"name":"projectId","in":"path","description":"ID of the project","required":true,"schema":{"type":"integer","format":"int64"},"example":1},{"name":"name","in":"query","description":"Filter by document name (substring match)","required":false,"schema":{"type":"string"},"example":"invoice"},{"name":"status","in":"query","description":"Filter by processing status","required":false,"schema":{"type":"string","enum":["COMPUTING_QUOTA","QUOTA_EXCEEDED","QUOTA_ERROR","UNPROCESSED","PROCESSING","COMPILING","ERROR","PREVIEW_ERROR","COMPLETED","FINALIZED","ARCHIVED"]}},{"name":"from","in":"query","description":"Only documents last modified at or after this timestamp (YYYY-MM-DDTHH:MM:SS)","required":false,"schema":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"example":"2024-01-01T00:00:00"},{"name":"to","in":"query","description":"Only documents last modified at or before this timestamp (YYYY-MM-DDTHH:MM:SS)","required":false,"schema":{"type":"string","format":"date-time","example":"2024-12-31T23:59:59"},"example":"2024-12-31T23:59:59"},{"name":"page","in":"query","description":"Zero-based page index","required":false,"schema":{"type":"integer","default":0,"example":0},"example":0},{"name":"size","in":"query","description":"Page size","required":false,"schema":{"type":"integer","default":20,"example":20},"example":20},{"name":"sort","in":"query","description":"Sort criteria as `fieldName=ASC` or `fieldName=DESC`. Sortable fields: `name`, `processingStatus`, `lastModified`, `createdAt`","required":false,"schema":{"type":"array","items":{"type":"string","example":"lastModified=DESC"}}},{"name":"tagKeyValues","in":"query","description":"Filter by tag key-value pairs (`key=value`)","required":false,"schema":{"type":"array","items":{"type":"string","example":"anonymousGroup=4711"}}}],"responses":{"200":{"description":"Paginated document overview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentOverviewPageDto"},"examples":{"Paginated documents":{"description":"Paginated documents","value":{"content":[{"id":42,"version":1,"projectId":1,"processingStatus":"COMPLETED","documentType":"PDF","fileSize":204800,"original":"invoice.pdf","anonymized":"invoice_anonymized.pdf","tags":[],"createdAt":"2024-06-15T10:00:00Z","lastModified":"2024-06-15T10:31:00Z"}],"pageable":{"pageNumber":0,"pageSize":20},"totalElements":1,"totalPages":1,"number":0,"size":20,"first":true,"last":true}}}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Project not accessible","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Project not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}},"post":{"tags":["Document Anonymization (Project-scoped)"],"summary":"Upload Document","description":"Uploads a document as `multipart/form-data` to the given project for anonymization.\n\nUses the project's stored configuration (see `GET /external/v1/projects/{projectId}/config`). Returns a `documentId` for status checks and retrieval.","operationId":"uploadProjectDocument","parameters":[{"name":"projectId","in":"path","description":"ID of the target project","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"requestBody":{"description":"Multipart form with the document file part.","content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"Document file (PDF, DOC, DOCX, or image) to upload"}},"required":["file"]}}},"required":true},"responses":{"200":{"description":"Document accepted for processing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalDocumentTaskStatusDto"},"examples":{"Accepted":{"description":"Accepted","value":{"documentId":42,"status":"COMPUTING_QUOTA"}}}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Project not accessible, insufficient credits, or invalid license","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Project not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"413":{"description":"Uploaded file exceeds the maximum allowed size","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/external/v1/documents/default-config":{"get":{"tags":["Configuration"],"summary":"Get Default Project Config","description":"Returns the default upload configuration for the project resolved from the API key (default project for user/org keys, or the fixed project for a project key).\n\nThis config is applied by `POST /external/v1/documents/upload` when no `config` is sent in the body. You can also use it as a template when building a custom `config` override.","operationId":"getDefaultUploadConfig","responses":{"200":{"description":"Default upload configuration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalUploadConfigDto"},"examples":{"Default config":{"description":"Default config","value":{"textAnonymization":{"blacklist":[],"whitelist":[],"labelsConfig":[{"name":"PER","config":{"type":"FULL_PSEUDONYMIZATION","pseudonym":"PER"}}]},"imageAnonymization":{"labelsConfig":[{"name":"face","anonymizationType":"MASK"}]}}}}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Access denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/external/v1/documents/upload":{"post":{"tags":["Document Anonymization (Default Project)"],"summary":"Upload Document","description":"Uploads a document as a Base64 string for anonymization.\n\nOptionally pass a `config` object to override the default project configuration (text/image labels, whitelist, blacklist, etc.). Omit `config` to use the default config from `GET /external/v1/documents/default-config`.\n\n**Convert a file to Base64**\n- Windows (PowerShell): `[Convert]::ToBase64String([System.IO.File]::ReadAllBytes(\"C:\\path\\to\\your\\file\")) | Out-File -FilePath \"C:\\path\\to\\save\\fileBase64.txt\"`\n- Linux / macOS: `base64 -i \"path-to-your-file\" -o \"path-to-your-output-file\"`\n\nReturns a `documentId` and initial processing `status`. Poll status until a terminal status (`COMPLETED`, `ERROR`, or quota failure). If the status is `COMPLETED` then download the result. Suggested polling interval: 5-10 seconds.\n\nAccepted types: PDF, DOC, DOCX, and common image formats.","operationId":"uploadDefaultDocument","requestBody":{"description":"Base64-encoded document content and optional upload configuration.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalDocumentUploadDto"},"examples":{"Minimal upload":{"description":"Minimal upload","value":{"content":"<base64-encoded-pdf-or-image>"}},"Upload with full config":{"description":"Upload with full config","value":{"content":"<base64-encoded-pdf-or-image>","config":{"textAnonymization":{"blacklist":[{"value":"Acme Corp","labelName":"ORG"}],"whitelist":[{"value":"Berlin","labelName":"LOC"}],"labelsConfig":[{"name":"PER","config":{"type":"FULL_PSEUDONYMIZATION","pseudonym":"PER"}},{"name":"TEL","config":{"type":"PARTIAL_PSEUDONYMIZATION","pseudonym":"*","partialPseudonymizationStart":1,"partialPseudonymizationStop":-1,"useNumericPartialPseudonymization":true}},{"name":"DATE","config":{"type":"DATE_PSEUDONYMIZATION","pseudonym":"*","replaceDay":true,"replaceMonth":false,"replaceYear":true,"dateLocale":"DE","showWeekday":false}}]},"imageAnonymization":{"labelsConfig":[{"name":"face","anonymizationType":"MASK"}]}}}}}}},"required":true},"responses":{"200":{"description":"Document accepted for processing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalDocumentTaskStatusDto"},"examples":{"Accepted":{"description":"Accepted","value":{"documentId":42,"status":"COMPUTING_QUOTA"}}}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Insufficient credits, invalid license, or access denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"},"examples":{"Credit limit":{"description":"Credit limit","value":{"title":"Forbidden","status":403,"detail":"Credit limit exceeded","instance":"/api/external/v1/documents/upload","problemCode":"CREDIT_LIMIT_EXCEEDED"}}}}}},"422":{"description":"Invalid request body (e.g. missing content or invalid config)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"},"examples":{"Validation failed":{"description":"Validation failed","value":{"title":"Unprocessable Content","status":422,"detail":"content: must not be blank","instance":"/api/external/v1/documents/upload","problemCode":"VALIDATION_FAILED","errors":[{"field":"content","code":"NOT_BLANK","message":"must not be blank"}]}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"},"examples":{"Rate limited":{"description":"Rate limited","value":{"title":"Too Many Requests","status":429,"detail":"Rate limit exceeded","instance":"/api/external/v1/documents/upload","problemCode":"RATE_LIMIT_EXCEEDED"}}}}}}}}},"/external/v1/projects/{projectId}/documents/{documentId}/status":{"get":{"tags":["Document Anonymization (Project-scoped)"],"summary":"Get Document Status","description":"Returns the processing status of a document in the given project.\n\nDownload the result only after the status is `COMPLETED`. Poll every 5-10 seconds. Terminal statuses: `COMPLETED`, `ERROR`, `QUOTA_EXCEEDED` and `QUOTA_ERROR`.","operationId":"getProjectDocumentStatus","parameters":[{"name":"projectId","in":"path","description":"ID of the project","required":true,"schema":{"type":"integer","format":"int64"},"example":1},{"name":"documentId","in":"path","description":"ID of the document","required":true,"schema":{"type":"integer","format":"int64"},"example":42}],"responses":{"200":{"description":"Current processing status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalDocumentTaskStatusDto"},"examples":{"Processing":{"description":"Processing","value":{"documentId":42,"status":"PROCESSING"}},"Completed":{"description":"Completed","value":{"documentId":42,"status":"COMPLETED"}},"Error":{"description":"Error","value":{"documentId":42,"status":"ERROR"}}}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Project not accessible","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Project or document not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/external/v1/documents/{documentId}/status":{"get":{"tags":["Document Anonymization (Default Project)"],"summary":"Get Document Status","description":"Returns the processing status of a document previously uploaded via `POST /external/v1/documents/upload`.\n\nTypical statuses include `PROCESSING`, `COMPLETED`, and `ERROR`. Download the result only after the status is `COMPLETED`. Terminal statuses: `COMPLETED`, `ERROR`, and quota failure statuses.","operationId":"getDefaultDocumentStatus","parameters":[{"name":"documentId","in":"path","description":"ID of the uploaded document","required":true,"schema":{"type":"integer","format":"int64"},"example":42}],"responses":{"200":{"description":"Current processing status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalDocumentTaskStatusDto"},"examples":{"Processing":{"description":"Processing","value":{"documentId":42,"status":"PROCESSING"}},"Completed":{"description":"Completed","value":{"documentId":42,"status":"COMPLETED"}},"Error":{"description":"Error","value":{"documentId":42,"status":"ERROR"}}}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Access denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Document not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/external/v1/projects/{projectId}/config":{"get":{"tags":["Configuration"],"summary":"Get Project Config","description":"Returns the upload/anonymization configuration for the given project.\n\nThis config is used by `POST /external/v1/projects/{projectId}/documents` (multipart upload) and reflects the project's stored settings.","operationId":"getProjectUploadConfig","parameters":[{"name":"projectId","in":"path","description":"ID of the project","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"200":{"description":"Project upload configuration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalUploadConfigDto"},"examples":{"Project config":{"description":"Project config","value":{"textAnonymization":{"labelsConfig":[{"name":"PER","config":{"type":"FULL_PSEUDONYMIZATION","pseudonym":"PER"}}]},"imageAnonymization":{"labelsConfig":[{"name":"face","anonymizationType":"MASK"}]}}}}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Project not accessible","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Project not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/external/v1/projects/{projectId}/documents/{documentId}/result":{"get":{"tags":["Document Anonymization (Project-scoped)"],"summary":"Download Document","description":"Downloads the anonymized document as a binary file (`application/octet-stream`). A `Content-Disposition` header provides the suggested filename.\n\nCall this after status is `COMPLETED`.","operationId":"downloadProjectDocumentResult","parameters":[{"name":"projectId","in":"path","description":"ID of the project","required":true,"schema":{"type":"integer","format":"int64"},"example":1},{"name":"documentId","in":"path","description":"ID of the document to download","required":true,"schema":{"type":"integer","format":"int64"},"example":42}],"responses":{"200":{"description":"Anonymized document file. Includes `Content-Disposition` with the filename.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Project not accessible","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Project, document, or result file not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/external/v1/documents/{documentId}/result":{"get":{"tags":["Document Anonymization (Default Project)"],"summary":"Download Document","description":"Downloads the anonymized document as a binary file (`Content-Type: application/octet-stream`). A `Content-Disposition` header provides the suggested filename.\n\nCall this after `GET /external/v1/documents/{documentId}/status` reports `COMPLETED`.","operationId":"downloadDefaultDocumentResult","parameters":[{"name":"documentId","in":"path","description":"ID of the document to download","required":true,"schema":{"type":"integer","format":"int64"},"example":42}],"responses":{"200":{"description":"Anonymized document file. Includes `Content-Disposition` with the filename.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Access denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Document or result file not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/external/v1/text-labels":{"get":{"tags":["Configuration"],"summary":"Text Labels","description":"Returns the available text labels (e.g. `PER`, `STR`, `MAIL`) for the project resolved from the API key (default project for user/org keys, or the fixed project for a project key).\n\nUse these label names in:\n- `textLabels` on `POST /external/v1/text`\n- upload `config` overrides on `POST /external/v1/documents/upload`","operationId":"listTextLabels","responses":{"200":{"description":"Available text labels","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TextLabelConfigDto"}}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}}}}},"/external/v1/projects/{projectId}/documents/{documentId}/original":{"get":{"tags":["Document Anonymization (Project-scoped)"],"summary":"Download Original Document","description":"Downloads the original uploaded document as a binary file (`application/octet-stream`). A `Content-Disposition` header provides the suggested filename.\n\nOnly available when the project stores original documents. Otherwise the API responds with `403` and `problemCode` `NO_PII_STORED`.\n\nCall this after status is `COMPLETED` or `FINALIZED`.","operationId":"downloadProjectDocumentOriginal","parameters":[{"name":"projectId","in":"path","description":"ID of the project","required":true,"schema":{"type":"integer","format":"int64"},"example":1},{"name":"documentId","in":"path","description":"ID of the document to download","required":true,"schema":{"type":"integer","format":"int64"},"example":42}],"responses":{"200":{"description":"Original document file. Includes `Content-Disposition` with the filename.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Project not accessible, or the project does not store original documents (`problemCode` = `NO_PII_STORED`)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Project, document, or original file not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"422":{"description":"Document is not `COMPLETED` or `FINALIZED`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/external/v1/documents/{documentId}/original":{"get":{"tags":["Document Anonymization (Default Project)"],"summary":"Download Original Document","description":"Downloads the original uploaded document as a binary file (`Content-Type: application/octet-stream`). A `Content-Disposition` header provides the suggested filename.\n\nOnly available when the project stores original documents. Otherwise the API responds with `403` and `problemCode` `NO_PII_STORED`.\n\nCall this after `GET /external/v1/documents/{documentId}/status` reports `COMPLETED` or `FINALIZED`.","operationId":"downloadDefaultDocumentOriginal","parameters":[{"name":"documentId","in":"path","description":"ID of the document to download","required":true,"schema":{"type":"integer","format":"int64"},"example":42}],"responses":{"200":{"description":"Original document file. Includes `Content-Disposition` with the filename.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Access denied, or the project does not store original documents (`problemCode` = `NO_PII_STORED`)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Document or original file not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"422":{"description":"Document is not `COMPLETED` or `FINALIZED`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/external/v1/image-labels":{"get":{"tags":["Configuration"],"summary":"Image Labels","description":"Returns the available image labels (e.g. `face`, `text`) for the project resolved from the API key (default project for user/org keys, or the fixed project for a project key).\n\nUse these label names in the `imageAnonymization.labelsConfig` section of an upload `config`.","operationId":"listImageLabels","responses":{"200":{"description":"Available image labels from the model","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ImageLabelConfigDto"}}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}}}}},"/external/v1/projects/{projectId}/documents/{documentId}/result/piis":{"get":{"tags":["Document Anonymization (Project-scoped)"],"summary":"Get Document PIIs","description":"Returns the personally identifiable information (PII) detected in the document, including page-level detections.\n\nOnly available when the project is configured to disable document correction.Otherwise the API responds with `403`.\n","operationId":"getProjectDocumentPiis","parameters":[{"name":"projectId","in":"path","description":"ID of the project","required":true,"schema":{"type":"integer","format":"int64"},"example":1},{"name":"documentId","in":"path","description":"ID of the document","required":true,"schema":{"type":"integer","format":"int64"},"example":42}],"responses":{"200":{"description":"Detected PIIs for the document","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentPiisDto"},"examples":{"Document PIIs":{"description":"Document PIIs","value":{"documentId":42,"version":1,"documentName":"invoice.pdf","processingStatus":"COMPLETED","documentType":"PDF","lastFileModified":"2024-06-15T10:30:00Z","lastModified":"2024-06-15T10:31:00Z","pageData":[{"pageNum":1,"textData":{"paragraphId":1,"detections":{"tokens":[{"startChar":0,"endChar":7,"text":"Kompakt","hasWs":false},{"startChar":7,"endChar":8,"text":":","hasWs":true},{"startChar":9,"endChar":15,"text":"Angela","hasWs":true},{"startChar":16,"endChar":22,"text":"Scholz","hasWs":true},{"startChar":23,"endChar":26,"text":"aus","hasWs":true},{"startChar":27,"endChar":37,"text":"Geheimdorf","hasWs":false}],"ents":[{"startChar":9,"endChar":22,"tag":"PER","text":"Angela Scholz","score":0.9999998807907104,"startTok":2,"endTok":3},{"startChar":27,"endChar":37,"tag":"LOC","text":"Geheimdorf","score":0.9999985694885254,"startTok":5,"endTok":5}],"sentenceStarts":[0,7,11],"pseudonyms":["PER-1","LOC-1"],"crIds":[1,1],"locationsInAnonymizedDocument":[{"x0":57,"y0":70,"x1":86,"y1":82},{"x0":107,"y0":70,"x1":139,"y1":82}],"locationsInOriginalDocument":[]}},"imagesData":[{"imageUrl":"https://app.doccape.de/api/projects/1/documents/42/images/1/1/image_file","xref":1,"detections":[{"label":"text","bboxs":[[[363.0,130.0],[499.0,130.0],[498.0,183.0],[363.0,184.0]]],"scores":[0.0]}]}]}]}}}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Project not accessible or PII storage disabled for the project","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Project or document not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/external/v1/documents/{documentId}/result/piis":{"get":{"tags":["Document Anonymization (Default Project)"],"summary":"Get Document PIIs","description":"Returns the personally identifiable information (PII) detected in the document, including page-level detections.\n\nThe document must belong to the project resolved from the API key (project key → that project; user/org key → default project).\n\nOnly available when the project is configured to disable document correction.Otherwise the API responds with `403`.\n","operationId":"getDefaultDocumentPiis","parameters":[{"name":"documentId","in":"path","description":"ID of the document","required":true,"schema":{"type":"integer","format":"int64"},"example":42}],"responses":{"200":{"description":"Detected PIIs for the document","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentPiisDto"},"examples":{"Document PIIs":{"description":"Document PIIs","value":{"documentId":42,"version":1,"documentName":"invoice.pdf","processingStatus":"COMPLETED","documentType":"PDF","lastFileModified":"2024-06-15T10:30:00Z","lastModified":"2024-06-15T10:31:00Z","pageData":[{"pageNum":1,"textData":{"paragraphId":1,"detections":{"tokens":[{"startChar":0,"endChar":7,"text":"Kompakt","hasWs":false},{"startChar":7,"endChar":8,"text":":","hasWs":true},{"startChar":9,"endChar":15,"text":"Angela","hasWs":true},{"startChar":16,"endChar":22,"text":"Scholz","hasWs":true},{"startChar":23,"endChar":26,"text":"aus","hasWs":true},{"startChar":27,"endChar":37,"text":"Geheimdorf","hasWs":false}],"ents":[{"startChar":9,"endChar":22,"tag":"PER","text":"Angela Scholz","score":0.9999998807907104,"startTok":2,"endTok":3},{"startChar":27,"endChar":37,"tag":"LOC","text":"Geheimdorf","score":0.9999985694885254,"startTok":5,"endTok":5}],"sentenceStarts":[0,7,11],"pseudonyms":["PER-1","LOC-1"],"crIds":[1,1],"locationsInAnonymizedDocument":[{"x0":57,"y0":70,"x1":86,"y1":82},{"x0":107,"y0":70,"x1":139,"y1":82}],"locationsInOriginalDocument":[]}},"imagesData":[{"imageUrl":"https://app.doccape.de/api/projects/1/documents/42/images/1/1/image_file","xref":1,"detections":[{"label":"text","bboxs":[[[363.0,130.0],[499.0,130.0],[498.0,183.0],[363.0,184.0]]],"scores":[0.0]}]}]}]}}}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Access denied or PII storage disabled for the project","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Document not found in the resolved project","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/external/v1/projects/{projectId}/documents/{documentId}":{"delete":{"tags":["Document Anonymization (Project-scoped)"],"summary":"Delete Document","description":"Permanently deletes a processed document from the given project.\n\nRecommended after downloading the result when handling sensitive data.","operationId":"deleteProjectDocument","parameters":[{"name":"projectId","in":"path","description":"ID of the project","required":true,"schema":{"type":"integer","format":"int64"},"example":1},{"name":"documentId","in":"path","description":"ID of the document to delete","required":true,"schema":{"type":"integer","format":"int64"},"example":42}],"responses":{"200":{"description":"Document deleted"},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Project not accessible","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Project or document not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/external/v1/documents/{documentId}":{"delete":{"tags":["Document Anonymization (Default Project)"],"summary":"Delete Document","description":"Permanently deletes a processed document and its files from the server.\n\nRecommended after downloading the result when handling sensitive data.","operationId":"deleteDefaultDocument","parameters":[{"name":"documentId","in":"path","description":"ID of the document to delete","required":true,"schema":{"type":"integer","format":"int64"},"example":42}],"responses":{"200":{"description":"Document deleted"},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Access denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Document not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/external/v1/documents":{"get":{"tags":["Document Anonymization (Default Project)"],"summary":"Find All Documents","description":"Returns a paginated list of documents in the project resolved from the API key (project key → that project; user/org key → default project).\n\nAll filters are optional. Defaults: `page = 0`, `size = 20`.","operationId":"listDefaultDocuments","parameters":[{"name":"name","in":"query","description":"Filter by document name (substring match)","required":false,"schema":{"type":"string"},"example":"invoice"},{"name":"status","in":"query","description":"Filter by processing status","required":false,"schema":{"type":"string","enum":["COMPUTING_QUOTA","QUOTA_EXCEEDED","QUOTA_ERROR","UNPROCESSED","PROCESSING","COMPILING","ERROR","PREVIEW_ERROR","COMPLETED","FINALIZED","ARCHIVED"]}},{"name":"from","in":"query","description":"Only documents last modified at or after this timestamp (YYYY-MM-DDTHH:MM:SS)","required":false,"schema":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"example":"2024-01-01T00:00:00"},{"name":"to","in":"query","description":"Only documents last modified at or before this timestamp (YYYY-MM-DDTHH:MM:SS)","required":false,"schema":{"type":"string","format":"date-time","example":"2024-12-31T23:59:59"},"example":"2024-12-31T23:59:59"},{"name":"page","in":"query","description":"Zero-based page index","required":false,"schema":{"type":"integer","default":0,"example":0},"example":0},{"name":"size","in":"query","description":"Page size","required":false,"schema":{"type":"integer","default":20,"example":20},"example":20},{"name":"sort","in":"query","description":"Sort criteria as `fieldName=ASC` or `fieldName=DESC`. Sortable fields: `name`, `processingStatus`, `lastModified`, `createdAt`","required":false,"schema":{"type":"array","items":{"type":"string","example":"lastModified=DESC"}}},{"name":"tagKeyValues","in":"query","description":"Filter by tag key-value pairs (`key=value`)","required":false,"schema":{"type":"array","items":{"type":"string","example":"anonymousGroup=4711"}}}],"responses":{"200":{"description":"Paginated document overview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentOverviewPageDto"},"examples":{"Paginated documents":{"description":"Paginated documents","value":{"content":[{"id":42,"version":1,"projectId":1,"processingStatus":"COMPLETED","documentType":"PDF","fileSize":204800,"original":"invoice.pdf","anonymized":"invoice_anonymized.pdf","tags":[],"createdAt":"2024-06-15T10:00:00Z","lastModified":"2024-06-15T10:31:00Z"}],"pageable":{"pageNumber":0,"pageSize":20},"totalElements":1,"totalPages":1,"number":0,"size":20,"first":true,"last":true}}}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Access denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"404":{"description":"Resolved project not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/external/v1/text":{"post":{"tags":["Text"],"summary":"Anonymize plain text","description":"Processes plain text and returns the anonymized result plus detection metadata.\n\n- Set `usePseudonyms` to `true` to replace entities with stable labels (e.g. `PER-1`).\n- Set `usePseudonyms` to `false` (default) to suppress/redact entities.\n- `textLabels` must list the label names to apply (see `GET /external/v1/text-labels`).","operationId":"anonymizeText","requestBody":{"description":"Plain text and processing options.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TextDto"},"examples":{"Anonymize person and location":{"description":"Anonymize person and location","value":{"text":"My name is John Doe and I live in California. Contact me at john@doe.com","usePseudonyms":false,"textLabels":["PER","STR","MAIL"]}}}}},"required":true},"responses":{"200":{"description":"Text successfully processed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PseudonymizedTextDto"},"examples":{"Anonymized text":{"description":"Anonymized text","value":{"pseudonymizedText":"My name is *** and I live in ***. Contact me at ***","detection":{"tokenCount":14,"detections":[{"startChar":11,"stopChar":19,"label":"PER","text":"John Doe","pseudonym":null},{"startChar":34,"stopChar":44,"label":"STR","text":"California","pseudonym":null},{"startChar":60,"stopChar":72,"label":"MAIL","text":"john@doe.com","pseudonym":null}]}}}}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}},"403":{"description":"Insufficient credits, invalid license, or access denied","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"},"examples":{"Credit limit":{"description":"Credit limit","value":{"title":"Forbidden","status":403,"detail":"Insufficient credits","instance":"/api/external/v1/text","problemCode":"CREDIT_LIMIT_EXCEEDED"}}}}}},"422":{"description":"Invalid request body (e.g. blank text or empty textLabels)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"},"examples":{"Validation error":{"description":"Validation error","value":{"title":"Unprocessable Entity","status":422,"detail":"Validation failed","instance":"/api/external/v1/text","problemCode":"VALIDATION_FAILED","errors":[{"field":"text","code":"NotBlank","message":"must not be blank"}]}}}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}},"502":{"description":"Upstream text model unavailable","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetail"}}}}}}},"/external/v1/projects/me":{"get":{"tags":["Projects"],"summary":"Retrieve accessible projects","description":"Returns projects visible to the current credential:\n\n| Credential | Result |\n|---|---|\n| User API key | Projects the user is a member of in their organization |\n| Organization API key | All projects in the organization |\n| Project API key | The single project bound to the key |\n\nUse a returned project `id` as `{projectId}` in document and configuration endpoints.","operationId":"listAccessibleProjects","responses":{"200":{"description":"Projects accessible with the current credential","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectOverviewDto"}},"examples":{"Accessible projects":{"description":"Accessible projects","value":[{"id":1,"name":"Customer invoices","description":"Invoices for Q1","documentCount":12,"lastUpdatedDocumentDate":"2024-06-15T10:30:00Z","isTemporary":false,"deleteCompletedDocumentsAfterHours":24,"deleteNonCompletedDocumentsAfterHours":72,"isStoringPII":true,"orgId":7}]}}}}},"401":{"description":"Missing or invalid API key / credentials.\nOften an empty body. Some auth failures return `application/problem+json`\nwith `type`, `title`, `status`, and `detail` (no `instance` or `problemCode`).\n","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/AuthProblemDetail"}}}}}}}},"components":{"schemas":{"TextDto":{"type":"object","properties":{"text":{"type":"string","description":"The text you want to be anonymized","example":"My name is John Doe and I live in California. Contact me at john@doe.com","minLength":1},"usePseudonyms":{"type":"boolean","default":false,"description":"If true, entities are replaced with stable labels like PER-1 instead of being redacted","example":false},"textLabels":{"type":"array","description":"List of text labels to be anonymized. \nUse `/external/v1/text-labels` to get all available text labels of the current model.","example":["PER","STR","MAIL"],"items":{"type":"string"},"minItems":1}},"required":["text","textLabels"]},"DetectionDto":{"type":"object","description":"A single detected entity span in the input text.","properties":{"startChar":{"type":"integer","format":"int32","description":"Inclusive start character offset.","example":11},"stopChar":{"type":"integer","format":"int32","description":"Exclusive end character offset.","example":19},"label":{"type":"string","description":"Text label applied to the span.","example":"PER"},"text":{"type":"string","description":"Original matched text.","example":"John Doe"},"pseudonym":{"type":["string","null"],"description":"Replacement/pseudonym when usePseudonyms was true; otherwise often null or a mask.","example":"PER-1"}}},"PseudonymizedTextDto":{"type":"object","description":"Result of plain-text anonymization.","example":{"pseudonymizedText":"My name is *** and I live in ***. Contact me at ***","detection":{"tokenCount":14,"detections":[{"startChar":11,"stopChar":19,"label":"PER","text":"John Doe","pseudonym":null},{"startChar":34,"stopChar":44,"label":"STR","text":"California","pseudonym":null},{"startChar":60,"stopChar":72,"label":"MAIL","text":"john@doe.com","pseudonym":null}]}},"properties":{"pseudonymizedText":{"type":"string","description":"The processed text with entities redacted or replaced by stable labels","example":"My name is *** and I live in ***. Contact me at ***"},"detection":{"$ref":"#/components/schemas/TextDetectionDto","description":"Detection metadata for entities found in the input text"}},"required":["detection","pseudonymizedText"]},"TextDetectionDto":{"type":"object","description":"Detection metadata for entities found in anonymized text.","properties":{"detections":{"type":"array","description":"Detected entities with character offsets.","items":{"$ref":"#/components/schemas/DetectionDto"}},"tokenCount":{"type":"integer","format":"int32","description":"Number of tokens in the input text.","example":12}}},"AuthProblemDetail":{"type":"object","description":"Minimal problem details written by the authentication filter.\nNote: missing or invalid credentials often produce an empty 401 body instead.","properties":{"type":{"type":"string","description":"Problem type URI. Always `about:blank` for filter-written responses.","example":"about:blank"},"title":{"type":"string","description":"Short summary of the failure.","example":"Unauthorized"},"status":{"type":"integer","format":"int32","description":"HTTP status code.","example":401},"detail":{"type":"string","description":"Explanation of the authentication/authorization failure.","example":"API keys are only valid for external endpoints"}}},"ValidationFieldError":{"type":"object","description":"Field-level validation error.","properties":{"field":{"type":"string","description":"Name of the invalid field.","example":"textLabels"},"code":{"type":"string","description":"Machine-readable validation error code.","example":"NotEmpty"},"message":{"type":"string","description":"Human-readable validation message.","example":"must not be empty"}}},"ProblemDetail":{"type":"object","description":"RFC 7807 problem details from application error handling.\n`type` is usually omitted when it would be `about:blank`.\n`problemCode` and `errors` are only present for some error kinds.","properties":{"type":{"type":"string","format":"uri","description":"URI reference identifying the problem type. Usually omitted when it would be `about:blank`.","example":"about:blank"},"title":{"type":"string","description":"Short, human-readable summary of the problem type.","example":"Forbidden"},"status":{"type":"integer","format":"int32","description":"HTTP status code for this occurrence of the problem.","example":403},"detail":{"type":"string","description":"Human-readable explanation specific to this occurrence of the problem.","example":"Credit limit exceeded"},"instance":{"type":"string","format":"uri-reference","description":"URI reference identifying the specific occurrence (typically the request path).","example":"/api/external/v1/text"},"problemCode":{"type":"string","description":"Application-specific error code when available. Absent for generic errors.","enum":["DOCUMENT_TOO_BIG","INVALID_PATH_PARAM","INVALID_FILE","RATE_LIMIT_EXCEEDED","CREDIT_LIMIT_EXCEEDED","STORAGE_LIMIT_EXCEEDED","NO_PII_STORED","INVALID_LICENSE","NO_ACTIVE_LICENSE","TEXT_MODEL_UNAVAILABLE","VALIDATION_FAILED"],"example":"CREDIT_LIMIT_EXCEEDED"},"errors":{"type":"array","description":"Field-level validation errors. Present for validation failures (`problemCode` = `VALIDATION_FAILED`).","items":{"$ref":"#/components/schemas/ValidationFieldError"}}}},"ExternalDocumentTaskStatusDto":{"type":"object","description":"Document identifier and current processing status.","example":{"documentId":42,"status":"COMPLETED"},"properties":{"documentId":{"type":"integer","format":"int64","description":"ID of the uploaded document","example":42},"status":{"type":"string","description":"Current processing status. Download the result when this is COMPLETED. Terminal statuses include COMPLETED and ERROR (and quota failure statuses).","enum":["COMPUTING_QUOTA","QUOTA_EXCEEDED","QUOTA_ERROR","UNPROCESSED","PROCESSING","COMPILING","ERROR","PREVIEW_ERROR","COMPLETED","FINALIZED","ARCHIVED"],"example":"COMPLETED"}},"required":["documentId","status"]},"BlackListItem":{"type":"object","properties":{"value":{"type":"string","description":"The text element that should always be anonymized."},"labelName":{"type":"string","description":"The name of the text label that should be used to always anonymize the given value."}},"required":["labelName","value"]},"DatePseudonymizationConfig":{"type":"object","description":"Anonymize date components selectively. Wire JSON includes `type: DATE_PSEUDONYMIZATION`.","properties":{"pseudonym":{"type":"string","description":"The replacement text that replaces the original text."},"replaceDay":{"type":"boolean","description":"Boolean flag for replacing the day in a date with *."},"replaceMonth":{"type":"boolean","description":"Boolean flag for replacing the month in a date with *."},"replaceYear":{"type":"boolean","description":"Boolean flag for replacing the year in a date with *."},"dateLocale":{"type":"string","description":"Defines the date format.","enum":["AUTO","DE","EN","ISO"]},"showWeekday":{"type":"boolean","description":"Shows the weekday after the anonymized date. E.g.: **.10.****(Thu)"},"type":{"type":"string","description":"Discriminator value identifying this replacement configuration subtype.","enum":["DATE_PSEUDONYMIZATION"],"example":"DATE_PSEUDONYMIZATION"}},"required":["dateLocale","pseudonym","replaceDay","replaceMonth","replaceYear","showWeekday","type"]},"DocumentImageAnonymization":{"type":"object","description":"Image anonymization settings (image labels).","properties":{"labelsConfig":{"type":["array","null"],"description":"List of objects specifying the image labels and their corresponding configuration.","items":{"$ref":"#/components/schemas/ImageLabelConfig"}}}},"DocumentTextAnonymization":{"type":"object","description":"Text anonymization settings (labels, blacklist, whitelist).","properties":{"blacklist":{"type":["array","null"],"description":"List of text elements that should always be anonymized with a given text label.","items":{"$ref":"#/components/schemas/BlackListItem"}},"whitelist":{"type":["array","null"],"description":"List of text elements that should be displayed (not anonymized) if they are classified as the given text label.","items":{"$ref":"#/components/schemas/WhiteListItem"}},"labelsConfig":{"type":["array","null"],"description":"List of objects specifying the text labels and their corresponding configuration.","items":{"$ref":"#/components/schemas/TextLabelConfig"}}}},"ExternalDocumentUploadDto":{"type":"object","description":"Consists of the content as a base64 string and an optional upload config to customize anonymization.","properties":{"content":{"type":"string","description":"The base64 string of the document."},"config":{"$ref":"#/components/schemas/ExternalUploadConfigDto","description":"Optional configuration object that overrides the default configuration when anonymizing a document. It specifies among others the text and image labels to use or what terms should be white- or blacklisted."}},"required":["content"]},"ExternalUploadConfigDto":{"type":"object","description":"Optional configuration object that overrides the default configuration when anonymizing a document.","properties":{"textAnonymization":{"$ref":"#/components/schemas/DocumentTextAnonymization","description":"Configuration object for anonymizing text in the document. Optional — omit to leave text settings unchanged."},"imageAnonymization":{"$ref":"#/components/schemas/DocumentImageAnonymization","description":"Configuration object for anonymizing images. Optional — omit to leave image settings unchanged."}}},"FullPseudonymizationConfig":{"type":"object","description":"Replace the full matched text with a fixed replacement string. Wire JSON includes `type: FULL_PSEUDONYMIZATION` (from Jackson polymorphism).","properties":{"pseudonym":{"type":"string","description":"The replacement text that replaces the original text."},"type":{"type":"string","description":"Discriminator value identifying this replacement configuration subtype.","enum":["FULL_PSEUDONYMIZATION"],"example":"FULL_PSEUDONYMIZATION"}},"required":["pseudonym","type"]},"ImageLabelConfig":{"type":"object","properties":{"name":{"type":"string","description":"The name of the image label."},"anonymizationType":{"type":"string","default":"MASK","description":"The type of the anonymization that should be used. Omit to use the default `MASK`.","enum":["MASK","BLUR","PIXELATE"],"example":"MASK"}},"required":["name"]},"PartialPseudonymizationConfig":{"type":"object","description":"Replace a character range of the matched text. Wire JSON includes `type: PARTIAL_PSEUDONYMIZATION`.","properties":{"partialPseudonymizationStart":{"type":"integer","format":"int32","default":1,"description":"The starting position of the anonymization as 1-based index. E.g. if the starting position is 1 (or 0) the string is replaced from and including the first character. Negative values count from the back of the string, a -1 refers to the last character. E.g. for a value of 2 and the string 'Hello', 'ello' is replaced and 'H' is ignored.","example":1},"partialPseudonymizationStop":{"type":"integer","format":"int32","default":-1,"description":"The end position of the anonymization as 1-based index. E.g. if the end position is 3 the string is replaced until and including the third character. Negative values count from the back of the string, a -1 (or 0) means to replace until the end of the string. E.g. for a value of 3 and the string 'Hello', 'Hel' is replaced and 'lo' is ignored.","example":-1},"useNumericPartialPseudonymization":{"type":"boolean","default":false,"description":"If true only numerical characters are replaced, non-numerical characters are ignored. E.g. in the string 'D4F56G' only '4','5' and '6' are replaced with a '*'","example":false},"pseudonym":{"type":"string","description":"The replacement text that replaces the original text."},"type":{"type":"string","description":"Discriminator value identifying this replacement configuration subtype.","enum":["PARTIAL_PSEUDONYMIZATION"],"example":"PARTIAL_PSEUDONYMIZATION"}},"required":["partialPseudonymizationStart","partialPseudonymizationStop","pseudonym","type","useNumericPartialPseudonymization"]},"ReplacementConfig":{"description":"Object for advanced configuration of anonymizing, replacing or suppressing text elements. Discriminated by `type`.","discriminator":{"propertyName":"type","mapping":{"SUPPRESSION":"#/components/schemas/SuppressionConfig","PARTIAL_PSEUDONYMIZATION":"#/components/schemas/PartialPseudonymizationConfig","FULL_PSEUDONYMIZATION":"#/components/schemas/FullPseudonymizationConfig","DATE_PSEUDONYMIZATION":"#/components/schemas/DatePseudonymizationConfig"}},"oneOf":[{"$ref":"#/components/schemas/FullPseudonymizationConfig"},{"$ref":"#/components/schemas/PartialPseudonymizationConfig"},{"$ref":"#/components/schemas/DatePseudonymizationConfig"},{"$ref":"#/components/schemas/SuppressionConfig"}],"properties":{"type":{"type":"string","enum":["FULL_PSEUDONYMIZATION","PARTIAL_PSEUDONYMIZATION","DATE_PSEUDONYMIZATION","SUPPRESSION"]}}},"SuppressionConfig":{"type":"object","description":"Replace the matched text with a fixed-length suppression mask. Wire JSON includes `type: SUPPRESSION`.","properties":{"suppressionLength":{"type":"integer","format":"int32","description":"The length of the suppression that replaces the classified text element. E.g. a suppression length of 3 results in *** replacing the text element."},"type":{"type":"string","description":"Discriminator value identifying this replacement configuration subtype.","enum":["SUPPRESSION"],"example":"SUPPRESSION"}},"required":["suppressionLength","type"]},"TextLabelConfig":{"type":"object","description":"Specifies the text label and special rules for displaying the anonymized text.","properties":{"name":{"type":"string","description":"The name of the text label."},"config":{"$ref":"#/components/schemas/ReplacementConfig","description":"Object for advanced configuration of anonymizing, replacing or suppressing text elements."}},"required":["name"]},"WhiteListItem":{"type":"object","properties":{"value":{"type":"string","description":"The text element that should be displayed if it was classified as the given text label."},"labelName":{"type":"string","description":"The name of the text label."}},"required":["labelName","value"]},"TextLabelConfigDto":{"type":"object","description":"Text label available for anonymization.","properties":{"name":{"type":"string","description":"Label name used in API requests","example":"PER"},"description":{"type":"string","description":"Human-readable description of the label","example":"Person names"}}},"DocumentOverviewDto":{"type":"object","description":"Summary of a document in a project listing.","properties":{"id":{"type":"integer","format":"int64","description":"Document ID.","example":42},"version":{"type":"integer","format":"int32","description":"Document version.","example":1},"projectId":{"type":"integer","format":"int64","description":"Owning project ID.","example":1},"processingStatus":{"type":"string","description":"Current processing status.","enum":["COMPUTING_QUOTA","QUOTA_EXCEEDED","QUOTA_ERROR","UNPROCESSED","PROCESSING","COMPILING","ERROR","PREVIEW_ERROR","COMPLETED","FINALIZED","ARCHIVED"],"example":"COMPLETED"},"documentType":{"type":"string","description":"Document type.","enum":["PDF","DOCX","DOC","IMAGE","DOCUMENT"],"example":"PDF"},"fileSize":{"type":"integer","format":"int32","description":"Original file size in bytes.","example":204800},"original":{"type":"string","description":"Original file name.","example":"invoice.pdf"},"anonymized":{"type":["string","null"],"description":"Anonymized file name when available.","example":"invoice_anonymized.pdf"},"tags":{"type":"array","description":"Optional document tags.","items":{"$ref":"#/components/schemas/TagKeyValueDto"}},"lastModified":{"type":"string","format":"date-time","description":"Last modification time (ISO-8601).","example":"2024-06-15T10:31:00Z"},"createdAt":{"type":"string","format":"date-time","description":"Creation time (ISO-8601).","example":"2024-06-15T10:00:00Z"},"estimatedDurationMs":{"type":["integer","null"],"format":"int64","description":"Estimated remaining processing duration in milliseconds, when available.","example":1500}},"required":["id","processingStatus","projectId"]},"TagKeyValueDto":{"type":"object","properties":{"key":{"type":"string","minLength":1},"value":{"type":"string","minLength":1}},"required":["key","value"]},"DocumentOverviewPageDto":{"type":"object","description":"Paginated list of document overviews (Spring Data Page shape).","properties":{"content":{"type":"array","description":"Documents on the current page.","items":{"$ref":"#/components/schemas/DocumentOverviewDto"}},"pageable":{"$ref":"#/components/schemas/DocumentPageableDto","description":"Pagination request metadata."},"totalElements":{"type":"integer","format":"int64","description":"Total number of documents matching the filter.","example":1},"totalPages":{"type":"integer","format":"int32","description":"Total number of pages.","example":1},"number":{"type":"integer","format":"int32","description":"Zero-based index of the current page.","example":0},"size":{"type":"integer","format":"int32","description":"Page size.","example":20},"first":{"type":"boolean","description":"Whether this is the first page.","example":true},"last":{"type":"boolean","description":"Whether this is the last page.","example":true}},"required":["content","first","last","number","size","totalElements","totalPages"]},"DocumentPageableDto":{"type":"object","description":"Page request metadata.","properties":{"pageNumber":{"type":"integer","format":"int32","description":"Zero-based page index that was requested.","example":0},"pageSize":{"type":"integer","format":"int32","description":"Requested page size.","example":20}}},"ImageDetection":{"type":"object","description":"A detected region in a document image (label, bounding boxes, scores).","properties":{"label":{"type":"string","description":"Detected image label.","example":"text"},"bboxs":{"type":"array","description":"Bounding boxes for the detection. Each box is a list of [x, y] corners.","items":{"type":"array","items":{"type":"array","items":{"type":"number","format":"double"}}}},"scores":{"type":"array","description":"Confidence scores aligned with bounding boxes.","items":{"type":"number","format":"double"}}}},"DocumentPiisDto":{"type":"object","description":"Personally identifiable information detected in a document, grouped by page.","properties":{"documentId":{"type":"integer","format":"int64","description":"Document ID.","example":42},"version":{"type":"integer","format":"int32","description":"Document version used when reading PIIs.","example":1},"documentName":{"type":"string","description":"Original document file name.","example":"invoice.pdf"},"processingStatus":{"type":"string","description":"Current processing status of the document.","enum":["COMPUTING_QUOTA","QUOTA_EXCEEDED","QUOTA_ERROR","UNPROCESSED","PROCESSING","COMPILING","ERROR","PREVIEW_ERROR","COMPLETED","FINALIZED","ARCHIVED"],"example":"COMPLETED"},"documentType":{"type":"string","description":"Document type.","enum":["PDF","DOCX","DOC","IMAGE","DOCUMENT"],"example":"PDF"},"lastFileModified":{"type":"string","format":"date-time","description":"Last modification time of the stored file.","example":"2024-06-15T10:30:00Z"},"lastModified":{"type":"string","format":"date-time","description":"Last modification time of the document metadata.","example":"2024-06-15T10:31:00Z"},"pageData":{"type":"array","description":"Per-page PII payloads.","items":{"$ref":"#/components/schemas/PageData"},"minItems":1}},"required":["documentId","pageData","version"]},"ImageData":{"type":"object","description":"An embedded image on a page with optional detections.","properties":{"imageUrl":{"type":"string","format":"uri","description":"URL to fetch the page image (`GET /api/projects/{projectId}/documents/{documentId}/images/{pageNum}/{xref}/image_file`). Only accessible by the doccape application.","example":"https://app.doccape.de/api/projects/1/documents/42/images/1/1/image_file"},"xref":{"type":"integer","format":"int32","description":"Image cross-reference / index within the page.","example":0},"detections":{"type":"array","description":"Detected regions in the image.","items":{"$ref":"#/components/schemas/ImageDetection"}},"textDetections":{"$ref":"#/components/schemas/PageTextData"},"ocrLayout":{"type":"object","additionalProperties":true,"description":"OCR layout metadata for text regions detected in the image."},"ocrText":{"type":"string"}},"required":["detections","xref"]},"PageData":{"type":"object","description":"PII data for a single document page.","properties":{"pageNum":{"type":"integer","format":"int32","description":"1-based page number.","example":1},"textData":{"$ref":"#/components/schemas/PageTextData"},"imagesData":{"type":"array","description":"Image regions on this page with detections.","items":{"$ref":"#/components/schemas/ImageData"}}},"required":["pageNum","textData"]},"PageTextData":{"type":"object","description":"Text PII payload for a single page/paragraph, including tokens and entity detections.","properties":{"paragraphId":{"type":"integer","format":"int32","description":"Paragraph identifier within the page.","example":1},"text":{"type":"string","description":"Full page/paragraph text when provided by the pipeline.","example":"Angela Scholz aus Geheimdorf"},"detections":{"$ref":"#/components/schemas/PageTextDetections","description":"Token and entity detection results for this text."}}},"PageTextDetections":{"type":"object","description":"Tokenization and entity detections for page text.","properties":{"tokens":{"type":"array","description":"Tokenized spans covering the page text.","items":{"$ref":"#/components/schemas/TextToken"}},"ents":{"type":"array","description":"Detected PII entities spanning one or more tokens.","items":{"$ref":"#/components/schemas/TextEntity"}},"sentenceStarts":{"type":"array","description":"Character offsets where sentences start.","items":{"type":"integer","format":"int32"}},"pseudonyms":{"type":"array","description":"Optional pseudonym values aligned with entities; may contain nulls.","items":{"type":["string","null"]}},"crIds":{"type":"array","description":"Cross-reference / cluster IDs aligned with entities.","items":{"type":"integer","format":"int32"}},"locationsInAnonymizedDocument":{"type":"array","description":"Bounding boxes of entities in the anonymized document.","items":{"$ref":"#/components/schemas/TextLocation"}},"locationsInOriginalDocument":{"type":"array","description":"Bounding boxes of entities in the original document.","items":{"$ref":"#/components/schemas/TextLocation"}}}},"TextEntity":{"type":"object","description":"A detected PII entity spanning one or more tokens.","properties":{"startChar":{"type":"integer","format":"int32","description":"Inclusive start character offset of the entity.","example":9},"endChar":{"type":"integer","format":"int32","description":"Exclusive end character offset of the entity.","example":22},"tag":{"type":"string","description":"Text label / tag of the entity.","example":"PER"},"text":{"type":"string","description":"Matched entity text.","example":"Angela Scholz"},"score":{"type":"number","format":"double","description":"Model confidence score.","example":0.9999998807907104},"startTok":{"type":"integer","format":"int32","description":"Inclusive start token index.","example":2},"endTok":{"type":"integer","format":"int32","description":"Inclusive end token index.","example":3}}},"TextLocation":{"type":"object","description":"Axis-aligned bounding box for a text entity.","properties":{"x0":{"type":"number","format":"double","description":"Left edge.","example":57},"y0":{"type":"number","format":"double","description":"Top edge.","example":70},"x1":{"type":"number","format":"double","description":"Right edge.","example":86},"y1":{"type":"number","format":"double","description":"Bottom edge.","example":82}}},"TextToken":{"type":"object","description":"A single token span in the page text.","properties":{"startChar":{"type":"integer","format":"int32","description":"Inclusive start character offset.","example":9},"endChar":{"type":"integer","format":"int32","description":"Exclusive end character offset.","example":15},"text":{"type":"string","description":"Token text.","example":"Angela"},"hasWs":{"type":"boolean","description":"Whether the token is followed by whitespace.","example":true}}},"ProjectOverviewDto":{"type":"object","description":"Overview of a project accessible with the current credential.","properties":{"id":{"type":"integer","format":"int64","description":"Project ID","example":1},"name":{"type":"string","description":"Project name","example":"Customer invoices"},"description":{"type":"string","description":"Optional project description","example":"Invoices for Q1"},"documentCount":{"type":"integer","format":"int32","description":"Number of documents in the project","example":12},"lastUpdatedDocumentDate":{"type":"string","format":"date-time","description":"Timestamp of the most recently updated document in the project","example":"2024-06-15T10:30:00Z"},"isTemporary":{"type":"boolean","description":"When true, documents in this project are deleted automatically after deleteCompletedDocumentsAfterHours (completed and finalized) or deleteNonCompletedDocumentsAfterHours (all other statuses).","example":false},"deleteCompletedDocumentsAfterHours":{"type":["integer","null"],"format":"int64","description":"Hours after which completed documents are deleted. Null when retention is disabled.","example":24},"deleteNonCompletedDocumentsAfterHours":{"type":["integer","null"],"format":"int64","description":"Hours after which non-completed documents are deleted. Null when retention is disabled.","example":72},"isStoringPII":{"type":"boolean","description":"Whether detected PII is stored and available via the PIIs endpoint","example":true},"orgId":{"type":"integer","format":"int64","description":"Owning organization ID","example":7}},"required":["id","name","orgId"]},"ImageLabelConfigDto":{"type":"object","description":"Image label available for image anonymization.","properties":{"name":{"type":"string","description":"Label name used in upload config","example":"face"}}}},"securitySchemes":{"bearerAuth":{"type":"http","description":"doccape API key. Send as: Authorization: Bearer YOUR_API_KEY","scheme":"bearer"}}}}