+{"openapi":"3.1.0","info":{"title":"Git Ranker API","description":"Machine-readable contract for Git Ranker's public `/api/v1/**` endpoints.\n\nAuthentication model:\n- Protected endpoints accept either an `Authorization: Bearer <JWT>` header or the `accessToken` cookie.\n- `/api/v1/auth/refresh` uses the `refreshToken` cookie.\n- Initial sign-in starts with the GitHub OAuth2 redirect flow exposed by Spring Security outside `/api/v1/**`.\n","version":"v1"},"servers":[{"url":"https://www.git-ranker.com","description":"Production"},{"url":"http://localhost:8080","description":"Local development"}],"paths":{"/api/v1/users/{username}/refresh":{"post":{"tags":["Users"],"summary":"Refresh the authenticated user's score","description":"Recalculates the caller's own profile. The authenticated user must match the path username.","operationId":"refreshUser","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string","pattern":"^(?=.{1,39}$)[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseRegisterUserResponse"}}}}},"security":[{"bearerAuth":[]},{"accessTokenCookie":[]}]}},"/api/v1/auth/refresh":{"post":{"tags":["Auth"],"summary":"Refresh access and refresh tokens","description":"Requires the refreshToken cookie and rotates the active session tokens.","operationId":"refreshToken","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVoid"}}}}},"security":[{"refreshTokenCookie":[]}]}},"/api/v1/auth/logout":{"post":{"tags":["Auth"],"summary":"Log out the current session","description":"Requires an authenticated session and the refreshToken cookie to invalidate the current login.","operationId":"logout","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVoid"}}}}},"security":[{"bearerAuth":[]},{"accessTokenCookie":[]}]}},"/api/v1/auth/logout/all":{"post":{"tags":["Auth"],"summary":"Log out every session for the current user","description":"Revokes all refresh tokens for the authenticated user.","operationId":"logoutAll","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseVoid"}}}}},"security":[{"bearerAuth":[]},{"accessTokenCookie":[]}]}},"/api/v1/users/{username}":{"get":{"tags":["Users"],"summary":"Get a user's profile","description":"Returns the public Git Ranker profile for a GitHub username.","operationId":"getUser","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string","pattern":"^(?=.{1,39}$)[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$"}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseRegisterUserResponse"}}}}}}},"/api/v1/ranking":{"get":{"tags":["Ranking"],"summary":"List ranking entries","description":"Returns paginated ranking results with an optional tier filter.","operationId":"getRankings","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0,"minimum":0}},{"name":"tier","in":"query","required":false,"schema":{"type":"string","enum":["CHALLENGER","MASTER","DIAMOND","EMERALD","PLATINUM","GOLD","SILVER","BRONZE","IRON"]}}],"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseRankingList"}}}}}}},"/api/v1/badges/{tier}/badge":{"get":{"tags":["Badges"],"summary":"Render a tier badge","description":"Returns an SVG badge template for the requested tier.","operationId":"getBadgeByTier","parameters":[{"name":"tier","in":"path","required":true,"schema":{"type":"string","enum":["CHALLENGER","MASTER","DIAMOND","EMERALD","PLATINUM","GOLD","SILVER","BRONZE","IRON"]}}],"responses":{"200":{"description":"OK","content":{"image/svg+xml":{"schema":{"type":"string"}}}}}}},"/api/v1/badges/{nodeId}":{"get":{"tags":["Badges"],"summary":"Render a badge for a GitHub node id","description":"Returns an SVG badge for a user's current Git Ranker profile.","operationId":"getBadge","parameters":[{"name":"nodeId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"image/svg+xml":{"schema":{"type":"string"}}}}}}},"/api/v1/auth/me":{"get":{"tags":["Auth"],"summary":"Get the current authenticated user","description":"Returns the current session user resolved from the access token.","operationId":"me","responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ApiResponseAuthMeResponse"}}}}},"security":[{"bearerAuth":[]},{"accessTokenCookie":[]}]}},"/api/v1/users/me":{"delete":{"tags":["Users"],"summary":"Delete the authenticated user's account","description":"Deletes the current account and clears authentication cookies.","operationId":"deleteMyAccount","responses":{"204":{"description":"No Content"}},"security":[{"bearerAuth":[]},{"accessTokenCookie":[]}]}}},"components":{"schemas":{"ApiResponseRegisterUserResponse":{"type":"object","properties":{"result":{"type":"string","enum":["SUCCESS","ERROR"]},"data":{"$ref":"#/components/schemas/RegisterUserResponse"},"error":{"$ref":"#/components/schemas/ErrorMessage"}}},"ErrorMessage":{"type":"object","properties":{"type":{"type":"string"},"message":{"type":"string"},"data":{}}},"RegisterUserResponse":{"type":"object","properties":{"userId":{"type":"integer","format":"int64"},"githubId":{"type":"integer","format":"int64"},"nodeId":{"type":"string"},"username":{"type":"string"},"email":{"type":"string"},"profileImage":{"type":"string"},"role":{"type":"string","enum":["GUEST","USER","ADMIN"]},"updatedAt":{"type":"string","format":"date-time"},"lastFullScanAt":{"type":"string","format":"date-time"},"totalScore":{"type":"integer","format":"int32"},"ranking":{"type":"integer","format":"int32"},"tier":{"type":"string","enum":["CHALLENGER","MASTER","DIAMOND","EMERALD","PLATINUM","GOLD","SILVER","BRONZE","IRON"]},"percentile":{"type":"number","format":"double"},"commitCount":{"type":"integer","format":"int32"},"issueCount":{"type":"integer","format":"int32"},"prCount":{"type":"integer","format":"int32"},"mergedPrCount":{"type":"integer","format":"int32"},"reviewCount":{"type":"integer","format":"int32"},"diffCommitCount":{"type":"integer","format":"int32"},"diffIssueCount":{"type":"integer","format":"int32"},"diffPrCount":{"type":"integer","format":"int32"},"diffMergedPrCount":{"type":"integer","format":"int32"},"diffReviewCount":{"type":"integer","format":"int32"},"isNewUser":{"type":"boolean"}}},"ApiResponseVoid":{"type":"object","properties":{"result":{"type":"string","enum":["SUCCESS","ERROR"]},"data":{},"error":{"$ref":"#/components/schemas/ErrorMessage"}}},"ApiResponseRankingList":{"type":"object","properties":{"result":{"type":"string","enum":["SUCCESS","ERROR"]},"data":{"$ref":"#/components/schemas/RankingList"},"error":{"$ref":"#/components/schemas/ErrorMessage"}}},"PageInfo":{"type":"object","properties":{"currentPage":{"type":"integer","format":"int32"},"pageSize":{"type":"integer","format":"int32"},"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"isFirst":{"type":"boolean"},"isLast":{"type":"boolean"}}},"RankingList":{"type":"object","properties":{"rankings":{"type":"array","items":{"$ref":"#/components/schemas/UserInfo"}},"pageInfo":{"$ref":"#/components/schemas/PageInfo"}}},"UserInfo":{"type":"object","properties":{"username":{"type":"string"},"profileImage":{"type":"string"},"ranking":{"type":"integer","format":"int64"},"totalScore":{"type":"integer","format":"int32"},"tier":{"type":"string","enum":["CHALLENGER","MASTER","DIAMOND","EMERALD","PLATINUM","GOLD","SILVER","BRONZE","IRON"]}}},"ApiResponseAuthMeResponse":{"type":"object","properties":{"result":{"type":"string","enum":["SUCCESS","ERROR"]},"data":{"$ref":"#/components/schemas/AuthMeResponse"},"error":{"$ref":"#/components/schemas/ErrorMessage"}}},"AuthMeResponse":{"type":"object","properties":{"username":{"type":"string"},"profileImage":{"type":"string"},"role":{"type":"string","enum":["GUEST","USER","ADMIN"]}}}},"securitySchemes":{"bearerAuth":{"type":"http","description":"Send `Authorization: Bearer <JWT>` for protected API calls.","scheme":"bearer","bearerFormat":"JWT"},"accessTokenCookie":{"type":"apiKey","description":"Browser session alternative to bearerAuth.","name":"accessToken","in":"cookie"},"refreshTokenCookie":{"type":"apiKey","description":"Required by refresh and logout flows that rotate or revoke session tokens.","name":"refreshToken","in":"cookie"}}}}
0 commit comments