Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/flagForgeCTF/flagForge/llms.txt

Use this file to discover all available pages before exploring further.

The flag submission API lets authenticated participants submit answers to challenges and receive immediate feedback. A correct submission records the solve, awards points to the user’s total score, and applies any hint penalties accrued during the attempt. Practice mode lets you re-attempt challenges you have already solved without affecting your score.

POST /api/problems/[id]

Submit a flag for a challenge. Requires an active session.
You must be signed in to submit flags. Unauthenticated requests return 401 Unauthorized.

Path parameters

id
string
required
The MongoDB _id of the challenge you are submitting a flag for.

Query parameters

practice
boolean
Set to true to submit in practice mode. Practice mode is only active if you have already solved the challenge. Your score is not affected — practice submissions never create a new UserQuestion record.

Request body

flag
string
required
The flag string to validate. Leading and trailing whitespace is trimmed before comparison.

Response fields

The response shape varies depending on the outcome. Correct flag (first solve):
message
string
"Right! Congratulations on solving the challenge!"
points
number
Points awarded for this solve, after any hint penalties have been deducted.
success
boolean
true
correct
boolean
true
Incorrect flag:
message
string
"Incorrect flag. Try again!"
success
boolean
false
correct
boolean
false
Already solved (no practice param):
message
string
"You have already solved this challenge!"
Practice mode — correct:
message
string
"Practice mode: Correct flag."
correct
boolean
true
practice
boolean
true
Practice mode — incorrect:
message
string
"Practice mode: Incorrect flag. Try again!"
correct
boolean
false
practice
boolean
true

Error responses

StatusCondition
401 UnauthorizedYou are not signed in.
404 Not FoundNo challenge exists with the given id.
410 GoneThe challenge has expired and no longer accepts submissions.

How points and hints interact

Hint deductions are applied immediately when a hint is unlocked via POST /api/problems/[id]/hints — they are not re-applied at submission time. The points field in the success response is the challenge’s full base point value. The net effect on a player’s score is the sum of hint deductions (already applied) plus the base points added on solve.

Examples

Submit a flag:
curl -X POST "https://flagforgectf.com/api/problems/665a1f2e3c4b5d6e7f8a9b0c" \
  -H "Content-Type: application/json" \
  -H "Cookie: next-auth.session-token=<session-token>" \
  -d '{"flag": "FF{xss_c00ki3_theft}"}'
{
  "message": "Right! Congratulations on solving the challenge!",
  "points": 150,
  "success": true,
  "correct": true
}
Submit in practice mode:
curl -X POST "https://flagforgectf.com/api/problems/665a1f2e3c4b5d6e7f8a9b0c?practice=true" \
  -H "Content-Type: application/json" \
  -H "Cookie: next-auth.session-token=<session-token>" \
  -d '{"flag": "FF{xss_c00ki3_theft}"}'
{
  "message": "Practice mode: Correct flag.",
  "correct": true,
  "practice": true
}

Dynamic flags and the flag generator

The codebase includes a utils/flagGenerator.ts utility that implements per-user dynamic flag generation. This powers challenges where the flag template in the database contains a marker like [GUID], [TEAM_HASH], [LEET], or [CLEET]. The generator is called internally when the admin creates a challenge with a dynamic flag template. See Dynamic flags for a full explanation of the four flag types and how they work from the player’s perspective.

GET /api/problems/[id]/hints

Retrieve hints for a challenge. Requires an active session. Accessing a hint records the usage against your account and deducts points from your score for that challenge before the flag is submitted.
Unlocking a hint is irreversible. The point deduction is applied to your account immediately and is factored into the points awarded when you submit the correct flag.

Path parameters

id
string
required
The MongoDB _id of the challenge.

Response fields

hints
object[]
Array of hint objects for this challenge. Locked hints have text: null; unlocked hints include the full text.
usedHints
number[]
Array of hint indices the authenticated user has already unlocked for this challenge.

Example

curl "https://flagforgectf.com/api/problems/665a1f2e3c4b5d6e7f8a9b0c/hints" \
  -H "Cookie: next-auth.session-token=<session-token>"
{
  "hints": [
    {
      "index": 0,
      "text": "Think about input sanitization",
      "pointsDeduction": 25
    },
    {
      "index": 1,
      "text": null,
      "pointsDeduction": 50
    }
  ],
  "usedHints": [0]
}

POST /api/problems/[id]/hints

Unlock a specific hint for a challenge. Requires an active session. Deducts the hint’s pointsDeduction from the user’s total score immediately on unlock. Cannot be used if the challenge is already solved.
Unlocking a hint is irreversible and immediately deducts points from your total score.

Path parameters

id
string
required
The MongoDB _id of the challenge.

Request body

hintIndex
number
required
Zero-based index of the hint to unlock. Use the index field from GET /api/problems/[id]/hints to determine the correct value.

Response fields

message
string
Confirmation message including the hint text and points deducted.
hint
string
The revealed hint text.
pointsDeducted
number
Points subtracted from the user’s total score for this hint reveal.
success
boolean
true on success.

Example

curl -X POST "https://flagforgectf.com/api/problems/665a1f2e3c4b5d6e7f8a9b0c/hints" \
  -H "Content-Type: application/json" \
  -H "Cookie: next-auth.session-token=<session-token>" \
  -d '{"hintIndex": 0}'
{
  "message": "Hint revealed: Think about input sanitization. 25 points deducted from your score.",
  "hint": "Think about input sanitization",
  "pointsDeducted": 25,
  "success": true
}

Build docs developers (and LLMs) love