Skip to content

Latest commit

 

History

History
508 lines (379 loc) · 12.1 KB

File metadata and controls

508 lines (379 loc) · 12.1 KB

BugArena — REST API Reference

Base URL: http://localhost:5000/api
Auth: All protected routes require a Bearer <accessToken> in the Authorization header (or the accessToken httpOnly cookie). The access token is obtained at login and is valid for 15 minutes. Use /auth/refresh-token to rotate.


Table of Contents

  1. Authentication
  2. Users & Profiles
  3. Programs
  4. Reports
  5. Statistics & Analytics
  6. Certificates
  7. Admin
  8. WebSocket Events
  9. Error Codes

1. Authentication

POST /auth/register

Create a new hunter account.

Body (JSON)

Field Type Required
fullName string
email string
password string ≥ 8 chars
collegeName string
role HUNTER | PROGRAM_OWNER – (default HUNTER)

Response 201

{
  "success": true,
  "message": "Registration successful. Please verify your email.",
  "data": { "userId": "..." }
}

POST /auth/login

Authenticate and receive JWT tokens.

Body (JSON)

Field Type Required
email string
password string
totpCode string (6-digit) if 2FA is enabled

Response 200 — sets accessToken and refreshToken as httpOnly cookies.

{
  "success": true,
  "data": {
    "user": { "_id": "...", "fullName": "...", "role": "HUNTER", "level": "TRACKER" },
    "accessToken": "eyJ..."
  }
}

Lockout: 5 consecutive failed logins locks the account for 15 minutes.
2FA redirect: if twoFactorEnabled=true and totpCode is missing, returns 403 TOTP_REQUIRED.


POST /auth/logout

🔒 Protected. Clears refresh token cookie and invalidates server-side token.


POST /auth/refresh-token

Rotate the access token using the refreshToken cookie.

Response 200

{ "success": true, "data": { "accessToken": "eyJ..." } }

GET /auth/verify-email/:token

Verify email address from the token sent during registration.


POST /auth/forgot-password

Send a password-reset email.

Body: { "email": "..." }


POST /auth/reset-password/:token

Reset password using the emailed token.

Body: { "password": "newSecurePassword1!" }


POST /auth/2fa/enroll

🔒 Protected. Generate a TOTP secret and QR code for Google Authenticator.

Response 200

{
  "success": true,
  "data": {
    "secret": "BASE32_SECRET",
    "otpAuthUrl": "otpauth://totp/BugArena:user@example.com?secret=...",
    "qrCodeDataUrl": "data:image/png;base64,..."
  }
}

POST /auth/2fa/verify

🔒 Protected. Activate 2FA by submitting the first valid TOTP code.

Body: { "token": "123456" }


POST /auth/2fa/disable

🔒 Protected. Deactivate 2FA.

Body: { "token": "123456" }


2. Users & Profiles

GET /users/:username

Public profile. If a valid Bearer token is present, returns isFollowing status.

Response 200

{
  "success": true,
  "data": {
    "user": { "_id": "...", "fullName": "Alice Chen", "level": "TRACKER", "totalPoints": 750, "rank": 3 },
    "badges": [{ "badgeId": { "name": "First Blood", "description": "..." }, "_id": "..." }],
    "recentReports": [ { "_id": "...", "title": "...", "severity": "HIGH", "status": "ACCEPTED" } ],
    "followerCount": 12,
    "followingCount": 5,
    "isFollowing": true
  }
}

POST /users/:id/follow

🔒 Protected. Toggle follow/unfollow. Returns the new state.

Response 200

{ "success": true, "data": { "followed": true }, "message": "Followed user successfully" }

GET /users/me/feed

🔒 Protected. Activity feed — recent notifications from hunters you follow (type: REPORT_ACCEPTED, BADGE_EARNED, POINTS_AWARDED). Populated with userId.fullName, userId.avatarUrl, userId.level.

Response 200

{
  "success": true,
  "data": {
    "feed": [
      {
        "_id": "...",
        "type": "REPORT_ACCEPTED",
        "message": "✅ Your report \"XSS in PayPal\" was accepted!",
        "userId": { "fullName": "Bob Ramirez", "avatarUrl": "", "level": "SCOUT" },
        "createdAt": "2026-05-29T10:00:00.000Z"
      }
    ]
  }
}

PUT /users/me

🔒 Protected. Update own profile fields.

Body (JSON — all optional)

{ "fullName": "...", "collegeName": "...", "bio": "...", "githubUrl": "...", "linkedinUrl": "...", "twitterUrl": "..." }

PUT /users/me/password

🔒 Protected. Change password.

Body: { "currentPassword": "...", "newPassword": "..." }


DELETE /users/me

🔒 Protected. Permanently delete own account.


GET /users/me/badges

🔒 Protected. All earned badges for the authenticated user.


GET /users/me/certificates

🔒 Protected. All earned certificates.


GET /users/me/notifications

🔒 Protected. Paginated notifications list.

Query params: limit (default 20), page (default 1)


PATCH /users/me/notifications/:id/read

🔒 Protected. Mark a single notification as read.


PATCH /users/me/notifications/read-all

🔒 Protected. Mark all notifications as read.


3. Programs

GET /programs

List approved programs. Supports filtering and pagination.

Query params

Param Type Description
limit number Default 20
page number Default 1
category string WEB, API, MOBILE, NETWORK
difficulty string EASY, MEDIUM, HARD
sort string reward, createdAt

Response 200

{
  "success": true,
  "data": { "programs": [ {...} ], "total": 5, "page": 1, "pages": 1 }
}

GET /programs/:slug

Get a single program by slug.


POST /programs

🔒 Protected (PROGRAM_OWNER or ADMIN). Create a new program.

Body (JSON)

{
  "name": "PayPal Security",
  "description": "...",
  "category": "WEB",
  "difficulty": "HARD",
  "rewards": { "critical": 50000, "high": 25000, "medium": 10000, "low": 3000, "info": 500 },
  "scopeUrls": ["*.paypal.com"],
  "outOfScopeUrls": ["sandbox.paypal.com"],
  "tags": ["fintech"]
}

PUT /programs/:id

🔒 Protected (owner or admin). Update program details.


DELETE /programs/:id

🔒 Protected (owner or admin). Soft-deactivate a program.


4. Reports

GET /reports

🔒 Protected. Hunters see their own reports; admins/owners see all or scoped to their program.

Query params: limit, page, status, severity, programId


POST /reports

🔒 Protected (HUNTER). Submit a new vulnerability report.

Content-Type: multipart/form-data

Field Type Required
title string
programId ObjectId
vulnerabilityType string
affectedUrl string
severity enum
cvssScore number 0-10
stepsToReproduce markdown string
impactDescription markdown string
pocVideoUrl URL string
isDraft boolean
screenshots file(s)

Duplicate warning: If the title/steps share ≥ 70% similarity with an existing report, the response includes { "duplicateWarning": true, "similarReports": [...] }.

Response 201

{ "success": true, "data": { "report": { "_id": "...", "status": "PENDING" } } }

GET /reports/:id

🔒 Protected. Get full report details.


PATCH /reports/:id/status

🔒 Protected (PROGRAM_OWNER or ADMIN). Update report status.

State machine:

DRAFT → PENDING → TRIAGING → ACCEPTED → REWARDED
                           → REJECTED
                           → DUPLICATE

Body: { "status": "ACCEPTED", "note": "Confirmed. Reward processing." }

Returns 422 if the transition is illegal.


GET /reports/export

🔒 Protected (admin/owner). Export reports.

Query: format=pdf|csv, programId, status, from, to


5. Statistics & Analytics

GET /stats/dashboard

🔒 Protected. Personal dashboard metrics for the authenticated user.

Response 200

{
  "success": true,
  "data": {
    "totalSubmissions": 42,
    "acceptedReports": 18,
    "totalPoints": 1250,
    "rank": 7,
    "level": "TRACKER",
    "recentNotifications": [ {...} ]
  }
}

GET /stats/admin

🔒 Protected (ADMIN only). Platform-wide analytics.

Response 200

{
  "success": true,
  "data": {
    "totalReports": 430,
    "acceptedReports": 190,
    "avgTriageHours": 28.4,
    "severityDistribution": {
      "CRITICAL": 12, "HIGH": 55, "MEDIUM": 98, "LOW": 140, "INFO": 125
    },
    "topHunters": [ { "fullName": "Alice Chen", "totalPoints": 4800 } ]
  }
}

6. Certificates

GET /certificates/verify/:verificationId

Public — no auth required. Verify a certificate's authenticity.

Response 200 (valid certificate)

{
  "success": true,
  "data": {
    "valid": true,
    "certificate": {
      "verificationId": "550e8400-e29b-41d4-a716-446655440000",
      "title": "XSS in PayPal Security #1",
      "programName": "PayPal Security",
      "severity": "CRITICAL",
      "issuedAt": "2026-05-01T00:00:00.000Z",
      "snapshots": {
        "hunterName": "Alice Chen",
        "reportTitle": "XSS in PayPal Security #1",
        "severity": "CRITICAL",
        "points": 500
      },
      "pdfUrl": "https://res.cloudinary.com/..."
    }
  }
}

Response 404 (invalid / not found)

{ "success": false, "message": "Certificate not found or has been revoked" }

GET /certificates/:id/pdf

🔒 Protected (certificate owner). Generate or retrieve the PDF certificate.


7. Admin

GET /admin/reports

🔒 Protected (ADMIN). Full paginated report list across all programs.

PATCH /admin/users/:id/ban

🔒 Protected (ADMIN). Ban/unban a user account.

PATCH /admin/programs/:id/approve

🔒 Protected (ADMIN). Approve a pending program.


8. WebSocket Events

BugArena uses Socket.io for real-time updates. Authenticate the WebSocket handshake by passing the access token in auth.token:

const socket = io('http://localhost:5000', {
  auth: { token: 'eyJ...' }
})

Server → Client Events

Event Payload Description
points_awarded { points, totalPoints, level } Hunter receives points for an accepted report
level_up { oldLevel, newLevel } Hunter advances to a new level
badge_earned { name, description } New badge awarded
report_status_changed { reportId, newStatus } Report status updated
leaderboard_update { topHunters: [...] } Periodic leaderboard broadcast
notification { type, message } Generic notification push

9. Error Codes

HTTP Code Meaning
400 VALIDATION_ERROR Request body failed validation
400 SELF_FOLLOW Cannot follow yourself
401 NO_TOKEN Authorization header / cookie missing
401 TOKEN_EXPIRED Access token has expired — refresh it
401 INVALID_TOKEN JWT signature invalid
403 ACCOUNT_BANNED Account suspended by admin
403 TOTP_REQUIRED 2FA code required to complete login
403 FORBIDDEN Insufficient role for this action
404 USER_NOT_FOUND User does not exist
404 REPORT_NOT_FOUND Report does not exist
404 PROGRAM_NOT_FOUND Program does not exist
409 DUPLICATE_EMAIL Email already registered
422 INVALID_STATE_TRANSITION Illegal report status change
423 ACCOUNT_LOCKED Too many failed logins — try again later
500 INTERNAL_ERROR Unexpected server error

Rate Limits: Login and register endpoints are limited to 20 requests / 15 minutes per IP.
Webhook retries: Outbound Slack/Discord webhooks retry up to 3 times with exponential back-off on failure.