{
  "openapi": "3.0.0",
  "info": {
    "title": "MediaForge API",
    "version": "1.0.0",
    "description": "API for uploading and managing processed media files on the MediaForge CDN. Files are processed locally in the user's browser before upload; the API server only receives already-cleaned files."
  },
  "servers": [
    {
      "url": "https://api.mediaforge.tech",
      "description": "Production Server"
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "summary": "Health check",
        "description": "Returns the status of the API service and database connection.",
        "responses": {
          "200": {
            "description": "Service is healthy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": { "type": "string", "example": "ok" }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable (database unreachable)"
          }
        }
      }
    },
    "/v1/auth/register": {
      "post": {
        "summary": "Register a new user account",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": { "type": "string", "format": "email" },
                  "password": { "type": "string", "minLength": 8 }
                },
                "required": ["email", "password"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Registration successful" },
          "409": { "description": "Email already in use" }
        }
      }
    },
    "/v1/auth/login": {
      "post": {
        "summary": "Authenticate and obtain JWT access token",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": { "type": "string", "format": "email" },
                  "password": { "type": "string" }
                },
                "required": ["email", "password"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Authentication successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": { "type": "string", "description": "JWT to be passed as Authorization: Bearer <token>" },
                    "user": { "type": "object" }
                  }
                }
              }
            }
          },
          "401": { "description": "Invalid credentials" }
        }
      }
    },
    "/v1/files/presign": {
      "post": {
        "summary": "Step 1 of 3: Request a presigned upload URL",
        "description": "Reserves storage quota and returns a time-limited presigned URL for direct upload to the CDN (Cloudflare R2). The client PUTs the file directly to the returned `uploadUrl` — the API server never receives the raw file bytes.",
        "security": [{ "BearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filename": { "type": "string", "description": "Target filename on CDN", "example": "photo-clean.webp" },
                  "sizeBytes": { "type": "integer", "description": "Exact byte size of the file to upload", "example": 172948 },
                  "mimeType": { "type": "string", "description": "MIME type of the file", "example": "image/webp" }
                },
                "required": ["filename", "sizeBytes", "mimeType"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Presigned URL generated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "uploadUrl": { "type": "string", "description": "Time-limited presigned PUT URL targeting CDN storage directly" },
                    "fileId": { "type": "string", "description": "UUID of the pending file record" },
                    "r2Key": { "type": "string", "description": "Storage object key; required in Step 3 /confirm call" }
                  }
                }
              }
            }
          },
          "403": { "description": "Storage quota exceeded or file size exceeds plan limit" }
        }
      }
    },
    "/v1/files/confirm": {
      "post": {
        "summary": "Step 3 of 3: Confirm upload and trigger server-side metadata strip",
        "description": "Called after the client successfully PUTs the file to the presigned URL. The backend downloads the file from CDN, validates MIME type (JPEG, PNG, WebP, MP4, MOV only), performs server-side metadata stripping as a final safety pass, re-uploads the clean file, and marks the record as confirmed.",
        "security": [{ "BearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filename": { "type": "string", "example": "photo-clean.webp" },
                  "r2Key": { "type": "string", "description": "The r2Key returned from /presign", "example": "user-uuid/file-uuid.webp" },
                  "mimeType": { "type": "string", "example": "image/webp" }
                },
                "required": ["filename", "r2Key", "mimeType"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Upload confirmed and file is live on CDN",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "file": {
                      "type": "object",
                      "properties": {
                        "id": { "type": "string" },
                        "cdnUrl": { "type": "string", "description": "Public CDN URL of the processed file" },
                        "filename": { "type": "string" },
                        "sizeBytes": { "type": "integer" },
                        "mimeType": { "type": "string" },
                        "metadataStripped": { "type": "boolean" },
                        "createdAt": { "type": "string", "format": "date-time" }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": { "description": "File not found in storage (upload may have failed)" },
          "409": { "description": "Upload already confirmed" },
          "415": { "description": "Unsupported file type detected" }
        }
      }
    },
    "/v1/files": {
      "get": {
        "summary": "List all hosted files",
        "description": "Returns a list of CDN-hosted files belonging to the authenticated user.",
        "security": [{ "BearerAuth": [] }],
        "responses": {
          "200": {
            "description": "File list retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": { "type": "string" },
                      "cdnUrl": { "type": "string" },
                      "filename": { "type": "string" },
                      "sizeBytes": { "type": "integer" },
                      "mimeType": { "type": "string" },
                      "createdAt": { "type": "string", "format": "date-time" }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/files/{id}": {
      "delete": {
        "summary": "Delete a hosted file",
        "description": "Permanently removes the file from CDN storage and frees the storage quota.",
        "security": [{ "BearerAuth": [] }],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "UUID of the file to delete"
          }
        ],
        "responses": {
          "200": { "description": "File deleted successfully" },
          "404": { "description": "File not found" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Obtain a JWT by POSTing credentials to /v1/auth/login. Pass the returned access_token as: Authorization: Bearer <token>"
      }
    }
  }
}
