openapi: 3.1.0

info:
  title: Blazelock API
  description: Fügen Sie Echtzeit-Malware-Erkennung mit nur wenigen Zeilen Code zu Ihrer Anwendung hinzu.
  version: 1.0.1
  contact:
    name: Blazelock Team
    url: https://blazelock.com

externalDocs:
  description: Lesen Sie die vollständige API-Dokumentation
  url: https://docs.blazelock.com/de/api-reference/introduction

servers:
  - url: https://api.blazelock.com/v1

security:
  - bearerAuth: []

tags:
  - name: Datei-Scans
    description: Scannen Sie Dateien über die Blazelock API auf Malware.

paths:
  /file-scans:
    post:
      operationId: submit-async-file-scan
      summary: Asynchronen Datei-Scan übermitteln
      description: |
        Laden Sie eine Datei für einen Malware-Scan hoch.
        Der Scan wird asynchron im Hintergrund fortgesetzt. Die Antwort gibt den
        initialen Verarbeitungsstatus zusammen mit der erstellten Scan-ID zurück.

        Verwenden Sie die Scan-ID, um das Ergebnis über die GET-Endpunkte abzufragen.

        Wenn Webhooks im Blazelock-Dashboard aktiviert sind, werden
        Webhook-Ereignisse gesendet, während der Scan fortschreitet.
      tags:
        - Datei-Scans
      parameters:
        - $ref: '#/components/parameters/ContentLanguageHeader'
      requestBody:
        $ref: '#/components/requestBodies/AsyncFileScanRequest'
      responses:
        '201':
          description: Datei-Scan akzeptiert und zur Verarbeitung in die Warteschlange gestellt.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FileScanProcessing'
              examples:
                processing:
                  $ref: '#/components/examples/FileScanProcessingAsyncExample'
        '409':
          $ref: '#/components/responses/DuplicateExternalReferenceIdResponse'

  /file-scans/sync:
    post:
      operationId: submit-sync-file-scan
      summary: Synchronen Datei-Scan übermitteln
      description: |
        Laden Sie eine Datei für einen Malware-Scan hoch und warten Sie innerhalb des
        synchronen Polling-Fensters von 90 Sekunden auf ein finales Ergebnis.

        Abhängig vom Ergebnis gibt die Antwort einen abgeschlossenen oder
        fehlgeschlagenen Status zurück.

        Wenn das Polling-Fenster endet, bevor ein finales Ergebnis verfügbar ist, wird
        ein Timeout-Fehler zusammen mit der erstellten Scan-ID zurückgegeben.
        Verwenden Sie die Scan-ID, um über die GET-Endpunkte weiter abzufragen.

        Wenn Webhooks im Blazelock-Dashboard aktiviert sind, werden
        Webhook-Ereignisse gesendet, während der Scan fortschreitet.
      tags:
        - Datei-Scans
      parameters:
        - $ref: '#/components/parameters/ContentLanguageHeader'
      requestBody:
        $ref: '#/components/requestBodies/SyncFileScanRequest'
      responses:
        '201':
          description: Finales Datei-Scan-Ergebnis, das innerhalb des synchronen Polling-Fensters zurückgegeben wurde.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/FileScanCompleted'
                  - $ref: '#/components/schemas/FileScanFailed'
                discriminator:
                  propertyName: status
                  mapping:
                    completed: '#/components/schemas/FileScanCompleted'
                    failed: '#/components/schemas/FileScanFailed'
              examples:
                completed_clean:
                  $ref: '#/components/examples/FileScanCompletedCleanSyncExample'
                completed_infected:
                  $ref: '#/components/examples/FileScanCompletedInfectedSyncExample'
                completed_warning:
                  $ref: '#/components/examples/FileScanCompletedWarningSyncExample'
                failed:
                  $ref: '#/components/examples/FileScanFailedSyncExample'
        '408':
          $ref: '#/components/responses/SyncScanTimeoutResponse'
        '409':
          $ref: '#/components/responses/DuplicateExternalReferenceIdResponse'

  /file-scans/{id}:
    get:
      operationId: get-file-scan
      summary: Datei-Scan abrufen
      description: |
        Rufen Sie den aktuellen Status eines Datei-Scans anhand seiner
        Blazelock-Scan-ID ab.

        Abhängig vom Fortschritt und Ergebnis des Scans gibt die Antwort einen
        Status `processing`, `completed` oder `failed` zurück.
      tags:
        - Datei-Scans
      parameters:
        - $ref: '#/components/parameters/ContentLanguageHeader'
        - $ref: '#/components/parameters/FileScanIdPathParameter'
      responses:
        '200':
          description: Aktueller Status des Datei-Scans.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/FileScanProcessing'
                  - $ref: '#/components/schemas/FileScanCompleted'
                  - $ref: '#/components/schemas/FileScanFailed'
                discriminator:
                  propertyName: status
                  mapping:
                    processing: '#/components/schemas/FileScanProcessing'
                    completed: '#/components/schemas/FileScanCompleted'
                    failed: '#/components/schemas/FileScanFailed'
              examples:
                processing:
                  $ref: '#/components/examples/FileScanProcessingAsyncExample'
                completed_clean:
                  $ref: '#/components/examples/FileScanCompletedCleanAsyncExample'
                completed_infected:
                  $ref: '#/components/examples/FileScanCompletedInfectedAsyncExample'
                completed_warning:
                  $ref: '#/components/examples/FileScanCompletedWarningAsyncExample'
                failed:
                  $ref: '#/components/examples/FileScanFailedAsyncExample'

  /file-scans/external-reference/{external_reference_id}:
    get:
      operationId: get-file-scan-by-external-reference-id
      summary: Datei-Scan per externer Referenz-ID abrufen
      description: |
        Rufen Sie einen Datei-Scan über die vom Client bereitgestellte externe
        Referenz-ID statt über die Blazelock-Scan-ID ab.

        Die externe Referenz-ID wird innerhalb der authentifizierten API-Anbindung
        aufgelöst.

        Abhängig vom Fortschritt und Ergebnis des Scans gibt die Antwort einen
        Status `processing`, `completed` oder `failed` zurück.
      tags:
        - Datei-Scans
      parameters:
        - $ref: '#/components/parameters/ContentLanguageHeader'
        - $ref: '#/components/parameters/ExternalReferenceIdPathParameter'
      responses:
        '200':
          description: Aktueller Status des Datei-Scans, aufgelöst über die externe Referenz-ID.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/FileScanProcessing'
                  - $ref: '#/components/schemas/FileScanCompleted'
                  - $ref: '#/components/schemas/FileScanFailed'
                discriminator:
                  propertyName: status
                  mapping:
                    processing: '#/components/schemas/FileScanProcessing'
                    completed: '#/components/schemas/FileScanCompleted'
                    failed: '#/components/schemas/FileScanFailed'
              examples:
                processing:
                  $ref: '#/components/examples/FileScanProcessingAsyncExample'
                completed_clean:
                  $ref: '#/components/examples/FileScanCompletedCleanAsyncExample'
                completed_infected:
                  $ref: '#/components/examples/FileScanCompletedInfectedAsyncExample'
                completed_warning:
                  $ref: '#/components/examples/FileScanCompletedWarningAsyncExample'
                failed:
                  $ref: '#/components/examples/FileScanFailedAsyncExample'

webhooks:
  file_scan.submitted:
    post:
      operationId: file-scan-submitted
      summary: Datei-Scan übermittelt
      description: |
        Wird ausgelöst, wenn ein neuer Datei-Scan über die API übermittelt wurde.

        Wir empfehlen, die Request-Signatur vor der Verarbeitung des Ereignisses zu
        verifizieren. Weitere Details finden Sie unter
        [Webhook-Signaturvalidierung](https://docs.blazelock.com/de/api-reference/webhook-validation).
      tags:
        - Datei-Scans
      security: []
      parameters:
        - $ref: '#/components/parameters/WebhookTimestampHeader'
        - $ref: '#/components/parameters/WebhookSignatureHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FileScanSubmittedWebhook'
            examples:
              file_scan_submitted:
                $ref: '#/components/examples/FileScanSubmittedWebhookExample'
      responses:
        2XX:
          $ref: '#/components/responses/WebhookResponse'

  file_scan.completed:
    post:
      operationId: file-scan-completed
      summary: Datei-Scan abgeschlossen
      description: |
        Wird ausgelöst, wenn ein über die API übermittelter Datei-Scan erfolgreich
        abgeschlossen wurde und die Ergebnisse verfügbar sind.

        Wir empfehlen, die Request-Signatur vor der Verarbeitung des Ereignisses zu
        verifizieren. Weitere Details finden Sie unter
        [Webhook-Signaturvalidierung](https://docs.blazelock.com/de/api-reference/webhook-validation).
      tags:
        - Datei-Scans
      security: []
      parameters:
        - $ref: '#/components/parameters/WebhookTimestampHeader'
        - $ref: '#/components/parameters/WebhookSignatureHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FileScanCompletedWebhook'
            examples:
              completed_clean:
                $ref: '#/components/examples/FileScanCompletedWebhookExample'
              completed_infected:
                $ref: '#/components/examples/FileScanCompletedInfectedWebhookExample'
              completed_warning:
                $ref: '#/components/examples/FileScanCompletedWarningWebhookExample'
      responses:
        2XX:
          $ref: '#/components/responses/WebhookResponse'

  file_scan.failed:
    post:
      operationId: file-scan-failed
      summary: Datei-Scan fehlgeschlagen
      description: |
        Wird ausgelöst, wenn ein über die API übermittelter Datei-Scan aufgrund eines
        Fehlers nicht abgeschlossen werden konnte.

        Wir empfehlen, die Request-Signatur vor der Verarbeitung des Ereignisses zu
        verifizieren. Weitere Details finden Sie unter
        [Webhook-Signaturvalidierung](https://docs.blazelock.com/de/api-reference/webhook-validation).
      tags:
        - Datei-Scans
      security: []
      parameters:
        - $ref: '#/components/parameters/WebhookTimestampHeader'
        - $ref: '#/components/parameters/WebhookSignatureHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FileScanFailedWebhook'
            examples:
              file_scan_failed:
                $ref: '#/components/examples/FileScanFailedWebhookExample'
      responses:
        2XX:
          $ref: '#/components/responses/WebhookResponse'

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API_KEY
      description: |
        Im Blazelock-Dashboard generierter API-Key.

        Senden Sie ihn im HTTP-Header `Authorization` als `Bearer <api-key>`.

  parameters:
    ContentLanguageHeader:
      name: Content-Language
      in: header
      required: false
      description: >
        Zweistelliger ISO-Sprachcode für lokalisierte menschenlesbare Antworttexte.
        Unterstützte Werte:
         * `en` = Englisch
         * `de` = Deutsch
      schema:
        type: string
        enum:
          - en
          - de
        examples:
          - en

    WebhookTimestampHeader:
      name: X-Blazelock-Webhook-Timestamp
      in: header
      required: true
      description: >
        Unix-Zeitstempel, der angibt, wann der Webhook gesendet wurde. Dieser Wert
        wird bei jedem Zustellversuch aktualisiert, einschließlich Retry-Versuchen.
        Als Best Practice sollten Sie prüfen, dass der Zeitstempel nicht mehr als
        5 Minuten in der Vergangenheit liegt, um Replay-Angriffe zu verhindern.
      schema:
        type: integer
        format: int64
        examples:
          - 1741520644

    WebhookSignatureHeader:
      name: X-Blazelock-Webhook-Signature
      in: header
      required: true
      description: >
        SHA256-Signatur zur Verifizierung der Authentizität des Webhook-Payloads.
        Die Signatur wird über den String `{timestamp}.{body}` berechnet, wobei
        `timestamp` der Wert des Headers `X-Blazelock-Webhook-Timestamp` und `body`
        der rohe JSON-Request-Body ist. Die Signatur wird mit dem Webhook-Secret
        erzeugt, das Sie im Blazelock-Dashboard in den Einstellungen der
        API-Anbindung finden.
      schema:
        type: string
        examples:
          - a3b9f1c8d4e7f2a1b5c3d9e6f8a2b4c7d1e5f3a8b6c4d2e9f7a1b3c5d8e6f4a2

    FileScanIdPathParameter:
      name: id
      in: path
      required: true
      description: ID des Datei-Scans.
      schema:
        $ref: '#/components/schemas/FileScanId'

    ExternalReferenceIdPathParameter:
      name: external_reference_id
      in: path
      required: true
      description: Vom Client vergebene externe Referenz-ID, die innerhalb der authentifizierten API-Anbindung aufgelöst wird.
      schema:
        allOf:
          - $ref: '#/components/schemas/FileScanExternalReferenceId'
          - type: string

  requestBodies:
    AsyncFileScanRequest:
      required: true
      description: >
        Multipart-Form-Payload für einen asynchronen Datei-Scan. Sie enthält
        einen binären `file`-Teil und einen als JSON codierten `attributes`-Teil
        mit dem Content-Type `application/json`.
      content:
        multipart/form-data:
          schema:
            $ref: '#/components/schemas/AsyncFileScanRequest'
          encoding:
            attributes:
              contentType: application/json

    SyncFileScanRequest:
      required: true
      description: >
        Multipart-Form-Payload für einen synchronen Datei-Scan. Sie enthält
        einen binären `file`-Teil und einen als JSON codierten `attributes`-Teil
        mit dem Content-Type `application/json`.
      content:
        multipart/form-data:
          schema:
            $ref: '#/components/schemas/SyncFileScanRequest'
          encoding:
            attributes:
              contentType: application/json

  schemas:
    AsyncFileScanRequest:
      type: object
      description: Request-Payload zum Übermitteln eines asynchronen Datei-Scans.
      properties:
        attributes:
          $ref: '#/components/schemas/FileScanRequestAttributes'
        file:
          $ref: '#/components/schemas/AsyncFileUpload'
      required:
        - attributes
        - file

    SyncFileScanRequest:
      type: object
      description: Request-Payload zum Übermitteln eines synchronen Datei-Scans.
      properties:
        attributes:
          $ref: '#/components/schemas/FileScanRequestAttributes'
        file:
          $ref: '#/components/schemas/SyncFileUpload'
      required:
        - attributes
        - file

    FileScanRequestAttributes:
      type: object
      description: Metadaten, die zusammen mit dem Datei-Upload übermittelt werden.
      properties:
        file_name:
          $ref: '#/components/schemas/FileScanFileName'
        external_reference_id:
          $ref: '#/components/schemas/FileScanExternalReferenceId'
      required:
        - file_name

    AsyncFileUpload:
      type: string
      format: binary
      maxLength: 104857600
      description: Binärer Dateiinhalt, der gescannt werden soll. Die maximale Dateigröße beträgt 100 MB.

    SyncFileUpload:
      type: string
      format: binary
      maxLength: 10485760
      description: Binärer Dateiinhalt, der gescannt werden soll. Die maximale Dateigröße beträgt 10 MB.

    FileScanProcessing:
      type: object
      description: Response-Payload für einen Datei-Scan, der noch verarbeitet wird.
      properties:
        id:
          $ref: '#/components/schemas/FileScanId'
        external_reference_id:
          $ref: '#/components/schemas/FileScanExternalReferenceId'
        status:
          $ref: '#/components/schemas/FileScanStatusProcessing'
        execution_mode:
          $ref: '#/components/schemas/FileScanExecutionMode'
        file_name:
          $ref: '#/components/schemas/FileScanFileName'
        file_size:
          $ref: '#/components/schemas/FileScanFileSize'
        submitted_at:
          $ref: '#/components/schemas/FileScanSubmittedAt'
      required:
        - id
        - external_reference_id
        - status
        - execution_mode
        - file_name
        - file_size
        - submitted_at

    FileScanCompleted:
      type: object
      description: Response-Payload für einen Datei-Scan, der erfolgreich abgeschlossen wurde.
      properties:
        id:
          $ref: '#/components/schemas/FileScanId'
        external_reference_id:
          $ref: '#/components/schemas/FileScanExternalReferenceId'
        status:
          $ref: '#/components/schemas/FileScanStatusCompleted'
        execution_mode:
          $ref: '#/components/schemas/FileScanExecutionMode'
        file_name:
          $ref: '#/components/schemas/FileScanFileName'
        file_size:
          $ref: '#/components/schemas/FileScanFileSize'
        file_type:
          $ref: '#/components/schemas/FileScanFileType'
        file_hash:
          $ref: '#/components/schemas/FileHash'
        result:
          $ref: '#/components/schemas/ScanResult'
        completed_at:
          $ref: '#/components/schemas/FileScanCompletedAt'
        scan_duration_ms:
          $ref: '#/components/schemas/FileScanDurationMs'
        submitted_at:
          $ref: '#/components/schemas/FileScanSubmittedAt'
      required:
        - id
        - external_reference_id
        - status
        - execution_mode
        - file_name
        - file_size
        - file_type
        - file_hash
        - result
        - completed_at
        - scan_duration_ms
        - submitted_at

    FileScanFailed:
      type: object
      description: Response-Payload für einen Datei-Scan, der fehlgeschlagen ist.
      properties:
        id:
          $ref: '#/components/schemas/FileScanId'
        external_reference_id:
          $ref: '#/components/schemas/FileScanExternalReferenceId'
        status:
          $ref: '#/components/schemas/FileScanStatusFailed'
        execution_mode:
          $ref: '#/components/schemas/FileScanExecutionMode'
        file_name:
          $ref: '#/components/schemas/FileScanFileName'
        file_size:
          $ref: '#/components/schemas/FileScanFileSize'
        error_code:
          $ref: '#/components/schemas/FileScanErrorCode'
        submitted_at:
          $ref: '#/components/schemas/FileScanSubmittedAt'
      required:
        - id
        - external_reference_id
        - status
        - execution_mode
        - file_name
        - file_size
        - error_code
        - submitted_at

    WebhookEnvelope:
      type: object
      description: Gemeinsamer Umschlag für alle ausgehenden Webhook-Payloads.
      properties:
        event:
          type: string
          description: Das Ereignis, welches diesen Webhook ausgelöst hat.
        integration_id:
          $ref: '#/components/schemas/IntegrationId'
        occurred_at:
          $ref: '#/components/schemas/WebhookOccurredAt'
        data:
          type: object
          description: Ereignisspezifisches Payload. Die Struktur hängt vom Wert von `event` ab.
      required:
        - event
        - integration_id
        - occurred_at
        - data

    FileScanSubmittedWebhook:
      description: Ausgehendes Webhook-Payload für das Ereignis `file_scan.submitted`.
      allOf:
        - $ref: '#/components/schemas/WebhookEnvelope'
        - type: object
          properties:
            event:
              $ref: '#/components/schemas/WebhookEventFileScanSubmitted'
            data:
              $ref: '#/components/schemas/FileScanProcessing'

    FileScanCompletedWebhook:
      description: Ausgehendes Webhook-Payload für das Ereignis `file_scan.completed`.
      allOf:
        - $ref: '#/components/schemas/WebhookEnvelope'
        - type: object
          properties:
            event:
              $ref: '#/components/schemas/WebhookEventFileScanCompleted'
            data:
              $ref: '#/components/schemas/FileScanCompleted'

    FileScanFailedWebhook:
      description: Ausgehendes Webhook-Payload für das Ereignis `file_scan.failed`.
      allOf:
        - $ref: '#/components/schemas/WebhookEnvelope'
        - type: object
          properties:
            event:
              $ref: '#/components/schemas/WebhookEventFileScanFailed'
            data:
              $ref: '#/components/schemas/FileScanFailed'

    WebhookEventFileScanSubmitted:
      type: string
      enum:
        - file_scan.submitted
      description: Wird ausgelöst, wenn ein neuer Datei-Scan über die API übermittelt wurde.

    WebhookEventFileScanCompleted:
      type: string
      enum:
        - file_scan.completed
      description: Wird ausgelöst, wenn ein Datei-Scan erfolgreich abgeschlossen wurde und die Ergebnisse verfügbar sind.

    WebhookEventFileScanFailed:
      type: string
      enum:
        - file_scan.failed
      description: Wird ausgelöst, wenn ein Datei-Scan aufgrund eines Fehlers nicht abgeschlossen werden konnte.

    IntegrationId:
      type: string
      format: uuid
      description: ID der API-Anbindung, die den Datei-Scan erstellt hat.
      examples:
        - 019583d8-b217-72e1-91a5-6f6b4e1a1c42

    WebhookOccurredAt:
      type: string
      format: date-time
      description: ISO-8601-Zeitstempel, der angibt, wann das Ereignis auf Seiten von Blazelock eingetreten ist.
      examples:
        - 2026-03-09T12:35:12.000Z

    FileScanId:
      type: string
      format: uuid
      description: Eindeutige Kennung des Datei-Scans.
      examples:
        - 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1

    FileScanExternalReferenceId:
      type:
        - string
        - 'null'
      maxLength: 255
      pattern: ^[a-zA-Z0-9._:/#@-]+$
      description: >
        Optionale externe Referenz-ID, die beim Übermitteln des Scans angegeben wird.
        Sie darf maximal 255 Zeichen lang sein und nur Groß- und Kleinbuchstaben,
        Ziffern, `.`, `_`, `:`, `/`, `#`, `@` und `-` enthalten. Leerzeichen und
        alle anderen Zeichen sind nicht erlaubt. Falls angegeben, muss der Wert
        innerhalb derselben API-Anbindung eindeutig sein.
      examples:
        - invoice-4711

    FileScanStatusProcessing:
      type: string
      enum:
        - processing
      description: Datei-Scan wird noch verarbeitet.

    FileScanStatusCompleted:
      type: string
      enum:
        - completed
      description: Datei-Scan wurde erfolgreich abgeschlossen.

    FileScanStatusFailed:
      type: string
      enum:
        - failed
      description: Datei-Scan ist fehlgeschlagen.

    FileScanExecutionMode:
      type: string
      enum:
        - sync
        - async
      description: Ob der Scan über den synchronen oder asynchronen Endpunkt angefordert wurde.

    FileScanFileName:
      type: string
      maxLength: 255
      description: Vom Client bereitgestellter Dateiname der hochgeladenen Datei. Die maximale Länge beträgt 255 Zeichen.
      examples:
        - invoice.pdf

    FileScanFileSize:
      type: integer
      format: int64
      description: Größe der hochgeladenen Datei in Bytes.
      examples:
        - 245761

    FileScanFileType:
      type: string
      description: Erkannter MIME-Typ der gescannten Datei.
      examples:
        - application/pdf

    FileScanSubmittedAt:
      type: string
      format: date-time
      description: ISO-8601-Zeitstempel, der angibt, wann der Scan übermittelt wurde.
      examples:
        - 2026-03-09T12:34:56.000Z

    FileScanCompletedAt:
      type: string
      format: date-time
      description: ISO-8601-Zeitstempel, der angibt, wann der Scan abgeschlossen wurde.
      examples:
        - 2026-03-09T12:35:11.000Z

    FileScanDurationMs:
      type: integer
      format: int32
      description: Gesamtdauer des Scans in Millisekunden.
      examples:
        - 250

    FileScanErrorCode:
      type: string
      description: >
        Maschinenlesbarer Fehlercode, der beschreibt, warum der Scan fehlgeschlagen ist.
         * `upload_failed` - Die hochgeladene Datei konnte nicht gespeichert werden.
         * `file_analysis_failed` - Dateimetadaten oder Hashes konnten nicht ermittelt werden.
         * `test_file_signature_failed` - Die Datei hat eine Testdatei-Signatur getroffen, die gezielt einen fehlgeschlagenen Scan erzwingt.
         * `scan_failed` - Der Malware-Scan ist aus einem anderen Grund als einem Timeout fehlgeschlagen.
         * `scan_timeout` - Der Malware-Scan hat die erlaubte Verarbeitungszeit überschritten.
         * `unknown_error` - Der Scan ist durch einen unerwarteten internen Fehler fehlgeschlagen.
      enum:
        - upload_failed
        - file_analysis_failed
        - test_file_signature_failed
        - scan_failed
        - scan_timeout
        - unknown_error
      examples:
        - scan_timeout

    FileHash:
      type: object
      description: Kryptografische Hashes der gescannten Datei.
      properties:
        md5:
          $ref: '#/components/schemas/FileHashMd5'
        sha1:
          $ref: '#/components/schemas/FileHashSha1'
        sha256:
          $ref: '#/components/schemas/FileHashSha256'
      required:
        - md5
        - sha1
        - sha256

    FileHashMd5:
      type: string
      description: MD5-Hash der Datei.
      examples:
        - d41d8cd98f00b204e9800998ecf8427e

    FileHashSha1:
      type: string
      description: SHA-1-Hash der Datei.
      examples:
        - da39a3ee5e6b4b0d3255bfef95601890afd80709

    FileHashSha256:
      type: string
      description: SHA-256-Hash der Datei.
      examples:
        - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

    ScanResult:
      type: object
      description: Das Ergebnis des Malware-Scans.
      properties:
        safe:
          type: boolean
          description: >
            `true`, wenn Blazelock die Datei als sicher einstuft, andernfalls `false`.
            Ein `warning`-Ergebnis wird als unsicher eingestuft und liefert `false`.
          examples:
            - true
        detailed:
          $ref: '#/components/schemas/FileScanDetailedResult'
        findings:
          type: array
          description: Erkannte Bedrohungen oder Warnungen für einen abgeschlossenen Scan.
          items:
            type: string
      required:
        - safe
        - detailed
        - findings

    FileScanDetailedResult:
      type: string
      enum:
        - clean
        - infected
        - warning
      description: Detaillierte Klassifizierung des Scan-Ergebnisses.
      examples:
        - clean

    ApiError:
      type: object
      description: Standard-Fehlerantwort der REST-API.
      properties:
        code:
          type: string
          description: Stabiler maschinenlesbarer Fehlerbezeichner.
          examples:
            - unauthenticated
        message:
          type: string
          description: Menschenlesbare Beschreibung des Problems.
          examples:
            - Sie müssen authentifiziert sein, um diese Aktion durchzuführen.
      required:
        - code
        - message

    SyncScanTimeoutError:
      allOf:
        - $ref: '#/components/schemas/ApiError'
        - type: object
          properties:
            file_scan_id:
              $ref: '#/components/schemas/FileScanId'
          required:
            - file_scan_id

  examples:
    FileScanProcessingAsyncExample:
      summary: In Verarbeitung
      value:
        id: 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1
        external_reference_id: invoice-4711
        status: processing
        execution_mode: async
        file_name: invoice.pdf
        file_size: 245761
        submitted_at: 2026-03-09T12:34:56.000Z

    FileScanCompletedCleanAsyncExample:
      summary: Abgeschlossen, ohne Befund
      value:
        id: 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1
        external_reference_id: invoice-4711
        status: completed
        execution_mode: async
        file_name: invoice.pdf
        file_size: 245761
        file_type: application/pdf
        file_hash:
          md5: d41d8cd98f00b204e9800998ecf8427e
          sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
          sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
        result:
          safe: true
          detailed: clean
          findings: []
        completed_at: 2026-03-09T12:35:11.000Z
        scan_duration_ms: 250
        submitted_at: 2026-03-09T12:34:56.000Z

    FileScanCompletedInfectedAsyncExample:
      summary: Abgeschlossen, infiziert
      value:
        id: 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1
        external_reference_id: invoice-4711
        status: completed
        execution_mode: async
        file_name: malware.exe
        file_size: 5678
        file_type: application/x-msdownload
        file_hash:
          md5: 7b8f4f9a4d6e2c1b3a5f7d9e0c2a4b6d
          sha1: 3f786850e387550fdab836ed7e6dc881de23001b
          sha256: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
        result:
          safe: false
          detailed: infected
          findings:
            - Virus.Script/Obfuscated.Dropper
            - Malware.Win32/Loader.B
        completed_at: 2026-03-09T12:35:11.000Z
        scan_duration_ms: 1200
        submitted_at: 2026-03-09T12:34:56.000Z

    FileScanCompletedWarningAsyncExample:
      summary: Abgeschlossen, Warnung
      value:
        id: 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1
        external_reference_id: invoice-4711
        status: completed
        execution_mode: async
        file_name: invoice.xlsm
        file_size: 3456
        file_type: application/vnd.ms-excel.sheet.macroEnabled.12
        file_hash:
          md5: e2fc714c4727ee9395f324cd2e7f331f
          sha1: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
          sha256: b94d27b9934d3e08a52e52d7da7dabfade4f6d3f1f9f5d7e0d7c6f216a73abdb
        result:
          safe: false
          detailed: warning
          findings:
            - This file contains macros that could potentially execute malicious code. Review the macros before enabling them.
        completed_at: 2026-03-09T12:35:11.000Z
        scan_duration_ms: 640
        submitted_at: 2026-03-09T12:34:56.000Z

    FileScanFailedAsyncExample:
      summary: Fehlgeschlagen
      value:
        id: 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1
        external_reference_id: invoice-4711
        status: failed
        execution_mode: async
        file_name: invoice.pdf
        file_size: 245761
        error_code: scan_failed
        submitted_at: 2026-03-09T12:34:56.000Z

    FileScanCompletedCleanSyncExample:
      summary: Abgeschlossen, ohne Befund
      value:
        id: 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1
        external_reference_id: invoice-4711
        status: completed
        execution_mode: sync
        file_name: invoice.pdf
        file_size: 245761
        file_type: application/pdf
        file_hash:
          md5: d41d8cd98f00b204e9800998ecf8427e
          sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
          sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
        result:
          safe: true
          detailed: clean
          findings: []
        completed_at: 2026-03-09T12:35:11.000Z
        scan_duration_ms: 250
        submitted_at: 2026-03-09T12:34:56.000Z

    FileScanCompletedInfectedSyncExample:
      summary: Abgeschlossen, infiziert
      value:
        id: 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1
        external_reference_id: invoice-4711
        status: completed
        execution_mode: sync
        file_name: malware.exe
        file_size: 5678
        file_type: application/x-msdownload
        file_hash:
          md5: 7b8f4f9a4d6e2c1b3a5f7d9e0c2a4b6d
          sha1: 3f786850e387550fdab836ed7e6dc881de23001b
          sha256: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
        result:
          safe: false
          detailed: infected
          findings:
            - Virus.Script/Obfuscated.Dropper
            - Malware.Win32/Loader.B
        completed_at: 2026-03-09T12:35:11.000Z
        scan_duration_ms: 1200
        submitted_at: 2026-03-09T12:34:56.000Z

    FileScanCompletedWarningSyncExample:
      summary: Abgeschlossen, Warnung
      value:
        id: 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1
        external_reference_id: invoice-4711
        status: completed
        execution_mode: sync
        file_name: invoice.xlsm
        file_size: 3456
        file_type: application/vnd.ms-excel.sheet.macroEnabled.12
        file_hash:
          md5: e2fc714c4727ee9395f324cd2e7f331f
          sha1: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
          sha256: b94d27b9934d3e08a52e52d7da7dabfade4f6d3f1f9f5d7e0d7c6f216a73abdb
        result:
          safe: false
          detailed: warning
          findings:
            - This file contains macros that could potentially execute malicious code. Review the macros before enabling them.
        completed_at: 2026-03-09T12:35:11.000Z
        scan_duration_ms: 640
        submitted_at: 2026-03-09T12:34:56.000Z

    FileScanFailedSyncExample:
      summary: Fehlgeschlagen
      value:
        id: 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1
        external_reference_id: invoice-4711
        status: failed
        execution_mode: sync
        file_name: invoice.pdf
        file_size: 245761
        error_code: scan_failed
        submitted_at: 2026-03-09T12:34:56.000Z

    FileScanSubmittedWebhookExample:
      summary: Datei-Scan übermittelt
      value:
        event: file_scan.submitted
        integration_id: 019583d8-b217-72e1-91a5-6f6b4e1a1c42
        occurred_at: 2026-03-09T12:35:12.000Z
        data:
          id: 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1
          external_reference_id: invoice-4711
          status: processing
          execution_mode: async
          file_name: invoice.pdf
          file_size: 245761
          submitted_at: 2026-03-09T12:34:56.000Z

    FileScanCompletedWebhookExample:
      summary: Datei-Scan abgeschlossen
      value:
        event: file_scan.completed
        integration_id: 019583d8-b217-72e1-91a5-6f6b4e1a1c42
        occurred_at: 2026-03-09T12:35:12.000Z
        data:
          id: 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1
          external_reference_id: invoice-4711
          status: completed
          execution_mode: async
          file_name: invoice.pdf
          file_size: 245761
          file_type: application/pdf
          file_hash:
            md5: d41d8cd98f00b204e9800998ecf8427e
            sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709
            sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
          result:
            safe: true
            detailed: clean
            findings: []
          completed_at: 2026-03-09T12:35:11.000Z
          scan_duration_ms: 250
          submitted_at: 2026-03-09T12:34:56.000Z

    FileScanCompletedInfectedWebhookExample:
      summary: Datei-Scan abgeschlossen, infiziert
      value:
        event: file_scan.completed
        integration_id: 019583d8-b217-72e1-91a5-6f6b4e1a1c42
        occurred_at: 2026-03-09T12:35:12.000Z
        data:
          id: 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1
          external_reference_id: invoice-4711
          status: completed
          execution_mode: async
          file_name: malware.exe
          file_size: 5678
          file_type: application/x-msdownload
          file_hash:
            md5: 7b8f4f9a4d6e2c1b3a5f7d9e0c2a4b6d
            sha1: 3f786850e387550fdab836ed7e6dc881de23001b
            sha256: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
          result:
            safe: false
            detailed: infected
            findings:
              - Virus.Script/Obfuscated.Dropper
              - Malware.Win32/Loader.B
          completed_at: 2026-03-09T12:35:11.000Z
          scan_duration_ms: 1200
          submitted_at: 2026-03-09T12:34:56.000Z

    FileScanCompletedWarningWebhookExample:
      summary: Datei-Scan abgeschlossen, Warnung
      value:
        event: file_scan.completed
        integration_id: 019583d8-b217-72e1-91a5-6f6b4e1a1c42
        occurred_at: 2026-03-09T12:35:12.000Z
        data:
          id: 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1
          external_reference_id: invoice-4711
          status: completed
          execution_mode: async
          file_name: invoice.xlsm
          file_size: 3456
          file_type: application/vnd.ms-excel.sheet.macroEnabled.12
          file_hash:
            md5: e2fc714c4727ee9395f324cd2e7f331f
            sha1: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
            sha256: b94d27b9934d3e08a52e52d7da7dabfade4f6d3f1f9f5d7e0d7c6f216a73abdb
          result:
            safe: false
            detailed: warning
            findings:
              - This file contains macros that could potentially execute malicious code. Review the macros before enabling them.
          completed_at: 2026-03-09T12:35:11.000Z
          scan_duration_ms: 640
          submitted_at: 2026-03-09T12:34:56.000Z

    FileScanFailedWebhookExample:
      summary: Datei-Scan fehlgeschlagen
      value:
        event: file_scan.failed
        integration_id: 019583d8-b217-72e1-91a5-6f6b4e1a1c42
        occurred_at: 2026-03-09T12:35:12.000Z
        data:
          id: 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1
          external_reference_id: invoice-4711
          status: failed
          execution_mode: async
          file_name: invoice.pdf
          file_size: 245761
          error_code: scan_failed
          submitted_at: 2026-03-09T12:34:56.000Z

  responses:
    WebhookResponse:
      description: Ihr Endpunkt sollte innerhalb von 15 Sekunden mit einem 2xx-Statuscode antworten. Länger laufende Verarbeitung sollte asynchron behandelt werden.

    DuplicateExternalReferenceIdResponse:
      description: Die angegebene externe Referenz-ID existiert innerhalb der authentifizierten API-Anbindung bereits.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          examples:
            duplicate_external_reference_id:
              summary: Doppelte externe Referenz-ID
              value:
                code: duplicate_external_reference_id
                message: Die externe Referenz-ID existiert bereits für diese Anbindung.

    SyncScanTimeoutResponse:
      description: Das synchrone Polling-Fenster hat geendet, bevor ein finales Ergebnis verfügbar war. Verwenden Sie `file_scan_id`, um über die Status-Endpunkte weiter zu pollen.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SyncScanTimeoutError'
          examples:
            sync_scan_timeout:
              summary: Synchroner Scan-Timeout
              value:
                code: sync_scan_timeout
                message: Der Datei-Scan dauert länger als erwartet. Sie können den Status dieses Scans weiterhin mit seiner ID über den Status-Endpunkt abfragen.
                file_scan_id: 019583d8-b2e4-7b8d-9d1f-6f4cb3d0b6f1
