openapi: 3.0.3
info:
  title: Leaks.ai API
  description: >-
    REST API for Leaks.ai - monitor credential exposures across your
    organization's domains. Access leaks, infected endpoints, compromised
    resources, and exposed users. All list endpoints support pagination and
    filtering. Authentication via API key.
  version: 1.0.0
servers:
  - url: https://api.leaks.ai/api/v1
    description: API base path
security:
  - ApiKeyAuth: []
tags:
  - name: Domains
    description: Monitored domains
  - name: Leaks
    description: Credential leaks
  - name: Endpoints
    description: Infected Endpoints associated with leaks
  - name: Resources
    description: Resources (domains, IPs, APKs) associated with leaks
  - name: Users
    description: Users represent leaks grouped by login (email or username).
paths:
  /domains:
    get:
      tags:
        - Domains
      summary: List domains
      description: >-
        Returns all non-archived domains for the organization associated with
        the API key.
      operationId: listDomains
      security:
        - ApiKeyAuth: []
      parameters: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Domain'
              example:
                data:
                  - id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                    domain: example.com
                  - id: b2c3d4e5-f6a7-8901-bcde-f23456789012
                    domain: example.dev
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /leaks:
    get:
      tags:
        - Leaks
      summary: List leaks
      description: >-
        Returns paginated leaks. Scope by domain(s) via `domain_id`. If omitted,
        returns leaks across all org domains.
      operationId: listLeaks
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/domain_id'
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: status
          in: query
          description: Filter by status (repeatable)
          schema:
            type: string
            enum:
              - new
              - investigating
              - resolved
              - false_positive
        - name: risk_level
          in: query
          description: >-
            Filter by risk level; comma-separated or repeated; case-insensitive
            (e.g. none,low,medium). To get only actionable leaks, use
            risk_level=low,medium,high
          schema:
            type: string
            example: none,medium
        - name: login
          in: query
          description: Search by login (substring)
          schema:
            type: string
        - name: password
          in: query
          description: Search by password (substring)
          schema:
            type: string
        - name: url
          in: query
          description: Search by URL (substring)
          schema:
            type: string
        - name: url_port
          in: query
          description: Filter by URL port (exact)
          schema:
            type: integer
        - name: url_path
          in: query
          description: Search by URL path (substring)
          schema:
            type: string
        - name: user_id
          in: query
          description: Filter by user UUID
          schema:
            type: string
            format: uuid
        - name: resource_id
          in: query
          description: Filter by resource UUID
          schema:
            type: string
            format: uuid
        - name: endpoint_id
          in: query
          description: Filter by endpoint UUID
          schema:
            type: string
            format: uuid
        - name: sort
          in: query
          description: >-
            Sort: prefix with - for desc. Allowed: risk_level, first_seen,
            added_at
          schema:
            type: string
            example: '-risk_level,added_at'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Leak'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
              example:
                data:
                  - id: f47ac10b-58cc-4372-a567-0e02b2c3d479
                    risk_level: 5
                    risk_level_name: medium
                    status: new
                    url: https://example.com/login
                    login: user@example.com
                    password: passw0rd123
                    first_seen: '2025-12-05T00:00:00.000Z'
                    added_at: '2025-12-05T01:09:22.879Z'
                pagination:
                  page: 1
                  per_page: 25
                  total_pages: 4
                  total_results: 92
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /leaks/count:
    get:
      tags:
        - Leaks
      summary: Count leaks
      description: >-
        Returns total count of leaks matching filters. Same query parameters as
        list (except page, per_page, sort).
      operationId: countLeaks
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/domain_id'
        - name: status
          in: query
          schema:
            type: string
            enum:
              - new
              - investigating
              - resolved
              - false_positive
        - name: risk_level
          in: query
          schema:
            type: string
        - name: login
          in: query
          schema:
            type: string
        - name: password
          in: query
          schema:
            type: string
        - name: url
          in: query
          schema:
            type: string
        - name: url_port
          in: query
          schema:
            type: integer
        - name: url_path
          in: query
          schema:
            type: string
        - name: user_id
          in: query
          schema:
            type: string
            format: uuid
        - name: resource_id
          in: query
          schema:
            type: string
            format: uuid
        - name: endpoint_id
          in: query
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      count:
                        type: integer
                        example: 92
              example:
                data:
                  count: 92
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /leaks/{leak_id}:
    get:
      tags:
        - Leaks
      summary: Get leak by ID
      description: Returns a single leak with connections (resources, users, endpoints).
      operationId: getLeak
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/domain_id'
        - name: leak_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/LeakWithConnections'
              example:
                data:
                  id: f47ac10b-58cc-4372-a567-0e02b2c3d479
                  risk_level: 5
                  risk_level_name: medium
                  status: new
                  url: https://example.com/login
                  login: user@example.com
                  password: '***'
                  first_seen: '2025-12-05T00:00:00.000Z'
                  added_at: '2025-12-05T01:09:22.879Z'
                  connections:
                    resources:
                      - id: b2c3d4e5-f6a7-8901-bcde-f23456789012
                        resource: api.example.com
                        type: domain
                    users:
                      - id: c3d4e5f6-a7b8-9012-cdef-345678901234
                        login: user@example.com
                        identity_type: email
                    endpoints:
                      - id: d4e5f6a7-b8c9-0123-def0-456789012345
                        filename: '[US]93.101.28.33.rar'
                        date: '2025-12-04T14:30:00.000Z'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /endpoints:
    get:
      tags:
        - Endpoints
      summary: List endpoints
      description: >-
        Returns paginated endpoints (infected machines / stealer logs). Scope by
        domain(s).
      operationId: listEndpoints
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/domain_id'
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: status
          in: query
          description: Filter by status (repeatable)
          schema:
            type: string
            enum:
              - new
              - investigating
              - resolved
              - false_positive
        - name: risk_level
          in: query
          description: Filter by risk level; comma-separated
          schema:
            type: string
        - name: sort
          in: query
          description: 'Sort: prefix - for desc. Allowed: risk_level, date'
          schema:
            type: string
            example: '-risk_level'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Endpoint'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
              example:
                data:
                  - id: d4e5f6a7-b8c9-0123-def0-456789012345
                    date: '2025-12-04T14:30:00.000Z'
                    added_at: '2025-12-05T01:09:22.879Z'
                    metadata:
                      exfiltration_date: '2025-12-04T14:30:00.000Z'
                    risk_level: 4
                    risk_level_name: medium
                    status: new
                    filename: '[US]93.101.28.33.rar'
                pagination:
                  page: 1
                  per_page: 25
                  total_pages: 2
                  total_results: 41
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /endpoints/count:
    get:
      tags:
        - Endpoints
      summary: Count endpoints
      operationId: countEndpoints
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/domain_id'
        - name: status
          in: query
          schema:
            type: string
            enum:
              - new
              - investigating
              - resolved
              - false_positive
        - name: risk_level
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      count:
                        type: integer
                        example: 41
              example:
                data:
                  count: 41
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /endpoints/{endpoint_id}:
    get:
      tags:
        - Endpoints
      summary: Get endpoint by ID
      description: >-
        Returns a single endpoint with connections (users and resources). Users
        in connections have risk_level not None.
      operationId: getEndpoint
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/domain_id'
        - name: endpoint_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/EndpointDetail'
              example:
                data:
                  id: d4e5f6a7-b8c9-0123-def0-456789012345
                  date: '2025-12-04T14:30:00.000Z'
                  added_at: '2025-12-05T01:09:22.879Z'
                  metadata:
                    exfiltration_date: '2025-12-04T14:30:00.000Z'
                  risk_level: 4
                  risk_level_name: medium
                  status: new
                  filename: '[US]93.101.28.33.rar'
                  tree:
                    - '[US]93.101.28.33.rar/All Passwords.txt'
                    - '[US]93.101.28.33.rar/System.txt'
                  connections:
                    users:
                      - id: c3d4e5f6-a7b8-9012-cdef-345678901234
                        login: user@example.com
                        identity_type: email
                    resources:
                      - id: b2c3d4e5-f6a7-8901-bcde-f23456789012
                        resource: api.example.com
                        type: domain
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /endpoints/{endpoint_id}/download:
    get:
      tags:
        - Endpoints
      summary: Download endpoint archive
      description: >-
        Returns a temporary pre-signed URL to download the stealer log archive.
        The URL expires in 1 hour.
      operationId: downloadEndpoint
      security:
        - ApiKeyAuth: []
      parameters:
        - name: endpoint_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      url:
                        type: string
                        description: Pre-signed download URL (expires in 1 hour)
                        example: https://storage.leaks.ai/archives/abc123.zip?token=...
                      expires_in:
                        type: integer
                        description: URL expiration time in seconds
                        example: 3600
              example:
                data:
                  url: https://storage.leaks.ai/archives/abc123.zip?token=...
                  expires_in: 3600
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Download feature not enabled for this organization
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                type: permission_denied
                status: 403
                detail: Archive download is not enabled for your organization.
        '404':
          description: Endpoint not found or archive unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                type: not_found
                status: 404
                detail: Endpoint not found or archive is not available.
  /resources:
    get:
      tags:
        - Resources
      summary: List resources
      description: >-
        Returns paginated resources (domains, IPs, APKs) associated with leaks.
        Includes owned and third-party; Scope by domain(s).
      operationId: listResources
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/domain_id'
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: risk_level
          in: query
          schema:
            type: string
        - name: resource
          in: query
          description: Search by resource name (substring)
          schema:
            type: string
        - name: is_internal
          in: query
          description: Filter by internal group (true/false)
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
        - name: is_third_party
          in: query
          description: true = only third-party, false = only owned
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
        - name: accessibility
          in: query
          description: Filter by accessibility status
          schema:
            type: string
            enum:
              - online
              - offline
              - unreachable
        - name: type
          in: query
          description: 'Filter by type; comma-separated: domain, ip, apk'
          schema:
            type: string
            example: domain,ip
        - name: sort
          in: query
          description: 'Sort: prefix - for desc. Allowed: risk_level'
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Resource'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
              example:
                data:
                  - id: e5f6a7b8-c9d0-1234-ef01-567890123456
                    resource: api.example.com
                    type: domain
                    is_internal: false
                    is_third_party: true
                    risk_level: 3
                    risk_level_name: low
                    accessibility: online
                pagination:
                  page: 1
                  per_page: 25
                  total_pages: 1
                  total_results: 18
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /resources/count:
    get:
      tags:
        - Resources
      summary: Count resources
      operationId: countResources
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/domain_id'
        - name: risk_level
          in: query
          schema:
            type: string
        - name: resource
          in: query
          schema:
            type: string
        - name: is_internal
          in: query
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
        - name: is_third_party
          in: query
          schema:
            type: string
            enum:
              - 'true'
              - 'false'
        - name: accessibility
          in: query
          schema:
            type: string
            enum:
              - online
              - offline
              - unreachable
        - name: type
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      count:
                        type: integer
                        example: 18
              example:
                data:
                  count: 18
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /resources/{resource_id}:
    get:
      tags:
        - Resources
      summary: Get resource by ID
      description: >-
        Returns a single resource with connections (endpoints and users). Users
        in connections have risk_level not None.
      operationId: getResource
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/domain_id'
        - name: resource_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/ResourceWithConnections'
              example:
                data:
                  id: e5f6a7b8-c9d0-1234-ef01-567890123456
                  resource: api.example.com
                  type: domain
                  is_internal: false
                  is_third_party: true
                  risk_level: 3
                  risk_level_name: low
                  accessibility: online
                  connections:
                    endpoints:
                      - id: d4e5f6a7-b8c9-0123-def0-456789012345
                        filename: '[US]93.101.28.33.rar'
                        date: '2025-12-04T14:30:00.000Z'
                    users:
                      - id: c3d4e5f6-a7b8-9012-cdef-345678901234
                        login: user@example.com
                        identity_type: email
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
  /users:
    get:
      tags:
        - Users
      summary: List users
      description: >-
        Returns paginated users — leaks grouped by login. Each user represents a
        unique identity (email or username) with an aggregated risk level across
        all associated leaks. Scope by domain(s).
      operationId: listUsers
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/domain_id'
        - $ref: '#/components/parameters/page'
        - $ref: '#/components/parameters/per_page'
        - name: risk_level
          in: query
          schema:
            type: string
        - name: login
          in: query
          description: Search by login (substring)
          schema:
            type: string
        - name: sort
          in: query
          description: 'Sort: prefix - for desc. Allowed: first_seen, login, risk_level'
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/User'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
              example:
                data:
                  - id: c3d4e5f6-a7b8-9012-cdef-345678901234
                    login: user@example.com
                    identity_type: email
                    first_seen: '2025-12-01T08:00:00.000Z'
                    risk_level: 5
                    risk_level_name: medium
                pagination:
                  page: 1
                  per_page: 25
                  total_pages: 3
                  total_results: 67
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /users/count:
    get:
      tags:
        - Users
      summary: Count users
      operationId: countUsers
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/domain_id'
        - name: risk_level
          in: query
          schema:
            type: string
        - name: login
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      count:
                        type: integer
                        example: 67
              example:
                data:
                  count: 67
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /users/{user_id}:
    get:
      tags:
        - Users
      summary: Get user by ID
      description: Returns a single user with connections (endpoints and resources).
      operationId: getUser
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/domain_id'
        - name: user_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/UserWithConnections'
              example:
                data:
                  id: c3d4e5f6-a7b8-9012-cdef-345678901234
                  login: user@example.com
                  identity_type: email
                  first_seen: '2025-12-01T08:00:00.000Z'
                  risk_level: 5
                  risk_level_name: medium
                  connections:
                    endpoints:
                      - id: d4e5f6a7-b8c9-0123-def0-456789012345
                        filename: '[US]93.101.28.33.rar'
                        date: '2025-12-04T14:30:00.000Z'
                    resources:
                      - id: b2c3d4e5-f6a7-8901-bcde-f23456789012
                        resource: api.example.com
                        type: domain
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: 'API key. Example: Api-Key YOUR_API_KEY'
  parameters:
    domain_id:
      name: domain_id
      in: query
      description: >-
        Domain UUID(s) to scope the request. Comma-separated for multiple. If
        omitted, all non-archived domains of the organization are used.
      schema:
        type: string
        format: uuid
      example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
    page:
      name: page
      in: query
      description: Page number (1-based).
      schema:
        type: integer
        default: 1
    per_page:
      name: per_page
      in: query
      description: Items per page (max 100).
      schema:
        type: integer
        default: 25
        maximum: 100
  responses:
    Unauthorized:
      description: Invalid or missing API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            type: authentication_failed
            status: 401
            detail: Invalid or missing API key.
    Forbidden:
      description: No access (e.g. no subscription for requested domains)
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            type: permission_denied
            status: 403
            detail: No subscription for one or more requested domains.
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            type: not_found
            status: 404
            detail: Leak not found.
    ValidationError:
      description: Invalid query or parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            type: validation_error
            status: 400
            detail: >-
              Invalid sort field: "foo". Valid: ["risk_level", "first_seen",
              "added_at"].
  schemas:
    Error:
      type: object
      properties:
        type:
          type: string
          example: validation_error
        status:
          type: integer
          example: 400
        detail:
          type: string
          example: >-
            Invalid sort field: "foo". Valid: ["risk_level", "first_seen",
            "added_at"].
    Pagination:
      type: object
      properties:
        page:
          type: integer
          example: 1
        per_page:
          type: integer
          example: 25
        total_pages:
          type: integer
          example: 4
        total_results:
          type: integer
          example: 92
    Domain:
      type: object
      properties:
        id:
          type: string
          format: uuid
          example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
        domain:
          type: string
          example: example.com
    Leak:
      type: object
      properties:
        id:
          type: string
          format: uuid
          example: f47ac10b-58cc-4372-a567-0e02b2c3d479
        risk_level:
          type: integer
          example: 5
        risk_level_name:
          type: string
          enum:
            - none
            - low
            - medium
            - high
          example: medium
        status:
          type: string
          enum:
            - new
            - investigating
            - resolved
            - false_positive
          example: new
        url:
          type: string
          nullable: true
          example: https://example.com/login
        login:
          type: string
          example: user@example.com
        password:
          type: string
          example: '***'
        first_seen:
          type: string
          format: date-time
          nullable: true
          description: ISO 8601 e.g. 2025-12-05T00:00:00.000Z
          example: '2025-12-05T00:00:00.000Z'
        added_at:
          type: string
          format: date-time
          nullable: true
          description: ISO 8601 e.g. 2025-12-05T01:09:22.879Z
          example: '2025-12-05T01:09:22.879Z'
    LeakWithConnections:
      allOf:
        - $ref: '#/components/schemas/Leak'
        - type: object
          properties:
            connections:
              type: object
              properties:
                resources:
                  type: array
                  items:
                    $ref: '#/components/schemas/ConnectionResource'
                users:
                  type: array
                  items:
                    $ref: '#/components/schemas/ConnectionUser'
                endpoints:
                  type: array
                  items:
                    $ref: '#/components/schemas/ConnectionEndpoint'
    ConnectionResource:
      type: object
      properties:
        id:
          type: string
          format: uuid
          example: b2c3d4e5-f6a7-8901-bcde-f23456789012
        resource:
          type: string
          example: api.example.com
        type:
          type: string
          enum:
            - domain
            - ip
            - apk
          example: domain
    ConnectionUser:
      type: object
      properties:
        id:
          type: string
          format: uuid
          example: c3d4e5f6-a7b8-9012-cdef-345678901234
        login:
          type: string
          example: user@example.com
        identity_type:
          type: string
          enum:
            - email
            - username
          example: email
    ConnectionEndpoint:
      type: object
      properties:
        id:
          type: string
          format: uuid
          example: d4e5f6a7-b8c9-0123-def0-456789012345
        filename:
          type: string
          example: '[US]93.101.28.33.rar'
        date:
          type: string
          format: date-time
          nullable: true
          example: '2025-12-04T14:30:00.000Z'
    Endpoint:
      type: object
      properties:
        id:
          type: string
          format: uuid
          example: d4e5f6a7-b8c9-0123-def0-456789012345
        date:
          type: string
          format: date-time
          nullable: true
          example: '2025-12-04T14:30:00.000Z'
        added_at:
          type: string
          format: date-time
          nullable: true
          example: '2025-12-05T01:09:22.879Z'
        metadata:
          type: object
          nullable: true
          description: May contain exfiltration_date (ISO 8601) and other fields
          example:
            exfiltration_date: '2025-12-04T14:30:00.000Z'
        risk_level:
          type: integer
          example: 4
        risk_level_name:
          type: string
          enum:
            - none
            - low
            - medium
            - high
          example: medium
        status:
          type: string
          enum:
            - new
            - investigating
            - resolved
            - false_positive
          example: new
        filename:
          type: string
          example: '[US]93.101.28.33.rar'
    EndpointDetail:
      allOf:
        - $ref: '#/components/schemas/Endpoint'
        - type: object
          properties:
            tree:
              type: array
              items:
                type: string
              description: File paths extracted from the stealer log archive
              example:
                - '[US]93.101.28.33.rar/All Passwords.txt'
                - '[US]93.101.28.33.rar/System.txt'
            connections:
              type: object
              properties:
                users:
                  type: array
                  items:
                    $ref: '#/components/schemas/ConnectionUser'
                resources:
                  type: array
                  items:
                    $ref: '#/components/schemas/ConnectionResource'
    Resource:
      type: object
      properties:
        id:
          type: string
          format: uuid
          example: e5f6a7b8-c9d0-1234-ef01-567890123456
        resource:
          type: string
          example: api.example.com
        type:
          type: string
          enum:
            - domain
            - ip
            - apk
          example: domain
        is_internal:
          type: boolean
          example: false
        is_third_party:
          type: boolean
          example: true
        risk_level:
          type: integer
          example: 3
        risk_level_name:
          type: string
          enum:
            - none
            - low
            - medium
            - high
          example: low
        accessibility:
          type: string
          nullable: true
          enum:
            - online
            - offline
            - unreachable
          example: online
    ResourceWithConnections:
      allOf:
        - $ref: '#/components/schemas/Resource'
        - type: object
          properties:
            connections:
              type: object
              properties:
                endpoints:
                  type: array
                  items:
                    $ref: '#/components/schemas/ConnectionEndpoint'
                users:
                  type: array
                  items:
                    $ref: '#/components/schemas/ConnectionUser'
    User:
      type: object
      properties:
        id:
          type: string
          format: uuid
          example: c3d4e5f6-a7b8-9012-cdef-345678901234
        login:
          type: string
          example: user@example.com
        identity_type:
          type: string
          enum:
            - email
            - username
          example: email
        first_seen:
          type: string
          format: date-time
          nullable: true
          example: '2025-12-01T08:00:00.000Z'
        risk_level:
          type: integer
          example: 5
        risk_level_name:
          type: string
          enum:
            - none
            - low
            - medium
            - high
          example: medium
    UserWithConnections:
      allOf:
        - $ref: '#/components/schemas/User'
        - type: object
          properties:
            connections:
              type: object
              properties:
                endpoints:
                  type: array
                  items:
                    $ref: '#/components/schemas/ConnectionEndpoint'
                resources:
                  type: array
                  items:
                    $ref: '#/components/schemas/ConnectionResource'
