{
  "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.\n\n### API Versioning & Deprecation Policy\nAll 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"
          }
        }
      }
    }
  }
}
