openapi: 3.0.3
info:
  title: PII Detection API
  description: |
    RESTful API for secure document PII (Personally Identifiable Information) detection with multi-tenant thread management.
    
    ## Features
    - 🔐 Secure authentication with private keys
    - 📄 PDF, JPG, PNG document processing
    - 🔍 AWS Textract & Comprehend integration
    - ⚡ Smart caching (60-80% API reduction)
    - 🔒 Complete data segregation per thread
    - 📊 Detailed PII detection results
    
    ## Authentication
    All endpoints (except thread creation) require both `thread_id` and `private_key` for authentication.
    
    ## Rate Limiting
    100 requests per hour per thread
    
    ## File Size Limits
    Maximum file size: 10MB
    
  version: 1.0.0
  contact:
    name: API Support
    url: https://redact.playground.rimbal.dev
  license:
    name: Proprietary
    
servers:
  - url: http://redact.playground.rimbal.dev/api/v1
    description: Production server
  - url: http://localhost/redact/api/v1
    description: Development server

tags:
  - name: Thread Management
    description: Create and manage isolated data threads
  - name: PII Detection
    description: Process documents and detect PII

paths:
  /thread_create.php:
    post:
      tags:
        - Thread Management
      summary: Create new thread
      description: |
        Creates a new thread and returns authentication credentials.
        
        **Important:** Store both `thread_id` and `private_key` securely. 
        The `private_key` cannot be retrieved later.
        
      operationId: createThread
      requestBody:
        description: Optional metadata for the thread
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                metadata:
                  type: object
                  description: Custom metadata for the thread
                  additionalProperties: true
                  example:
                    user_id: "12345"
                    app_name: "MyApp"
                    description: "Legal document review"
      responses:
        '201':
          description: Thread created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ThreadCreateResponse'
              examples:
                success:
                  value:
                    success: true
                    thread_id: "thread_abc123def456..."
                    private_key: "key_xyz789abc123..."
                    created_at: "2025-12-18 14:30:00"
                    message: "Thread created successfully. Keep the private_key secure!"
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalError'

  /process_file.php:
    post:
      tags:
        - PII Detection
      summary: Process document and detect PII
      description: |
        Uploads and processes a document (PDF, JPG, PNG) to detect Personally Identifiable Information.
        
        The file must be base64 encoded. Processing time varies based on document size and complexity (typically 10-60 seconds).
        
        **Authentication Required:** Both `thread_id` and `private_key` must be provided.
        
      operationId: processFile
      security:
        - ThreadAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProcessFileRequest'
            examples:
              pdfFile:
                summary: PDF Document
                value:
                  thread_id: "thread_abc123def456..."
                  private_key: "key_xyz789abc123..."
                  file_data: "JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQg..."
                  file_name: "document.pdf"
              imageFile:
                summary: Image File
                value:
                  thread_id: "thread_abc123def456..."
                  private_key: "key_xyz789abc123..."
                  file_data: "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQN..."
                  file_name: "scan.jpg"
      responses:
        '200':
          description: Document processed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProcessFileResponse'
              examples:
                success:
                  value:
                    success: true
                    thread_id: "thread_abc123def456..."
                    processing_time: "12345ms"
                    total_pages: 3
                    layout_count: 156
                    layouts_processed: 44
                    layouts_skipped: 112
                    unique_words: 523
                    pii_words: 18
                    total_pii_instances: 156
                    total_tables: 17
                    comprehend_calls: 44
                    optimization_rate: 71.8
                    cache:
                      before:
                        cache_exists: true
                        cached_words: 15
                        last_updated: "2025-12-18 14:30:00"
                      after:
                        cache_exists: true
                        cached_words: 18
                        last_updated: "2025-12-18 14:35:00"
                      words_learned: 3
                    tables:
                      - page: 1
                        table_index: 1
                        rows: 8
                        columns: 4
                        confidence: 99.6
                      - page: 1
                        table_index: 2
                        rows: 5
                        columns: 2
                        confidence: 99.5
                    pages:
                      - page_number: 1
                        pii_count: 52
                        pii_blocks:
                          - Type: "NAME"
                            Text: "John"
                            Score: 0.99
                            Left: 0.123
                            Top: 0.456
                            Width: 0.045
                            Height: 0.012
                        tables:
                          - table_index: 1
                            rows: 8
                            columns: 4
                            confidence: 99.6
                            data: [[{"text": "Earnings", "confidence": 80.9, "rowSpan": 1, "columnSpan": 1, "isHeader": true}]]
                        word_blocks: []
                        image_data: "base64_encoded_image..."
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalError'

  /thread_info.php:
    get:
      tags:
        - Thread Management
      summary: Get thread information
      description: |
        Retrieves detailed information about a specific thread including statistics and activity.
        
        **Authentication Required:** Both `thread_id` and `private_key` must be provided as query parameters.
        
      operationId: getThreadInfo
      security:
        - ThreadAuth: []
      parameters:
        - name: thread_id
          in: query
          required: true
          schema:
            type: string
          description: Thread identifier
          example: "thread_abc123def456..."
        - name: private_key
          in: query
          required: true
          schema:
            type: string
          description: Authentication private key
          example: "key_xyz789abc123..."
      responses:
        '200':
          description: Thread information retrieved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ThreadInfoResponse'
              examples:
                success:
                  value:
                    success: true
                    thread:
                      thread_id: "thread_abc123def456..."
                      created_at: "2025-12-18 14:30:00"
                      last_activity: "2025-12-18 15:45:00"
                      document_count: 3
                      total_pii_found: 156
                      total_api_calls: 45
                      metadata:
                        user_id: "12345"
                        app_name: "MyApp"
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'

  /thread_delete.php:
    delete:
      tags:
        - Thread Management
      summary: Delete thread
      description: |
        Permanently deletes a thread and all associated data including cache, documents, and statistics.
        
        **Warning:** This action cannot be undone!
        
        **Authentication Required:** Both `thread_id` and `private_key` must be provided.
        
      operationId: deleteThread
      security:
        - ThreadAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ThreadDeleteRequest'
            examples:
              default:
                value:
                  thread_id: "thread_abc123def456..."
                  private_key: "key_xyz789abc123..."
      responses:
        '200':
          description: Thread deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ThreadDeleteResponse'
              examples:
                success:
                  value:
                    success: true
                    thread_id: "thread_abc123def456..."
                    message: "Thread and all associated data deleted successfully"
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
    post:
      tags:
        - Thread Management
      summary: Delete thread (POST alternative)
      description: Alternative POST method for deleting threads (same as DELETE)
      operationId: deleteThreadPost
      security:
        - ThreadAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ThreadDeleteRequest'
      responses:
        '200':
          description: Thread deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ThreadDeleteResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'

components:
  securitySchemes:
    ThreadAuth:
      type: apiKey
      in: header
      name: X-Thread-Auth
      description: |
        Thread authentication requires both `thread_id` and `private_key`.
        Include them in the request body (POST/DELETE) or query parameters (GET).

  schemas:
    ThreadCreateResponse:
      type: object
      required:
        - success
        - thread_id
        - private_key
        - created_at
      properties:
        success:
          type: boolean
          example: true
        thread_id:
          type: string
          description: Unique thread identifier
          example: "thread_abc123def456..."
        private_key:
          type: string
          description: Authentication key (store securely!)
          example: "key_xyz789abc123..."
        created_at:
          type: string
          format: date-time
          description: Thread creation timestamp
          example: "2025-12-18 14:30:00"
        message:
          type: string
          example: "Thread created successfully. Keep the private_key secure!"

    ProcessFileRequest:
      type: object
      required:
        - thread_id
        - private_key
        - file_data
        - file_name
      properties:
        thread_id:
          type: string
          description: Thread identifier
          example: "thread_abc123def456..."
        private_key:
          type: string
          description: Authentication key
          example: "key_xyz789abc123..."
        file_data:
          type: string
          format: byte
          description: Base64 encoded file content
          example: "JVBERi0xLjQKJeLjz9MK..."
        file_name:
          type: string
          description: Original file name
          example: "document.pdf"

    ProcessFileResponse:
      type: object
      required:
        - success
        - thread_id
        - processing_time
        - total_pages
        - total_pii_instances
      properties:
        success:
          type: boolean
          example: true
        thread_id:
          type: string
          example: "thread_abc123def456..."
        processing_time:
          type: string
          description: Time taken to process
          example: "12345ms"
        total_pages:
          type: integer
          description: Number of pages in document
          example: 3
        layout_count:
          type: integer
          description: Total layouts detected
          example: 156
        layouts_processed:
          type: integer
          description: Layouts sent to Comprehend
          example: 44
        layouts_skipped:
          type: integer
          description: Layouts skipped (from cache)
          example: 112
        unique_words:
          type: integer
          description: Unique words in document
          example: 523
        pii_words:
          type: integer
          description: Words containing PII
          example: 18
        total_pii_instances:
          type: integer
          description: Total PII instances found
          example: 156
        total_tables:
          type: integer
          description: Total number of tables extracted from all pages
          example: 17
        comprehend_calls:
          type: integer
          description: AWS Comprehend API calls made
          example: 44
        optimization_rate:
          type: number
          format: float
          description: Cache optimization percentage
          example: 71.8
        cache:
          $ref: '#/components/schemas/CacheInfo'
        tables:
          type: array
          description: Summary of all tables found across all pages
          items:
            type: object
            properties:
              page:
                type: integer
                description: Page number where table was found
                example: 1
              table_index:
                type: integer
                description: Table index on the page
                example: 1
              rows:
                type: integer
                description: Number of rows in table
                example: 8
              columns:
                type: integer
                description: Number of columns in table
                example: 4
              confidence:
                type: number
                format: float
                description: Confidence score for table detection
                example: 99.6
        pages:
          type: array
          items:
            $ref: '#/components/schemas/PageData'

    CacheInfo:
      type: object
      properties:
        before:
          type: object
          properties:
            cache_exists:
              type: boolean
            cached_words:
              type: integer
            last_updated:
              type: string
        after:
          type: object
          properties:
            cache_exists:
              type: boolean
            cached_words:
              type: integer
            last_updated:
              type: string
        words_learned:
          type: integer
          description: New PII words added to cache

    PageData:
      type: object
      properties:
        page_number:
          type: integer
          example: 1
        pii_count:
          type: integer
          description: PII instances on this page
          example: 52
        pii_blocks:
          type: array
          items:
            $ref: '#/components/schemas/PIIBlock'
        word_blocks:
          type: array
          items:
            type: object
        tables:
          type: array
          description: Tables found on this page with full data
          items:
            type: object
            properties:
              table_index:
                type: integer
                description: Index of table on this page
                example: 1
              rows:
                type: integer
                description: Number of rows
                example: 8
              columns:
                type: integer
                description: Number of columns
                example: 4
              confidence:
                type: number
                format: float
                description: Confidence score
                example: 99.6
              data:
                type: array
                description: Array of rows, each containing cell objects with text and metadata
                items:
                  type: array
                  description: Row of cells
                  items:
                    type: object
                    properties:
                      text:
                        type: string
                        description: Cell text content
                      confidence:
                        type: number
                        description: Cell confidence score
                      rowSpan:
                        type: integer
                        description: Number of rows cell spans
                      columnSpan:
                        type: integer
                        description: Number of columns cell spans
                      isHeader:
                        type: boolean
                        description: Whether cell is a header
        image_data:
          type: string
          format: byte
          description: Base64 encoded page image

    PIIBlock:
      type: object
      properties:
        Type:
          type: string
          enum:
            - NAME
            - EMAIL
            - PHONE
            - ADDRESS
            - SSN
            - BANK_ACCOUNT_NUMBER
            - BANK_ROUTING
            - CREDIT_DEBIT_NUMBER
            - DATE_TIME
            - AGE
            - URL
            - USERNAME
            - PASSWORD
            - PIN
            - LICENSE_PLATE
            - VEHICLE_IDENTIFICATION_NUMBER
            - MAC_ADDRESS
            - IP_ADDRESS
          description: Type of PII detected
          example: "NAME"
        Text:
          type: string
          description: Detected text
          example: "John"
        Score:
          type: number
          format: float
          description: Confidence score (0-1)
          example: 0.99
        Left:
          type: number
          format: float
          description: Left position (0-1)
          example: 0.123
        Top:
          type: number
          format: float
          description: Top position (0-1)
          example: 0.456
        Width:
          type: number
          format: float
          description: Width (0-1)
          example: 0.045
        Height:
          type: number
          format: float
          description: Height (0-1)
          example: 0.012

    ThreadInfoResponse:
      type: object
      required:
        - success
        - thread
      properties:
        success:
          type: boolean
          example: true
        thread:
          $ref: '#/components/schemas/ThreadData'

    ThreadData:
      type: object
      properties:
        thread_id:
          type: string
          example: "thread_abc123def456..."
        created_at:
          type: string
          format: date-time
          example: "2025-12-18 14:30:00"
        last_activity:
          type: string
          format: date-time
          example: "2025-12-18 15:45:00"
        document_count:
          type: integer
          description: Number of documents processed
          example: 3
        total_pii_found:
          type: integer
          description: Total PII instances found across all documents
          example: 156
        total_api_calls:
          type: integer
          description: Total AWS API calls made
          example: 45
        metadata:
          type: object
          additionalProperties: true
          description: Custom metadata

    ThreadDeleteRequest:
      type: object
      required:
        - thread_id
        - private_key
      properties:
        thread_id:
          type: string
          description: Thread identifier
          example: "thread_abc123def456..."
        private_key:
          type: string
          description: Authentication key
          example: "key_xyz789abc123..."

    ThreadDeleteResponse:
      type: object
      required:
        - success
        - thread_id
        - message
      properties:
        success:
          type: boolean
          example: true
        thread_id:
          type: string
          example: "thread_abc123def456..."
        message:
          type: string
          example: "Thread and all associated data deleted successfully"

    ErrorResponse:
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
          description: Error message
          example: "Invalid thread_id or private_key"
        details:
          type: string
          description: Additional error details (optional)

  responses:
    BadRequest:
      description: Bad request - Invalid parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            missingField:
              value:
                success: false
                error: "file_data is required (base64 encoded)"
            invalidBase64:
              value:
                success: false
                error: "Invalid base64 encoding in file_data"
            fileTooLarge:
              value:
                success: false
                error: "File size exceeds 10MB limit"

    Unauthorized:
      description: Unauthorized - Invalid credentials
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            invalidCredentials:
              value:
                success: false
                error: "Invalid thread_id or private_key"
            missingCredentials:
              value:
                success: false
                error: "thread_id and private_key are required"

    NotFound:
      description: Not found - Thread does not exist
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            threadNotFound:
              value:
                success: false
                error: "Thread not found"

    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            serverError:
              value:
                success: false
                error: "Internal server error"

  examples:
    CreateThreadExample:
      value:
        metadata:
          user_id: "12345"
          app_name: "MyApp"
          description: "Legal document review session"

    ProcessFileExample:
      value:
        thread_id: "thread_abc123def456..."
        private_key: "key_xyz789abc123..."
        file_data: "JVBERi0xLjQKJeLjz9MKMyAwIG9iago..."
        file_name: "contract.pdf"

