Responses
Reference for rCTF responses, common errors, and shared API objects.
The @rctf/types package defines each response’s kind, HTTP status, message, and optional data. Individual endpoint pages list their relevant responses. This page collects the shared definitions.
Response format
Most responses contain kind, message, and optional data fields:
{ "kind": "goodUserSelfData", "message": "The user's own data was successfully retrieved.", "data": {}}Responses with no additional data omit data:
{ "kind": "goodToken", "message": "The authorization token is valid."}Unknown API routes usually return 404 badEndpoint. Unexpected server errors return 500 errorInternal.
Common errors
| Response | Data | Meaning |
|---|---|---|
400 badJson |
No data | The request body was not valid JSON. |
400 badBody |
{ reason: string } |
Validation did not pass for body, query, path parameters, or form data. |
401 badToken |
No data | The auth token was missing or could not be used. |
403 badPerms |
No data | The authenticated team does not have the permission bits for this route. |
404 badEndpoint |
No data | The route is not available, or the provider behind the route is not configured. |
401 badNotStarted |
No data | The CTF has not started yet for this request. |
401 badEnded |
No data | The CTF has ended for this action. |
403 badCaptcha |
No data | V2 captcha validation did not pass. |
401 badRecaptchaCode |
No data | V1 captcha validation did not pass. |
429 badRateLimit |
{ timeLeft: number } |
This rate limit needs more time before another request. |
500 errorInternal |
No data | The server hit an unexpected error. |
Auth and account errors
| Response | Data | Meaning |
|---|---|---|
400 badEmail |
No data | The email did not pass validation. |
400 badName |
No data | The team name did not pass validation. |
409 badKnownEmail |
No data | Another account already uses this email. |
409 badKnownName |
No data | Another account already uses this team name. |
409 badKnownCtftimeId |
No data | Another account already uses this CTFtime ID. |
404 badUnknownEmail |
No data | No account is associated with this email. |
404 badUnknownUser |
No data | No user exists for that ID. |
401 badTokenVerification |
No data | The verify, team, or CTFtime auth token could not be verified. |
401 badCtftimeToken |
No data | The CTFtime auth token could not be used. |
401 badCtftimeCode |
No data | The CTFtime OAuth code could not be used. |
404 badCtftimeNoExists |
No data | The current user does not have a linked CTFtime team. |
404 badEmailNoExists |
No data | The current user does not have an email address. |
403 badEmailChangeDivision |
No data | The new email would move the account outside its current division rules. |
403 badDivisionNotAllowed |
No data | The account is not allowed to use the requested division. |
403 badCompetitionNotAllowed |
No data | Registration rules do not allow this account. |
400 badRegistrationsDisabled |
No data | Registrations are currently disabled. |
409 badTooManyMembers |
No data | The team is already at maxMembers. |
409 badZeroAuth |
No data | The change would remove the final auth method from the account. |
403 badUserPrivileged |
No data | The target user has admin permissions, so this route does not modify it. |
Challenge and integration errors
| Response | Data | Meaning |
|---|---|---|
404 badChallenge |
No data | The challenge was not found or is not available to this route. |
400 badFlag |
No data | The submitted flag was not accepted. |
409 badAlreadySolvedChallenge |
No data | The team has already solved this challenge. |
404 badUnknownSolveV2 |
No data | The solve row was not found. |
400 badDataUri |
No data | The V1 upload data URI could not be read. |
500 badFilesUpload |
No data | The upload provider could not finish the upload. |
400 badAvatarFile |
No data | The avatar file was not accepted as an image. |
400 badAvatarFileSize |
{ maxSize: number } |
The avatar is larger than maxAvatarSize. |
400 badModerationNotPassed |
No data | Avatar moderation did not approve the image. |
400 badInstancerConfig |
{ error: string } |
The instancer provider did not accept the challenge config. |
400 badInstancerError |
{ message: string } |
The instancer could not create, read, extend, or stop the instance. |
400 badInstancerState |
{ error: string } |
The admin bot route needs a running instance, but one was not available. |
400 badAdminBotConfig |
{ error: string } |
The admin bot provider did not accept the challenge source. |
404 badUnknownVerification |
No data | The pending user verification was not found. |
401 badSignature |
No data | The dynamic-scoring webhook signature, timestamp, or challenge target was rejected. The endpoint deliberately doesn’t distinguish causes. |
400 badExternalAuthRequest |
No data | An external-auth call was rejected. The same response is used for unknown client, wrong secret, wrong/expired/reused code, and mismatched redirect URI so the endpoint can’t be probed. |
Success response data
| Response | Data |
|---|---|
200 goodRegister |
{ authToken: string } |
200 goodRegisterV2 |
{ authToken: string, teamToken: string } |
200 goodLogin |
{ authToken: string } |
200 goodVerify |
{ authToken: string } |
200 goodVerifyInfo |
{ kind: "register" | "team" | "update", email: string | null, name?: string } |
200 goodToken |
No data. |
200 goodVerifySent |
No data. |
200 goodEmailSet |
No data. |
200 goodEmailRemoved |
No data. |
200 goodCtftimeAuthSet |
No data. |
200 goodCtftimeRemoved |
No data. |
200 goodCtftimeToken |
{ ctftimeToken: string, ctftimeName: string, ctftimeId: string } |
200 goodChallenges 200 goodChallengesV2 |
Challenge array. Fields depend on API version. |
200 goodChallengeSolves 200 goodChallengeSolvesV2 |
Solve list. Fields depend on API version. |
200 goodFlag |
No data. |
200 goodLeaderboard 200 goodLeaderboardV2 |
{ total: number, leaderboard: LeaderboardEntry[] }. Entry fields depend on API version. |
200 goodLeaderboardWithGraph |
{ total: number, leaderboard: LeaderboardEntryV2[], graph: LeaderboardGraphEntry[] } |
200 goodLeaderboardGraph |
{ graph: LeaderboardGraphEntry[] } |
200 goodLeaderboardChallengesV2 |
{ challenges: Record<string, LeaderboardChallenge> } |
200 goodUserData 200 goodUserDataV2 |
Public user profile. Fields depend on API version. |
200 goodUserSelfData 200 goodUserSelfDataV2 |
Authenticated user’s own profile. Fields depend on API version. |
200 goodUserUpdate 200 goodUserUpdateV2 |
{ user: UserUpdateResult } |
200 goodAvatarUpdated |
{ url: string | null } |
200 goodMemberData |
Team member array. |
200 goodMemberCreate |
Team member object. |
200 goodMemberDelete |
No data. |
200 goodAdminChallenges 200 goodAdminChallengesV2 |
Admin challenge array. Fields depend on API version. |
200 goodAdminChallenge 200 goodAdminChallengeV2 |
Admin challenge object. Fields depend on API version. |
200 goodChallengeUpdate 200 goodChallengeUpdateV2 |
Updated admin challenge object. |
200 goodChallengeDelete |
No data. |
200 goodChallengeSolveDeleteV2 |
No data. |
200 goodFilesUpload 200 goodFilesUploadV2 |
Uploaded file array. Fields depend on API version. |
200 goodUploadsQuery 200 goodUploadsQueryV2 |
Upload query result array. Fields depend on API version. |
200 goodAdminUsersV2 |
{ total: number, users: AdminUserListItem[] } |
200 goodAdminUserV2 |
Admin user detail with solves. |
200 goodAdminUserUpdateV2 |
No data. |
200 goodAdminUserDeleteV2 |
No data. |
200 goodCreateUserTokenV2 |
{ token: string } |
200 goodAdminUserVerificationsV2 |
{ verifications: PendingUserVerification[] } |
200 goodAdminUserVerificationCompleteV2 |
{ userId: string } |
200 goodAdminUserVerificationResendV2 |
{ id: string } |
200 goodAdminSubmissions |
{ total: number, submissions: AdminSubmission[] } |
200 goodAdminSettings |
{ overrides: AdminSettings, defaults: AdminSettings } |
200 goodAdminSettingsUpdate |
{ overrides: AdminSettings, defaults: AdminSettings } |
200 goodClientConfig 200 goodClientConfigV2 |
Client config object. Fields depend on API version. |
200 goodCtftimeLeaderboard |
{ standings: { pos: number, team: string, score: number }[] } |
200 goodInstanceStatus |
{ status: InstanceStatus, timeLeftMilliseconds: number | null, endpoints: Endpoint[] | null } |
200 goodInstancerSchema |
{ schema: Record<string, unknown>, defaults: Record<string, unknown> } |
200 goodAdminBotConfig |
{ sourceCode: string, fileExtension: string } |
200 goodAdminBotStatus |
{ enabled: boolean, configLanguage: string } |
200 goodAdminBotJobSubmitted |
{ jobId: string } |
200 goodAdminBotJobStatus |
{ job: AdminBotJobStatusResponse | null } |
200 goodAdminBotJobHistory |
{ jobs: AdminBotJobHistoryItem[] } |
200 goodAdminBotJobLogs |
{ logs: string | null } |
200 goodAdminBotJobPull |
{ job: PulledAdminBotJob | null } |
200 goodAdminBotChallengeSource |
{ sourceCode: string, configRevision: string } |
200 goodAdminBotJobUpdate |
{ ok: boolean } |
200 goodAdminBotQueueDepth |
{ depth: number } |
200 goodDynamicScores |
{ inserted: number, updated: number, deleted: number } |
200 goodExternalAuthClient |
{ id: string, name: string, redirectUri: string } |
200 goodExternalAuthAuthorize |
{ redirectTo: string } |
200 goodExternalAuthToken |
{ accessToken: string, tokenType: "bearer" } |
200 goodAdminExternalAuthClients |
{ id, name, redirectUri, createdAt, createdBy }[] |
200 goodAdminExternalAuthClientCreate |
{ id, name, redirectUri, createdAt, createdBy, secret } (secret shown once) |
200 goodAdminExternalAuthClientDelete |
No data. |
Shared objects
ChallengeFileV2
| Field | Type |
|---|---|
name |
string |
url |
string |
size |
number | null |
Endpoint
| Field | Type |
|---|---|
kind |
"tcp" | "tcp-ssl" | "http" | "https" |
host |
string |
port |
number |
title |
string | undefined |
InstancerConfig
| Field | Type |
|---|---|
challengeIntegrationId |
string |
config |
Record<string, unknown> |
expose |
Expose[] |
timeoutMilliseconds |
number |
extendable |
boolean | undefined |
Expose
| Field | Type |
|---|---|
kind |
"tcp" | "tcp-ssl" | "http" | "https" |
hostPrefix |
string |
containerName |
string |
containerPort |
number |
shouldDisplay |
boolean | undefined |
title |
string | undefined |
AdminBotConfig
| Field | Type |
|---|---|
code |
string |
inputs |
Record<string, RegexRule> |
revision |
string |
timeoutMilliseconds |
number |
requireInstancerInstancesRunning |
boolean | undefined |
RegexRule
| Field | Type |
|---|---|
pattern |
string |
flags |
string | undefined |
Enum values
| Enum | Values |
|---|---|
InstanceStatus |
stopped, running, starting, stopping, errored |
AdminBotJobStatus |
queued, running, completed, failed |
AdminTeamSortBy |
createdAt, team, email, division, score, solves, status |
SortOrder |
asc, desc |
AdminTeamStatus |
active, banned, admin |
SubmissionKind |
flag, admin_bot |
SubmissionSortBy |
createdAt, challenge, team, ip, kind, result |
SubmissionResult |
correct, incorrect, already_solved, queued, active_job, invalid_input, bad_instancer_state |
SubmissionTeamStatus |
banned, not_banned |
ProtectedAction |
register, recover, setEmail, instancerStart, instancerExtend, avatarUpload, adminBotSubmit |