---
components:
  responses: {}
  schemas:
    SearchErrorResponse:
      description: Search failure response returned by the search controller.
      properties:
        details:
          description: Search backend error details
          x-struct:
          x-validate:
        error:
          example: Search failed
          type: string
          x-struct:
          x-validate:
      required:
        - error
        - details
      title: SearchErrorResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.SearchErrorResponse
      x-validate:
    CollectionsResponse:
      description: Response containing a list of collections
      properties:
        data:
          description: List of collections
          items:
            $ref: '#/components/schemas/Collection'
          type: array
          x-struct:
          x-validate:
      required:
        - data
      title: CollectionsResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.CollectionsResponse
      x-validate:
    AdminViewerResolveResponse:
      properties:
        data:
          properties:
            device_limit_override:
              nullable: true
              type: integer
              x-struct:
              x-validate:
            external_id:
              type: string
              x-struct:
              x-validate:
            session_management_exempt:
              type: boolean
              x-struct:
              x-validate:
            viewer_id:
              format: uuid
              type: string
              x-struct:
              x-validate:
          required:
            - viewer_id
            - external_id
            - session_management_exempt
          type: object
          x-struct:
          x-validate:
      required:
        - data
      title: AdminViewerResolveResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AdminViewerResolveResponse
      x-validate:
    Error:
      description: API error response
      properties:
        code:
          description: Machine-readable error code
          example: not_found
          type: string
          x-struct:
          x-validate:
        message:
          description: Human-readable error message
          example: Video not found
          type: string
          x-struct:
          x-validate:
        retryable:
          description: Whether the request can be retried
          example: false
          type: boolean
          x-struct:
          x-validate:
        type:
          description: Error type
          example: error
          type: string
          x-struct:
          x-validate:
      required:
        - code
        - message
      title: Error
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.Error
      x-validate:
    ViewerMemory:
      description: A viewer's AI-maintained memory document, distilled from their conversations.
      properties:
        content:
          description: The distilled memory document. AI-maintained; cleared via DELETE; regrows from future conversations unless `enabled` is false. Null when nothing has been distilled yet.
          example: |-
            Situation & goals:
            - Runs a 3-person agency scaling to $1M ARR.
          nullable: true
          type: string
          x-struct:
          x-validate:
        conversations_count:
          description: Number of summarized conversations that fed this memory.
          example: 4
          type: integer
          x-struct:
          x-validate:
        enabled:
          description: Whether memory distillation is active for this viewer. Set false via PATCH to opt out (re-distillation stops; existing content is retained until cleared).
          example: true
          type: boolean
          x-struct:
          x-validate:
        last_conversation_at:
          description: Timestamp of the most recent conversation activity.
          format: date-time
          nullable: true
          type: string
          x-struct:
          x-validate:
        last_distilled_at:
          description: When the memory document was last rewritten.
          format: date-time
          nullable: true
          type: string
          x-struct:
          x-validate:
        updated_at:
          description: Last update timestamp for the memory row.
          format: date-time
          nullable: true
          type: string
          x-struct:
          x-validate:
      required:
        - content
        - enabled
        - conversations_count
      title: ViewerMemory
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ViewerMemory
      x-validate:
    ProgressListResponse:
      description: Response containing a list of progress records with metadata
      example:
        data:
          - completed: false
            completed_at:
            created_at: 2026-01-07T12:00:00Z
            current_time: 300
            duration: 1000
            id: 98936fa0-6826-48cc-aac1-89f42235dc8e
            percentage: 30.0
            updated_at: 2026-01-07T12:05:00Z
            video_id: 87654321-4321-4321-4321-987654321cba
            viewer_id: 12345678-1234-1234-1234-123456789abc
        meta:
          completed: 3
          in_progress: 7
          total: 10
      properties:
        data:
          description: List of progress records
          items:
            $ref: '#/components/schemas/Progress'
          type: array
          x-struct:
          x-validate:
        meta:
          properties:
            completed:
              description: Number of completed videos
              type: integer
              x-struct:
              x-validate:
            in_progress:
              description: Number of videos in progress
              type: integer
              x-struct:
              x-validate:
            total:
              description: Total number of progress records
              type: integer
              x-struct:
              x-validate:
          type: object
          x-struct:
          x-validate:
      required:
        - data
        - meta
      title: ProgressListResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.Progress.ProgressListResponse
      x-validate:
    ConversationVideoContext:
      description: Lightweight video metadata for conversation listings
      properties:
        id:
          description: Video external ID (hashid or UUID per account settings)
          type: string
          x-struct:
          x-validate:
        thumbnail_url:
          description: Video thumbnail URL
          nullable: true
          type: string
          x-struct:
          x-validate:
        title:
          description: Video title
          type: string
          x-struct:
          x-validate:
        url:
          description: Video page URL on portal
          nullable: true
          type: string
          x-struct:
          x-validate:
      required:
        - id
        - title
      title: ConversationVideoContext
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ConversationVideoContext
      x-validate:
    SessionManagementRevokeSessionResponse:
      properties:
        ok:
          type: boolean
          x-struct:
          x-validate:
        session_id:
          format: uuid
          type: string
          x-struct:
          x-validate:
      required:
        - ok
        - session_id
      title: SessionManagementRevokeSessionResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.SessionManagementRevokeSessionResponse
      x-validate:
    AdminSessionManagementExemptionResponse:
      properties:
        data:
          properties:
            device_limit_override:
              nullable: true
              type: integer
              x-struct:
              x-validate:
            session_management_exempt:
              type: boolean
              x-struct:
              x-validate:
            viewer_id:
              format: uuid
              type: string
              x-struct:
              x-validate:
          required:
            - viewer_id
            - session_management_exempt
          type: object
          x-struct:
          x-validate:
      required:
        - data
      title: AdminSessionManagementExemptionResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AdminSessionManagementExemptionResponse
      x-validate:
    ConversationPagination:
      properties:
        has_more:
          type: boolean
          x-struct:
          x-validate:
        limit:
          type: integer
          x-struct:
          x-validate:
        offset:
          type: integer
          x-struct:
          x-validate:
      required:
        - limit
        - offset
        - has_more
      title: ConversationPagination
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ConversationPagination
      x-validate:
    CommunityComment:
      description: A comment on a community post
      properties:
        author:
          $ref: '#/components/schemas/CommunityAuthor'
        content:
          description: Comment content
          example: Great post! Thanks for sharing.
          type: string
          x-struct:
          x-validate:
        created_at:
          description: Creation timestamp
          format: date-time
          type: string
          x-struct:
          x-validate:
        depth:
          description: Nesting depth (0 = top-level, max 2)
          example: 0
          type: integer
          x-struct:
          x-validate:
        id:
          description: Comment UUID
          format: uuid
          type: string
          x-struct:
          x-validate:
        reactions:
          description: Reactions summary (mirrors the post shape, without reacted_by)
          properties:
            count:
              description: Total number of reactions
              example: 5
              type: integer
              x-struct:
              x-validate:
            viewer_has_reacted:
              description: Whether the current viewer has reacted (only when X-Viewer-ID header is provided)
              nullable: true
              type: boolean
              x-struct:
              x-validate:
          required:
            - count
          type: object
          x-struct:
          x-validate:
        replies:
          description: Nested replies (same structure as comment)
          items:
            type: object
            x-struct:
            x-validate:
          type: array
          x-struct:
          x-validate:
        updated_at:
          description: Last update timestamp
          format: date-time
          type: string
          x-struct:
          x-validate:
      required:
        - id
        - content
        - depth
        - reactions
        - author
        - created_at
      title: CommunityComment
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.CommunityComment
      x-validate:
    ConversationResponse:
      description: Full conversation history
      properties:
        conversation_id:
          description: Conversation ID
          type: string
          x-struct:
          x-validate:
        created_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
        messages:
          description: Message history
          items:
            properties:
              content:
                type: string
                x-struct:
                x-validate:
              role:
                enum:
                  - user
                  - assistant
                type: string
                x-struct:
                x-validate:
            type: object
            x-struct:
            x-validate:
          type: array
          x-struct:
          x-validate:
        updated_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
      required:
        - conversation_id
        - messages
      title: ConversationResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ConversationResponse
      x-validate:
    AiSearchRequest:
      description: Search request with optional AI synthesis
      example:
        limit: 10
        prompt: authentication setup
      properties:
        collection_id:
          description: Filter to a specific collection (legacy single-value filter)
          nullable: true
          type: string
          x-struct:
          x-validate:
        collection_ids:
          description: Filter to multiple collections (OR semantics)
          items:
            type: string
            x-struct:
            x-validate:
          nullable: true
          type: array
          x-struct:
          x-validate:
        images:
          description: Optional array of images (max 5). Requires the Vision feature flag. Each image can be base64-encoded or a URL.
          items:
            anyOf:
              - $ref: '#/components/schemas/AiImageBase64'
              - $ref: '#/components/schemas/AiImageUrl'
            x-struct:
            x-validate:
          maxItems: 5
          nullable: true
          type: array
          x-struct:
          x-validate:
        limit:
          description: 'Maximum sources to return (default: 15)'
          example: 10
          type: integer
          x-struct:
          x-validate:
        prompt:
          description: Search query
          example: How do I set up authentication?
          type: string
          x-struct:
          x-validate:
        stream:
          default: true
          description: 'Stream response via SSE (default: true)'
          type: boolean
          x-struct:
          x-validate:
        tags:
          description: Filter by video tags
          items:
            type: string
            x-struct:
            x-validate:
          nullable: true
          type: array
          x-struct:
          x-validate:
        video_id:
          description: Filter to a specific video
          nullable: true
          type: string
          x-struct:
          x-validate:
      required:
        - prompt
      title: AiSearchRequest
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AiSearchRequest
      x-validate:
    ApiAuthErrorResponse:
      description: Authentication failure response returned by API token plugs.
      properties:
        error:
          example: Unauthorized
          type: string
          x-struct:
          x-validate:
        status:
          example: 401
          type: integer
          x-struct:
          x-validate:
        timestamp:
          example: 2026-04-25 04:00:00Z
          type: string
          x-struct:
          x-validate:
      required:
        - error
        - status
        - timestamp
      title: ApiAuthErrorResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ApiAuthErrorResponse
      x-validate:
    ProgressUpsert:
      description: Parameters for creating or updating progress
      example:
        progress:
          completed: false
          current_time: 500
          duration: 1000
      properties:
        progress:
          properties:
            completed:
              default: false
              description: Whether the video has been completed
              type: boolean
              x-struct:
              x-validate:
            current_time:
              description: Current playback position in seconds
              minimum: 0
              type: integer
              x-struct:
              x-validate:
            duration:
              description: Total video duration in seconds
              minimum: 1
              type: integer
              x-struct:
              x-validate:
          required:
            - current_time
            - duration
          type: object
          x-struct:
          x-validate:
      required:
        - progress
      title: ProgressUpsert
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.Progress.ProgressUpsert
      x-validate:
    CommunityPostsResponse:
      description: Response containing a list of community posts
      properties:
        data:
          description: List of community posts
          items:
            $ref: '#/components/schemas/CommunityPost'
          type: array
          x-struct:
          x-validate:
        meta:
          description: Pagination metadata
          properties:
            page:
              description: Current page number (1-indexed)
              example: 1
              type: integer
              x-struct:
              x-validate:
            page_size:
              description: Items per page
              example: 20
              type: integer
              x-struct:
              x-validate:
            total_entries:
              description: Total number of items across all pages
              example: 47
              type: integer
              x-struct:
              x-validate:
            total_pages:
              description: Total number of pages
              example: 3
              type: integer
              x-struct:
              x-validate:
          required:
            - page
            - page_size
            - total_entries
            - total_pages
          type: object
          x-struct:
          x-validate:
      required:
        - data
        - meta
      title: CommunityPostsResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.CommunityPostsResponse
      x-validate:
    Progress:
      description: A viewer's progress on a video
      example:
        completed: false
        completed_at:
        created_at: 2026-01-07T12:00:00Z
        current_time: 300
        duration: 1000
        id: 98936fa0-6826-48cc-aac1-89f42235dc8e
        percentage: 30.0
        updated_at: 2026-01-07T12:05:00Z
        video_id: 87654321-4321-4321-4321-987654321cba
        viewer_id: 12345678-1234-1234-1234-123456789abc
      properties:
        completed:
          description: Whether the video has been completed
          type: boolean
          x-struct:
          x-validate:
        completed_at:
          description: Timestamp when video was completed
          format: date-time
          nullable: true
          type: string
          x-struct:
          x-validate:
        created_at:
          description: Record creation timestamp
          format: date-time
          type: string
          x-struct:
          x-validate:
        current_time:
          description: Current playback position in seconds
          minimum: 0
          type: integer
          x-struct:
          x-validate:
        duration:
          description: Total video duration in seconds
          minimum: 1
          type: integer
          x-struct:
          x-validate:
        id:
          description: Progress record UUID
          format: uuid
          type: string
          x-struct:
          x-validate:
        percentage:
          description: Completion percentage (0-100)
          format: decimal
          type: number
          x-struct:
          x-validate:
        updated_at:
          description: Record last updated timestamp
          format: date-time
          type: string
          x-struct:
          x-validate:
        video_id:
          description: Video UUID
          format: uuid
          type: string
          x-struct:
          x-validate:
        viewer_id:
          description: Viewer UUID
          format: uuid
          type: string
          x-struct:
          x-validate:
      required:
        - id
        - viewer_id
        - video_id
        - current_time
        - duration
        - percentage
        - completed
      title: Progress
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.Progress.Progress
      x-validate:
    HeroSettings:
      description: Hero section configuration
      properties:
        type:
          description: Hero section type
          enum:
            - none
            - custom
          example: none
          type: string
          x-struct:
          x-validate:
      required:
        - type
      title: HeroSettings
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.HeroSettings
      x-validate:
    CommunityCommentResponse:
      description: Response containing a single comment
      properties:
        data:
          $ref: '#/components/schemas/CommunityComment'
      required:
        - data
      title: CommunityCommentResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.CommunityCommentResponse
      x-validate:
    AdminSessionManagementExemptionRequest:
      properties:
        exempt:
          description: Whether this viewer is exempt from session-management enforcement.
          type: boolean
          x-struct:
          x-validate:
      required:
        - exempt
      title: AdminSessionManagementExemptionRequest
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AdminSessionManagementExemptionRequest
      x-validate:
    AiImageUrl:
      description: Image referenced by URL (will be fetched and validated)
      properties:
        type:
          description: Image type
          enum:
            - url
          type: string
          x-struct:
          x-validate:
        url:
          description: HTTPS URL pointing to an image (max 20MB)
          type: string
          x-struct:
          x-validate:
      required:
        - type
        - url
      title: AiImageUrl
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AiImageUrl
      x-validate:
    VideoConversationListResponse:
      properties:
        conversations:
          items:
            $ref: '#/components/schemas/ConversationSummary'
          type: array
          x-struct:
          x-validate:
        pagination:
          $ref: '#/components/schemas/ConversationPagination'
        video_id:
          type: string
          x-struct:
          x-validate:
      required:
        - video_id
        - conversations
        - pagination
      title: VideoConversationListResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.VideoConversationListResponse
      x-validate:
    ProgressResponse:
      description: Response containing a single progress record
      example:
        data:
          completed: false
          completed_at:
          created_at: 2026-01-07T12:00:00Z
          current_time: 300
          duration: 1000
          id: 98936fa0-6826-48cc-aac1-89f42235dc8e
          percentage: 30.0
          updated_at: 2026-01-07T12:05:00Z
          video_id: 87654321-4321-4321-4321-987654321cba
          viewer_id: 12345678-1234-1234-1234-123456789abc
      properties:
        data:
          $ref: '#/components/schemas/Progress'
      required:
        - data
      title: ProgressResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.Progress.ProgressResponse
      x-validate:
    CommunityAuthor:
      description: Author information for community posts and comments
      properties:
        avatar_url:
          description: Author avatar URL
          example: https://example.com/avatar.jpg
          format: uri
          nullable: true
          type: string
          x-struct:
          x-validate:
        id:
          description: Author UUID
          format: uuid
          type: string
          x-struct:
          x-validate:
        name:
          description: Author display name
          example: John Doe
          type: string
          x-struct:
          x-validate:
      required:
        - id
        - name
      title: CommunityAuthor
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.CommunityAuthor
      x-validate:
    ThemeConfig:
      description: Theme configuration with light and dark mode tokens
      properties:
        color_scheme:
          description: Color scheme preference
          enum:
            - light
            - dark
            - toggle
          type: string
          x-struct:
          x-validate:
        dark:
          $ref: '#/components/schemas/ThemeTokens'
        light:
          $ref: '#/components/schemas/ThemeTokens'
        radius:
          description: Border radius
          example: 0.625rem
          type: string
          x-struct:
          x-validate:
      title: ThemeConfig
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ThemeConfig
      x-validate:
    ThemeTokens:
      description: OKLCH color tokens for a theme mode (light or dark)
      properties:
        accent:
          description: Accent color (OKLCH)
          type: string
          x-struct:
          x-validate:
        accent_foreground:
          description: Accent foreground color (OKLCH)
          type: string
          x-struct:
          x-validate:
        background:
          description: Background color (OKLCH)
          type: string
          x-struct:
          x-validate:
        border:
          description: Border color (OKLCH)
          type: string
          x-struct:
          x-validate:
        foreground:
          description: Foreground/text color (OKLCH)
          type: string
          x-struct:
          x-validate:
        muted:
          description: Muted background color (OKLCH)
          type: string
          x-struct:
          x-validate:
        muted_foreground:
          description: Muted text color (OKLCH)
          type: string
          x-struct:
          x-validate:
        primary:
          description: Optional sidebar primary color for buttons/headers (OKLCH)
          nullable: true
          type: string
          x-struct:
          x-validate:
        ring:
          description: Focus ring color (OKLCH)
          type: string
          x-struct:
          x-validate:
        sidebar:
          description: Optional sidebar background color (OKLCH)
          nullable: true
          type: string
          x-struct:
          x-validate:
        sidebarAccent:
          description: Optional sidebar accent color for section headers (OKLCH)
          nullable: true
          type: string
          x-struct:
          x-validate:
        surface:
          description: Surface/card color (OKLCH)
          type: string
          x-struct:
          x-validate:
      title: ThemeTokens
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ThemeTokens
      x-validate:
    AiSearchResponse:
      description: Search results with AI synthesis
      properties:
        content:
          description: Synthesized answer
          type: string
          x-struct:
          x-validate:
        query:
          description: Original search query
          type: string
          x-struct:
          x-validate:
        sources:
          description: Source citations
          items:
            $ref: '#/components/schemas/Citation'
          type: array
          x-struct:
          x-validate:
      required:
        - content
        - sources
        - query
      title: AiSearchResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AiSearchResponse
      x-validate:
    AdminViewerSessionsResponse:
      properties:
        data:
          items:
            $ref: '#/components/schemas/AdminSessionWithRevocation'
          type: array
          x-struct:
          x-validate:
      required:
        - data
      title: AdminViewerSessionsResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AdminViewerSessionsResponse
      x-validate:
    ViewerCreate:
      description: Parameters for creating a viewer
      properties:
        avatar_url:
          description: URL to avatar image
          example: https://example.com/avatars/john.jpg
          format: uri
          nullable: true
          type: string
          x-struct:
          x-validate:
        display_name:
          description: Preferred display name
          example: Johnny D
          nullable: true
          type: string
          x-struct:
          x-validate:
        email:
          description: Viewer email
          example: john@example.com
          format: email
          type: string
          x-struct:
          x-validate:
        external_id:
          description: External ID from course platform
          example: usr_123abc
          nullable: true
          type: string
          x-struct:
          x-validate:
        first_name:
          description: First name
          example: John
          nullable: true
          type: string
          x-struct:
          x-validate:
        last_name:
          description: Last name
          example: Doe
          nullable: true
          type: string
          x-struct:
          x-validate:
        name:
          description: Viewer name
          example: John Doe
          type: string
          x-struct:
          x-validate:
        traits:
          description: Custom traits map
          example:
            business_name: Acme Corp
            stage: growth
          nullable: true
          type: object
          x-struct:
          x-validate:
      required:
        - name
      title: ViewerCreate
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ViewerCreate
      x-validate:
    SessionManagementRevokeAllResponse:
      properties:
        ok:
          type: boolean
          x-struct:
          x-validate:
        revoked_count:
          type: integer
          x-struct:
          x-validate:
      required:
        - ok
        - revoked_count
      title: SessionManagementRevokeAllResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.SessionManagementRevokeAllResponse
      x-validate:
    PlaylistResponse:
      description: Single playlist with videos
      properties:
        data:
          $ref: '#/components/schemas/Playlist'
      required:
        - data
      title: PlaylistResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.PlaylistResponse
      x-validate:
    CustomRedirect:
      description: A branded shortlink redirect
      properties:
        path:
          description: URL path (e.g., /apple)
          example: /apple
          type: string
          x-struct:
          x-validate:
        permanent:
          description: Whether redirect is permanent (301 vs 307)
          example: false
          type: boolean
          x-struct:
          x-validate:
        url:
          description: Target URL
          example: https://podcasts.apple.com/...
          type: string
          x-struct:
          x-validate:
      required:
        - path
        - url
        - permanent
      title: CustomRedirect
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.CustomRedirect
      x-validate:
    SessionManagementViewerSessionsResponse:
      properties:
        data:
          items:
            $ref: '#/components/schemas/SessionManagementSessionWithRevocation'
          type: array
          x-struct:
          x-validate:
        viewer:
          $ref: '#/components/schemas/SessionManagementViewerState'
      required:
        - viewer
        - data
      title: SessionManagementViewerSessionsResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.SessionManagementViewerSessionsResponse
      x-validate:
    AiChatRequest:
      description: Request body for AI chat endpoints
      example:
        prompt: What are the key takeaways from this video?
        stream: false
      properties:
        conversation_id:
          description: Existing conversation ID to continue
          nullable: true
          type: string
          x-struct:
          x-validate:
        current_time:
          description: Current video playback position in seconds for contextual answers
          nullable: true
          type: integer
          x-struct:
          x-validate:
        images:
          description: Optional array of images (max 5). Requires the Vision feature flag. Each image can be base64-encoded or a URL.
          items:
            anyOf:
              - $ref: '#/components/schemas/AiImageBase64'
              - $ref: '#/components/schemas/AiImageUrl'
            x-struct:
            x-validate:
          maxItems: 5
          nullable: true
          type: array
          x-struct:
          x-validate:
        max_tokens:
          description: Maximum tokens in response
          nullable: true
          type: integer
          x-struct:
          x-validate:
        model:
          description: AI model to use (optional, uses account default)
          nullable: true
          type: string
          x-struct:
          x-validate:
        prompt:
          description: The user's question or prompt
          example: What are the main topics discussed in this video?
          type: string
          x-struct:
          x-validate:
        stream:
          default: true
          description: 'Whether to stream the response via SSE (default: true)'
          type: boolean
          x-struct:
          x-validate:
        temperature:
          description: Temperature for response generation (0.0-2.0)
          format: float
          nullable: true
          type: number
          x-struct:
          x-validate:
        viewer:
          description: Viewer identifier (UUID or your external ID) to associate with the conversation. When the viewers feature is enabled, the viewer's traits also personalize AI responses.
          nullable: true
          type: string
          x-struct:
          x-validate:
        viewer_profile:
          anyOf:
            - description: Free text or markdown describing the viewer; replaces the synced viewer's traits for this request. Up to 8000 characters.
              example: Sarah runs a 3-person agency, pre-launch, wants her first 10 customers.
              type: string
              x-struct:
              x-validate:
            - additionalProperties:
                anyOf:
                  - type: string
                    x-struct:
                    x-validate:
                  - type: number
                    x-struct:
                    x-validate:
                  - type: boolean
                    x-struct:
                    x-validate:
                x-struct:
                x-validate:
              description: Key-value traits merged over the synced viewer's traits (inline wins per key). Max 20 keys; keys must match ^[a-zA-Z_][a-zA-Z0-9_]*$; values are strings (up to 2000 characters), numbers, or booleans.
              example:
                business_name: Acme Corp
                goal: find first customers
                stage: growth
              type: object
              x-struct:
              x-validate:
          description: Tell the AI about the person asking, for this request only (never persisted). Pass free text/markdown, or a key-value object. Requires the viewers feature.
          nullable: true
          x-struct:
          x-validate:
      required:
        - prompt
      title: AiChatRequest
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AiChatRequest
      x-validate:
    AiChatResponse:
      description: JSON response from AI chat (when stream=false)
      properties:
        content:
          description: The AI's response content
          type: string
          x-struct:
          x-validate:
        conversation_id:
          description: Conversation ID for continuing the chat
          type: string
          x-struct:
          x-validate:
        id:
          description: 'Deprecated: Use conversation_id instead'
          type: string
          x-struct:
          x-validate:
        model:
          description: The AI model used
          example: claude-3-5-sonnet-20241022
          type: string
          x-struct:
          x-validate:
        usage:
          description: Token usage statistics
          properties:
            input_tokens:
              type: integer
              x-struct:
              x-validate:
            output_tokens:
              type: integer
              x-struct:
              x-validate:
          type: object
          x-struct:
          x-validate:
        video_id:
          description: The video's internal ID
          type: string
          x-struct:
          x-validate:
      required:
        - conversation_id
        - content
        - video_id
      title: AiChatResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AiChatResponse
      x-validate:
    RevokeAuthSessionResponse:
      properties:
        ok:
          type: boolean
          x-struct:
          x-validate:
        session_id:
          format: uuid
          type: string
          x-struct:
          x-validate:
      required:
        - ok
        - session_id
      title: RevokeAuthSessionResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.RevokeAuthSessionResponse
      x-validate:
    VideoConversationResponse:
      properties:
        conversation_id:
          type: string
          x-struct:
          x-validate:
        created_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
        messages:
          items:
            properties:
              content:
                type: string
                x-struct:
                x-validate:
              id:
                type: string
                x-struct:
                x-validate:
              inserted_at:
                format: date-time
                type: string
                x-struct:
                x-validate:
              role:
                enum:
                  - user
                  - assistant
                type: string
                x-struct:
                x-validate:
              sources:
                items:
                  type: object
                  x-struct:
                  x-validate:
                type: array
                x-struct:
                x-validate:
            type: object
            x-struct:
            x-validate:
          type: array
          x-struct:
          x-validate:
        metadata:
          type: object
          x-struct:
          x-validate:
        updated_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
        video_id:
          type: string
          x-struct:
          x-validate:
      required:
        - conversation_id
        - video_id
        - messages
        - created_at
        - updated_at
      title: VideoConversationResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.VideoConversationResponse
      x-validate:
    SessionManagementViewerResolveResponse:
      properties:
        data:
          $ref: '#/components/schemas/SessionManagementViewerState'
      required:
        - data
      title: SessionManagementViewerResolveResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.SessionManagementViewerResolveResponse
      x-validate:
    SearchHit:
      description: A raw Meilisearch hit for a matching transcript segment or indexed video document.
      properties:
        _rankingScore:
          description: Meilisearch ranking score when returned
          nullable: true
          type: number
          x-struct:
          x-validate:
        document_type:
          description: Indexed document type, such as transcript or attachment
          nullable: true
          type: string
          x-struct:
          x-validate:
        duration_ms:
          description: Segment duration in milliseconds
          nullable: true
          type: integer
          x-struct:
          x-validate:
        id:
          description: Search document ID
          type: string
          x-struct:
          x-validate:
        speaker:
          description: Speaker name when identified, otherwise the diarization label.
          nullable: true
          type: string
          x-struct:
          x-validate:
        speaker_label:
          description: Raw diarization label, or null.
          nullable: true
          type: string
          x-struct:
          x-validate:
        speaker_name:
          description: Resolved speaker name, or null.
          nullable: true
          type: string
          x-struct:
          x-validate:
        text:
          description: Matched transcript text
          nullable: true
          type: string
          x-struct:
          x-validate:
        timestamp_end_ms:
          description: Segment end time in milliseconds
          nullable: true
          type: integer
          x-struct:
          x-validate:
        timestamp_start_ms:
          description: Segment start time in milliseconds
          nullable: true
          type: integer
          x-struct:
          x-validate:
        title:
          description: Source video title
          nullable: true
          type: string
          x-struct:
          x-validate:
        video_id:
          description: Source video UUID
          type: string
          x-struct:
          x-validate:
      title: SearchHit
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.SearchHit
      x-validate:
    ViewerMemoryUpdate:
      description: Parameters for updating a viewer's memory settings.
      properties:
        memory:
          description: Memory settings to update.
          properties:
            enabled:
              description: Set false to opt the viewer out of re-distillation; true to opt back in.
              example: false
              type: boolean
              x-struct:
              x-validate:
          required:
            - enabled
          type: object
          x-struct:
          x-validate:
      required:
        - memory
      title: ViewerMemoryUpdate
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ViewerMemoryUpdate
      x-validate:
    AdminRevokeAuthSessionResponse:
      properties:
        ok:
          type: boolean
          x-struct:
          x-validate:
        session_id:
          format: uuid
          type: string
          x-struct:
          x-validate:
      required:
        - ok
        - session_id
      title: AdminRevokeAuthSessionResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AdminRevokeAuthSessionResponse
      x-validate:
    ViewerUpdate:
      description: Parameters for updating a viewer
      properties:
        avatar_url:
          description: URL to avatar image
          example: https://example.com/avatars/john.jpg
          format: uri
          nullable: true
          type: string
          x-struct:
          x-validate:
        display_name:
          description: Preferred display name
          example: Johnny D
          nullable: true
          type: string
          x-struct:
          x-validate:
        email:
          description: Viewer email
          example: john@example.com
          format: email
          type: string
          x-struct:
          x-validate:
        external_id:
          description: External ID from course platform
          example: usr_123abc
          nullable: true
          type: string
          x-struct:
          x-validate:
        first_name:
          description: First name
          example: John
          nullable: true
          type: string
          x-struct:
          x-validate:
        last_name:
          description: Last name
          example: Doe
          nullable: true
          type: string
          x-struct:
          x-validate:
        name:
          description: Viewer name
          example: John Doe
          type: string
          x-struct:
          x-validate:
        traits:
          description: Custom traits map
          example:
            business_name: Acme Corp
            stage: growth
          nullable: true
          type: object
          x-struct:
          x-validate:
      title: ViewerUpdate
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ViewerUpdate
      x-validate:
    VideosResponse:
      description: Response containing a list of videos
      properties:
        data:
          description: List of videos
          items:
            $ref: '#/components/schemas/Video'
          type: array
          x-struct:
          x-validate:
      required:
        - data
      title: VideosResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.VideosResponse
      x-validate:
    PortalSettings:
      description: Portal configuration
      properties:
        analytics:
          $ref: '#/components/schemas/AnalyticsSettings'
        auth:
          description: Authentication configuration
          type: object
          x-struct:
          x-validate:
        color_scheme:
          description: Color scheme
          enum:
            - light
            - dark
            - toggle
          type: string
          x-struct:
          x-validate:
        custom_redirects:
          description: Branded shortlink redirects
          items:
            $ref: '#/components/schemas/CustomRedirect'
          type: array
          x-struct:
          x-validate:
        display:
          description: Display configuration
          type: object
          x-struct:
          x-validate:
        hero:
          $ref: '#/components/schemas/HeroSettings'
        layout:
          description: Layout configuration
          type: object
          x-struct:
          x-validate:
        navigation:
          description: Navigation configuration
          type: object
          x-struct:
          x-validate:
        theme:
          description: Theme configuration
          type: object
          x-struct:
          x-validate:
      title: PortalSettings
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.PortalSettings
      x-validate:
    LibraryAiChatResponse:
      description: |
        AI response with citations from your video library.

        Citation indices in the answer text (e.g., `[4]`) map to source array positions: `[4]` → `sources[3]`.
        Each source has a `cited` boolean indicating whether it's referenced in the answer.
      properties:
        citations:
          deprecated: true
          description: 'Deprecated: Use `sources` instead. Same data as sources.'
          items:
            $ref: '#/components/schemas/Citation'
          type: array
          x-struct:
          x-validate:
        content:
          description: AI response
          type: string
          x-struct:
          x-validate:
        conversation_id:
          description: Conversation ID for follow-up questions
          type: string
          x-struct:
          x-validate:
        metadata:
          anyOf:
            - $ref: '#/components/schemas/LibraryAiRetrievalMetadata'
          description: Public-safe retrieval metadata for answer responses. Clarification responses may omit this field.
          nullable: true
          x-struct:
          x-validate:
        response_type:
          description: Whether this is a direct answer or clarifying question
          enum:
            - answer
            - clarification
          type: string
          x-struct:
          x-validate:
        sources:
          description: 'All retrieved sources. Each has `cited: true/false` to indicate if referenced in the answer.'
          items:
            $ref: '#/components/schemas/Citation'
          type: array
          x-struct:
          x-validate:
      required:
        - conversation_id
        - content
        - response_type
        - sources
      title: LibraryAiChatResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.LibraryAiChatResponse
      x-validate:
    AnalyticsSettings:
      description: Analytics provider configuration
      properties:
        provider:
          description: Analytics provider
          enum:
            - none
            - plausible
            - ga4
            - fathom
          example: none
          type: string
          x-struct:
          x-validate:
        site_id:
          description: Analytics site ID
          nullable: true
          type: string
          x-struct:
          x-validate:
      required:
        - provider
      title: AnalyticsSettings
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AnalyticsSettings
      x-validate:
    AuthSessionChallengeResponse:
      properties:
        challenge_id:
          format: uuid
          type: string
          x-struct:
          x-validate:
        challenge_required:
          type: boolean
          x-struct:
          x-validate:
        email_hint:
          description: Masked destination email for the verification code.
          nullable: true
          type: string
          x-struct:
          x-validate:
      required:
        - challenge_required
        - challenge_id
        - email_hint
      title: AuthSessionChallengeResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AuthSessionChallengeResponse
      x-validate:
    UnifiedConversationListResponse:
      description: Paginated list of all conversations for a viewer across all scopes
      properties:
        conversations:
          items:
            $ref: '#/components/schemas/UnifiedConversationSummary'
          type: array
          x-struct:
          x-validate:
        pagination:
          $ref: '#/components/schemas/ConversationPagination'
      required:
        - conversations
        - pagination
      title: UnifiedConversationListResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.UnifiedConversationListResponse
      x-validate:
    ProjectSettings:
      description: Public configuration for your video portal
      properties:
        data:
          description: Settings data
          properties:
            account:
              description: Per-account capability flags
              properties:
                multimodal:
                  $ref: '#/components/schemas/MultimodalSettings'
              type: object
              x-struct:
              x-validate:
            ai_avatar:
              description: AI assistant avatar URL
              nullable: true
              type: string
              x-struct:
              x-validate:
            ai_greeting:
              description: AI greeting message
              nullable: true
              type: string
              x-struct:
              x-validate:
            ai_name:
              description: AI assistant name
              nullable: true
              type: string
              x-struct:
              x-validate:
            chat_disclaimer:
              description: Disclaimer text displayed below the AI chat input
              nullable: true
              type: string
              x-struct:
              x-validate:
            favicon_url:
              description: Favicon URL
              nullable: true
              type: string
              x-struct:
              x-validate:
            has_ai:
              description: Whether AI features are enabled
              type: boolean
              x-struct:
              x-validate:
            logo_url:
              description: Logo URL
              nullable: true
              type: string
              x-struct:
              x-validate:
            name:
              description: Account name
              type: string
              x-struct:
              x-validate:
            portal:
              $ref: '#/components/schemas/PortalSettings'
            slug:
              description: Account slug
              type: string
              x-struct:
              x-validate:
            theme_config:
              $ref: '#/components/schemas/ThemeConfig'
          type: object
          x-struct:
          x-validate:
        version:
          description: API version
          example: '0.1'
          type: string
          x-struct:
          x-validate:
      required:
        - version
        - data
      title: ProjectSettings
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ProjectSettings
      x-validate:
    LibraryAiRetrievalMetadata:
      description: Public-safe retrieval status metadata for library AI answers. Internal stage names, timeouts, query counts, and fallback timing are intentionally omitted.
      properties:
        degraded:
          description: True when retrieval recovered through a degraded fallback path
          type: boolean
          x-struct:
          x-validate:
        degraded_reason:
          description: Coarse public reason for degraded retrieval, when degraded is true
          enum:
            - stage1_exhausted
          nullable: true
          type: string
          x-struct:
          x-validate:
        retrieval_mode:
          description: Whether the answer used the normal retrieval path or a degraded fallback path
          enum:
            - normal
            - degraded
          type: string
          x-struct:
          x-validate:
      required:
        - retrieval_mode
        - degraded
      title: LibraryAiRetrievalMetadata
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.LibraryAiRetrievalMetadata
      x-validate:
    AiImageBase64:
      description: Base64-encoded image
      properties:
        data:
          description: Base64-encoded image data (max 20MB decoded)
          type: string
          x-struct:
          x-validate:
        media_type:
          description: MIME type of the image
          enum:
            - image/png
            - image/jpeg
            - image/webp
            - image/gif
          type: string
          x-struct:
          x-validate:
        type:
          description: Image type
          enum:
            - base64
          type: string
          x-struct:
          x-validate:
      required:
        - type
        - media_type
        - data
      title: AiImageBase64
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AiImageBase64
      x-validate:
    SessionManagementRevokeSessionRequest:
      properties:
        reason:
          maxLength: 255
          nullable: true
          type: string
          x-struct:
          x-validate:
      title: SessionManagementRevokeSessionRequest
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.SessionManagementRevokeSessionRequest
      x-validate:
    CollectionVideosResponse:
      description: Response containing videos in a collection
      properties:
        data:
          description: List of videos in the collection
          items:
            $ref: '#/components/schemas/Video'
          type: array
          x-struct:
          x-validate:
      required:
        - data
      title: CollectionVideosResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.CollectionVideosResponse
      x-validate:
    PlaylistsResponse:
      description: List of playlists
      properties:
        data:
          description: Playlists
          items:
            $ref: '#/components/schemas/Playlist'
          type: array
          x-struct:
          x-validate:
      required:
        - data
      title: PlaylistsResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.PlaylistsResponse
      x-validate:
    ViewersResponse:
      description: Response containing a paginated list of viewers
      properties:
        data:
          description: List of viewers
          items:
            $ref: '#/components/schemas/Viewer'
          type: array
          x-struct:
          x-validate:
        meta:
          description: Pagination metadata
          properties:
            page:
              description: Current page number (1-indexed)
              example: 1
              type: integer
              x-struct:
              x-validate:
            page_size:
              description: Items per page
              example: 20
              type: integer
              x-struct:
              x-validate:
            total_entries:
              description: Total number of items across all pages
              example: 47
              type: integer
              x-struct:
              x-validate:
            total_pages:
              description: Total number of pages
              example: 3
              type: integer
              x-struct:
              x-validate:
          required:
            - page
            - page_size
            - total_entries
            - total_pages
          type: object
          x-struct:
          x-validate:
      required:
        - data
        - meta
      title: ViewersResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ViewersResponse
      x-validate:
    VerifyAuthChallengeRequest:
      properties:
        code:
          description: Six-digit verification code from the latest challenge email.
          pattern: ^\d{6}$
          type: string
          x-struct:
          x-validate:
      required:
        - code
      title: VerifyAuthChallengeRequest
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.VerifyAuthChallengeRequest
      x-validate:
    ViewerMemoryResponse:
      description: Response containing a viewer's memory document.
      properties:
        data:
          $ref: '#/components/schemas/ViewerMemory'
      required:
        - data
      title: ViewerMemoryResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ViewerMemoryResponse
      x-validate:
    CommunityCommentCreate:
      description: Parameters for creating a comment
      example:
        comment:
          content: Great post! Thanks for sharing.
      properties:
        comment:
          description: Comment parameters
          properties:
            content:
              description: Comment content (required)
              example: Great post! Thanks for sharing.
              type: string
              x-struct:
              x-validate:
            parent_id:
              description: Parent comment UUID for replies (optional)
              format: uuid
              nullable: true
              type: string
              x-struct:
              x-validate:
          required:
            - content
          type: object
          x-struct:
          x-validate:
      required:
        - comment
      title: CommunityCommentCreate
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.CommunityCommentCreate
      x-validate:
    AiRecommendationsResponse:
      description: AI-curated video recommendations
      properties:
        guidance:
          description: AI explanation of why these videos were recommended
          nullable: true
          type: string
          x-struct:
          x-validate:
        recommendations:
          description: Recommended videos
          items:
            $ref: '#/components/schemas/Video'
          type: array
          x-struct:
          x-validate:
        sources:
          description: Source citations from video content
          items:
            $ref: '#/components/schemas/Citation'
          type: array
          x-struct:
          x-validate:
      required:
        - recommendations
      title: AiRecommendationsResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AiRecommendationsResponse
      x-validate:
    Playlist:
      description: A curated list of videos
      properties:
        cover_image_url:
          description: Cover image URL
          nullable: true
          type: string
          x-struct:
          x-validate:
        description:
          description: Playlist description
          nullable: true
          type: string
          x-struct:
          x-validate:
        id:
          description: Playlist ID
          type: string
          x-struct:
          x-validate:
        is_private:
          description: Whether the playlist is private
          type: boolean
          x-struct:
          x-validate:
        title:
          description: Playlist title
          example: Getting Started
          type: string
          x-struct:
          x-validate:
        videos:
          description: Videos in this playlist
          items:
            $ref: '#/components/schemas/Video'
          type: array
          x-struct:
          x-validate:
      required:
        - id
        - title
        - is_private
      title: Playlist
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.Playlist
      x-validate:
    Attachment:
      description: A file attached to a video
      properties:
        description:
          description: Optional attachment description
          nullable: true
          type: string
          x-struct:
          x-validate:
        file_size:
          description: Attachment size in bytes
          example: 42000
          nullable: true
          type: integer
          x-struct:
          x-validate:
        file_url:
          description: Public URL for downloading the attachment
          example: https://uploads.eu1.boldvideo.io/uploads/bt_demo/attachments/file.pdf
          format: uri
          type: string
          x-struct:
          x-validate:
        id:
          description: Attachment ID
          example: 123
          type: integer
          x-struct:
          x-validate:
        mime_type:
          description: Attachment MIME type
          example: application/pdf
          nullable: true
          type: string
          x-struct:
          x-validate:
        title:
          description: Attachment title or original filename
          example: Strategy worksheet.pdf
          type: string
          x-struct:
          x-validate:
      required:
        - id
        - title
        - file_url
      title: Attachment
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.Attachment
      x-validate:
    SelfManagementDisabledError:
      properties:
        error:
          enum:
            - self_management_disabled
          type: string
          x-struct:
          x-validate:
      required:
        - error
      title: SelfManagementDisabledError
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.SelfManagementDisabledError
      x-validate:
    AdminErrorResponse:
      properties:
        details:
          additionalProperties: true
          description: Field-level validation errors when present
          nullable: true
          type: object
          x-struct:
          x-validate:
        error:
          description: Machine-readable admin API error code
          type: string
          x-struct:
          x-validate:
        status:
          nullable: true
          type: integer
          x-struct:
          x-validate:
        timestamp:
          format: date-time
          nullable: true
          type: string
          x-struct:
          x-validate:
      required:
        - error
      title: AdminErrorResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AdminErrorResponse
      x-validate:
    AdminDeviceLimitRequest:
      properties:
        limit:
          minimum: 1
          nullable: true
          type: integer
          x-struct:
          x-validate:
      title: AdminDeviceLimitRequest
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AdminDeviceLimitRequest
      x-validate:
    Video:
      description: A video resource
      properties:
        imported_from:
          description: Original import source when available
          nullable: true
          type: string
          x-struct:
          x-validate:
        meta_data:
          description: Embeddable metadata for title, description, and image
          type: object
          x-struct:
          x-validate:
        slug:
          description: URL-friendly identifier (optional, unique)
          example: introduction-to-bold
          nullable: true
          type: string
          x-struct:
          x-validate:
        captions:
          description: Caption file URL
          nullable: true
          type: string
          x-struct:
          x-validate:
        thumbnail:
          description: Thumbnail URL
          nullable: true
          type: string
          x-struct:
          x-validate:
        captions_lang:
          description: Caption language code
          nullable: true
          type: string
          x-struct:
          x-validate:
        chapters:
          description: AI-generated chapter data
          items:
            type: object
            x-struct:
            x-validate:
          nullable: true
          type: array
          x-struct:
          x-validate:
        description:
          description: Full video description
          nullable: true
          type: string
          x-struct:
          x-validate:
        progress:
          description: Viewer's watch progress (only present when viewer_id is provided)
          nullable: true
          oneOf:
            - $ref: '#/components/schemas/VideoProgress'
          x-struct:
          x-validate:
        transcript:
          description: Transcript track URLs keyed by format
          type: object
          x-struct:
          x-validate:
        playback_mode:
          description: How the public player should source the stream. "native" plays from Mux; "source" embeds the original imported provider (e.g., YouTube). Always present.
          enum:
            - native
            - source
          example: native
          type: string
          x-struct:
          x-validate:
        published_at:
          description: Publication timestamp
          format: date-time
          nullable: true
          type: string
          x-struct:
          x-validate:
        teaser:
          description: Short teaser text
          nullable: true
          type: string
          x-struct:
          x-validate:
        tags:
          description: Tags assigned to this video
          items:
            type: object
            x-struct:
            x-validate:
          type: array
          x-struct:
          x-validate:
        attachments:
          description: Files attached to this video. Populated on single-video responses and video list responses when attachments are present.
          items:
            $ref: '#/components/schemas/Attachment'
          type: array
          x-struct:
          x-validate:
        captions_label:
          description: Caption language label
          nullable: true
          type: string
          x-struct:
          x-validate:
        playback_speed:
          description: Default playback speed
          nullable: true
          type: number
          x-struct:
          x-validate:
        subtitles:
          description: Subtitle track metadata
          nullable: true
          type: object
          x-struct:
          x-validate:
        created_at:
          description: Creation timestamp
          format: date-time
          type: string
          x-struct:
          x-validate:
        updated_at:
          description: Last update timestamp
          format: date-time
          type: string
          x-struct:
          x-validate:
        source_provider:
          description: Original provider key (mirrors imported_from). Included only when playback_mode is "source".
          example: youtube
          nullable: true
          type: string
          x-struct:
          x-validate:
        duration:
          description: Duration in seconds
          example: 120
          type: integer
          x-struct:
          x-validate:
        legacy_video_url:
          description: Legacy source video URL when available
          nullable: true
          type: string
          x-struct:
          x-validate:
        source_id:
          description: Original provider's video ID (mirrors imported_id). Included only when playback_mode is "source".
          example: dQw4w9WgXcQ
          nullable: true
          type: string
          x-struct:
          x-validate:
        stream_url:
          description: Playable stream URL
          nullable: true
          type: string
          x-struct:
          x-validate:
        type:
          description: Resource type
          example: video
          type: string
          x-struct:
          x-validate:
        internal_id:
          description: Internal UUID
          example: 550e8400-e29b-41d4-a716-446655440000
          format: uuid
          type: string
          x-struct:
          x-validate:
        languages:
          description: 'Available languages for this video: the source language plus any ready translations. Always present; a video with no translations returns just its source entry.'
          items:
            properties:
              code:
                description: Language code
                example: es
                type: string
                x-struct:
                x-validate:
              mux_audio_track_id:
                description: Mux audio track reference (null for the source language)
                nullable: true
                type: string
                x-struct:
                x-validate:
              mux_subtitle_track_id:
                description: Mux subtitle track reference (null for the source language)
                nullable: true
                type: string
                x-struct:
                x-validate:
              name:
                description: Display name
                example: Spanish
                type: string
                x-struct:
                x-validate:
              ready:
                description: Whether this language is playable
                type: boolean
                x-struct:
                x-validate:
              role:
                description: Whether this is the original language or a translation
                enum:
                  - source
                  - translation
                type: string
                x-struct:
                x-validate:
              subtitle_url:
                description: Subtitle (VTT) URL for this language
                nullable: true
                type: string
                x-struct:
                x-validate:
            type: object
            x-struct:
            x-validate:
          type: array
          x-struct:
          x-validate:
        playback_id:
          description: Mux playback ID
          nullable: true
          type: string
          x-struct:
          x-validate:
        chapters_url:
          description: Signed URL for chapter data
          nullable: true
          type: string
          x-struct:
          x-validate:
        cta:
          description: Effective call-to-action for this video
          nullable: true
          type: object
          x-struct:
          x-validate:
        id:
          description: Video ID (hashid)
          example: abc123
          type: string
          x-struct:
          x-validate:
        title:
          description: Video title
          example: Introduction to BOLD
          type: string
          x-struct:
          x-validate:
        download_urls:
          description: Available download URLs keyed by quality or asset type
          nullable: true
          type: object
          x-struct:
          x-validate:
      required:
        - id
        - title
      title: Video
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.Video
      x-validate:
    CollectionResponse:
      description: Response containing a single collection
      properties:
        data:
          $ref: '#/components/schemas/Collection'
      required:
        - data
      title: CollectionResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.CollectionResponse
      x-validate:
    AdminSessionWithRevocation:
      properties:
        device_id:
          type: string
          x-struct:
          x-validate:
        device_label:
          description: Server-derived human-readable label for the device/browser and OS (e.g. "Chrome · macOS", "Safari · iPhone"). Derived from the `user_agent` supplied at session creation. Nullable when the user_agent is absent or unrecognised; callers should fall back to `device_id` for display.
          nullable: true
          type: string
          x-struct:
          x-validate:
        id:
          format: uuid
          type: string
          x-struct:
          x-validate:
        inserted_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
        last_seen_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
        location:
          description: Coarse, pre-formatted client location (e.g. "Berlin, DE" or "DE"). Never the raw IP.
          nullable: true
          type: string
          x-struct:
          x-validate:
        platform:
          type: string
          x-struct:
          x-validate:
        revoked_at:
          format: date-time
          nullable: true
          type: string
          x-struct:
          x-validate:
        revoked_by:
          nullable: true
          type: string
          x-struct:
          x-validate:
        revoked_reason:
          nullable: true
          type: string
          x-struct:
          x-validate:
        travel_verdict:
          description: Impossible-travel verdict label. "impossible_travel" when the sign-in was flagged as physically implausible, otherwise null. Label only — never exposes coordinates, the raw IP, or derived distance/speed metrics.
          nullable: true
          type: string
          x-struct:
          x-validate:
      title: AdminSessionWithRevocation
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AdminSessionWithRevocation
      x-validate:
    DeviceLimitError:
      properties:
        active_sessions:
          items:
            $ref: '#/components/schemas/ActiveSessionSummary'
          type: array
          x-struct:
          x-validate:
        error:
          enum:
            - device_limit_exceeded
          type: string
          x-struct:
          x-validate:
      required:
        - error
      title: DeviceLimitError
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.DeviceLimitError
      x-validate:
    LibraryAiChatRequest:
      description: Chat request across your entire video library
      example:
        prompt: What are the best practices for user authentication?
        stream: false
      properties:
        collection_id:
          description: Limit search to a specific collection (legacy single-value filter)
          nullable: true
          type: string
          x-struct:
          x-validate:
        collection_ids:
          description: Limit search to multiple collections (OR semantics)
          items:
            type: string
            x-struct:
            x-validate:
          nullable: true
          type: array
          x-struct:
          x-validate:
        conversation_id:
          description: Continue an existing conversation
          nullable: true
          type: string
          x-struct:
          x-validate:
        images:
          description: Optional array of images (max 5). Requires the Vision feature flag. Each image can be base64-encoded or a URL.
          items:
            anyOf:
              - $ref: '#/components/schemas/AiImageBase64'
              - $ref: '#/components/schemas/AiImageUrl'
            x-struct:
            x-validate:
          maxItems: 5
          nullable: true
          type: array
          x-struct:
          x-validate:
        prompt:
          description: Your question
          example: What videos cover authentication?
          type: string
          x-struct:
          x-validate:
        stream:
          default: true
          description: 'Stream response via SSE (default: true)'
          type: boolean
          x-struct:
          x-validate:
        tags:
          description: Filter by video tags
          items:
            type: string
            x-struct:
            x-validate:
          nullable: true
          type: array
          x-struct:
          x-validate:
        viewer:
          description: Viewer identifier (UUID or your external ID) to associate with the conversation. When the viewers feature is enabled, the viewer's traits also personalize AI responses.
          nullable: true
          type: string
          x-struct:
          x-validate:
        viewer_profile:
          anyOf:
            - description: Free text or markdown describing the viewer; replaces the synced viewer's traits for this request. Up to 8000 characters.
              example: Sarah runs a 3-person agency, pre-launch, wants her first 10 customers.
              type: string
              x-struct:
              x-validate:
            - additionalProperties:
                anyOf:
                  - type: string
                    x-struct:
                    x-validate:
                  - type: number
                    x-struct:
                    x-validate:
                  - type: boolean
                    x-struct:
                    x-validate:
                x-struct:
                x-validate:
              description: Key-value traits merged over the synced viewer's traits (inline wins per key). Max 20 keys; keys must match ^[a-zA-Z_][a-zA-Z0-9_]*$; values are strings (up to 2000 characters), numbers, or booleans.
              example:
                business_name: Acme Corp
                goal: find first customers
                stage: growth
              type: object
              x-struct:
              x-validate:
          description: Tell the AI about the person asking, for this request only (never persisted). Pass free text/markdown, or a key-value object. Requires the viewers feature.
          nullable: true
          x-struct:
          x-validate:
      required:
        - prompt
      title: LibraryAiChatRequest
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.LibraryAiChatRequest
      x-validate:
    SearchResponse:
      description: Search results for public videos and transcript content.
      example:
        hits:
          - document_type: transcript
            duration_ms: 5000
            id: 550e8400-e29b-41d4-a716-446655440000_1_5000-10000
            speaker: Speaker 1
            text: The first step is to connect your account...
            timestamp_end_ms: 10000
            timestamp_start_ms: 5000
            title: Getting Started
            video_id: 550e8400-e29b-41d4-a716-446655440000
        page: 1
        per_page: 10
        processing_time_ms: 4
        total_hits: 1
      properties:
        hits:
          description: Matching search hits
          items:
            $ref: '#/components/schemas/SearchHit'
          type: array
          x-struct:
          x-validate:
        page:
          description: Current page number
          type: integer
          x-struct:
          x-validate:
        per_page:
          description: Results per page
          type: integer
          x-struct:
          x-validate:
        processing_time_ms:
          description: Search processing time in milliseconds
          type: integer
          x-struct:
          x-validate:
        total_hits:
          description: Estimated total matching hits
          type: integer
          x-struct:
          x-validate:
      required:
        - hits
        - page
        - per_page
        - total_hits
        - processing_time_ms
      title: SearchResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.SearchResponse
      x-validate:
    AdminRevokeAllResponse:
      properties:
        ok:
          type: boolean
          x-struct:
          x-validate:
        revoked_count:
          type: integer
          x-struct:
          x-validate:
      required:
        - ok
        - revoked_count
      title: AdminRevokeAllResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AdminRevokeAllResponse
      x-validate:
    AdminRevokeAuthSessionRequest:
      properties:
        reason:
          nullable: true
          type: string
          x-struct:
          x-validate:
      title: AdminRevokeAuthSessionRequest
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AdminRevokeAuthSessionRequest
      x-validate:
    Collection:
      description: A video collection that can be nested in a hierarchy
      properties:
        children:
          description: Child collections (only present when include=children or include=descendants)
          items:
            description: Nested Collection object
            type: object
            x-struct:
            x-validate:
          nullable: true
          type: array
          x-struct:
          x-validate:
        children_count:
          description: Number of direct child collections
          example: 3
          type: integer
          x-struct:
          x-validate:
        created_at:
          description: Creation timestamp
          format: date-time
          type: string
          x-struct:
          x-validate:
        id:
          description: Collection UUID
          format: uuid
          type: string
          x-struct:
          x-validate:
        name:
          description: Collection name
          example: Getting Started
          type: string
          x-struct:
          x-validate:
        parent_id:
          description: Parent collection UUID (null for root collections)
          format: uuid
          nullable: true
          type: string
          x-struct:
          x-validate:
        position:
          description: Position within parent (0-indexed)
          example: 0
          type: integer
          x-struct:
          x-validate:
        slug:
          description: URL-friendly slug
          example: getting-started
          type: string
          x-struct:
          x-validate:
        updated_at:
          description: Last update timestamp
          format: date-time
          type: string
          x-struct:
          x-validate:
        video_count:
          description: Number of public videos in collection
          example: 5
          type: integer
          x-struct:
          x-validate:
      required:
        - id
        - name
        - slug
      title: Collection
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.Collection
      x-validate:
    MultimodalSettings:
      description: |
        Per-account capability flag for multimodal (image input) on AI endpoints.

        When `enabled` is `true`, clients may attach the `images` array on requests to
        `/api/v1/ai/chat`, `/api/v1/ai/search`, and `/api/v1/ai/videos/:id/chat`
        (`/api/v1/ai/ask` remains as a deprecated alias for `/api/v1/ai/chat`). When
        `false`, those requests are rejected with `feature_disabled`.

        Limits (`max_images`, `accepted_media_types`) are only included when enabled.
      properties:
        accepted_media_types:
          description: Accepted base64 media types (only present when enabled)
          example:
            - image/png
            - image/jpeg
            - image/webp
            - image/gif
          items:
            type: string
            x-struct:
            x-validate:
          type: array
          x-struct:
          x-validate:
        enabled:
          description: Whether image inputs are accepted on AI endpoints
          example: false
          type: boolean
          x-struct:
          x-validate:
        max_images:
          description: Maximum number of images per request (only present when enabled)
          example: 5
          type: integer
          x-struct:
          x-validate:
      required:
        - enabled
      title: MultimodalSettings
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.MultimodalSettings
      x-validate:
    RevokeOthersResponse:
      properties:
        ok:
          type: boolean
          x-struct:
          x-validate:
        revoked_count:
          type: integer
          x-struct:
          x-validate:
      required:
        - ok
        - revoked_count
      title: RevokeOthersResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.RevokeOthersResponse
      x-validate:
    ActiveSessionSummary:
      properties:
        device_id:
          type: string
          x-struct:
          x-validate:
        device_label:
          description: Server-derived human-readable label for the device/browser and OS (e.g. "Chrome · macOS", "Safari · iPhone"). Derived from the `user_agent` supplied at session creation. Nullable when the user_agent is absent or unrecognised; callers should fall back to `device_id` for display.
          nullable: true
          type: string
          x-struct:
          x-validate:
        id:
          format: uuid
          type: string
          x-struct:
          x-validate:
        inserted_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
        last_seen_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
        platform:
          type: string
          x-struct:
          x-validate:
      title: ActiveSessionSummary
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ActiveSessionSummary
      x-validate:
    Citation:
      description: |
        A source reference from video content.

        The `cited` field indicates whether this source is referenced in the answer text.
        Citation indices in the answer (e.g., `[4]`) map to array positions: `[4]` → `sources[3]`.

        **Field naming**: Use the canonical field names (`title`, `timestamp`, `timestamp_end`, `playback_id`).
        Deprecated aliases (`video_title`, `timestamp_seconds`, `timestamp_end_seconds`, `mux_playback_id`)
        are included for backward compatibility and will be removed in a future release.
      properties:
        canonical_url:
          description: Canonical video URL for click-through
          nullable: true
          type: string
          x-struct:
          x-validate:
        cited:
          description: 'Whether this source is cited in the answer text. Filter by `cited: true` to show only referenced sources.'
          type: boolean
          x-struct:
          x-validate:
        document_type:
          description: Document type (transcript or attachment)
          type: string
          x-struct:
          x-validate:
        id:
          description: Citation ID
          type: string
          x-struct:
          x-validate:
        kind:
          description: |
            Discriminates citation provenance:
            - `"chunk"` (default) — transcript chunk, resource, or attachment
            - `"moment"` — LLM-extracted curated moment (insight / story / framework / q_and_a / exercise)
            When `"moment"`, the `moment_id`, `type`, `summary`, and `transcript_excerpt`
            fields are populated.
          enum:
            - chunk
            - moment
          type: string
          x-struct:
          x-validate:
        matched_sentence:
          description: |
            The transcript sentence whose text best matches the cited claim, when a
            confident match was found. When present, the citation's `timestamp` /
            `timestamp_end` are narrowed to this sentence instead of the coarse chunk
            bounds. The key is **omitted entirely** (not null) for legacy chunks or
            low-confidence matches, so the citation falls back to chunk-level timing.
          nullable: true
          properties:
            end_ms:
              description: Sentence end (ms)
              type: integer
              x-struct:
              x-validate:
            speaker_label:
              description: Raw diarization label for this sentence, or null.
              nullable: true
              type: string
              x-struct:
              x-validate:
            speaker_name:
              description: Resolved speaker name for this sentence, or null.
              nullable: true
              type: string
              x-struct:
              x-validate:
            start_ms:
              description: Sentence start (ms)
              type: integer
              x-struct:
              x-validate:
            text:
              description: Sentence text
              type: string
              x-struct:
              x-validate:
            timestamp:
              description: Sentence start in seconds (canonical)
              type: integer
              x-struct:
              x-validate:
            timestamp_end:
              description: Sentence end in seconds (canonical)
              type: integer
              x-struct:
              x-validate:
            timestamp_end_seconds:
              deprecated: true
              description: 'DEPRECATED: Use `timestamp_end` instead'
              type: integer
              x-struct:
              x-validate:
            timestamp_seconds:
              deprecated: true
              description: 'DEPRECATED: Use `timestamp` instead'
              type: integer
              x-struct:
              x-validate:
          type: object
          x-struct:
          x-validate:
        moment_id:
          description: Source moment UUID (present only when `kind="moment"`)
          nullable: true
          type: string
          x-struct:
          x-validate:
        mux_playback_id:
          deprecated: true
          description: 'DEPRECATED: Use `playback_id` instead'
          type: string
          x-struct:
          x-validate:
        playback_id:
          description: Mux playback ID
          type: string
          x-struct:
          x-validate:
        published_at:
          description: Publication timestamp (Unix epoch seconds)
          nullable: true
          type: integer
          x-struct:
          x-validate:
        slug:
          description: Video slug when available
          nullable: true
          type: string
          x-struct:
          x-validate:
        speaker:
          description: Resolved speaker name when identified, otherwise the raw diarization label (back-compat). Prefer `speaker_name`.
          nullable: true
          type: string
          x-struct:
          x-validate:
        speaker_label:
          description: Raw diarization label (e.g. "A"), or null.
          nullable: true
          type: string
          x-struct:
          x-validate:
        speaker_name:
          description: Resolved speaker display name, or null when the speaker is unnamed or the chunk predates speaker resolution.
          nullable: true
          type: string
          x-struct:
          x-validate:
        summary:
          description: Curated LLM-extracted summary of the moment (present only when `kind="moment"`). Frontend may show this as the primary label for the citation pill.
          nullable: true
          type: string
          x-struct:
          x-validate:
        text:
          description: Quoted text
          type: string
          x-struct:
          x-validate:
        timestamp:
          description: Start time in seconds
          type: integer
          x-struct:
          x-validate:
        timestamp_end:
          description: End time in seconds
          type: integer
          x-struct:
          x-validate:
        timestamp_end_seconds:
          deprecated: true
          description: 'DEPRECATED: Use `timestamp_end` instead'
          type: integer
          x-struct:
          x-validate:
        timestamp_seconds:
          deprecated: true
          description: 'DEPRECATED: Use `timestamp` instead'
          type: integer
          x-struct:
          x-validate:
        timestamp_url:
          description: Canonical URL with `?t=<seconds>` when timestamp is available
          nullable: true
          type: string
          x-struct:
          x-validate:
        title:
          description: Video title
          type: string
          x-struct:
          x-validate:
        transcript_excerpt:
          description: Verbatim transcript text covered by the moment (present only when `kind="moment"`). Mirrors `text` for clients that don't discriminate by `kind`.
          nullable: true
          type: string
          x-struct:
          x-validate:
        type:
          description: Moment type (present only when `kind="moment"`)
          enum:
            - insight
            - story
            - framework
            - q_and_a
            - exercise
          nullable: true
          type: string
          x-struct:
          x-validate:
        video_id:
          description: Source video ID
          type: string
          x-struct:
          x-validate:
        video_title:
          deprecated: true
          description: 'DEPRECATED: Use `title` instead'
          type: string
          x-struct:
          x-validate:
      required:
        - id
        - video_id
        - title
        - text
        - timestamp
        - cited
      title: Citation
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.Citation
      x-validate:
    VideoProgress:
      description: A viewer's watch progress on a video
      example:
        completed: false
        completed_at:
        current_time: 300
        duration: 1000
        id: 550e8400-e29b-41d4-a716-446655440000
        percentage: 30.0
      nullable: true
      properties:
        completed:
          description: Whether the viewer has completed watching
          example: false
          type: boolean
          x-struct:
          x-validate:
        completed_at:
          description: Timestamp when video was marked complete
          format: date-time
          nullable: true
          type: string
          x-struct:
          x-validate:
        current_time:
          description: Current playback position in seconds
          example: 300
          type: integer
          x-struct:
          x-validate:
        duration:
          description: Total video duration in seconds
          example: 1000
          type: integer
          x-struct:
          x-validate:
        id:
          description: Progress record ID
          format: uuid
          type: string
          x-struct:
          x-validate:
        percentage:
          description: Watch progress percentage (0-100)
          example: 30.0
          format: float
          type: number
          x-struct:
          x-validate:
      title: VideoProgress
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.VideoProgress
      x-validate:
    VideoResponse:
      description: Response containing a single video
      properties:
        data:
          $ref: '#/components/schemas/Video'
      required:
        - data
      title: VideoResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.VideoResponse
      x-validate:
    AuthSessionsListResponse:
      properties:
        data:
          items:
            $ref: '#/components/schemas/ActiveSessionSummary'
          type: array
          x-struct:
          x-validate:
      required:
        - data
      title: AuthSessionsListResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AuthSessionsListResponse
      x-validate:
    AuthChallengeError:
      properties:
        attempts_remaining:
          nullable: true
          type: integer
          x-struct:
          x-validate:
        error:
          enum:
            - bad_request
            - challenge_invalid
            - challenge_expired
            - code_incorrect
            - too_many_attempts
            - resend_rate_limited
            - resend_limit_exceeded
            - viewer_email_required
            - challenge_delivery_unavailable
            - viewer_not_found
            - forbidden
          type: string
          x-struct:
          x-validate:
        retry_after:
          nullable: true
          type: integer
          x-struct:
          x-validate:
      required:
        - error
      title: AuthChallengeError
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AuthChallengeError
      x-validate:
    ViewerResponse:
      description: Response containing a single viewer
      properties:
        data:
          $ref: '#/components/schemas/Viewer'
      required:
        - data
      title: ViewerResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ViewerResponse
      x-validate:
    SessionManagementExemptionRequest:
      properties:
        exempt:
          description: Whether this viewer is exempt from session-management enforcement.
          type: boolean
          x-struct:
          x-validate:
      required:
        - exempt
      title: SessionManagementExemptionRequest
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.SessionManagementExemptionRequest
      x-validate:
    CommunityPost:
      description: A community post
      properties:
        author:
          $ref: '#/components/schemas/CommunityAuthor'
        category:
          description: Post category
          enum:
            - announcements
            - q_and_a
            - general
          example: announcements
          type: string
          x-struct:
          x-validate:
        comments:
          description: Comments summary
          properties:
            commented_by:
              description: Users who commented (unique, capped at 10)
              items:
                $ref: '#/components/schemas/CommunityAuthor'
              maxItems: 10
              type: array
              x-struct:
              x-validate:
            count:
              description: Total number of comments
              example: 3
              type: integer
              x-struct:
              x-validate:
            items:
              description: Full comment threads (only in detail endpoint)
              items:
                $ref: '#/components/schemas/CommunityComment'
              type: array
              x-struct:
              x-validate:
          required:
            - count
            - commented_by
          type: object
          x-struct:
          x-validate:
        content:
          description: Post content
          example: Welcome to our community!
          type: string
          x-struct:
          x-validate:
        created_at:
          description: Creation timestamp
          format: date-time
          type: string
          x-struct:
          x-validate:
        id:
          description: Post UUID
          format: uuid
          type: string
          x-struct:
          x-validate:
        pinned:
          description: Whether the post is pinned
          example: false
          type: boolean
          x-struct:
          x-validate:
        pinned_at:
          description: When the post was pinned
          format: date-time
          nullable: true
          type: string
          x-struct:
          x-validate:
        reactions:
          description: Reactions summary
          properties:
            count:
              description: Total number of reactions
              example: 10
              type: integer
              x-struct:
              x-validate:
            reacted_by:
              description: Users who reacted (most recent, capped at 10)
              items:
                $ref: '#/components/schemas/CommunityAuthor'
              maxItems: 10
              type: array
              x-struct:
              x-validate:
            viewer_has_reacted:
              description: Whether the current viewer has reacted (only when X-Viewer-ID header is provided)
              nullable: true
              type: boolean
              x-struct:
              x-validate:
          required:
            - count
            - reacted_by
          type: object
          x-struct:
          x-validate:
        updated_at:
          description: Last update timestamp
          format: date-time
          type: string
          x-struct:
          x-validate:
      required:
        - id
        - content
        - category
        - pinned
        - author
        - reactions
        - comments
        - created_at
      title: CommunityPost
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.CommunityPost
      x-validate:
    SessionManagementViewerState:
      properties:
        active_session_count:
          minimum: 0
          type: integer
          x-struct:
          x-validate:
        admin_overrides_allowed:
          type: boolean
          x-struct:
          x-validate:
        can_update_device_limit_override:
          description: Whether this tenant key can set or clear the viewer's numeric override.
          type: boolean
          x-struct:
          x-validate:
        can_update_session_management_exemption:
          description: Whether this tenant key can set or clear the viewer's exemption flag.
          type: boolean
          x-struct:
          x-validate:
        device_limit_override:
          minimum: 1
          nullable: true
          type: integer
          x-struct:
          x-validate:
        effective_device_limit:
          minimum: 1
          nullable: true
          type: integer
          x-struct:
          x-validate:
        effective_device_limit_source:
          enum:
            - policy
            - override
            - exempt
          type: string
          x-struct:
          x-validate:
        external_id:
          type: string
          x-struct:
          x-validate:
        policy_default_device_limit:
          minimum: 1
          type: integer
          x-struct:
          x-validate:
        session_management_exempt:
          type: boolean
          x-struct:
          x-validate:
        viewer_id:
          format: uuid
          type: string
          x-struct:
          x-validate:
      required:
        - viewer_id
        - external_id
        - active_session_count
        - policy_default_device_limit
        - effective_device_limit
        - effective_device_limit_source
        - device_limit_override
        - session_management_exempt
        - admin_overrides_allowed
        - can_update_device_limit_override
        - can_update_session_management_exemption
      title: SessionManagementViewerState
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.SessionManagementViewerState
      x-validate:
    SessionManagementViewerStateResponse:
      properties:
        data:
          $ref: '#/components/schemas/SessionManagementViewerState'
      required:
        - data
      title: SessionManagementViewerStateResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.SessionManagementViewerStateResponse
      x-validate:
    AdminAuthPolicyResponse:
      properties:
        admin_override_per_user:
          type: boolean
          x-struct:
          x-validate:
        allow_member_self_manage:
          type: boolean
          x-struct:
          x-validate:
        auth_challenge_product_name:
          nullable: true
          type: string
          x-struct:
          x-validate:
        auth_challenge_reply_to_email:
          format: email
          nullable: true
          type: string
          x-struct:
          x-validate:
        auth_challenge_sender_name:
          nullable: true
          type: string
          x-struct:
          x-validate:
        auth_challenge_support_url:
          format: uri
          nullable: true
          type: string
          x-struct:
          x-validate:
        auth_challenge_template_id:
          nullable: true
          type: string
          x-struct:
          x-validate:
        enforcement_mode:
          enum:
            - block_new
            - kick_oldest
            - challenge_new
          type: string
          x-struct:
          x-validate:
        enforcement_phase:
          enum:
            - 'off'
            - shadow
            - enforce
          type: string
          x-struct:
          x-validate:
        impossible_travel_mode:
          description: Impossible travel detection mode. off disables detection.
          enum:
            - 'off'
            - flag_only
            - challenge
          type: string
          x-struct:
          x-validate:
        impossible_travel_speed_kmh:
          description: Speed threshold in km/h above which a login is flagged as impossible travel.
          minimum: 1
          type: integer
          x-struct:
          x-validate:
        inserted_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
        max_devices_per_user:
          type: integer
          x-struct:
          x-validate:
        session_ttl_days:
          type: integer
          x-struct:
          x-validate:
        updated_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
      title: AdminAuthPolicyResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AdminAuthPolicyResponse
      x-validate:
    SessionManagementDeviceLimitRequest:
      properties:
        limit:
          description: Set a positive integer override, or null to clear it.
          minimum: 1
          nullable: true
          type: integer
          x-struct:
          x-validate:
      required:
        - limit
      title: SessionManagementDeviceLimitRequest
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.SessionManagementDeviceLimitRequest
      x-validate:
    CommunityPostCreate:
      description: Parameters for creating a community post
      example:
        post:
          category: announcements
          content: Welcome to our community!
      properties:
        post:
          description: Post parameters
          properties:
            category:
              description: "Post category (optional, defaults to 'general')"
              enum:
                - announcements
                - q_and_a
                - general
              example: announcements
              type: string
              x-struct:
              x-validate:
            content:
              description: Post content (required)
              example: Welcome to our community!
              type: string
              x-struct:
              x-validate:
          required:
            - content
          type: object
          x-struct:
          x-validate:
      required:
        - post
      title: CommunityPostCreate
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.CommunityPostCreate
      x-validate:
    LibraryConversationListResponse:
      properties:
        conversations:
          items:
            $ref: '#/components/schemas/ConversationSummary'
          type: array
          x-struct:
          x-validate:
        pagination:
          $ref: '#/components/schemas/ConversationPagination'
      required:
        - conversations
        - pagination
      title: LibraryConversationListResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.LibraryConversationListResponse
      x-validate:
    AdminDeviceLimitResponse:
      properties:
        data:
          properties:
            device_limit_override:
              nullable: true
              type: integer
              x-struct:
              x-validate:
            viewer_id:
              format: uuid
              type: string
              x-struct:
              x-validate:
          type: object
          x-struct:
          x-validate:
      required:
        - data
      title: AdminDeviceLimitResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AdminDeviceLimitResponse
      x-validate:
    UnifiedConversationSummary:
      description: Conversation summary with scope indicator and optional video context
      properties:
        conversation_id:
          type: string
          x-struct:
          x-validate:
        created_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
        message_count:
          type: integer
          x-struct:
          x-validate:
        preview:
          description: Preview of first user message
          nullable: true
          type: string
          x-struct:
          x-validate:
        scope:
          description: Conversation scope
          enum:
            - video
            - library
          type: string
          x-struct:
          x-validate:
        status:
          type: string
          x-struct:
          x-validate:
        title:
          description: Conversation title (auto-generated)
          nullable: true
          type: string
          x-struct:
          x-validate:
        updated_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
        video:
          anyOf:
            - $ref: '#/components/schemas/ConversationVideoContext'
          description: Video context for video-scoped conversations, null for library conversations
          nullable: true
          x-struct:
          x-validate:
      required:
        - conversation_id
        - scope
        - status
        - message_count
        - created_at
        - updated_at
      title: UnifiedConversationSummary
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.UnifiedConversationSummary
      x-validate:
    AuthSessionResponse:
      properties:
        bypassed:
          nullable: true
          type: boolean
          x-struct:
          x-validate:
        expires_at:
          format: date-time
          nullable: true
          type: string
          x-struct:
          x-validate:
        session_id:
          format: uuid
          nullable: true
          type: string
          x-struct:
          x-validate:
      title: AuthSessionResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AuthSessionResponse
      x-validate:
    CommunityPostResponse:
      description: Response containing a single community post with comments
      properties:
        data:
          $ref: '#/components/schemas/CommunityPost'
      required:
        - data
      title: CommunityPostResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.CommunityPostResponse
      x-validate:
    VerifyAuthSessionResponse:
      properties:
        reason:
          enum:
            - session_not_found
            - session_revoked
            - session_expired
          nullable: true
          type: string
          x-struct:
          x-validate:
        valid:
          type: boolean
          x-struct:
          x-validate:
      required:
        - valid
      title: VerifyAuthSessionResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.VerifyAuthSessionResponse
      x-validate:
    AdminAuthPolicyUpdateRequest:
      properties:
        admin_override_per_user:
          type: boolean
          x-struct:
          x-validate:
        allow_member_self_manage:
          type: boolean
          x-struct:
          x-validate:
        auth_challenge_product_name:
          nullable: true
          type: string
          x-struct:
          x-validate:
        auth_challenge_reply_to_email:
          format: email
          nullable: true
          type: string
          x-struct:
          x-validate:
        auth_challenge_sender_name:
          nullable: true
          type: string
          x-struct:
          x-validate:
        auth_challenge_support_url:
          format: uri
          nullable: true
          type: string
          x-struct:
          x-validate:
        auth_challenge_template_id:
          nullable: true
          type: string
          x-struct:
          x-validate:
        enforcement_mode:
          enum:
            - block_new
            - kick_oldest
            - challenge_new
          type: string
          x-struct:
          x-validate:
        enforcement_phase:
          enum:
            - 'off'
            - shadow
            - enforce
          type: string
          x-struct:
          x-validate:
        impossible_travel_mode:
          description: Impossible travel detection mode. off disables detection.
          enum:
            - 'off'
            - flag_only
            - challenge
          type: string
          x-struct:
          x-validate:
        impossible_travel_speed_kmh:
          description: Speed threshold in km/h above which a login is flagged as impossible travel.
          minimum: 1
          type: integer
          x-struct:
          x-validate:
        max_devices_per_user:
          minimum: 1
          type: integer
          x-struct:
          x-validate:
        session_ttl_days:
          minimum: 1
          type: integer
          x-struct:
          x-validate:
      title: AdminAuthPolicyUpdateRequest
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AdminAuthPolicyUpdateRequest
      x-validate:
    AuthChallengeResendResponse:
      properties:
        challenge_id:
          format: uuid
          type: string
          x-struct:
          x-validate:
        email_hint:
          nullable: true
          type: string
          x-struct:
          x-validate:
        expires_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
        ok:
          type: boolean
          x-struct:
          x-validate:
        resend_count:
          type: integer
          x-struct:
          x-validate:
      required:
        - ok
        - challenge_id
        - email_hint
        - resend_count
        - expires_at
      title: AuthChallengeResendResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AuthChallengeResendResponse
      x-validate:
    SessionManagementSessionWithRevocation:
      properties:
        device_id:
          type: string
          x-struct:
          x-validate:
        device_label:
          description: Server-derived human-readable label for the device/browser and OS (e.g. "Chrome · macOS", "Safari · iPhone"). Derived from the `user_agent` supplied at session creation. Nullable when the user_agent is absent or unrecognised; callers should fall back to `device_id` for display.
          nullable: true
          type: string
          x-struct:
          x-validate:
        id:
          format: uuid
          type: string
          x-struct:
          x-validate:
        inserted_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
        last_seen_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
        location:
          description: Coarse, pre-formatted client location (e.g. "Berlin, DE" or "DE"). Never the raw IP.
          nullable: true
          type: string
          x-struct:
          x-validate:
        platform:
          type: string
          x-struct:
          x-validate:
        revoked_at:
          format: date-time
          nullable: true
          type: string
          x-struct:
          x-validate:
        revoked_by:
          nullable: true
          type: string
          x-struct:
          x-validate:
        revoked_reason:
          nullable: true
          type: string
          x-struct:
          x-validate:
        travel_verdict:
          description: Impossible-travel verdict label. "impossible_travel" when the sign-in was flagged as physically implausible, otherwise null. Label only — never exposes coordinates, the raw IP, or derived distance/speed metrics.
          nullable: true
          type: string
          x-struct:
          x-validate:
      title: SessionManagementSessionWithRevocation
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.SessionManagementSessionWithRevocation
      x-validate:
    VideoIngestResponse:
      properties:
        callback_status:
          description: Callback delivery status
          enum:
            - pending
            - delivered
            - failed
            - blocked
          nullable: true
          type: string
          x-struct:
          x-validate:
        callback_url:
          description: Webhook URL for processing callbacks
          nullable: true
          type: string
          x-struct:
          x-validate:
        created_at:
          description: Creation timestamp
          format: date-time
          type: string
          x-struct:
          x-validate:
        external_id:
          description: Caller's reference ID
          nullable: true
          type: string
          x-struct:
          x-validate:
        id:
          description: Video UUID
          format: uuid
          type: string
          x-struct:
          x-validate:
        status:
          description: Current processing status
          type: string
          x-struct:
          x-validate:
      required:
        - id
        - status
        - created_at
      title: VideoIngestResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.VideoIngestResponse
      x-validate:
    ReactionResponse:
      description: Response after toggling a reaction on a post or comment
      example:
        data:
          reacted: true
          reactions_count: 5
      properties:
        data:
          description: Reaction result
          properties:
            reacted:
              description: Whether the viewer currently has an active reaction
              example: true
              type: boolean
              x-struct:
              x-validate:
            reactions_count:
              description: Updated total number of reactions
              example: 5
              type: integer
              x-struct:
              x-validate:
          required:
            - reacted
            - reactions_count
          type: object
          x-struct:
          x-validate:
      required:
        - data
      title: ReactionResponse
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ReactionResponse
      x-validate:
    Viewer:
      description: An external viewer (user from course platform)
      properties:
        avatar_url:
          description: URL to avatar image
          example: https://example.com/avatars/john.jpg
          format: uri
          nullable: true
          type: string
          x-struct:
          x-validate:
        computed_display_name:
          description: "Computed display name (priority: display_name > first+last name > first name > name > 'Anonymous')"
          example: John Doe
          type: string
          x-struct:
          x-validate:
        created_at:
          description: Creation timestamp
          format: date-time
          type: string
          x-struct:
          x-validate:
        display_name:
          description: Preferred display name
          example: Johnny D
          nullable: true
          type: string
          x-struct:
          x-validate:
        email:
          description: Viewer email
          example: john@example.com
          format: email
          type: string
          x-struct:
          x-validate:
        external_id:
          description: External ID from course platform
          example: usr_123abc
          nullable: true
          type: string
          x-struct:
          x-validate:
        first_name:
          description: First name
          example: John
          nullable: true
          type: string
          x-struct:
          x-validate:
        id:
          description: Viewer UUID
          format: uuid
          type: string
          x-struct:
          x-validate:
        is_admin:
          description: Whether this viewer is a community administrator (read-only via API)
          example: false
          type: boolean
          x-struct:
          x-validate:
        last_name:
          description: Last name
          example: Doe
          nullable: true
          type: string
          x-struct:
          x-validate:
        name:
          description: Viewer name
          example: John Doe
          type: string
          x-struct:
          x-validate:
        traits:
          description: Custom traits map
          example:
            business_name: Acme Corp
            stage: growth
          nullable: true
          type: object
          x-struct:
          x-validate:
        updated_at:
          description: Last update timestamp
          format: date-time
          type: string
          x-struct:
          x-validate:
      required:
        - id
        - name
        - computed_display_name
      title: Viewer
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.Viewer
      x-validate:
    ConversationSummary:
      properties:
        conversation_id:
          type: string
          x-struct:
          x-validate:
        created_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
        message_count:
          type: integer
          x-struct:
          x-validate:
        preview:
          nullable: true
          type: string
          x-struct:
          x-validate:
        scope:
          description: 'Conversation scope: video (video-scoped chat) or library (library-wide chat)'
          enum:
            - video
            - library
          nullable: true
          type: string
          x-struct:
          x-validate:
        status:
          type: string
          x-struct:
          x-validate:
        title:
          description: Conversation title (auto-generated)
          nullable: true
          type: string
          x-struct:
          x-validate:
        updated_at:
          format: date-time
          type: string
          x-struct:
          x-validate:
      required:
        - conversation_id
        - status
        - message_count
        - created_at
        - updated_at
      title: ConversationSummary
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.ConversationSummary
      x-validate:
    VideoIngestRequest:
      properties:
        callback_url:
          description: HTTPS URL to receive a webhook POST when video processing completes or fails. Must use HTTPS.
          nullable: true
          type: string
          x-struct:
          x-validate:
        collection_id:
          description: Collection to add the video to
          format: uuid
          type: string
          x-struct:
          x-validate:
        description:
          description: Video description
          type: string
          x-struct:
          x-validate:
        external_id:
          description: Caller's reference ID. Used for idempotency within tenant.
          type: string
          x-struct:
          x-validate:
        language:
          description: 'ISO 639-1 language code (default: "en")'
          type: string
          x-struct:
          x-validate:
        source_url:
          description: URL to download the video from
          type: string
          x-struct:
          x-validate:
        tags:
          description: Tag names to assign (created if they don't exist)
          items:
            type: string
            x-struct:
            x-validate:
          type: array
          x-struct:
          x-validate:
        title:
          description: Video title
          type: string
          x-struct:
          x-validate:
      required:
        - source_url
        - title
      title: VideoIngestRequest
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.VideoIngestRequest
      x-validate:
    AiRecommendationsRequest:
      description: Request for AI-powered video recommendations
      example:
        limit: 5
        topics:
          - authentication
          - user management
      properties:
        collection_id:
          description: Filter to a specific collection (legacy single-value filter)
          nullable: true
          type: string
          x-struct:
          x-validate:
        collection_ids:
          description: Filter to multiple collections (OR semantics)
          items:
            type: string
            x-struct:
            x-validate:
          nullable: true
          type: array
          x-struct:
          x-validate:
        include_guidance:
          default: true
          description: Include AI guidance text explaining recommendations
          type: boolean
          x-struct:
          x-validate:
        limit:
          description: 'Maximum recommendations (default: 5, max: 20)'
          example: 5
          type: integer
          x-struct:
          x-validate:
        stream:
          default: true
          description: 'Stream response via SSE (default: true)'
          type: boolean
          x-struct:
          x-validate:
        tags:
          description: Filter by video tags
          items:
            type: string
            x-struct:
            x-validate:
          nullable: true
          type: array
          x-struct:
          x-validate:
        topics:
          description: Topics or learning goals
          example:
            - authentication
            - getting started
          items:
            type: string
            x-struct:
            x-validate:
          type: array
          x-struct:
          x-validate:
      required:
        - topics
      title: AiRecommendationsRequest
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.AiRecommendationsRequest
      x-validate:
    CreateAuthSessionRequest:
      properties:
        client_ip:
          description: "Optional end-user IP address used only for the session's coarse geo-location (city/country); the raw IP is never returned. Intended for trusted server-side integrators whose connecting IP is a datacenter egress (e.g. a Next.js app on Vercel): forward the real viewer IP here so the stored location reflects the viewer, not your server. When omitted, the server uses the proxy-aware connecting IP. Accepts IPv4 or IPv6; an unparseable value is ignored and the connecting IP is used."
          nullable: true
          type: string
          x-struct:
          x-validate:
        device_id:
          type: string
          x-struct:
          x-validate:
        device_label:
          description: Optional human-readable device label. When omitted (the usual case), the server derives one from `user_agent` (e.g. "Chrome · macOS"). A non-blank value supplied here takes precedence and is stored as-is (max 255 chars).
          nullable: true
          type: string
          x-struct:
          x-validate:
        platform:
          enum:
            - web
            - ios
            - android
          type: string
          x-struct:
          x-validate:
        user_agent:
          nullable: true
          type: string
          x-struct:
          x-validate:
      required:
        - device_id
        - platform
      title: CreateAuthSessionRequest
      type: object
      x-struct: Elixir.BoldAdminWeb.ApiSchemas.CreateAuthSessionRequest
      x-validate:
  securitySchemes:
    admin_api_token:
      description: 'Privileged admin key (bold_live_* with admin: true) for Mission Control and support automation. Do not put this key in customer-owned apps.'
      in: header
      name: X-Bold-Admin-Api-Key
      type: apiKey
    api_token:
      description: API token provided by BOLD Admin
      scheme: bearer
      type: http
    upstream_jwt:
      bearerFormat: JWT
      description: Customer IdP JWT used by session-management client endpoints. Must match the tenant policy's issuer/audience/JWKS settings.
      scheme: bearer
      type: http
info:
  description: |
    API for accessing video content, collections, playlists, and AI-powered features.

    ## Authentication

    Most API endpoints require authentication via a BOLD API token. Include your token
    in the `Authorization` header as a bearer token:

    ```
    Authorization: Bearer YOUR_API_TOKEN
    ```

    Session-management client endpoints under `/api/v1/auth/*` use the customer's
    upstream IdP JWT instead:

    ```
    Authorization: Bearer UPSTREAM_IDP_JWT
    X-Bold-Tenant-Slug: YOUR_TENANT_SLUG
    ```

    Server-side session-management integration endpoints under
    `/api/v1/session-management/*` use the normal tenant BOLD API token. These
    endpoints are for customer-owned servers to inspect and revoke device sessions
    after the customer app has already decided the viewer is allowed to access content.

    Admin endpoints under `/api/v1/admin/*` require `X-Bold-Admin-Api-Key` and are
    reserved for Mission Control or deliberately privileged support automation.
  title: BoldAdmin API
  version: 1.0.0
openapi: 3.0.0
paths:
  /api/v1/admin/auth/policy:
    get:
      callbacks: {}
      description: Returns max_devices_per_user, enforcement_mode/phase, session_ttl_days, allow_member_self_manage, admin_override_per_user, and auth challenge email branding fields. JWT-verification config (jwks_url, jwt_issuer, jwt_audience) is deliberately excluded.
      operationId: BoldAdminWeb.Api.Admin.PolicyController.show
      parameters: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminAuthPolicyResponse'
          description: Policy
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
      security:
        - admin_api_token: []
      summary: Get the tenant's user-tunable auth policy
      tags:
        - Admin Auth Policy
    put:
      callbacks: {}
      description: Casts any provided user-tunable fields and preserves omitted values. Auth challenge email branding may be configured here, but arbitrary From-domain configuration is not supported. JWKS/issuer/audience are silently ignored if present in the request body — they are infra config edited via Mission Control, not over the API.
      operationId: BoldAdminWeb.Api.Admin.PolicyController.update
      parameters: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AdminAuthPolicyUpdateRequest'
        description: User-tunable policy fields
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminAuthPolicyResponse'
          description: Updated policy
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation failed
      security:
        - admin_api_token: []
      summary: Update the tenant's user-tunable auth policy
      tags:
        - Admin Auth Policy
  /api/v1/viewers/{id}:
    delete:
      callbacks: {}
      description: Deletes an existing viewer.
      operationId: BoldAdminWeb.Api.ViewerController.delete
      parameters:
        - description: Viewer UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '204':
          content:
            application/json: {}
          description: Viewer deleted
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive, or the viewers feature is not enabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer not found
      summary: Delete a viewer
      tags:
        - Viewers
    get:
      callbacks: {}
      description: Returns a single viewer by ID.
      operationId: BoldAdminWeb.Api.ViewerController.show
      parameters:
        - description: Viewer UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ViewerResponse'
          description: Viewer details
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive, or the viewers feature is not enabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer not found
      summary: Get a viewer
      tags:
        - Viewers
    patch:
      callbacks: {}
      description: Updates an existing viewer.
      operationId: BoldAdminWeb.Api.ViewerController.update (2)
      parameters:
        - description: Viewer UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ViewerUpdate'
        description: Viewer parameters
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ViewerResponse'
          description: Viewer updated
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid parameters
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive, or the viewers feature is not enabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation errors
      summary: Update a viewer
      tags:
        - Viewers
    put:
      callbacks: {}
      description: Updates an existing viewer.
      operationId: BoldAdminWeb.Api.ViewerController.update
      parameters:
        - description: Viewer UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ViewerUpdate'
        description: Viewer parameters
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ViewerResponse'
          description: Viewer updated
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid parameters
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive, or the viewers feature is not enabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation errors
      summary: Update a viewer
      tags:
        - Viewers
  /api/v1/admin/viewers/{viewer_id}/sessions/{id}/revoke:
    post:
      callbacks: {}
      operationId: BoldAdminWeb.Api.Admin.ViewerSessionController.revoke
      parameters:
        - description: Viewer UUID
          in: path
          name: viewer_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Session UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AdminRevokeAuthSessionRequest'
        description: Optional reason
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminRevokeAuthSessionResponse'
          description: Session revoked
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Session not found
      security:
        - admin_api_token: []
      summary: Admin-revoke a single session
      tags:
        - Admin Auth Sessions
  /api/v1/ai/chat:
    get:
      callbacks: {}
      description: Retrieve paginated conversation history for library-scoped AI chat.
      operationId: BoldAdminWeb.Api.AskStreamController.index
      parameters:
        - description: Max results (default 20, max 100)
          in: query
          name: limit
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
        - description: Pagination offset (default 0)
          in: query
          name: offset
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
        - description: Viewer UUID or external ID
          in: query
          name: viewer
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LibraryConversationListResponse'
          description: Conversation list
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid profile_id
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Forbidden — account inactive (subscription expired or no active plan) or required feature disabled
      summary: List library chat conversations
      tags:
        - AI Chat
    post:
      callbacks: {}
      description: |
        Ask questions across your entire video library.

        The AI searches all transcripts, finds relevant content, and synthesizes an answer with citations.
        Use `conversation_id` from the response to ask follow-up questions.

        **Streaming (default):** Returns SSE events:
        - `message_start`: Stream started
        - `conversation_created`: Conversation record created
        - `image_analysis`: Uploaded images analyzed
        - `progress`: Pipeline stage status (e.g. "Searching your library…")
        - `sources`: Search results found
        - `citation_map`: Stable citation map for streamed text
        - `text_delta`: Answer text chunk
        - `answer`: Complete answer with citations and public-safe retrieval metadata
        - `message_complete`: Stream finished

        Answer responses include public-safe retrieval metadata: `retrieval_mode`, `degraded`, and
        `degraded_reason`. When retrieval recovers after Stage 1 exhaustion, `retrieval_mode` is
        `degraded` and `degraded_reason` is `stage1_exhausted`.

        Set `stream=false` for a single JSON response with the same retrieval metadata.
      operationId: BoldAdminWeb.Api.AskStreamController.ask
      parameters:
        - description: Set to "true" to bypass caching for this request. Requires allow_per_request_model to be enabled on the account.
          in: header
          name: X-Bold-Cache-Bypass
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LibraryAiChatRequest'
        description: Chat request
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LibraryAiChatResponse'
          description: Chat response
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid request
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: AI not enabled
      summary: Chat with your video library
      tags:
        - AI Chat
  /api/v1/ai/conversations:
    get:
      callbacks: {}
      description: Returns a unified list of all AI conversations (video and library) for a viewer, in reverse-chronological order.
      operationId: BoldAdminWeb.Api.ConversationsController.index
      parameters:
        - description: Viewer UUID or external ID
          in: query
          name: viewer
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Results per page (max 100)
          in: query
          name: limit
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
        - description: Offset for pagination
          in: query
          name: offset
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnifiedConversationListResponse'
          description: Conversation list
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Missing viewer parameter
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: AI not enabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer not found
      summary: List all conversations for a viewer
      tags:
        - AI Conversations
  /api/v1/viewers:
    get:
      callbacks: {}
      description: Returns a paginated list of viewers for the current tenant.
      operationId: BoldAdminWeb.Api.ViewerController.index
      parameters:
        - description: 'Page number (default: 1)'
          example: 1
          in: query
          name: page
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
        - description: 'Items per page (default: 20)'
          example: 20
          in: query
          name: page_size
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ViewersResponse'
          description: Viewers list with pagination metadata
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive, or the viewers feature is not enabled
      summary: List viewers (paginated)
      tags:
        - Viewers
    post:
      callbacks: {}
      description: Creates a new viewer for the current tenant.
      operationId: BoldAdminWeb.Api.ViewerController.create
      parameters: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ViewerCreate'
        description: Viewer parameters
        required: false
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ViewerResponse'
          description: Viewer created
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid parameters
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive, or the viewers feature is not enabled
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation errors
      summary: Create a viewer
      tags:
        - Viewers
  /api/v1/playlists:
    get:
      callbacks: {}
      description: Returns all playlists for your account.
      operationId: BoldAdminWeb.Api.PlaylistController.index
      parameters:
        - description: 'Maximum number of playlists (1-1000, default: 50)'
          in: query
          name: limit
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
        - description: 'Offset for pagination (default: 0)'
          in: query
          name: offset
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlaylistsResponse'
          description: Playlists
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
      summary: List playlists
      tags:
        - Playlists
  /api/v1/ai/chat/{id}:
    delete:
      callbacks: {}
      description: Delete a library-scoped conversation and all associated messages.
      operationId: BoldAdminWeb.Api.AskStreamController.delete
      parameters:
        - description: Conversation ID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '204':
          content:
            application/json: {}
          description: Conversation deleted
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: AI feature not available
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Conversation not found
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Deletion failed
      summary: Delete a library chat conversation
      tags:
        - AI Chat
    get:
      callbacks: {}
      description: Retrieve the full message history for a conversation.
      operationId: BoldAdminWeb.Api.AskStreamController.show (2)
      parameters:
        - description: Conversation ID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConversationResponse'
          description: Conversation
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Forbidden — account inactive (subscription expired or no active plan) or required feature disabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Conversation not found
      summary: Get conversation history
      tags:
        - AI Chat
    post:
      callbacks: {}
      description: |
        Continue an existing conversation with follow-up questions.

        The AI maintains context from previous messages in the conversation.
        Answer responses include public-safe retrieval metadata: `retrieval_mode`, `degraded`, and
        `degraded_reason`.
      operationId: BoldAdminWeb.Api.AskStreamController.continue_ask (2)
      parameters:
        - description: Conversation ID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LibraryAiChatRequest'
        description: Chat request
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LibraryAiChatResponse'
          description: Chat response
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid request
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Forbidden — account inactive (subscription expired or no active plan) or required feature disabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Conversation not found
      summary: Continue a library chat
      tags:
        - AI Chat
  /api/v1/ai/videos/{id}/chat:
    get:
      callbacks: {}
      description: Retrieve paginated conversation history for a specific video.
      operationId: BoldAdminWeb.Api.AiController.index
      parameters:
        - description: Video ID or slug
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Max results (default 20, max 100)
          in: query
          name: limit
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
        - description: Pagination offset (default 0)
          in: query
          name: offset
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
        - description: Viewer UUID or external ID
          in: query
          name: viewer
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoConversationListResponse'
          description: Conversation list
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Missing viewer parameter
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: AI feature not available
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Video or viewer not found
      summary: List video chat conversations
      tags:
        - AI Chat
    post:
      callbacks: {}
      description: |
        Ask questions about a specific video using its transcript.

        Set `stream=false` to receive a JSON response instead of SSE stream.

        **Streaming (default)**: Returns `text/event-stream` with events:
        - `message_start`: Initial event with conversation_id
        - `text_delta`: Incremental text chunks
        - `message_complete`: Final event with full content and metadata
        - `error`: Error event if something goes wrong
      operationId: BoldAdminWeb.Api.AiController.ask
      parameters:
        - description: Video ID or slug
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AiChatRequest'
        description: Chat request
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AiChatResponse'
          description: Chat response (JSON when stream=false)
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid request
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: AI feature not available
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Video, transcript, or viewer not found
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Processing failed
      summary: Chat about a video
      tags:
        - AI Chat
  /api/v1/auth/sessions:
    get:
      callbacks: {}
      operationId: BoldAdminWeb.Api.Auth.SessionController.index
      parameters:
        - description: Tenant slug for the BOLD account, for example `hrtu`.
          in: header
          name: X-Bold-Tenant-Slug
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthSessionsListResponse'
          description: Active sessions
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid bearer JWT
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SelfManagementDisabledError'
          description: Self-management disabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer not provisioned
      security:
        - upstream_jwt: []
      summary: List active sessions for the authenticated viewer
      tags:
        - Auth Sessions
    post:
      callbacks: {}
      description: "Verifies the upstream IdP bearer JWT, resolves the viewer, runs device-limit enforcement per the tenant's auth_policies row. Captures a coarse session location from the connecting IP; trusted server-side integrators may pass `client_ip` to geo-locate the real end user instead of their server's egress IP."
      operationId: BoldAdminWeb.Api.Auth.SessionController.create
      parameters:
        - description: Tenant slug for the BOLD account, for example `hrtu`.
          in: header
          name: X-Bold-Tenant-Slug
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAuthSessionRequest'
        description: Create-session payload
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthSessionResponse'
          description: Session created or bypassed
        '202':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthSessionChallengeResponse'
          description: Challenge required
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid bearer JWT
        '403':
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/DeviceLimitError'
                  - $ref: '#/components/schemas/Error'
                x-struct:
                x-validate:
          description: Device limit exceeded or account inactive
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer not provisioned
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer email required for challenge delivery
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Challenge delivery unavailable
      security:
        - upstream_jwt: []
      summary: Create a session for the authenticated viewer's device
      tags:
        - Auth Sessions
  /api/v1/videos:
    get:
      callbacks: {}
      description: Returns a paginated list of public videos for the current tenant.
      operationId: BoldAdminWeb.Api.VideoController.index
      parameters:
        - description: Page number
          in: query
          name: page
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
        - description: Filter by tag
          in: query
          name: tag
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Filter by a single collection UUID
          in: query
          name: collection_id
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Filter by multiple collection UUIDs (OR semantics). Supports repeated query params and comma-separated values.
          explode: true
          in: query
          name: collection_ids
          required: false
          schema:
            items:
              type: string
              x-struct:
              x-validate:
            type: array
            x-struct:
            x-validate:
          style: form
        - description: Only return uncategorized videos
          in: query
          name: no_collection
          required: false
          schema:
            type: boolean
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideosResponse'
          description: Videos list
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
      summary: List public videos
      tags:
        - Videos
    post:
      callbacks: {}
      description: Accepts a video URL for ingestion. Returns immediately with a video ID. Poll GET /api/v1/videos/:id for processing status.
      operationId: BoldAdminWeb.Api.VideoController.create
      parameters: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VideoIngestRequest'
        description: Video ingestion request
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoIngestResponse'
          description: Existing video (idempotent)
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoIngestResponse'
          description: Video created
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Collection not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation error
      summary: Create a video from URL
      tags:
        - Videos
  /api/v1/viewers/lookup:
    get:
      callbacks: {}
      description: Finds a viewer by external_id or email. At least one query parameter must be provided.
      operationId: BoldAdminWeb.Api.ViewerController.lookup
      parameters:
        - description: External ID from course platform
          in: query
          name: external_id
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Viewer email
          in: query
          name: email
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ViewerResponse'
          description: Viewer found
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Missing query parameters
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive, or the viewers feature is not enabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer not found
      summary: Look up a viewer
      tags:
        - Viewers
  /api/v1/community/posts/{post_id}/comments:
    post:
      callbacks: {}
      description: |
        Creates a new comment on a post. Requires the `X-Viewer-ID` header.

        To create a reply to another comment, include `parent_id` in the request body.
        Comments can be nested up to 2 levels deep.
      operationId: BoldAdminWeb.Api.CommunityController.create_comment
      parameters:
        - description: Post UUID
          in: path
          name: post_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Viewer UUID (required)
          in: header
          name: X-Viewer-ID
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CommunityCommentCreate'
        description: Comment parameters
        required: false
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommunityCommentResponse'
          description: Comment created
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid parameters
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Post not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation errors (e.g., max depth exceeded)
      summary: Create a comment on a post
      tags:
        - Community
  /api/v1/search:
    get:
      callbacks: {}
      description: |
        Searches public, published video transcript and indexed attachment content.

        This endpoint is shared by public API clients and the hosted portal runtime.
        Server-side filters always restrict results to public videos published before the request time.
      operationId: BoldAdminWeb.Shared.SearchController.search (2)
      parameters:
        - description: Search query
          in: query
          name: query
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: 'Page number (default: 1)'
          in: query
          name: page
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
        - description: 'Results per page (default: 10)'
          in: query
          name: per_page
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
        - description: Comma-separated speaker labels
          in: query
          name: speakers
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Filter by a single collection UUID
          in: query
          name: collection_id
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Filter by multiple collection UUIDs (OR semantics). Supports repeated query params and comma-separated values.
          explode: true
          in: query
          name: collection_ids
          required: false
          schema:
            items:
              type: string
              x-struct:
              x-validate:
            type: array
            x-struct:
            x-validate:
          style: form
        - description: Only include content published after this ISO 8601 timestamp
          in: query
          name: published_after
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Only include content published before this ISO 8601 timestamp
          in: query
          name: published_before
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Meilisearch sort expression, such as published_at:desc
          in: query
          name: sort
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
          description: Search results
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchErrorResponse'
          description: Search failed
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiAuthErrorResponse'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
      summary: Search public video content
      tags:
        - Search
  /api/v1/videos/{id}:
    get:
      callbacks: {}
      description: |
        Returns a single video by hashid, UUID, or slug.

        **Lookup order:** UUID → hashid → slug.
      operationId: BoldAdminWeb.Api.VideoController.show
      parameters:
        - description: Video ID (hashid, UUID) or slug
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoResponse'
          description: Video details
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Video not found
      summary: Get a video
      tags:
        - Videos
  /api/v1/collections/{collection_id}/videos:
    get:
      callbacks: {}
      description: Returns all videos belonging to a collection.
      operationId: BoldAdminWeb.Api.CollectionController.videos
      parameters:
        - description: Collection UUID or slug
          in: path
          name: collection_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: 'Maximum number of videos (1-1000, default: 100)'
          in: query
          name: limit
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
        - description: 'Offset for pagination (default: 0)'
          in: query
          name: offset
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CollectionVideosResponse'
          description: Collection videos
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid parameters
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Collection not found
      summary: List videos in a collection
      tags:
        - Collections
  /api/v1/collections:
    get:
      callbacks: {}
      description: |
        Returns collections for the current tenant. Use query params to filter.

        If both `root_only` and `parent_id` are provided, `root_only` takes precedence.
      operationId: BoldAdminWeb.Api.CollectionController.index
      parameters:
        - description: Only return root-level collections (no parent)
          in: query
          name: root_only
          required: false
          schema:
            type: boolean
            x-struct:
            x-validate:
        - description: Filter by parent collection UUID
          in: query
          name: parent_id
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: 'Maximum number of collections (1-1000, default: 50)'
          in: query
          name: limit
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
        - description: 'Offset for pagination (default: 0)'
          in: query
          name: offset
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CollectionsResponse'
          description: Collections list
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid parent_id format
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
      summary: List collections
      tags:
        - Collections
  /api/v1/admin/viewers/{viewer_id}/device-limit:
    put:
      callbacks: {}
      operationId: BoldAdminWeb.Api.Admin.ViewerController.update_device_limit
      parameters:
        - description: Bold viewer UUID
          in: path
          name: viewer_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AdminDeviceLimitRequest'
        description: Limit value
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminDeviceLimitResponse'
          description: Override updated
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Invalid request
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Unauthorized
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Viewer not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Invalid limit
      security:
        - admin_api_token: []
      summary: Set or clear a viewer's device-limit override
      tags:
        - Admin Viewers
  /api/v1/auth/sessions/{id}/verify:
    get:
      callbacks: {}
      operationId: BoldAdminWeb.Api.Auth.SessionController.verify
      parameters:
        - description: Session UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Tenant slug for the BOLD account, for example `hrtu`.
          in: header
          name: X-Bold-Tenant-Slug
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerifyAuthSessionResponse'
          description: Verification result
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid bearer JWT
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Ownership mismatch or account inactive
      security:
        - upstream_jwt: []
      summary: Verify a session is still valid
      tags:
        - Auth Sessions
  /api/v1/viewers/{viewer_id}/memory:
    delete:
      callbacks: {}
      description: "Clears the viewer's memory content (idempotent). The document regrows from future conversations unless the viewer is also opted out via PATCH `{\"memory\": {\"enabled\": false}}`. Requires the `viewer_memory` feature."
      operationId: BoldAdminWeb.Api.ViewerMemoryController.delete
      parameters:
        - description: Viewer UUID
          in: path
          name: viewer_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '204':
          content:
            application/json: {}
          description: Memory cleared
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive, or the viewers/viewer_memory feature is not enabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer not found
      summary: Clear a viewer's memory
      tags:
        - Viewers
    get:
      callbacks: {}
      description: Returns the AI-maintained memory document for a viewer. If nothing has been distilled yet, returns an empty default (content null, enabled true). Requires the `viewer_memory` feature.
      operationId: BoldAdminWeb.Api.ViewerMemoryController.show
      parameters:
        - description: Viewer UUID
          in: path
          name: viewer_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ViewerMemoryResponse'
          description: Viewer memory
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive, or the viewers/viewer_memory feature is not enabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer not found
      summary: Get a viewer's memory
      tags:
        - Viewers
    patch:
      callbacks: {}
      description: 'Opts a viewer in or out of memory re-distillation via `{"memory": {"enabled": bool}}`. Opting out stops future distillation but retains existing content until cleared. Requires the `viewer_memory` feature.'
      operationId: BoldAdminWeb.Api.ViewerMemoryController.update
      parameters:
        - description: Viewer UUID
          in: path
          name: viewer_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ViewerMemoryUpdate'
        description: Memory settings
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ViewerMemoryResponse'
          description: Updated viewer memory
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid parameters
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive, or the viewers/viewer_memory feature is not enabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation errors
      summary: Update a viewer's memory settings
      tags:
        - Viewers
  /api/v1/auth/sessions/{id}/revoke:
    post:
      callbacks: {}
      operationId: BoldAdminWeb.Api.Auth.SessionController.revoke
      parameters:
        - description: Session UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Tenant slug for the BOLD account, for example `hrtu`.
          in: header
          name: X-Bold-Tenant-Slug
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RevokeAuthSessionResponse'
          description: Session revoked
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid bearer JWT
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Self-management disabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Session not found or not owned by viewer
      security:
        - upstream_jwt: []
      summary: Self-revoke one of the authenticated viewer's sessions
      tags:
        - Auth Sessions
  /api/v1/session-management/viewers/by-external-id/{external_id}/session-management-exemption:
    put:
      callbacks: {}
      description: Tenant-scoped customer-server endpoint. Marks whether the resolved viewer is exempt from session-management enforcement when per-user admin overrides are enabled.
      operationId: BoldAdminWeb.Api.SessionManagement.ViewerController.update_session_management_exemption
      parameters:
        - description: Optional tenant slug. When provided, it must match the tenant API key's account slug.
          in: header
          name: X-Bold-Tenant-Slug
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Upstream IdP user ID
          in: path
          name: external_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SessionManagementExemptionRequest'
        description: Exemption value
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionManagementViewerStateResponse'
          description: Viewer state
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Invalid request
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Customer-admin overrides disabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Viewer not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Invalid value
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Auth policy or tenant migration unavailable
      security:
        - api_token: []
      summary: Set or clear a viewer's session-management exemption by upstream user ID
      tags:
        - Session Management
  /api/v1/session-management/viewers/by-external-id/{external_id}/sessions/{id}/revoke:
    post:
      callbacks: {}
      operationId: BoldAdminWeb.Api.SessionManagement.ViewerSessionController.revoke
      parameters:
        - description: Optional tenant slug. When provided, it must match the tenant API key's account slug.
          in: header
          name: X-Bold-Tenant-Slug
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Upstream IdP user ID
          in: path
          name: external_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Session UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SessionManagementRevokeSessionRequest'
        description: Optional reason
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionManagementRevokeSessionResponse'
          description: Session revoked
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Invalid reason
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Session management unavailable or account inactive
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Viewer or session not found
      security:
        - api_token: []
      summary: Revoke a viewer session by upstream user ID
      tags:
        - Session Management
  /api/v1/admin/viewers/by-external-id/{external_id}:
    get:
      callbacks: {}
      operationId: BoldAdminWeb.Api.Admin.ViewerController.by_external_id
      parameters:
        - description: Upstream IdP user ID
          in: path
          name: external_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminViewerResolveResponse'
          description: Resolved viewer
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Unauthorized
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Viewer not found
      security:
        - admin_api_token: []
      summary: Resolve an upstream IdP user ID to a Bold viewer_id
      tags:
        - Admin Viewers
  /api/v1/session-management/viewers/by-external-id/{external_id}/device-limit:
    put:
      callbacks: {}
      description: Tenant-scoped customer-server endpoint. Mutates only the resolved viewer's device-limit override when per-user admin overrides are enabled for the account.
      operationId: BoldAdminWeb.Api.SessionManagement.ViewerController.update_device_limit
      parameters:
        - description: Optional tenant slug. When provided, it must match the tenant API key's account slug.
          in: header
          name: X-Bold-Tenant-Slug
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Upstream IdP user ID
          in: path
          name: external_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SessionManagementDeviceLimitRequest'
        description: Limit value
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionManagementViewerStateResponse'
          description: Viewer state
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Invalid request
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Customer-admin overrides disabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Viewer not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Invalid limit
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Auth policy unavailable
      security:
        - api_token: []
      summary: Set or clear a viewer's device-limit override by upstream user ID
      tags:
        - Session Management
  /api/v1/admin/viewers/{viewer_id}/sessions/revoke-all:
    post:
      callbacks: {}
      operationId: BoldAdminWeb.Api.Admin.ViewerSessionController.revoke_all
      parameters:
        - description: Viewer UUID
          in: path
          name: viewer_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AdminRevokeAuthSessionRequest'
        description: Optional reason
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminRevokeAllResponse'
          description: All sessions revoked
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer not found
      security:
        - admin_api_token: []
      summary: Admin-revoke every active session for a viewer
      tags:
        - Admin Auth Sessions
  /api/v1/admin/viewers/{viewer_id}/sessions:
    get:
      callbacks: {}
      operationId: BoldAdminWeb.Api.Admin.ViewerSessionController.index
      parameters:
        - description: Viewer UUID
          in: path
          name: viewer_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminViewerSessionsResponse'
          description: Sessions for viewer
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer not found
      security:
        - admin_api_token: []
      summary: List active + last-30-days revoked sessions for a viewer
      tags:
        - Admin Auth Sessions
  /api/v1/ai/videos/{id}/chat/{conversation_id}:
    delete:
      callbacks: {}
      description: Delete a video chat conversation and all associated messages.
      operationId: BoldAdminWeb.Api.AiController.delete
      parameters:
        - description: Video ID or slug
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Conversation ID
          in: path
          name: conversation_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '204':
          content:
            application/json: {}
          description: Conversation deleted
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Conversation/video mismatch
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: AI feature not available
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Video or conversation not found
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Deletion failed
      summary: Delete a video chat conversation
      tags:
        - AI Chat
    get:
      callbacks: {}
      description: Retrieve the full message history for a video chat conversation.
      operationId: BoldAdminWeb.Api.AiController.show
      parameters:
        - description: Video ID or slug
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Conversation ID
          in: path
          name: conversation_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoConversationResponse'
          description: Conversation
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Conversation/video mismatch
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: AI feature not available
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Video or conversation not found
      summary: Get a video chat conversation
      tags:
        - AI Chat
    post:
      callbacks: {}
      description: Continue an existing conversation about a video.
      operationId: BoldAdminWeb.Api.AiController.continue_chat
      parameters:
        - description: Video ID or slug
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Existing conversation ID
          in: path
          name: conversation_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AiChatRequest'
        description: Chat request
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AiChatResponse'
          description: Chat response
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid request or conversation mismatch
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: AI feature not available
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Video, transcript, or conversation not found
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Processing failed
      summary: Continue a video chat conversation
      tags:
        - AI Chat
  /api/v1/session-management/viewers/by-external-id/{external_id}/sessions:
    get:
      callbacks: {}
      description: Tenant-scoped customer-server endpoint. Returns the resolved viewer's computed session-management state plus active and recently revoked sessions.
      operationId: BoldAdminWeb.Api.SessionManagement.ViewerSessionController.index
      parameters:
        - description: Optional tenant slug. When provided, it must match the tenant API key's account slug.
          in: header
          name: X-Bold-Tenant-Slug
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Upstream IdP user ID
          in: path
          name: external_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionManagementViewerSessionsResponse'
          description: Sessions for viewer
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Session management unavailable or account inactive
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Viewer not found
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Auth policy unavailable
      security:
        - api_token: []
      summary: List sessions for a viewer by upstream user ID
      tags:
        - Session Management
  /api/v1/ai/recommendations:
    post:
      callbacks: {}
      description: |
        Get AI-powered video recommendations based on topics or learning goals.

        Optionally includes guidance text explaining why each video was recommended.

        **Streaming (default):** Returns SSE events:
        - `message_start`: Stream started
        - `text_delta`: Guidance text chunk
        - `recommendations`: Video list
        - `message_complete`: Complete response

        Set `stream=false` for a single JSON response.
      operationId: BoldAdminWeb.Api.RecommendController.recommend
      parameters: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AiRecommendationsRequest'
        description: Recommendations request
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AiRecommendationsResponse'
          description: Recommendations
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid topics
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: AI not enabled
      summary: Get video recommendations
      tags:
        - AI Recommendations
  /api/v1/community/comments/{id}/react:
    post:
      callbacks: {}
      description: |
        Toggles the current viewer's reaction on a comment. If the viewer has already
        reacted, the reaction is removed. If not, a reaction is added.

        Requires the `X-Viewer-ID` header.
      operationId: BoldAdminWeb.Api.CommunityController.react_to_comment
      parameters:
        - description: Comment UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Viewer UUID (required)
          in: header
          name: X-Viewer-ID
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReactionResponse'
          description: Reaction toggled
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Comment not found
      summary: Toggle reaction on a comment
      tags:
        - Community
  /api/v1/ai/search:
    post:
      callbacks: {}
      description: |
        Semantic search across your video library with AI-synthesized results.

        Returns relevant transcript segments and an AI-generated summary.
        Faster than full chat—use this for search experiences.

        **Streaming (default):** Returns SSE events:
        - `message_start`: Stream started
        - `sources`: Matching transcript segments
        - `text_delta`: Synthesis text chunk
        - `message_complete`: Complete response

        Set `stream=false` for a single JSON response.
      operationId: BoldAdminWeb.Api.AiSearchController.search
      parameters: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AiSearchRequest'
        description: Search request
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AiSearchResponse'
          description: Search results
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid query
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: AI not enabled
      summary: Search with AI synthesis
      tags:
        - AI Search
  /api/v1/session-management/viewers/by-external-id/{external_id}/sessions/revoke-all:
    post:
      callbacks: {}
      operationId: BoldAdminWeb.Api.SessionManagement.ViewerSessionController.revoke_all
      parameters:
        - description: Optional tenant slug. When provided, it must match the tenant API key's account slug.
          in: header
          name: X-Bold-Tenant-Slug
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Upstream IdP user ID
          in: path
          name: external_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SessionManagementRevokeSessionRequest'
        description: Optional reason
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionManagementRevokeAllResponse'
          description: All sessions revoked
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Invalid reason
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Session management unavailable or account inactive
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Viewer not found
      security:
        - api_token: []
      summary: Revoke every active session for a viewer by upstream user ID
      tags:
        - Session Management
  /api/v1/admin/viewers/{viewer_id}/session-management-exemption:
    put:
      callbacks: {}
      description: Marks whether a viewer is exempt from device-limit enforcement. This is distinct from numeric device_limit_override.
      operationId: BoldAdminWeb.Api.Admin.ViewerController.update_session_management_exemption
      parameters:
        - description: Bold viewer UUID
          in: path
          name: viewer_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AdminSessionManagementExemptionRequest'
        description: Exemption value
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminSessionManagementExemptionResponse'
          description: Exemption updated
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Invalid request
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Unauthorized
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Viewer not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Invalid value
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Tenant migration unavailable
      security:
        - admin_api_token: []
      summary: Set or clear a viewer's session-management exemption
      tags:
        - Admin Viewers
  /api/v1/collections/{id}:
    get:
      callbacks: {}
      description: Returns a single collection by ID or slug.
      operationId: BoldAdminWeb.Api.CollectionController.show
      parameters:
        - description: Collection UUID or slug
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: "Include 'children' for direct children or 'descendants' for full tree"
          in: query
          name: include
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CollectionResponse'
          description: Collection details
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Collection not found
      summary: Get a collection
      tags:
        - Collections
  /api/v1/community/posts/{id}/react:
    post:
      callbacks: {}
      description: |
        Toggles the current viewer's reaction on a post. If the viewer has already
        reacted, the reaction is removed. If not, a reaction is added.

        Requires the `X-Viewer-ID` header.
      operationId: BoldAdminWeb.Api.CommunityController.react_to_post
      parameters:
        - description: Post UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Viewer UUID (required)
          in: header
          name: X-Viewer-ID
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReactionResponse'
          description: Reaction toggled
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Post not found
      summary: Toggle reaction on a post
      tags:
        - Community
  /api/v1/community/posts:
    get:
      callbacks: {}
      description: |
        Returns community posts for the current tenant with optional filtering and pagination.

        Posts are ordered by: pinned first, then by pin timestamp, then by creation date.

        Pass the `X-Viewer-ID` header to include `viewer_has_reacted` boolean in each post's reactions.
      operationId: BoldAdminWeb.Api.CommunityController.index
      parameters:
        - description: Filter by category
          example: announcements
          in: query
          name: category
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: 'Page number (default: 1)'
          example: 1
          in: query
          name: page
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
        - description: 'Items per page (default: 20, max: 100)'
          example: 20
          in: query
          name: page_size
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
        - description: Viewer UUID for reaction status
          in: header
          name: X-Viewer-ID
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommunityPostsResponse'
          description: Community posts list
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
      summary: List community posts
      tags:
        - Community
    post:
      callbacks: {}
      description: |
        Creates a new community post. Requires the `X-Viewer-ID` header to identify the author.

        The viewer must exist in the system before creating a post.
      operationId: BoldAdminWeb.Api.CommunityController.create
      parameters:
        - description: Viewer UUID (required)
          in: header
          name: X-Viewer-ID
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CommunityPostCreate'
        description: Post parameters
        required: false
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommunityPostResponse'
          description: Post created
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid parameters
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized - X-Viewer-ID header required
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation errors
      summary: Create a community post
      tags:
        - Community
  /api/v1/auth/challenges/{id}/resend:
    post:
      callbacks: {}
      description: Generates and emails a fresh verification code for an active challenge. The original challenge expiry is preserved and only the latest emailed code is valid.
      operationId: BoldAdminWeb.Api.Auth.ChallengeController.resend
      parameters:
        - description: Challenge UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Tenant slug for the BOLD account, for example `hrtu`.
          in: header
          name: X-Bold-Tenant-Slug
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthChallengeResendResponse'
          description: Challenge code resent
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthChallengeError'
          description: Invalid, expired, or resend-limited challenge
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthChallengeError'
          description: Invalid bearer JWT
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthChallengeError'
          description: Challenge ownership mismatch
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthChallengeError'
          description: Viewer not provisioned
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthChallengeError'
          description: Viewer email required
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthChallengeError'
          description: Resend rate limited
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthChallengeError'
          description: Challenge email delivery unavailable
      security:
        - upstream_jwt: []
      summary: Resend an auth challenge code
      tags:
        - Auth Challenges
  /api/v1/session-management/viewers/by-external-id/{external_id}:
    get:
      callbacks: {}
      description: Tenant-scoped customer-server endpoint. The normal BOLD tenant API key determines the account; no admin API key is required.
      operationId: BoldAdminWeb.Api.SessionManagement.ViewerController.by_external_id
      parameters:
        - description: Optional tenant slug. When provided, it must match the tenant API key's account slug.
          in: header
          name: X-Bold-Tenant-Slug
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Upstream IdP user ID
          in: path
          name: external_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionManagementViewerResolveResponse'
          description: Resolved viewer
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Session management unavailable or account inactive
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Viewer not found
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminErrorResponse'
          description: Auth policy unavailable
      security:
        - api_token: []
      summary: Resolve an upstream user ID to a BOLD viewer
      tags:
        - Session Management
  /api/v1/community/comments/{id}:
    delete:
      callbacks: {}
      description: |
        Deletes an existing comment. Requires the `X-Viewer-ID` header.

        Only the comment author or an admin viewer can delete a comment.
      operationId: BoldAdminWeb.Api.CommunityController.delete_comment
      parameters:
        - description: Comment UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Viewer UUID (required)
          in: header
          name: X-Viewer-ID
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '204':
          content:
            application/json: {}
          description: Comment deleted
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Forbidden - not comment owner or admin
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Comment not found
      summary: Delete a comment
      tags:
        - Community
  /api/v1/community/posts/{id}:
    delete:
      callbacks: {}
      description: |
        Deletes an existing community post. Requires the `X-Viewer-ID` header.

        Only the post author or an admin viewer can delete a post.
      operationId: BoldAdminWeb.Api.CommunityController.delete
      parameters:
        - description: Post UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Viewer UUID (required)
          in: header
          name: X-Viewer-ID
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '204':
          content:
            application/json: {}
          description: Post deleted
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Forbidden - not post owner or admin
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Post not found
      summary: Delete a community post
      tags:
        - Community
    get:
      callbacks: {}
      description: |
        Returns a single community post by ID with nested comments.

        Pass the `X-Viewer-ID` header to include `viewer_has_reacted` booleans in the response.
      operationId: BoldAdminWeb.Api.CommunityController.show
      parameters:
        - description: Post UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Viewer UUID for reaction status
          in: header
          name: X-Viewer-ID
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommunityPostResponse'
          description: Community post details
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Post not found
      summary: Get a community post
      tags:
        - Community
    patch:
      callbacks: {}
      description: |
        Updates an existing community post. Requires the `X-Viewer-ID` header.

        Only the post author or an admin viewer can update a post.
      operationId: BoldAdminWeb.Api.CommunityController.update (2)
      parameters:
        - description: Post UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Viewer UUID (required)
          in: header
          name: X-Viewer-ID
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CommunityPostCreate'
        description: Post parameters
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommunityPostResponse'
          description: Post updated
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid parameters
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Forbidden - not post owner or admin
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Post not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation errors
      summary: Update a community post
      tags:
        - Community
    put:
      callbacks: {}
      description: |
        Updates an existing community post. Requires the `X-Viewer-ID` header.

        Only the post author or an admin viewer can update a post.
      operationId: BoldAdminWeb.Api.CommunityController.update
      parameters:
        - description: Post UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Viewer UUID (required)
          in: header
          name: X-Viewer-ID
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CommunityPostCreate'
        description: Post parameters
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommunityPostResponse'
          description: Post updated
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid parameters
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Forbidden - not post owner or admin
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Post not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation errors
      summary: Update a community post
      tags:
        - Community
  /api/v1/videos/latest:
    get:
      callbacks: {}
      description: |
        Returns the most recently published public videos.

        When `viewer_id` is provided, each video includes a `progress` field showing the viewer's
        watch progress (current_time, duration, percentage, completed status). Videos without
        progress for that viewer will have `progress: null`.
      operationId: BoldAdminWeb.Api.VideoController.latest
      parameters:
        - description: 'Maximum number of videos (default: 6, max: 50)'
          in: query
          name: limit
          required: false
          schema:
            type: integer
            x-struct:
            x-validate:
        - description: Filter by tag
          in: query
          name: tag
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Filter by collection ID
          in: query
          name: collection_id
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Filter by multiple collection IDs (OR semantics). Supports repeated query params and comma-separated values.
          explode: true
          in: query
          name: collection_ids
          required: false
          schema:
            items:
              type: string
              x-struct:
              x-validate:
            type: array
            x-struct:
            x-validate:
          style: form
        - description: Viewer UUID to include watch progress
          in: query
          name: viewer_id
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideosResponse'
          description: Videos list
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
      summary: Get latest videos
      tags:
        - Videos
  /api/v1/auth/sessions/revoke-others:
    post:
      callbacks: {}
      operationId: BoldAdminWeb.Api.Auth.SessionController.revoke_others
      parameters:
        - description: Tenant slug for the BOLD account, for example `hrtu`.
          in: header
          name: X-Bold-Tenant-Slug
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: ID of the session to keep
          in: header
          name: x-bold-session-id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RevokeOthersResponse'
          description: Other sessions revoked
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Missing X-Bold-Session-Id header
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid bearer JWT
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SelfManagementDisabledError'
          description: Self-management disabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer or keep-session not found
      security:
        - upstream_jwt: []
      summary: Revoke all of the authenticated viewer's sessions except the current one
      tags:
        - Auth Sessions
  /api/v1/viewers/{viewer_id}/progress/{video_id}/complete:
    post:
      callbacks: {}
      description: Marks a video as completed for the viewer. Sets completed=true, current_time=duration, and records completion timestamp. Progress must already exist.
      operationId: BoldAdminWeb.Api.ProgressController.complete
      parameters:
        - description: Viewer UUID
          in: path
          name: viewer_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Video UUID
          in: path
          name: video_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProgressResponse'
          description: Video marked as complete
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive, or the viewers feature is not enabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Progress not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation errors
      summary: Mark video as complete
      tags:
        - Progress
  /api/v1/viewers/{viewer_id}/progress/{video_id}:
    delete:
      callbacks: {}
      description: Resets progress by deleting the progress record. This allows the viewer to start fresh on the video.
      operationId: BoldAdminWeb.Api.ProgressController.delete
      parameters:
        - description: Viewer UUID
          in: path
          name: viewer_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Video UUID
          in: path
          name: video_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '204':
          content:
            application/json: {}
          description: Progress reset
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive, or the viewers feature is not enabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Progress not found
      summary: Reset progress
      tags:
        - Progress
    get:
      callbacks: {}
      description: Returns progress for a specific viewer-video pair.
      operationId: BoldAdminWeb.Api.ProgressController.show
      parameters:
        - description: Viewer UUID
          in: path
          name: viewer_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Video UUID
          in: path
          name: video_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProgressResponse'
          description: Progress details
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive, or the viewers feature is not enabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Progress not found
      summary: Get progress for a video
      tags:
        - Progress
    post:
      callbacks: {}
      description: Creates or updates progress for a viewer-video pair. If progress exists, it will be updated; otherwise, a new record will be created.
      operationId: BoldAdminWeb.Api.ProgressController.upsert
      parameters:
        - description: Viewer UUID
          in: path
          name: viewer_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Video UUID
          in: path
          name: video_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProgressUpsert'
        description: Progress parameters
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProgressResponse'
          description: Progress updated
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProgressResponse'
          description: Progress created
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid parameters
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive, or the viewers feature is not enabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer or video not found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Validation errors
      summary: Create or update progress
      tags:
        - Progress
  /api/v1/playlists/{id}:
    get:
      callbacks: {}
      description: Returns a playlist with its videos.
      operationId: BoldAdminWeb.Api.PlaylistController.show
      parameters:
        - description: Playlist ID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlaylistResponse'
          description: Playlist
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Playlist not found
      summary: Get a playlist
      tags:
        - Playlists
  /api/v1/viewers/{viewer_id}/progress:
    get:
      callbacks: {}
      description: Returns all progress records for a viewer with metadata statistics.
      operationId: BoldAdminWeb.Api.ProgressController.index
      parameters:
        - description: Viewer UUID
          in: path
          name: viewer_id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Filter by completion status
          in: query
          name: completed
          required: false
          schema:
            type: boolean
            x-struct:
            x-validate:
        - description: Filter by collection UUID
          in: query
          name: collection_id
          required: false
          schema:
            type: string
            x-struct:
            x-validate:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProgressListResponse'
          description: Progress list
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive, or the viewers feature is not enabled
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Viewer not found
      summary: List viewer progress
      tags:
        - Progress
  /api/v1/settings:
    get:
      callbacks: {}
      description: |
        Returns public configuration for your video portal.

        Includes branding (logos, colors), AI settings, and portal layout configuration.
        Use this to customize embedded players or build custom portal UIs.
      operationId: BoldAdminWeb.Api.ProjectSettingsController.settings (2)
      parameters: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProjectSettings'
          description: Settings
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Account inactive — subscription expired or no active plan
      summary: Get portal settings
      tags:
        - Settings
  /api/v1/auth/challenges/{id}/verify:
    post:
      callbacks: {}
      description: Verifies a short-lived email code for the authenticated viewer and materializes the pending auth session if the code is valid.
      operationId: BoldAdminWeb.Api.Auth.ChallengeController.verify
      parameters:
        - description: Challenge UUID
          in: path
          name: id
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
        - description: Tenant slug for the BOLD account, for example `hrtu`.
          in: header
          name: X-Bold-Tenant-Slug
          required: true
          schema:
            type: string
            x-struct:
            x-validate:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VerifyAuthChallengeRequest'
        description: Challenge verification payload
        required: false
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthSessionResponse'
          description: Session created
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthChallengeError'
          description: Invalid, expired, or incorrect challenge code
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthChallengeError'
          description: Invalid bearer JWT
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthChallengeError'
          description: Challenge ownership mismatch
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthChallengeError'
          description: Viewer not provisioned
      security:
        - upstream_jwt: []
      summary: Verify an auth challenge code
      tags:
        - Auth Challenges
security:
  - api_token: []
servers:
  - description: Production API
    url: https://app.boldvideo.io
    variables: {}
tags: []
