
{
  "openapi": "3.0.3",
  "info": {
    "title": "HotTRDeals API",
    "version": "1.0.0",
    "description": "Backend endpoints documented from current Express routes. Each operation includes auth/api-key requirements and data sources (db/redis)."
  },
  "servers": [
    { "url": "http://localhost:3000" }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" },
      "cookieAuth": { "type": "apiKey", "in": "cookie", "name": "at" },
      "apiKeyAuth": { "type": "apiKey", "in": "header", "name": "x-api-key" }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": { "type": "string" },
          "message": { "type": "string" }
        }
      },
      "UserPublic": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "username": { "type": "string" },
          "avatarUrl": { "type": "string", "nullable": true }
        }
      },
      "AuthUser": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "username": { "type": "string" },
          "email": { "type": "string" },
          "role": { "type": "string" },
          "avatarUrl": { "type": "string", "nullable": true }
        }
      },
      "AuthResponse": {
        "type": "object",
        "properties": {
          "user": { "$ref": "#/components/schemas/AuthUser" }
        }
      },
      "DealCard": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "title": { "type": "string" },
          "description": { "type": "string", "nullable": true },
          "price": { "type": "number", "nullable": true },
          "originalPrice": { "type": "number", "nullable": true },
          "shippingPrice": { "type": "number", "nullable": true },
          "couponCode": { "type": "string", "nullable": true },
          "location": { "type": "string", "nullable": true },
          "discountType": { "type": "string", "nullable": true },
          "discountValue": { "type": "number", "nullable": true },
          "score": { "type": "integer" },
          "commentsCount": { "type": "integer" },
          "status": { "type": "string" },
          "saleType": { "type": "string" },
          "affiliateType": { "type": "string" },
          "myVote": { "type": "integer" },
          "isSaved": { "type": "boolean" },
          "createdAt": { "type": "string" },
          "updatedAt": { "type": "string" },
          "user": { "$ref": "#/components/schemas/UserPublic" },
          "seller": { "type": "object", "nullable": true }
        }
      },
      "DealDetail": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "title": { "type": "string" },
          "description": { "type": "string", "nullable": true },
          "url": { "type": "string", "nullable": true },
          "price": { "type": "number", "nullable": true },
          "originalPrice": { "type": "number", "nullable": true },
          "shippingPrice": { "type": "number", "nullable": true },
          "couponCode": { "type": "string", "nullable": true },
          "location": { "type": "string", "nullable": true },
          "discountType": { "type": "string", "nullable": true },
          "discountValue": { "type": "number", "nullable": true },
          "score": { "type": "integer" },
          "commentsCount": { "type": "integer" },
          "status": { "type": "string" },
          "saleType": { "type": "string" },
          "affiliateType": { "type": "string" },
          "createdAt": { "type": "string" },
          "updatedAt": { "type": "string" },
          "user": { "$ref": "#/components/schemas/UserPublic" },
          "seller": { "type": "object", "nullable": true },
          "images": { "type": "array", "items": { "type": "object" } },
          "comments": { "type": "array", "items": { "type": "object" } }
        }
      },
      "PaginatedDeals": {
        "type": "object",
        "properties": {
          "page": { "type": "integer" },
          "total": { "type": "integer" },
          "totalPages": { "type": "integer" },
          "results": { "type": "array", "items": { "$ref": "#/components/schemas/DealCard" } }
        }
      },
      "Notification": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "message": { "type": "string" },
          "type": { "type": "string" },
          "createdAt": { "type": "string" },
          "readAt": { "type": "string", "nullable": true },
          "unread": { "type": "boolean" }
        }
      },
      "Badge": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "name": { "type": "string" },
          "iconUrl": { "type": "string", "nullable": true },
          "description": { "type": "string", "nullable": true }
        }
      },
      "UserBadge": {
        "type": "object",
        "properties": {
          "badge": { "$ref": "#/components/schemas/Badge" },
          "earnedAt": { "type": "string" }
        }
      }
    }
  },
  "paths": {
    "/api/auth/register": {
      "post": {
        "tags": ["Auth"],
        "summary": "Register",
        "description": "Creates user; sets access/refresh cookies.",
        "x-auth": "none",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "username": { "type": "string", "minLength": 5, "maxLength": 18 },
                  "email": { "type": "string" },
                  "password": { "type": "string", "minLength": 8 }
                },
                "required": ["username", "email", "password"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Auth response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } },
          "400": { "description": "Validation error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },
    "/api/auth/login": {
      "post": {
        "tags": ["Auth"],
        "summary": "Login",
        "description": "Login with email/password; sets access/refresh cookies.",
        "x-auth": "none",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": { "type": "string" },
                  "password": { "type": "string" }
                },
                "required": ["email", "password"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Auth response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } },
          "401": { "description": "Invalid credentials", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },
    "/api/auth/refresh": {
      "post": {
        "tags": ["Auth"],
        "summary": "Refresh tokens",
        "description": "Rotates refresh token from cookie `rt`.",
        "x-auth": "cookie-only",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "responses": {
          "200": { "description": "Auth response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } },
          "401": { "description": "Invalid/expired refresh", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },
    "/api/auth/logout": {
      "post": {
        "tags": ["Auth"],
        "summary": "Logout",
        "description": "Revokes refresh token if present; clears cookies.",
        "x-auth": "cookie-only",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "responses": {
          "204": { "description": "No content" },
          "500": { "description": "Server error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },
    "/api/auth/me": {
      "get": {
        "tags": ["Auth"],
        "summary": "Get current user",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "responses": {
          "200": { "description": "Auth user", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthUser" } } } },
          "401": { "description": "Unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },

    "/api/account/avatar": {
      "post": {
        "tags": ["Account"],
        "summary": "Update avatar",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": { "type": "string", "format": "binary" }
                },
                "required": ["file"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Avatar updated", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" }, "user": { "$ref": "#/components/schemas/UserPublic" } } } } } }
        }
      }
    },
    "/api/account/me": {
      "get": {
        "tags": ["Account"],
        "summary": "Account profile",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "responses": {
          "200": {
            "description": "User + recent notifications",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": { "type": "integer" },
                    "username": { "type": "string" },
                    "avatarUrl": { "type": "string", "nullable": true },
                    "createdAt": { "type": "string" },
                    "notifications": { "type": "array", "items": { "$ref": "#/components/schemas/Notification" } },
                    "badges": { "type": "array", "items": { "$ref": "#/components/schemas/UserBadge" } }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/account/notifications/read": {
      "get": {
        "tags": ["Account"],
        "summary": "Mark all notifications read",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": false, "redis": true },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "responses": {
          "200": { "description": "OK" }
        }
      }
    },
    "/api/account/notifications": {
      "get": {
        "tags": ["Account"],
        "summary": "Notifications list",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } }
        ],
        "responses": {
          "200": {
            "description": "Paginated notifications",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "page": { "type": "integer" },
                    "total": { "type": "integer" },
                    "totalPages": { "type": "integer" },
                    "results": { "type": "array", "items": { "$ref": "#/components/schemas/Notification" } }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/account/password": {
      "post": {
        "tags": ["Account"],
        "summary": "Change password",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "currentPassword": { "type": "string" },
                  "newPassword": { "type": "string", "minLength": 8 }
                },
                "required": ["currentPassword", "newPassword"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Password changed", "content": { "application/json": { "schema": { "type": "object", "properties": { "message": { "type": "string" } } } } } }
        }
      }
    },
    "/api/badges": {
      "get": {
        "tags": ["Badges"],
        "summary": "List badges",
        "x-auth": "none",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "responses": {
          "200": {
            "description": "Badges",
            "content": {
              "application/json": {
                "schema": { "type": "array", "items": { "$ref": "#/components/schemas/Badge" } }
              }
            }
          }
        }
      }
    },

    "/api/deals/users/{userName}/deals": {
      "get": {
        "tags": ["Deals"],
        "summary": "User deals (public or my)",
        "x-auth": "optional",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          {},
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "userName", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "q", "in": "query", "schema": { "type": "string" } },
          { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 10 } }
        ],
        "responses": {
          "200": { "description": "Paginated deals", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedDeals" } } } }
        }
      }
    },
    "/api/deals/me/deals": {
      "get": {
        "tags": ["Deals"],
        "summary": "My deals",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 10 } }
        ],
        "responses": {
          "200": { "description": "Paginated deals", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedDeals" } } } }
        }
      }
    },
    "/api/deals/new": {
      "get": {
        "tags": ["Deals"],
        "summary": "New deals",
        "x-auth": "optional",
        "x-api-key": "required",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "apiKeyAuth": [], "bearerAuth": [] },
          { "apiKeyAuth": [], "cookieAuth": [] },
          { "apiKeyAuth": [] }
        ],
        "parameters": [
          { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 10 } }
        ],
        "responses": {
          "200": { "description": "Paginated deals", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedDeals" } } } }
        }
      }
    },
    "/api/deals/hot": {
      "get": {
        "tags": ["Deals"],
        "summary": "Hot deals",
        "x-auth": "optional",
        "x-api-key": "required",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "apiKeyAuth": [], "bearerAuth": [] },
          { "apiKeyAuth": [], "cookieAuth": [] },
          { "apiKeyAuth": [] }
        ],
        "parameters": [
          { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 10 } }
        ],
        "responses": {
          "200": { "description": "Paginated deals", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedDeals" } } } }
        }
      }
    },
    "/api/deals/trending": {
      "get": {
        "tags": ["Deals"],
        "summary": "Trending deals",
        "x-auth": "optional",
        "x-api-key": "required",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "apiKeyAuth": [], "bearerAuth": [] },
          { "apiKeyAuth": [], "cookieAuth": [] },
          { "apiKeyAuth": [] }
        ],
        "parameters": [
          { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 10 } }
        ],
        "responses": {
          "200": { "description": "Paginated deals", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedDeals" } } } }
        }
      }
    },
    "/api/deals": {
      "post": {
        "tags": ["Deals"],
        "summary": "Create deal",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": { "type": "string" },
                  "description": { "type": "string" },
                  "url": { "type": "string" },
                  "price": { "type": "number" },
                  "originalPrice": { "type": "number" },
                  "shippingPrice": { "type": "number" },
                  "couponCode": { "type": "string" },
                  "location": { "type": "string" },
                  "discountType": { "type": "string" },
                  "discountValue": { "type": "number" },
                  "sellerName": { "type": "string" },
                  "customSeller": { "type": "string" },
                  "images": { "type": "array", "items": { "type": "string", "format": "binary" } }
                },
                "required": ["title"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Deal detail", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DealDetail" } } } }
        }
      }
    },
    "/api/deals/search/suggest": {
      "get": {
        "tags": ["Deals"],
        "summary": "Deal search suggestions",
        "x-auth": "optional",
        "x-api-key": "none",
        "x-deps": { "db": false, "redis": true },
        "security": [
          {},
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "q", "in": "query", "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 8 } }
        ],
        "responses": {
          "200": { "description": "DealCard[]", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/DealCard" } } } } }
        }
      }
    },
    "/api/deals/url": {
      "post": {
        "tags": ["Deals"],
        "summary": "Resolve deal URL",
        "x-auth": "optional",
        "x-api-key": "required",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "apiKeyAuth": [], "bearerAuth": [] },
          { "apiKeyAuth": [], "cookieAuth": [] },
          { "apiKeyAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": { "dealId": { "type": "integer" } },
                "required": ["dealId"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "URL", "content": { "application/json": { "schema": { "type": "object", "properties": { "url": { "type": "string", "nullable": true } } } } } }
        }
      }
    },
    "/api/deals/{id}/report": {
      "post": {
        "tags": ["Deals"],
        "summary": "Report deal",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "type": "object", "properties": { "reason": { "type": "string" }, "note": { "type": "string" } } }
            }
          }
        },
        "responses": {
          "200": { "description": "Report created", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/api/deals/{id}/save": {
      "post": {
        "tags": ["Deals"],
        "summary": "Save deal",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }
        ],
        "responses": {
          "200": { "description": "Saved", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      },
      "delete": {
        "tags": ["Deals"],
        "summary": "Unsave deal",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }
        ],
        "responses": {
          "200": { "description": "OK" }
        }
      }
    },
    "/api/deals/saved": {
      "get": {
        "tags": ["Deals"],
        "summary": "Saved deals",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } }
        ],
        "responses": {
          "200": { "description": "Paginated deals", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedDeals" } } } }
        }
      }
    },
    "/api/deals/widgets/best": {
      "get": {
        "tags": ["Deals"],
        "summary": "Best deals widget",
        "x-auth": "optional",
        "x-api-key": "required",
        "x-deps": { "db": false, "redis": true },
        "security": [
          { "apiKeyAuth": [], "bearerAuth": [] },
          { "apiKeyAuth": [], "cookieAuth": [] },
          { "apiKeyAuth": [] }
        ],
        "parameters": [
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 5 } }
        ],
        "responses": {
          "200": { "description": "Widget data", "content": { "application/json": { "schema": { "type": "object", "properties": { "hotDay": { "type": "array", "items": { "$ref": "#/components/schemas/DealCard" } }, "hotWeek": { "type": "array", "items": { "$ref": "#/components/schemas/DealCard" } }, "hotMonth": { "type": "array", "items": { "$ref": "#/components/schemas/DealCard" } } } } } } }
        }
      }
    },
    "/api/deals/search": {
      "get": {
        "tags": ["Deals"],
        "summary": "Search deals",
        "x-auth": "optional",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          {},
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "q", "in": "query", "schema": { "type": "string" } },
          { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 10 } }
        ],
        "responses": {
          "200": { "description": "Paginated deals", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedDeals" } } } }
        }
      }
    },
    "/api/deals/top": {
      "get": {
        "tags": ["Deals"],
        "summary": "Top deals by range",
        "x-auth": "optional",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          {},
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "range", "in": "query", "schema": { "type": "string", "enum": ["day", "week", "month"], "default": "day" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 6 } }
        ],
        "responses": {
          "200": { "description": "DealCard[]", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/DealCard" } } } } }
        }
      }
    },
    "/api/deals/engagement": {
      "post": {
        "tags": ["Deals"],
        "summary": "Engagement (my votes)",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "type": "object", "properties": { "ids": { "type": "array", "items": { "type": "integer" } } }, "required": ["ids"] }
            }
          }
        },
        "responses": {
          "200": { "description": "Engagement list", "content": { "application/json": { "schema": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "integer" }, "myVote": { "type": "integer" } } } } } } }
        }
      }
    },
    "/api/deals/{id}": {
      "get": {
        "tags": ["Deals"],
        "summary": "Deal detail",
        "x-auth": "optional",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          {},
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }
        ],
        "responses": {
          "200": { "description": "Deal detail", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DealDetail" } } } },
          "404": { "description": "Not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },

    "/api/comments/{dealId}": {
      "get": {
        "tags": ["Comments"],
        "summary": "List comments",
        "x-auth": "optional",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          {},
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "dealId", "in": "path", "required": true, "schema": { "type": "integer" } },
          { "name": "parentId", "in": "query", "schema": { "type": "integer", "nullable": true } },
          { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 10 } },
          { "name": "sort", "in": "query", "schema": { "type": "string", "enum": ["NEW", "TOP"], "default": "NEW" } }
        ],
        "responses": {
          "200": { "description": "Paginated comments", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/api/comments": {
      "post": {
        "tags": ["Comments"],
        "summary": "Create comment",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "type": "object", "properties": { "dealId": { "type": "integer" }, "text": { "type": "string" }, "parentId": { "type": "integer", "nullable": true } }, "required": ["dealId", "text"] }
            }
          }
        },
        "responses": {
          "200": { "description": "Comment", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/api/comments/{id}": {
      "delete": {
        "tags": ["Comments"],
        "summary": "Delete comment",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }
        ],
        "responses": {
          "200": { "description": "Deleted" },
          "403": { "description": "Forbidden" },
          "404": { "description": "Not found" }
        }
      }
    },

    "/api/comment-likes": {
      "post": {
        "tags": ["Comments"],
        "summary": "Like/unlike comment",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "type": "object", "properties": { "commentId": { "type": "integer" }, "like": { "type": "boolean" } }, "required": ["commentId", "like"] }
            }
          }
        },
        "responses": {
          "200": { "description": "Like result", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },

    "/api/vote": {
      "post": {
        "tags": ["Votes"],
        "summary": "Vote deal",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "type": "object", "properties": { "dealId": { "type": "integer" }, "voteType": { "type": "integer" }, "dealVote": { "type": "integer" } }, "required": ["dealId", "voteType"] }
            }
          }
        },
        "responses": {
          "200": { "description": "Vote result", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/api/vote/{dealId}": {
      "get": {
        "tags": ["Votes"],
        "summary": "List votes for deal",
        "x-auth": "none",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "parameters": [
          { "name": "dealId", "in": "path", "required": true, "schema": { "type": "integer" } }
        ],
        "responses": {
          "200": { "description": "Votes", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },

    "/api/deal-votes": {
      "post": { "$ref": "#/paths/~1api~1vote/post" }
    },
    "/api/deal-votes/{dealId}": {
      "get": { "$ref": "#/paths/~1api~1vote~1{dealId}/get" }
    },

    "/api/users/{userName}": {
      "get": {
        "tags": ["Users"],
        "summary": "User profile",
        "x-auth": "none",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "parameters": [
          { "name": "userName", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Profile", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/api/users/{userName}/comments": {
      "get": {
        "tags": ["Users"],
        "summary": "User comments",
        "x-auth": "none",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "parameters": [
          { "name": "userName", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } }
        ],
        "responses": {
          "200": { "description": "Paginated comments", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/api/users/{userName}/deals": {
      "get": {
        "tags": ["Users"],
        "summary": "User deals",
        "x-auth": "optional",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          {},
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "userName", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } }
        ],
        "responses": {
          "200": { "description": "Paginated deals", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedDeals" } } } }
        }
      }
    },

    "/api/user/{userName}": { "get": { "$ref": "#/paths/~1api~1users~1{userName}/get" } },
    "/api/user/{userName}/comments": { "get": { "$ref": "#/paths/~1api~1users~1{userName}~1comments/get" } },
    "/api/user/{userName}/deals": { "get": { "$ref": "#/paths/~1api~1users~1{userName}~1deals/get" } },

    "/api/seller/from-link": {
      "post": {
        "tags": ["Seller"],
        "summary": "Resolve seller from URL",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": { "schema": { "type": "object", "properties": { "url": { "type": "string" } }, "required": ["url"] } }
          }
        },
        "responses": {
          "200": { "description": "Seller lookup", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/api/seller": {
      "get": {
        "tags": ["Seller"],
        "summary": "Active sellers",
        "x-auth": "none",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "responses": {
          "200": { "description": "Seller list", "content": { "application/json": { "schema": { "type": "array", "items": { "type": "object" } } } } }
        }
      }
    },
    "/api/seller/{sellerName}": {
      "get": {
        "tags": ["Seller"],
        "summary": "Seller detail",
        "x-auth": "none",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "parameters": [
          { "name": "sellerName", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Seller detail", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/api/seller/{sellerName}/deals": {
      "get": {
        "tags": ["Seller"],
        "summary": "Seller deals",
        "x-auth": "optional",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          {},
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "sellerName", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 10 } }
        ],
        "responses": {
          "200": { "description": "Paginated deals", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedDeals" } } } }
        }
      }
    },

    "/api/category/{slug}": {
      "get": {
        "tags": ["Category"],
        "summary": "Category detail",
        "x-auth": "none",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Category detail", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/api/category/{slug}/deals": {
      "get": {
        "tags": ["Category"],
        "summary": "Category deals",
        "x-auth": "optional",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          {},
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 10 } }
        ],
        "responses": {
          "200": { "description": "Paginated deals", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedDeals" } } } }
        }
      }
    },

    "/api/mod/deals/pending": {
      "get": {
        "tags": ["Mod"],
        "summary": "Pending deals",
        "description": "Requires MOD role.",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "q", "in": "query", "schema": { "type": "string" } },
          { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 10 } }
        ],
        "responses": {
          "200": { "description": "DealCard[]", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/DealCard" } } } } }
        }
      }
    },
    "/api/mod/deals/{id}/approve": {
      "post": {
        "tags": ["Mod"],
        "summary": "Approve deal",
        "description": "Requires MOD role.",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }
        ],
        "responses": { "200": { "description": "Status updated" } }
      }
    },
    "/api/mod/deals/{id}/reject": { "post": { "$ref": "#/paths/~1api~1mod~1deals~1{id}~1approve/post" } },
    "/api/mod/deals/{id}/expire": { "post": { "$ref": "#/paths/~1api~1mod~1deals~1{id}~1approve/post" } },
    "/api/mod/deals/{id}/unexpire": { "post": { "$ref": "#/paths/~1api~1mod~1deals~1{id}~1approve/post" } },
    "/api/mod/deals/{id}/detail": {
      "get": {
        "tags": ["Mod"],
        "summary": "Deal detail for mod",
        "description": "Requires MOD role.",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }
        ],
        "responses": { "200": { "description": "Deal detail + aiReview", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    },
    "/api/mod/deals/{id}": {
      "patch": {
        "tags": ["Mod"],
        "summary": "Update deal (mod)",
        "description": "Requires MOD role.",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": true },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }
        ],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object" } } } },
        "responses": { "200": { "description": "Updated deal", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    },
    "/api/mod/sellers": {
      "get": {
        "tags": ["Mod"],
        "summary": "List sellers",
        "description": "Requires MOD role.",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "responses": { "200": { "description": "Seller list", "content": { "application/json": { "schema": { "type": "array", "items": { "type": "object" } } } } } }
      }
    },
    "/api/mod/categories": {
      "get": {
        "tags": ["Mod"],
        "summary": "List categories",
        "description": "Requires MOD role.",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "responses": { "200": { "description": "Category list", "content": { "application/json": { "schema": { "type": "array", "items": { "type": "object" } } } } } }
      }
    },
    "/api/mod/badges": {
      "post": {
        "tags": ["Mod"],
        "summary": "Create badge",
        "description": "Requires MOD role.",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": { "type": "string" },
                  "iconUrl": { "type": "string", "nullable": true },
                  "description": { "type": "string", "nullable": true }
                },
                "required": ["name"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Badge", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Badge" } } } }
        }
      }
    },
    "/api/mod/badges/{id}": {
      "patch": {
        "tags": ["Mod"],
        "summary": "Update badge",
        "description": "Requires MOD role.",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": { "type": "string" },
                  "iconUrl": { "type": "string", "nullable": true },
                  "description": { "type": "string", "nullable": true }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Badge", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Badge" } } } }
        }
      }
    },
    "/api/mod/badges/assign": {
      "post": {
        "tags": ["Mod"],
        "summary": "Assign badge to user",
        "description": "Requires MOD role.",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userId": { "type": "integer" },
                  "badgeId": { "type": "integer" },
                  "earnedAt": { "type": "string" }
                },
                "required": ["userId", "badgeId"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Assignment",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "userId": { "type": "integer" },
                    "badgeId": { "type": "integer" },
                    "earnedAt": { "type": "string" }
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Mod"],
        "summary": "Remove badge from user",
        "description": "Requires MOD role.",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userId": { "type": "integer" },
                  "badgeId": { "type": "integer" }
                },
                "required": ["userId", "badgeId"]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Removed", "content": { "application/json": { "schema": { "type": "object", "properties": { "removed": { "type": "boolean" } } } } } }
        }
      }
    },
    "/api/mod/deals/reports": {
      "get": {
        "tags": ["Mod"],
        "summary": "Deal reports",
        "description": "Requires MOD role.",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": true, "redis": false },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "parameters": [
          { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } },
          { "name": "status", "in": "query", "schema": { "type": "string" } },
          { "name": "dealId", "in": "query", "schema": { "type": "integer" } },
          { "name": "userId", "in": "query", "schema": { "type": "integer" } }
        ],
        "responses": { "200": { "description": "Reports", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    },

    "/api/uploads/image": {
      "post": {
        "tags": ["Uploads"],
        "summary": "Upload image",
        "x-auth": "required",
        "x-api-key": "none",
        "x-deps": { "db": false, "redis": false },
        "security": [
          { "bearerAuth": [] },
          { "cookieAuth": [] }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": { "file": { "type": "string", "format": "binary" } },
                "required": ["file"]
              }
            }
          }
        },
        "responses": { "200": { "description": "URL", "content": { "application/json": { "schema": { "type": "object", "properties": { "url": { "type": "string" } } } } } } }
      }
    }
  }
}
