basePath: /api definitions: dto.CastVoteRequest: properties: type: enum: - up - down - none type: string required: - type type: object dto.ConfirmAccountDeletionRequest: properties: delete_posts: type: boolean token: type: string required: - token type: object dto.CreatePostRequest: properties: content: maxLength: 10000 type: string title: maxLength: 200 minLength: 3 type: string url: maxLength: 2048 type: string required: - url type: object dto.ForgotPasswordRequest: properties: username_or_email: type: string required: - username_or_email type: object dto.LoginRequest: properties: password: maxLength: 128 minLength: 8 type: string username: maxLength: 50 minLength: 3 type: string required: - password - username type: object dto.RefreshTokenRequest: properties: refresh_token: example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... type: string required: - refresh_token type: object dto.RegisterRequest: properties: email: maxLength: 254 type: string password: maxLength: 128 minLength: 8 type: string username: maxLength: 50 minLength: 3 type: string required: - email - password - username type: object dto.ResendVerificationRequest: properties: email: maxLength: 254 type: string required: - email type: object dto.ResetPasswordRequest: properties: new_password: maxLength: 128 minLength: 8 type: string token: type: string required: - new_password - token type: object dto.RevokeTokenRequest: properties: refresh_token: example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... type: string required: - refresh_token type: object dto.UpdateEmailRequest: properties: email: maxLength: 254 type: string required: - email type: object dto.UpdatePasswordRequest: properties: current_password: type: string new_password: maxLength: 128 minLength: 8 type: string required: - current_password - new_password type: object dto.UpdatePostRequest: properties: content: maxLength: 10000 type: string title: maxLength: 200 minLength: 3 type: string required: - title type: object dto.UpdateUsernameRequest: properties: username: maxLength: 50 minLength: 3 type: string required: - username type: object handlers.APIInfo: properties: data: {} error: type: string message: type: string success: type: boolean type: object handlers.AuthResponse: properties: data: {} error: type: string message: type: string success: type: boolean type: object handlers.AuthTokensDetail: properties: access_token: example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... type: string refresh_token: example: f94d4ddc7d9b4fcb9d3a2c44c400b780 type: string user: $ref: '#/definitions/handlers.AuthUserSummary' type: object handlers.AuthTokensResponse: properties: data: $ref: '#/definitions/handlers.AuthTokensDetail' message: example: Authentication successful type: string success: example: true type: boolean type: object handlers.AuthUserSummary: properties: email: example: jane@example.com type: string email_verified: example: true type: boolean id: example: 42 type: integer locked: example: false type: boolean username: example: janedoe type: string type: object handlers.CommonResponse: properties: data: {} error: type: string message: type: string success: type: boolean type: object handlers.PostResponse: properties: data: {} error: type: string message: type: string success: type: boolean type: object handlers.UserResponse: properties: data: {} error: type: string message: type: string success: type: boolean type: object handlers.VoteResponse: properties: data: {} error: type: string message: type: string success: type: boolean type: object host: localhost:8080 info: contact: email: sandro@cazzaniga.fr name: Goyco Team description: Goyco is a Y Combinator-style news aggregation platform API. license: name: GPLv3 url: https://www.gnu.org/licenses/gpl-3.0.html title: Goyco API version: 0.1.0 paths: /api: get: consumes: - application/json description: Retrieve API metadata, available endpoints, authentication details, and response formats produces: - application/json responses: "200": description: API information retrieved successfully schema: $ref: '#/definitions/handlers.APIInfo' summary: Get API information tags: - api /api/auth/account: delete: consumes: - application/json description: Initiate the deletion process for the authenticated user's account produces: - application/json responses: "200": description: Deletion email sent schema: $ref: '#/definitions/handlers.AuthResponse' "401": description: Authentication required schema: $ref: '#/definitions/handlers.AuthResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.AuthResponse' "503": description: Email delivery unavailable schema: $ref: '#/definitions/handlers.AuthResponse' security: - BearerAuth: [] summary: Request account deletion tags: - auth /api/auth/account/confirm: post: consumes: - application/json description: Confirm account deletion using the provided token parameters: - description: Account deletion data in: body name: request required: true schema: $ref: '#/definitions/dto.ConfirmAccountDeletionRequest' produces: - application/json responses: "200": description: Account deleted successfully schema: $ref: '#/definitions/handlers.AuthResponse' "400": description: Invalid or expired token schema: $ref: '#/definitions/handlers.AuthResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.AuthResponse' "503": description: Email delivery unavailable schema: $ref: '#/definitions/handlers.AuthResponse' summary: Confirm account deletion tags: - auth /api/auth/confirm: get: consumes: - application/json description: Confirm user email with verification token parameters: - description: Email verification token in: query name: token required: true type: string produces: - application/json responses: "200": description: Email confirmed successfully schema: $ref: '#/definitions/handlers.AuthResponse' "400": description: Invalid or missing token schema: $ref: '#/definitions/handlers.AuthResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.AuthResponse' summary: Confirm email address tags: - auth /api/auth/email: put: consumes: - application/json description: Update the authenticated user's email address parameters: - description: New email address in: body name: request required: true schema: $ref: '#/definitions/dto.UpdateEmailRequest' produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/handlers.AuthResponse' "400": description: Bad Request schema: $ref: '#/definitions/handlers.AuthResponse' "401": description: Unauthorized schema: $ref: '#/definitions/handlers.AuthResponse' "409": description: Conflict schema: $ref: '#/definitions/handlers.AuthResponse' "500": description: Internal Server Error schema: $ref: '#/definitions/handlers.AuthResponse' "503": description: Service Unavailable schema: $ref: '#/definitions/handlers.AuthResponse' security: - BearerAuth: [] summary: Update email address tags: - auth /api/auth/forgot-password: post: consumes: - application/json description: Send a password reset email using a username or email parameters: - description: Username or email in: body name: request required: true schema: $ref: '#/definitions/dto.ForgotPasswordRequest' produces: - application/json responses: "200": description: Password reset email sent if account exists schema: $ref: '#/definitions/handlers.AuthResponse' "400": description: Invalid request data schema: $ref: '#/definitions/handlers.AuthResponse' summary: Request a password reset tags: - auth /api/auth/login: post: consumes: - application/json description: Authenticate user with username and password parameters: - description: Login credentials in: body name: request required: true schema: $ref: '#/definitions/dto.LoginRequest' produces: - application/json responses: "200": description: Authentication successful schema: $ref: '#/definitions/handlers.AuthTokensResponse' "400": description: Invalid request data or validation failed schema: $ref: '#/definitions/handlers.AuthResponse' "401": description: Invalid credentials schema: $ref: '#/definitions/handlers.AuthResponse' "403": description: Account is locked schema: $ref: '#/definitions/handlers.AuthResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.AuthResponse' summary: Login user tags: - auth /api/auth/logout: post: consumes: - application/json description: Logout the authenticated user and invalidate their session produces: - application/json responses: "200": description: Logged out successfully schema: $ref: '#/definitions/handlers.AuthResponse' "401": description: Authentication required schema: $ref: '#/definitions/handlers.AuthResponse' security: - BearerAuth: [] summary: Logout user tags: - auth /api/auth/me: get: consumes: - application/json description: Retrieve the authenticated user's profile information produces: - application/json responses: "200": description: User profile retrieved successfully schema: $ref: '#/definitions/handlers.AuthResponse' "401": description: Authentication required schema: $ref: '#/definitions/handlers.AuthResponse' "404": description: User not found schema: $ref: '#/definitions/handlers.AuthResponse' security: - BearerAuth: [] summary: Get current user profile tags: - auth /api/auth/password: put: consumes: - application/json description: Update the authenticated user's password parameters: - description: Password update data in: body name: request required: true schema: $ref: '#/definitions/dto.UpdatePasswordRequest' produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/handlers.AuthResponse' "400": description: Bad Request schema: $ref: '#/definitions/handlers.AuthResponse' "401": description: Unauthorized schema: $ref: '#/definitions/handlers.AuthResponse' "500": description: Internal Server Error schema: $ref: '#/definitions/handlers.AuthResponse' security: - BearerAuth: [] summary: Update password tags: - auth /api/auth/refresh: post: consumes: - application/json description: Use a refresh token to get a new access token. This endpoint allows clients to obtain a new access token using a valid refresh token without requiring user credentials. parameters: - description: Refresh token data in: body name: request required: true schema: $ref: '#/definitions/dto.RefreshTokenRequest' produces: - application/json responses: "200": description: Token refreshed successfully schema: $ref: '#/definitions/handlers.AuthTokensResponse' "400": description: Invalid request body or missing refresh token schema: $ref: '#/definitions/handlers.AuthResponse' "401": description: Invalid or expired refresh token schema: $ref: '#/definitions/handlers.AuthResponse' "403": description: Account is locked schema: $ref: '#/definitions/handlers.AuthResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.AuthResponse' summary: Refresh access token tags: - auth /api/auth/register: post: consumes: - application/json description: Register a new user with username, email and password parameters: - description: Registration data in: body name: request required: true schema: $ref: '#/definitions/dto.RegisterRequest' produces: - application/json responses: "201": description: Registration successful schema: $ref: '#/definitions/handlers.AuthResponse' "400": description: Invalid request data or validation failed schema: $ref: '#/definitions/handlers.AuthResponse' "409": description: Username or email already exists schema: $ref: '#/definitions/handlers.AuthResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.AuthResponse' summary: Register a new user tags: - auth /api/auth/resend-verification: post: consumes: - application/json description: Send a new verification email to the provided address parameters: - description: Email address in: body name: request required: true schema: $ref: '#/definitions/dto.ResendVerificationRequest' produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/handlers.AuthResponse' "400": description: Bad Request schema: $ref: '#/definitions/handlers.AuthResponse' "404": description: Not Found schema: $ref: '#/definitions/handlers.AuthResponse' "409": description: Conflict schema: $ref: '#/definitions/handlers.AuthResponse' "429": description: Too Many Requests schema: $ref: '#/definitions/handlers.AuthResponse' "500": description: Internal Server Error schema: $ref: '#/definitions/handlers.AuthResponse' "503": description: Service Unavailable schema: $ref: '#/definitions/handlers.AuthResponse' summary: Resend verification email tags: - auth /api/auth/reset-password: post: consumes: - application/json description: Reset a user's password using a reset token parameters: - description: Password reset data in: body name: request required: true schema: $ref: '#/definitions/dto.ResetPasswordRequest' produces: - application/json responses: "200": description: Password reset successfully schema: $ref: '#/definitions/handlers.AuthResponse' "400": description: Invalid or expired token, or validation failed schema: $ref: '#/definitions/handlers.AuthResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.AuthResponse' summary: Reset password tags: - auth /api/auth/revoke: post: consumes: - application/json description: Revoke a specific refresh token. This endpoint allows authenticated users to invalidate a specific refresh token, preventing its future use. parameters: - description: Token revocation data in: body name: request required: true schema: $ref: '#/definitions/dto.RevokeTokenRequest' produces: - application/json responses: "200": description: Token revoked successfully schema: $ref: '#/definitions/handlers.AuthResponse' "400": description: Invalid request body or missing refresh token schema: $ref: '#/definitions/handlers.AuthResponse' "401": description: Invalid or expired access token schema: $ref: '#/definitions/handlers.AuthResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.AuthResponse' security: - BearerAuth: [] summary: Revoke refresh token tags: - auth /api/auth/revoke-all: post: consumes: - application/json description: Revoke all refresh tokens for the authenticated user. This endpoint allows users to invalidate all their refresh tokens at once, effectively logging them out from all devices. produces: - application/json responses: "200": description: All tokens revoked successfully schema: $ref: '#/definitions/handlers.AuthResponse' "401": description: Invalid or expired access token schema: $ref: '#/definitions/handlers.AuthResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.AuthResponse' security: - BearerAuth: [] summary: Revoke all user tokens tags: - auth /api/auth/username: put: consumes: - application/json description: Update the authenticated user's username parameters: - description: New username in: body name: request required: true schema: $ref: '#/definitions/dto.UpdateUsernameRequest' produces: - application/json responses: "200": description: OK schema: $ref: '#/definitions/handlers.AuthResponse' "400": description: Bad Request schema: $ref: '#/definitions/handlers.AuthResponse' "401": description: Unauthorized schema: $ref: '#/definitions/handlers.AuthResponse' "409": description: Conflict schema: $ref: '#/definitions/handlers.AuthResponse' "500": description: Internal Server Error schema: $ref: '#/definitions/handlers.AuthResponse' security: - BearerAuth: [] summary: Update username tags: - auth /api/posts: get: consumes: - application/json description: Get a list of posts with pagination. Posts include vote statistics (up_votes, down_votes, score) and current user's vote status. parameters: - default: 20 description: Number of posts to return in: query name: limit type: integer - default: 0 description: Number of posts to skip in: query name: offset type: integer produces: - application/json responses: "200": description: Posts retrieved successfully with vote statistics schema: $ref: '#/definitions/handlers.PostResponse' "400": description: Invalid pagination parameters schema: $ref: '#/definitions/handlers.PostResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.PostResponse' summary: Get posts tags: - posts post: consumes: - application/json description: Create a new post with URL and optional title parameters: - description: Post data in: body name: request required: true schema: $ref: '#/definitions/dto.CreatePostRequest' produces: - application/json responses: "201": description: Created schema: $ref: '#/definitions/handlers.PostResponse' "400": description: Invalid request data or validation failed schema: $ref: '#/definitions/handlers.PostResponse' "401": description: Authentication required schema: $ref: '#/definitions/handlers.PostResponse' "409": description: URL already submitted schema: $ref: '#/definitions/handlers.PostResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.PostResponse' "502": description: Failed to fetch title from URL schema: $ref: '#/definitions/handlers.PostResponse' security: - BearerAuth: [] summary: Create a new post tags: - posts /api/posts/{id}: delete: consumes: - application/json description: Delete a post owned by the authenticated user parameters: - description: Post ID in: path name: id required: true type: integer produces: - application/json responses: "200": description: Post deleted successfully schema: $ref: '#/definitions/handlers.PostResponse' "400": description: Invalid post ID schema: $ref: '#/definitions/handlers.PostResponse' "401": description: Authentication required schema: $ref: '#/definitions/handlers.PostResponse' "403": description: Not authorized to delete this post schema: $ref: '#/definitions/handlers.PostResponse' "404": description: Post not found schema: $ref: '#/definitions/handlers.PostResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.PostResponse' security: - BearerAuth: [] summary: Delete a post tags: - posts get: consumes: - application/json description: Get a post by ID with vote statistics and current user's vote status parameters: - description: Post ID in: path name: id required: true type: integer produces: - application/json responses: "200": description: Post retrieved successfully with vote statistics schema: $ref: '#/definitions/handlers.PostResponse' "400": description: Invalid post ID schema: $ref: '#/definitions/handlers.PostResponse' "404": description: Post not found schema: $ref: '#/definitions/handlers.PostResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.PostResponse' summary: Get a single post tags: - posts put: consumes: - application/json description: Update the title and content of a post owned by the authenticated user parameters: - description: Post ID in: path name: id required: true type: integer - description: Post update data in: body name: request required: true schema: $ref: '#/definitions/dto.UpdatePostRequest' produces: - application/json responses: "200": description: Post updated successfully schema: $ref: '#/definitions/handlers.PostResponse' "400": description: Invalid request data or validation failed schema: $ref: '#/definitions/handlers.PostResponse' "401": description: Authentication required schema: $ref: '#/definitions/handlers.PostResponse' "403": description: Not authorized to update this post schema: $ref: '#/definitions/handlers.PostResponse' "404": description: Post not found schema: $ref: '#/definitions/handlers.PostResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.PostResponse' security: - BearerAuth: [] summary: Update a post tags: - posts /api/posts/{id}/vote: delete: consumes: - application/json description: Remove a vote from a post for the authenticated user. This is equivalent to casting a vote with type 'none'. parameters: - description: Post ID in: path name: id required: true type: integer produces: - application/json responses: "200": description: Vote removed successfully with updated post statistics schema: $ref: '#/definitions/handlers.VoteResponse' "400": description: Invalid post ID schema: $ref: '#/definitions/handlers.VoteResponse' "401": description: Authentication required schema: $ref: '#/definitions/handlers.VoteResponse' "404": description: Post not found schema: $ref: '#/definitions/handlers.VoteResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.VoteResponse' security: - BearerAuth: [] summary: Remove a vote tags: - votes get: consumes: - application/json description: |- Retrieve the current user's vote for a specific post. Requires authentication and returns the vote type if it exists. **Response:** - If vote exists: Returns vote details with contextual metadata (including `is_anonymous`) - If no vote: Returns success with null vote data and metadata parameters: - description: Post ID in: path name: id required: true type: integer produces: - application/json responses: "200": description: No vote found for this user/post combination schema: $ref: '#/definitions/handlers.VoteResponse' "400": description: Invalid post ID schema: $ref: '#/definitions/handlers.VoteResponse' "401": description: Authentication required schema: $ref: '#/definitions/handlers.VoteResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.VoteResponse' security: - BearerAuth: [] summary: Get current user's vote tags: - votes post: consumes: - application/json description: |- Vote on a post (upvote, downvote, or remove vote). Authentication is required; the vote is performed on behalf of the current user. **Vote Types:** - `up`: Upvote the post - `down`: Downvote the post - `none`: Remove existing vote **Response includes:** - Updated post vote counts (up_votes, down_votes, score) - Success message parameters: - description: Post ID in: path name: id required: true type: integer - description: 'Vote data (type: ''up'', ''down'', or ''none'' to remove)' in: body name: request required: true schema: $ref: '#/definitions/dto.CastVoteRequest' produces: - application/json responses: "200": description: Vote cast successfully with updated post statistics schema: $ref: '#/definitions/handlers.VoteResponse' "400": description: Invalid request data or vote type schema: $ref: '#/definitions/handlers.VoteResponse' "401": description: Authentication required schema: $ref: '#/definitions/handlers.VoteResponse' "404": description: Post not found schema: $ref: '#/definitions/handlers.VoteResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.VoteResponse' security: - BearerAuth: [] summary: Cast a vote on a post tags: - votes /api/posts/{id}/votes: get: consumes: - application/json description: |- Retrieve all votes for a specific post. Returns all votes in a single format. **Authentication Required:** Yes (Bearer token) **Response includes:** - Array of all votes - Total vote count - Each vote includes type and unauthenticated status parameters: - description: Post ID in: path name: id required: true type: integer produces: - application/json responses: "200": description: Votes retrieved successfully with count schema: $ref: '#/definitions/handlers.VoteResponse' "400": description: Invalid post ID schema: $ref: '#/definitions/handlers.VoteResponse' "401": description: Authentication required schema: $ref: '#/definitions/handlers.VoteResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.VoteResponse' security: - BearerAuth: [] summary: Get post votes tags: - votes /api/posts/search: get: consumes: - application/json description: Search posts by title or content keywords. Results include vote statistics and current user's vote status. parameters: - description: Search term in: query name: q type: string - default: 20 description: Number of posts to return in: query name: limit type: integer - default: 0 description: Number of posts to skip in: query name: offset type: integer produces: - application/json responses: "200": description: Search results with vote statistics schema: $ref: '#/definitions/handlers.PostResponse' "400": description: Invalid search parameters schema: $ref: '#/definitions/handlers.PostResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.PostResponse' summary: Search posts tags: - posts /api/posts/title: get: consumes: - application/json description: Fetch the HTML title for the provided URL parameters: - description: URL to inspect in: query name: url required: true type: string produces: - application/json responses: "200": description: Title fetched successfully schema: $ref: '#/definitions/handlers.PostResponse' "400": description: Invalid URL or URL parameter missing schema: $ref: '#/definitions/handlers.PostResponse' "501": description: Title fetching is not available schema: $ref: '#/definitions/handlers.PostResponse' "502": description: Failed to fetch title from URL schema: $ref: '#/definitions/handlers.PostResponse' summary: Fetch title from URL tags: - posts /api/users: get: consumes: - application/json description: Retrieve a paginated list of users parameters: - default: 20 description: Number of users to return in: query name: limit type: integer - default: 0 description: Number of users to skip in: query name: offset type: integer produces: - application/json responses: "200": description: Users retrieved successfully schema: $ref: '#/definitions/handlers.UserResponse' "401": description: Authentication required schema: $ref: '#/definitions/handlers.UserResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.UserResponse' security: - BearerAuth: [] summary: List users tags: - users post: consumes: - application/json description: Create a new user account parameters: - description: User data in: body name: request required: true schema: $ref: '#/definitions/dto.RegisterRequest' produces: - application/json responses: "201": description: User created successfully schema: $ref: '#/definitions/handlers.UserResponse' "400": description: Invalid request data or validation failed schema: $ref: '#/definitions/handlers.UserResponse' "401": description: Authentication required schema: $ref: '#/definitions/handlers.UserResponse' "409": description: Username or email already exists schema: $ref: '#/definitions/handlers.UserResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.UserResponse' security: - BearerAuth: [] summary: Create user tags: - users /api/users/{id}: get: consumes: - application/json description: Retrieve a specific user by ID parameters: - description: User ID in: path name: id required: true type: integer produces: - application/json responses: "200": description: User retrieved successfully schema: $ref: '#/definitions/handlers.UserResponse' "400": description: Invalid user ID schema: $ref: '#/definitions/handlers.UserResponse' "401": description: Authentication required schema: $ref: '#/definitions/handlers.UserResponse' "404": description: User not found schema: $ref: '#/definitions/handlers.UserResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.UserResponse' security: - BearerAuth: [] summary: Get user tags: - users /api/users/{id}/posts: get: consumes: - application/json description: Retrieve posts created by a specific user parameters: - description: User ID in: path name: id required: true type: integer - default: 20 description: Number of posts to return in: query name: limit type: integer - default: 0 description: Number of posts to skip in: query name: offset type: integer produces: - application/json responses: "200": description: User posts retrieved successfully schema: $ref: '#/definitions/handlers.UserResponse' "400": description: Invalid user ID or pagination parameters schema: $ref: '#/definitions/handlers.UserResponse' "401": description: Authentication required schema: $ref: '#/definitions/handlers.UserResponse' "500": description: Internal server error schema: $ref: '#/definitions/handlers.UserResponse' security: - BearerAuth: [] summary: Get user posts tags: - users /health: get: consumes: - application/json description: Check the API health status along with database connectivity details produces: - application/json responses: "200": description: Health check successful schema: $ref: '#/definitions/handlers.CommonResponse' summary: Health check tags: - api /metrics: get: consumes: - application/json description: Retrieve application metrics including aggregate counts and database performance data produces: - application/json responses: "200": description: Application metrics retrieved successfully schema: $ref: '#/definitions/handlers.CommonResponse' summary: Get metrics tags: - api schemes: - http swagger: "2.0"