openapi: 3.0.3
info:
  title: DomainOps API
  description: |
    Complete API specification for DomainOps - Domain and SSL monitoring platform.

    ## Features
    - Domain management with WHOIS and SSL tracking
    - Multi-endpoint monitoring per domain
    - Liveness/uptime monitoring
    - Health score tracking
    - Portfolio organization
    - Renewal tracking

    ## Authentication
    All API endpoints require authentication via API key. Include your API key in one of three ways:
    1. **Authorization header**: `Authorization: Bearer YOUR_API_KEY`
    2. **Query parameter**: `?api_key=YOUR_API_KEY`
    3. **Request body**: `{"api_key": "YOUR_API_KEY", ...}`

  version: 2.0.0
  contact:
    name: DomainOps API Support
  license:
    name: Proprietary

servers:
  - url: http://localhost:54321/functions/v1
    description: Local development (User API - Supabase Edge Functions)
  - url: https://your-project.supabase.co/functions/v1
    description: Production (User API - Supabase Edge Functions)
  - url: http://localhost:3003
    description: Local development (Public API)
  - url: https://api.domainops.io
    description: Production (Public API)

security:
  - bearerAuth: []
  - apiKeyQuery: []

paths:
  /api-auth:
    post:
      tags:
        - Authentication
      summary: Validate API Key
      description: Validate an API key and get team information
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - apiKey
                - endpoint
                - method
              properties:
                apiKey:
                  type: string
                  description: API key to validate
                endpoint:
                  type: string
                  description: Endpoint path being accessed
                method:
                  type: string
                  description: HTTP method being used
                userAgent:
                  type: string
                  description: User agent string
                ipAddress:
                  type: string
                  description: IP address of the client
      responses:
        '200':
          description: Valid API key
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  teamId:
                    type: string
                    format: uuid
                  apiTokenId:
                    type: string
                    format: uuid
        '401':
          $ref: '#/components/responses/Unauthorized'

  /api-domains:
    get:
      tags:
        - Domains
      summary: List Domains
      description: Get a paginated list of domains for your team with optional filtering
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
        - name: domain
          in: query
          description: Filter by domain name (partial match)
          schema:
            type: string
        - name: portfolio_id
          in: query
          description: Filter by portfolio
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: List of domains
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/DomainSummary'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
        '401':
          $ref: '#/components/responses/Unauthorized'

    post:
      tags:
        - Domains
      summary: Create Domain
      description: Create a new domain in your team
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DomainCreate'
      responses:
        '201':
          description: Domain created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DomainSummary'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /api-domains/{domainId}:
    get:
      tags:
        - Domains
      summary: Get Domain
      description: Get detailed information for a specific domain including WHOIS, SSL, and optionally endpoints
      parameters:
        - $ref: '#/components/parameters/domainId'
        - name: include_endpoints
          in: query
          description: Include all endpoints for this domain
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: Domain details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DomainDetail'
        '404':
          $ref: '#/components/responses/NotFound'

    put:
      tags:
        - Domains
      summary: Update Domain
      description: Update domain properties
      parameters:
        - $ref: '#/components/parameters/domainId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DomainUpdate'
      responses:
        '200':
          description: Domain updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DomainSummary'
        '404':
          $ref: '#/components/responses/NotFound'

    delete:
      tags:
        - Domains
      summary: Delete Domain
      description: Delete a domain (cascades to all endpoints and related data)
      parameters:
        - $ref: '#/components/parameters/domainId'
      responses:
        '200':
          description: Domain deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  deleted_domain:
                    type: string
        '404':
          $ref: '#/components/responses/NotFound'

  /api-domains/bulk:
    post:
      tags:
        - Domains
      summary: Bulk Create Domains
      description: Create multiple domains in a single request
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - operation
                - domains
              properties:
                operation:
                  type: string
                  enum: [create]
                domains:
                  type: array
                  items:
                    $ref: '#/components/schemas/DomainCreate'
      responses:
        '201':
          description: Domains created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  domains:
                    type: array
                    items:
                      $ref: '#/components/schemas/DomainSummary'

  /api-endpoints:
    get:
      tags:
        - Endpoints
      summary: List Endpoints
      description: Get a paginated list of endpoints for your team with optional filtering
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
        - name: domain_id
          in: query
          description: Filter by domain
          schema:
            type: string
            format: uuid
        - name: endpoint_type
          in: query
          description: Filter by endpoint type
          schema:
            type: string
            enum: [https, http, port]
        - name: is_enabled
          in: query
          description: Filter by enabled status
          schema:
            type: boolean
      responses:
        '200':
          description: List of endpoints
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/EndpointSummary'
                  pagination:
                    $ref: '#/components/schemas/Pagination'

    post:
      tags:
        - Endpoints
      summary: Create Endpoint
      description: Create a new endpoint for monitoring
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EndpointCreate'
      responses:
        '201':
          description: Endpoint created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EndpointSummary'
        '400':
          $ref: '#/components/responses/BadRequest'
        '409':
          description: Endpoint with this name already exists for this domain

  /api-endpoints/{endpointId}:
    get:
      tags:
        - Endpoints
      summary: Get Endpoint
      description: Get detailed information for a specific endpoint including SSL, liveness, and health scores
      parameters:
        - $ref: '#/components/parameters/endpointId'
      responses:
        '200':
          description: Endpoint details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EndpointDetail'
        '404':
          $ref: '#/components/responses/NotFound'

    put:
      tags:
        - Endpoints
      summary: Update Endpoint
      description: Update endpoint configuration
      parameters:
        - $ref: '#/components/parameters/endpointId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EndpointUpdate'
      responses:
        '200':
          description: Endpoint updated successfully
        '404':
          $ref: '#/components/responses/NotFound'

    delete:
      tags:
        - Endpoints
      summary: Delete Endpoint
      description: Delete an endpoint
      parameters:
        - $ref: '#/components/parameters/endpointId'
      responses:
        '200':
          description: Endpoint deleted successfully
        '404':
          $ref: '#/components/responses/NotFound'

  /api-endpoints/bulk:
    post:
      tags:
        - Endpoints
      summary: Bulk Create Endpoints
      description: Create multiple endpoints in a single request
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - operation
                - endpoints
              properties:
                operation:
                  type: string
                  enum: [create]
                endpoints:
                  type: array
                  items:
                    $ref: '#/components/schemas/EndpointCreate'
      responses:
        '201':
          description: Endpoints created successfully

  /api-liveness:
    get:
      tags:
        - Liveness Monitoring
      summary: List Liveness Configs
      description: Get liveness monitoring configurations
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
        - name: endpoint_id
          in: query
          schema:
            type: string
            format: uuid
        - name: domain_id
          in: query
          schema:
            type: string
            format: uuid
        - name: is_enabled
          in: query
          schema:
            type: boolean
      responses:
        '200':
          description: List of liveness configurations
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/LivenessConfig'
                  pagination:
                    $ref: '#/components/schemas/Pagination'

    post:
      tags:
        - Liveness Monitoring
      summary: Create Liveness Config
      description: Enable liveness monitoring for an endpoint
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LivenessConfigCreate'
      responses:
        '201':
          description: Liveness monitoring enabled
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LivenessConfig'
        '409':
          description: Liveness monitoring already configured for this endpoint

  /api-liveness/{livenessId}:
    get:
      tags:
        - Liveness Monitoring
      summary: Get Liveness Config
      description: Get details for a specific liveness configuration
      parameters:
        - $ref: '#/components/parameters/livenessId'
      responses:
        '200':
          description: Liveness configuration details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LivenessConfigDetail'

    put:
      tags:
        - Liveness Monitoring
      summary: Update Liveness Config
      description: Update liveness monitoring settings
      parameters:
        - $ref: '#/components/parameters/livenessId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LivenessConfigUpdate'
      responses:
        '200':
          description: Liveness configuration updated

    delete:
      tags:
        - Liveness Monitoring
      summary: Delete Liveness Config
      description: Disable/delete liveness monitoring
      parameters:
        - $ref: '#/components/parameters/livenessId'
      responses:
        '200':
          description: Liveness monitoring deleted

  /api-liveness/{livenessId}/results:
    get:
      tags:
        - Liveness Monitoring
      summary: Get Test Results
      description: Get recent liveness test results with response times
      parameters:
        - $ref: '#/components/parameters/livenessId'
        - name: hours
          in: query
          description: Number of hours to look back
          schema:
            type: integer
            default: 24
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
      responses:
        '200':
          description: List of test results
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/LivenessTestResult'
                  pagination:
                    $ref: '#/components/schemas/Pagination'

  /api-liveness/{livenessId}/stats:
    get:
      tags:
        - Liveness Monitoring
      summary: Get Historical Stats
      description: Get daily aggregated statistics
      parameters:
        - $ref: '#/components/parameters/livenessId'
        - name: days
          in: query
          description: Number of days to retrieve
          schema:
            type: integer
            default: 30
      responses:
        '200':
          description: Historical statistics
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/LivenessStats'

  /api-liveness/{livenessId}/status:
    get:
      tags:
        - Liveness Monitoring
      summary: Get Current Status
      description: Get current status with uptime percentages
      parameters:
        - $ref: '#/components/parameters/livenessId'
      responses:
        '200':
          description: Current liveness status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LivenessStatus'

  /api-endpoint-status/{endpointId}:
    get:
      tags:
        - Status & Health
      summary: Get Endpoint Status
      description: Get comprehensive endpoint status including SSL, liveness, and health scores
      parameters:
        - $ref: '#/components/parameters/endpointId'
      responses:
        '200':
          description: Comprehensive endpoint status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EndpointStatus'

  /api-endpoint-status:
    get:
      tags:
        - Status & Health
      summary: Get All Endpoints Status
      description: Get status summary for all endpoints with health filtering
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
        - name: domain_id
          in: query
          schema:
            type: string
            format: uuid
        - name: health
          in: query
          description: Filter by health status
          schema:
            type: string
            enum: [healthy, warning, critical]
      responses:
        '200':
          description: Endpoint status summary
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/EndpointStatusSummary'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
                  summary:
                    type: object
                    properties:
                      healthy:
                        type: integer
                      warning:
                        type: integer
                      critical:
                        type: integer
                      unknown:
                        type: integer

  /api-domain-status/{domainId}:
    get:
      tags:
        - Status & Health
      summary: Get Domain Status
      description: Get comprehensive domain status including WHOIS, SSL, and health
      parameters:
        - $ref: '#/components/parameters/domainId'
      responses:
        '200':
          description: Domain status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DomainStatus'

  # ============================================================================
  # Public API Endpoints (v1)
  # ============================================================================
  /health:
    get:
      tags:
        - Public API - Health
      summary: Health Check
      description: Health check endpoint (no authentication required)
      security: []
      responses:
        '200':
          description: Service is healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  service:
                    type: string
                    example: domainops-public-api
                  version:
                    type: string
                    example: v1
                  timestamp:
                    type: string
                    format: date-time
                  database:
                    type: string
                    example: connected
        '503':
          description: Service is degraded or unavailable
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: degraded
                  service:
                    type: string
                  database:
                    type: string
                    example: disconnected
                  error:
                    type: string

  /api/v1/validate:
    get:
      tags:
        - Public API - Authentication
      summary: Validate API Key
      description: Validate API token and get token information
      responses:
        '200':
          description: Valid API key
          content:
            application/json:
              schema:
                type: object
                properties:
                  valid:
                    type: boolean
                    example: true
                  team_id:
                    type: string
                    format: uuid
                  token_name:
                    type: string
                  message:
                    type: string
        '401':
          $ref: '#/components/responses/Unauthorized'

  /api/v1/auth:
    post:
      tags:
        - Public API - Authentication
      summary: Authenticate
      description: Authenticate API request (same as validate, but POST)
      responses:
        '200':
          description: Authentication successful
          content:
            application/json:
              schema:
                type: object
                properties:
                  authenticated:
                    type: boolean
                    example: true
                  team_id:
                    type: string
                    format: uuid
                  user_id:
                    type: string
                    format: uuid
                  token_name:
                    type: string
                  message:
                    type: string
        '401':
          $ref: '#/components/responses/Unauthorized'

  /api/v1/portfolios:
    get:
      tags:
        - Public API - Portfolios
      summary: List Portfolios
      description: List all portfolios for the authenticated team
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
        - name: name
          in: query
          description: Filter by portfolio name (partial match)
          schema:
            type: string
      responses:
        '200':
          description: List of portfolios
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/PortfolioSummary'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
        '401':
          $ref: '#/components/responses/Unauthorized'

    post:
      tags:
        - Public API - Portfolios
      summary: Create Portfolio
      description: Create a new portfolio
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
              properties:
                name:
                  type: string
                description:
                  type: string
      responses:
        '201':
          description: Portfolio created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortfolioSummary'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /api/v1/portfolios/{portfolioId}:
    get:
      tags:
        - Public API - Portfolios
      summary: Get Portfolio
      description: Get a single portfolio by ID
      parameters:
        - name: portfolioId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Portfolio details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortfolioSummary'
        '404':
          $ref: '#/components/responses/NotFound'

    put:
      tags:
        - Public API - Portfolios
      summary: Update Portfolio
      description: Update an existing portfolio
      parameters:
        - name: portfolioId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                description:
                  type: string
      responses:
        '200':
          description: Portfolio updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortfolioSummary'
        '404':
          $ref: '#/components/responses/NotFound'

    delete:
      tags:
        - Public API - Portfolios
      summary: Delete Portfolio
      description: Delete a portfolio (only if it has no associated domains)
      parameters:
        - name: portfolioId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Portfolio deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  deleted_portfolio:
                    type: string
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Portfolio contains domains and cannot be deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string

  /api/v1/domains:
    get:
      tags:
        - Public API - Domains
      summary: List Domains
      description: List all domains for the authenticated team
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
        - name: domain
          in: query
          description: Filter by domain name (partial match)
          schema:
            type: string
        - name: portfolio_id
          in: query
          description: Filter by portfolio ID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: List of domains
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/DomainSummary'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
        '401':
          $ref: '#/components/responses/Unauthorized'

    post:
      tags:
        - Public API - Domains
      summary: Create Domain
      description: Create a new domain
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DomainCreate'
      responses:
        '201':
          description: Domain created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DomainSummary'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /api/v1/domains/bulk:
    post:
      tags:
        - Public API - Domains
      summary: Create Domains (Bulk)
      description: Create multiple domains in a single request
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - domains
              properties:
                domains:
                  type: array
                  items:
                    $ref: '#/components/schemas/DomainCreate'
      responses:
        '201':
          description: Domains created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/DomainSummary'
                  created:
                    type: integer
                  failed:
                    type: integer
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /api/v1/domains/{domainId}:
    get:
      tags:
        - Public API - Domains
      summary: Get Domain
      description: Get a single domain by ID with detailed information
      parameters:
        - name: domainId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: include_endpoints
          in: query
          description: Include all endpoints for this domain
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: Domain details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DomainDetail'
        '404':
          $ref: '#/components/responses/NotFound'

    put:
      tags:
        - Public API - Domains
      summary: Update Domain
      description: Update an existing domain
      parameters:
        - name: domainId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DomainUpdate'
      responses:
        '200':
          description: Domain updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DomainSummary'
        '404':
          $ref: '#/components/responses/NotFound'

    delete:
      tags:
        - Public API - Domains
      summary: Delete Domain
      description: Delete a domain
      parameters:
        - name: domainId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Domain deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  deleted_domain:
                    type: string
        '404':
          $ref: '#/components/responses/NotFound'

  /api/v1/domains/{domainId}/status:
    get:
      tags:
        - Public API - Domains
      summary: Get Domain Status
      description: Get domain status information (WHOIS, expiry, etc.)
      parameters:
        - name: domainId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Domain status information
          content:
            application/json:
              schema:
                type: object
                properties:
                  domain_id:
                    type: string
                    format: uuid
                  whois_expiry:
                    type: string
                    format: date-time
                  registrar:
                    type: string
                  last_checked_at:
                    type: string
                    format: date-time
        '404':
          $ref: '#/components/responses/NotFound'

  /api/v1/endpoints:
    get:
      tags:
        - Public API - Endpoints
      summary: List Endpoints
      description: List all endpoints for the authenticated team
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
        - name: domain_id
          in: query
          description: Filter by domain ID
          schema:
            type: string
            format: uuid
        - name: endpoint_type
          in: query
          description: Filter by endpoint type
          schema:
            type: string
            enum: [https, http, port]
        - name: is_enabled
          in: query
          description: Filter by enabled status
          schema:
            type: boolean
      responses:
        '200':
          description: List of endpoints
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Endpoint'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
        '401':
          $ref: '#/components/responses/Unauthorized'

    post:
      tags:
        - Public API - Endpoints
      summary: Create Endpoint
      description: Create a new endpoint
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - domain_id
                - name
                - endpoint_type
              properties:
                domain_id:
                  type: string
                  format: uuid
                name:
                  type: string
                endpoint_type:
                  type: string
                  enum: [https, http, port]
                subdomain:
                  type: string
                path:
                  type: string
                port:
                  type: integer
                is_enabled:
                  type: boolean
                  default: true
                timeout_seconds:
                  type: integer
                  default: 10
      responses:
        '201':
          description: Endpoint created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EndpointDetail'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /api/v1/endpoints/bulk:
    post:
      tags:
        - Public API - Endpoints
      summary: Create Endpoints (Bulk)
      description: Create multiple endpoints in a single request
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - endpoints
              properties:
                endpoints:
                  type: array
                  items:
                    type: object
                    required:
                      - domain_id
                      - name
                      - endpoint_type
                    properties:
                      domain_id:
                        type: string
                        format: uuid
                      name:
                        type: string
                      endpoint_type:
                        type: string
                        enum: [https, http, port]
                      subdomain:
                        type: string
                      path:
                        type: string
                      port:
                        type: integer
                      is_enabled:
                        type: boolean
                      timeout_seconds:
                        type: integer
      responses:
        '201':
          description: Endpoints created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Endpoint'
                  created:
                    type: integer
                  failed:
                    type: integer
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /api/v1/endpoints/{endpointId}:
    get:
      tags:
        - Public API - Endpoints
      summary: Get Endpoint
      description: Get a single endpoint by ID with detailed information
      parameters:
        - name: endpointId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Endpoint details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EndpointDetail'
        '404':
          $ref: '#/components/responses/NotFound'

    put:
      tags:
        - Public API - Endpoints
      summary: Update Endpoint
      description: Update an existing endpoint
      parameters:
        - name: endpointId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                endpoint_type:
                  type: string
                  enum: [https, http, port]
                subdomain:
                  type: string
                path:
                  type: string
                port:
                  type: integer
                is_enabled:
                  type: boolean
                timeout_seconds:
                  type: integer
      responses:
        '200':
          description: Endpoint updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EndpointDetail'
        '404':
          $ref: '#/components/responses/NotFound'

    delete:
      tags:
        - Public API - Endpoints
      summary: Delete Endpoint
      description: Delete an endpoint
      parameters:
        - name: endpointId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Endpoint deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  deleted_endpoint:
                    type: string
        '404':
          $ref: '#/components/responses/NotFound'

  /api/v1/endpoints/{endpointId}/status:
    get:
      tags:
        - Public API - Endpoints
      summary: Get Endpoint Status
      description: Get endpoint SSL status information
      parameters:
        - name: endpointId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Endpoint SSL status
          content:
            application/json:
              schema:
                type: object
                properties:
                  endpoint_id:
                    type: string
                    format: uuid
                  cert_expiry:
                    type: string
                    format: date-time
                  issuer:
                    type: string
                  subject:
                    type: string
                  last_checked_at:
                    type: string
                    format: date-time
        '404':
          $ref: '#/components/responses/NotFound'

  /api/v1/liveness:
    get:
      tags:
        - Public API - Liveness
      summary: List Liveness Configurations
      description: List all liveness configurations for the authenticated team
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
        - name: endpoint_id
          in: query
          description: Filter by endpoint ID
          schema:
            type: string
            format: uuid
        - name: domain_id
          in: query
          description: Filter by domain ID
          schema:
            type: string
            format: uuid
        - name: is_enabled
          in: query
          description: Filter by enabled status
          schema:
            type: boolean
      responses:
        '200':
          description: List of liveness configurations
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/LivenessConfigDetail'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
        '401':
          $ref: '#/components/responses/Unauthorized'

    post:
      tags:
        - Public API - Liveness
      summary: Create Liveness Configuration
      description: Create a new liveness monitoring configuration
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - endpoint_id
              properties:
                endpoint_id:
                  type: string
                  format: uuid
                is_enabled:
                  type: boolean
                  default: true
                timeout_seconds:
                  type: integer
                  default: 10
                expected_status_code:
                  type: integer
                  default: 200
      responses:
        '201':
          description: Liveness configuration created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LivenessConfigDetail'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /api/v1/liveness/{livenessId}:
    get:
      tags:
        - Public API - Liveness
      summary: Get Liveness Configuration
      description: Get a single liveness configuration by ID
      parameters:
        - name: livenessId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Liveness configuration details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LivenessConfigDetail'
        '404':
          $ref: '#/components/responses/NotFound'

    put:
      tags:
        - Public API - Liveness
      summary: Update Liveness Configuration
      description: Update an existing liveness configuration
      parameters:
        - name: livenessId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                is_enabled:
                  type: boolean
                timeout_seconds:
                  type: integer
                expected_status_code:
                  type: integer
      responses:
        '200':
          description: Liveness configuration updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LivenessConfigDetail'
        '404':
          $ref: '#/components/responses/NotFound'

    delete:
      tags:
        - Public API - Liveness
      summary: Delete Liveness Configuration
      description: Delete a liveness configuration
      parameters:
        - name: livenessId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Liveness configuration deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  deleted_liveness:
                    type: string
        '404':
          $ref: '#/components/responses/NotFound'

  /api/v1/liveness/{livenessId}/results:
    get:
      tags:
        - Public API - Liveness
      summary: Get Liveness Results
      description: Get liveness test results for a configuration
      parameters:
        - name: livenessId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
      responses:
        '200':
          description: Liveness test results
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          format: uuid
                        is_successful:
                          type: boolean
                        test_timestamp:
                          type: string
                          format: date-time
                        response_time_ms:
                          type: integer
                  pagination:
                    $ref: '#/components/schemas/Pagination'
        '404':
          $ref: '#/components/responses/NotFound'

  /api/v1/liveness/{livenessId}/stats:
    get:
      tags:
        - Public API - Liveness
      summary: Get Liveness Stats
      description: Get liveness statistics for a configuration
      parameters:
        - name: livenessId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Liveness statistics
          content:
            application/json:
              schema:
                type: object
                properties:
                  total_tests:
                    type: integer
                  successful_tests:
                    type: integer
                  success_rate:
                    type: number
                    format: float
                  avg_response_time_ms:
                    type: integer
                  status:
                    type: string
                    enum: [healthy, warning, critical]
                  consecutive_failures:
                    type: integer
        '404':
          $ref: '#/components/responses/NotFound'

  /api/v1/liveness/{livenessId}/status:
    get:
      tags:
        - Public API - Liveness
      summary: Get Liveness Status
      description: Get current liveness status for a configuration
      parameters:
        - name: livenessId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Current liveness status
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum: [up, down]
                  consecutive_failures:
                    type: integer
                  last_check:
                    type: string
                    format: date-time
                  last_check_successful:
                    type: boolean
                  response_time_ms:
                    type: integer
        '404':
          $ref: '#/components/responses/NotFound'

  /api/v1/renewals:
    get:
      tags:
        - Public API - Renewals
      summary: Get Renewals
      description: Get domain and SSL certificate renewal information
      parameters:
        - name: type
          in: query
          description: Type of renewals to retrieve
          schema:
            type: string
            enum: [domains, certificates]
            default: domains
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 100
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
        - name: from
          in: query
          description: Filter renewals from date (ISO 8601 format)
          schema:
            type: string
            format: date-time
        - name: to
          in: query
          description: Filter renewals to date (ISO 8601 format)
          schema:
            type: string
            format: date-time
        - name: status
          in: query
          description: Filter by status
          schema:
            type: string
            enum: [active, expired, expiring_soon]
      responses:
        '200':
          description: Renewal information
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        domain:
                          type: string
                        endpoint_name:
                          type: string
                        type:
                          type: string
                          enum: [domain, ssl]
                        current_expiry:
                          type: string
                          format: date-time
                        days_until_expiry:
                          type: integer
                        status:
                          type: string
                          enum: [active, expired, expiring_soon]
                        registrar:
                          type: string
                        issuer:
                          type: string
                        portfolio_name:
                          type: string
                  pagination:
                    $ref: '#/components/schemas/Pagination'
        '401':
          $ref: '#/components/responses/Unauthorized'

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
    apiKeyQuery:
      type: apiKey
      in: query
      name: api_key

  parameters:
    domainId:
      name: domainId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Domain UUID

    endpointId:
      name: endpointId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Endpoint UUID

    livenessId:
      name: livenessId
      in: path
      required: true
      schema:
        type: string
        format: uuid
      description: Liveness configuration UUID

  schemas:
    Pagination:
      type: object
      properties:
        limit:
          type: integer
        offset:
          type: integer
        total:
          type: integer

    HealthScore:
      type: object
      properties:
        overall_score:
          type: integer
          minimum: 0
          maximum: 100
        domain_health_score:
          type: integer
          minimum: 0
          maximum: 100
        ssl_health_score:
          type: integer
          minimum: 0
          maximum: 100
        liveness_health_score:
          type: integer
          minimum: 0
          maximum: 100
        score_breakdown:
          type: object
        recommendations:
          type: array
          items:
            type: string
        calculated_at:
          type: string
          format: date-time

    DomainCreate:
      type: object
      required:
        - domain
      properties:
        domain:
          type: string
          example: example.com
        portfolio_id:
          type: string
          format: uuid
        notes:
          type: string

    DomainUpdate:
      type: object
      properties:
        domain:
          type: string
        portfolio_id:
          type: string
          format: uuid
        notes:
          type: string

    DomainSummary:
      type: object
      properties:
        id:
          type: string
          format: uuid
        domain:
          type: string
        portfolio_id:
          type: string
          format: uuid
        portfolio_name:
          type: string
        notes:
          type: string
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    DomainDetail:
      allOf:
        - $ref: '#/components/schemas/DomainSummary'
        - type: object
          properties:
            team_id:
              type: string
              format: uuid
            owner_user_id:
              type: string
              format: uuid
            whois_status:
              type: object
              properties:
                expiry_date:
                  type: string
                  format: date-time
                registrar:
                  type: string
                creation_date:
                  type: string
                  format: date-time
                updated_date:
                  type: string
                  format: date-time
                statuses:
                  type: array
                  items:
                    type: string
                name_servers:
                  type: array
                  items:
                    type: string
            ssl_status:
              type: object
              properties:
                cert_expiry:
                  type: string
                  format: date-time
                issuer:
                  type: string
                days_until_expiry:
                  type: integer
            health_score:
              $ref: '#/components/schemas/HealthScore'
            endpoints:
              type: array
              items:
                type: object
                properties:
                  id:
                    type: string
                    format: uuid
                  name:
                    type: string
                  endpoint_type:
                    type: string
                    enum: [https, http, port]
                  full_url:
                    type: string
                  is_enabled:
                    type: boolean
                  health_score:
                    type: integer

    EndpointCreate:
      type: object
      required:
        - domain_id
        - name
        - endpoint_type
      properties:
        domain_id:
          type: string
          format: uuid
        name:
          type: string
          example: www
        endpoint_type:
          type: string
          enum: [https, http, port]
        subdomain:
          type: string
          example: www
        path:
          type: string
          default: /
        port:
          type: integer
          minimum: 1
          maximum: 65535
        is_enabled:
          type: boolean
          default: true
        timeout_seconds:
          type: integer
          default: 30
        notes:
          type: string

    EndpointUpdate:
      type: object
      properties:
        name:
          type: string
        endpoint_type:
          type: string
          enum: [https, http, port]
        subdomain:
          type: string
        path:
          type: string
        port:
          type: integer
        is_enabled:
          type: boolean
        timeout_seconds:
          type: integer
        notes:
          type: string

    EndpointSummary:
      type: object
      properties:
        id:
          type: string
          format: uuid
        domain_id:
          type: string
          format: uuid
        domain:
          type: string
        name:
          type: string
        endpoint_type:
          type: string
          enum: [https, http, port]
        full_url:
          type: string
        is_enabled:
          type: boolean
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    EndpointDetail:
      allOf:
        - $ref: '#/components/schemas/EndpointSummary'
        - type: object
          properties:
            subdomain:
              type: string
            path:
              type: string
            port:
              type: integer
            timeout_seconds:
              type: integer
            notes:
              type: string
            ssl_status:
              type: object
              properties:
                cert_expiry:
                  type: string
                  format: date-time
                issuer:
                  type: string
                days_until_expiry:
                  type: integer
            liveness_config:
              type: object
              properties:
                id:
                  type: string
                  format: uuid
                is_enabled:
                  type: boolean
                timeout_seconds:
                  type: integer
            health_score:
              $ref: '#/components/schemas/HealthScore'

    LivenessConfigCreate:
      type: object
      required:
        - endpoint_id
      properties:
        endpoint_id:
          type: string
          format: uuid
        is_enabled:
          type: boolean
          default: true
        timeout_seconds:
          type: integer
          default: 30

    LivenessConfigUpdate:
      type: object
      properties:
        is_enabled:
          type: boolean
        timeout_seconds:
          type: integer

    LivenessConfig:
      type: object
      properties:
        id:
          type: string
          format: uuid
        endpoint_id:
          type: string
          format: uuid
        endpoint_name:
          type: string
        domain:
          type: string
        is_enabled:
          type: boolean
        timeout_seconds:
          type: integer
        created_at:
          type: string
          format: date-time

    LivenessConfigDetail:
      allOf:
        - $ref: '#/components/schemas/LivenessConfig'
        - type: object
          properties:
            endpoint_url:
              type: string
            updated_at:
              type: string
              format: date-time

    LivenessTestResult:
      type: object
      properties:
        timestamp:
          type: string
          format: date-time
        is_successful:
          type: boolean
        response_time_ms:
          type: integer
        status_code:
          type: integer
        error_message:
          type: string

    LivenessStats:
      type: object
      properties:
        date:
          type: string
          format: date
        total_tests:
          type: integer
        successful_tests:
          type: integer
        success_rate:
          type: number
          format: float
        avg_response_time_ms:
          type: integer

    LivenessStatus:
      type: object
      properties:
        endpoint:
          type: string
        status:
          type: string
          enum: [up, down]
        consecutive_failures:
          type: integer
        last_failure:
          type: string
          format: date-time
        last_check:
          type: string
          format: date-time
        last_check_successful:
          type: boolean
        uptime_24h:
          type: number
          format: float
        uptime_7d:
          type: number
          format: float
        avg_response_time_ms:
          type: integer
        is_monitoring_enabled:
          type: boolean

    EndpointStatus:
      type: object
      properties:
        endpoint:
          type: object
          properties:
            id:
              type: string
              format: uuid
            name:
              type: string
            full_url:
              type: string
            domain:
              type: string
        ssl:
          type: object
          properties:
            status:
              type: string
              enum: [valid, expiring_soon, expired, unknown]
            cert_expiry:
              type: string
              format: date-time
            days_until_expiry:
              type: integer
            issuer:
              type: string
        liveness:
          $ref: '#/components/schemas/LivenessStatus'
        health_score:
          $ref: '#/components/schemas/HealthScore'
        overall_health:
          type: string
          enum: [healthy, warning, critical, unknown]

    PortfolioSummary:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        description:
          type: string
        domain_count:
          type: integer
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time

    EndpointStatusSummary:
      type: object
      properties:
        id:
          type: string
          format: uuid
        domain:
          type: string
        name:
          type: string
        full_url:
          type: string
        is_enabled:
          type: boolean
        ssl_status:
          type: string
          enum: [valid, expiring_soon, expired, unknown]
        ssl_days_until_expiry:
          type: integer
        liveness_enabled:
          type: boolean
        health_score:
          type: integer
        overall_health:
          type: string
          enum: [healthy, warning, critical, unknown]

    DomainStatus:
      type: object
      properties:
        domain:
          type: object
          properties:
            id:
              type: string
              format: uuid
            domain:
              type: string
        whois:
          type: object
          properties:
            registrar:
              type: string
            expiry_date:
              type: string
              format: date-time
            days_until_expiry:
              type: integer
            status:
              type: string
              enum: [active, expired, expiring_soon]
        ssl:
          type: object
          properties:
            issuer:
              type: string
            expiry_date:
              type: string
              format: date-time
            days_until_expiry:
              type: integer
            status:
              type: string
              enum: [active, expired, expiring_soon]
        overall_status:
          type: string
          enum: [healthy, warning, critical]

  responses:
    Unauthorized:
      description: Unauthorized - Invalid or missing API key
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: Invalid or inactive API key

    BadRequest:
      description: Bad Request - Invalid input
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string

    NotFound:
      description: Not Found - Resource does not exist
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: Resource not found

tags:
  - name: Authentication
    description: API key validation
  - name: Domains
    description: Domain management with WHOIS and SSL tracking
  - name: Portfolios
    description: Portfolio organization for domains
  - name: Endpoints
    description: Multi-endpoint monitoring per domain
  - name: Liveness Monitoring
    description: Uptime and liveness monitoring configuration
  - name: Status & Health
    description: Unified status views with health scores
  - name: Public API - Health
    description: Public API health check endpoint (no authentication required)
  - name: Public API - Authentication
    description: Public API authentication endpoints
  - name: Public API - Portfolios
    description: Public API portfolio management
  - name: Public API - Domains
    description: Public API domain management
  - name: Public API - Endpoints
    description: Public API endpoint management
  - name: Public API - Liveness
    description: Public API liveness monitoring
  - name: Public API - Renewals
    description: Public API renewal tracking
