openapi: 3.0.3
info:
  title: yleoeditor Portfolio API
  description: |
    Official public REST API for yleoeditor (Leonardo Daitx). Provides structured access to video editing portfolio data, high-retention project catalogs, viral shorts showcase, and client channels.

    ### API Versioning & Deprecation Policy
    All endpoints follow URL path versioning (`/v1/` or `/api/v1/`) and semantic versioning (`1.0.0`). Deprecations are announced at least 180 days in advance via the standard `Sunset` and `Deprecation` HTTP headers (RFC 8594), as well as updates in `/llms.txt` and the Developer Portal (`/developers`).
  version: 1.0.0
  x-versioning-policy:
    strategy: URL Path Versioning (/v1/) and semantic versioning
    currentVersion: v1
    deprecationNotice: Deprecations are announced 180 days in advance via Sunset and Deprecation HTTP headers (RFC 8594).
  contact:
    name: Leonardo Daitx (yleoeditor)
    email: leonnardomelo3@gmail.com
    url: https://yleoeditor.com
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT
servers:
  - url: https://yleoeditor.com
    description: Production server
paths:
  /api:
    get:
      summary: Root API discovery
      description: Returns API metadata, supported versions, documentation links, and endpoint directory.
      operationId: getApiRoot
      responses:
        '200':
          description: API discovery metadata
          headers:
            X-API-Version:
              schema:
                type: string
              description: Current API version
            Sunset:
              schema:
                type: string
              description: RFC 8594 Sunset date header
            Deprecation:
              schema:
                type: string
              description: RFC 8594 Deprecation header
            RateLimit-Limit:
              schema:
                type: integer
              description: Maximum allowed requests per minute
          content:
            application/json:
              schema:
                type: object
  /api/v1/content:
    get:
      summary: Get portfolio content
      description: Retrieves the complete portfolio dataset including featured video projects, viral shorts, creator channels, and client testimonials.
      operationId: getPortfolioContent
      parameters:
        - name: category
          in: query
          required: false
          description: Optional category filter, e.g. 'Story-telling vlog'
          schema:
            type: string
        - name: limit
          in: query
          required: false
          description: Maximum number of projects to return
          schema:
            type: integer
            default: 10
            minimum: 1
            maximum: 50
      responses:
        '200':
          description: Portfolio content retrieved successfully
          headers:
            RateLimit-Limit:
              schema:
                type: integer
              description: Maximum allowed requests per minute
            RateLimit-Remaining:
              schema:
                type: integer
              description: Remaining requests in current window
            RateLimit-Reset:
              schema:
                type: integer
              description: Seconds until rate limit reset
            X-API-Version:
              schema:
                type: string
              description: Current API version
            Sunset:
              schema:
                type: string
              description: RFC 8594 Sunset date header
            Deprecation:
              schema:
                type: string
              description: RFC 8594 Deprecation header
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortfolioContentResponse'
        '500':
          description: Server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    put:
      summary: Update portfolio content
      description: Updates portfolio dataset. Requires administrative authorization token.
      operationId: updatePortfolioContent
      security:
        - BearerAuth: []
      requestBody:
        required: true
        description: Updated portfolio content object
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateContentRequest'
      responses:
        '200':
          description: Content updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessResponse'
        '400':
          description: Invalid payload format
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Server error while saving content
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/content:
    get:
      summary: Get portfolio content (Legacy Alias)
      description: Legacy alias for /api/v1/content. Retrieves complete portfolio dataset.
      operationId: getPortfolioContentLegacy
      parameters:
        - name: category
          in: query
          required: false
          description: Optional category filter
          schema:
            type: string
        - name: limit
          in: query
          required: false
          description: Maximum number of projects to return
          schema:
            type: integer
            default: 10
      responses:
        '200':
          description: Portfolio content retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortfolioContentResponse'
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: Administrative token for authenticated management requests
  schemas:
    Project:
      type: object
      required:
        - id
        - title
        - category
        - thumbnail
        - youtubeId
        - description
        - views
      properties:
        id:
          type: string
          description: Unique identifier for the project
        title:
          type: string
          description: Title of the video
        category:
          type: string
          description: Content category, e.g. Story-telling vlog
        thumbnail:
          type: string
          description: URL to the video thumbnail image
        youtubeId:
          type: string
          description: YouTube video ID
        description:
          type: string
          description: Brief description of editing techniques applied
        views:
          type: string
          description: View count achieved, e.g. 6.2M
    Short:
      type: object
      required:
        - id
        - title
        - youtubeId
      properties:
        id:
          type: string
          description: Unique identifier for the short
        title:
          type: string
          description: Title of the short-form video
        youtubeId:
          type: string
          description: YouTube Short ID
    Channel:
      type: object
      required:
        - id
        - name
        - subs
        - image
      properties:
        id:
          type: string
          description: Unique identifier of the channel
        name:
          type: string
          description: Creator or channel name
        subs:
          type: string
          description: Subscriber count, e.g. 19M+
        image:
          type: string
          description: Avatar image URL
    Review:
      type: object
      required:
        - id
        - channelName
        - image
        - comment
        - rating
      properties:
        id:
          type: string
          description: Review identifier
        channelName:
          type: string
          description: Channel name providing testimonial
        image:
          type: string
          description: Creator avatar image URL
        comment:
          type: string
          description: Testimonial text
        rating:
          type: number
          description: Rating score out of 5
    Socials:
      type: object
      required:
        - email
        - twitter
        - youtubeJobs
        - discord
      properties:
        email:
          type: string
          description: Primary business email
        twitter:
          type: string
          description: X / Twitter URL
        youtubeJobs:
          type: string
          description: YT Jobs profile URL
        discord:
          type: string
          description: Discord profile link
    PortfolioData:
      type: object
      required:
        - projects
        - shorts
        - channels
        - reviews
        - socials
      properties:
        projects:
          type: array
          items:
            $ref: '#/components/schemas/Project'
        shorts:
          type: array
          items:
            $ref: '#/components/schemas/Short'
        channels:
          type: array
          items:
            $ref: '#/components/schemas/Channel'
        reviews:
          type: array
          items:
            $ref: '#/components/schemas/Review'
        socials:
          $ref: '#/components/schemas/Socials'
    PortfolioContentResponse:
      type: object
      required:
        - content
      properties:
        content:
          $ref: '#/components/schemas/PortfolioData'
    UpdateContentRequest:
      type: object
      required:
        - content
      properties:
        content:
          $ref: '#/components/schemas/PortfolioData'
    SuccessResponse:
      type: object
      required:
        - success
      properties:
        success:
          type: boolean
          example: true
    ErrorDetail:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
          description: Machine-readable error identifier
          example: NOT_FOUND
        message:
          type: string
          description: Human-readable error explanation
          example: The requested resource was not found
        hint:
          type: string
          description: Actionable guidance to resolve error
          example: Refer to /openapi.json for valid paths
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          $ref: '#/components/schemas/ErrorDetail'
