rCTF Docs

Admin

Challenge management, uploads, teams, verifications, submissions, settings, and admin bot service routes.

These admin API pages cover challenge data, uploads, teams, pending email verifications, submission audit rows, runtime settings, admin bot service work, and external-auth client registration. Most user facing admin routes need a user auth token with the listed permission bits. Admin bot service routes use the shared admin bot bearer token instead. The end-user side of the external-auth flow lives under External auth.

Permissions, captcha actions, and rate limit conventions are documented in the API overview.

Permissions#

PermissionUsed by
challsReadReading admin challenge data, upload state, instancer schemas, admin bot status, and admin user solve history.
challsWriteUpdating challenges and uploading files.
challsSolveWriteRemoving solves.
usersWriteListing and editing teams, creating team tokens, managing pending verifications, and reading submission audit rows.
settingsWriteReading and updating runtime settings.

When a route lists more than one permission bit, the token needs every listed bit.

GET Admin challenge list

GET /api/[v2,v1]/admin/challs

Auth
Required
Gate
None
Permissions
challsRead
Captcha
No captcha
Rate limit
No rate limit

This route shows every challenge with admin fields. Hidden and unreleased challenges are included so the admin panel can display the full challenge set.

For new clients, V2 is usually the best fit. It includes hidden state, release time, instancer config, admin bot config, and file sizes. V1 remains available for older admin tooling.

Response fields

idstring
Unique identifier.
namestring
Display name.
descriptionstring
Returned description value.
categorystring
Returned category value.
authorstring
Returned author value.
files[].namestring
Display name.
files[].urlstring
Resource URL.
files[].sizenumber | null
Size in bytes.
points.minnumber
Returned points min value.
points.maxnumber
Returned points max value.
flagstring
Returned flag value.
tiebreakEligibleboolean
Returned tiebreak eligible value.
sortWeightnumber | null | undefined
Returned sort weight value.
instancerConfigobject | null | undefined
Returned instancer config value.
adminBotConfigobject | null | undefined
Returned admin bot config value.
hiddenboolean
Returned hidden value.
releaseTimenumber | null | undefined
Returned release time value.
scoringobject | object | null | undefined
Returned scoring value.

Response fields

idstring
Unique identifier.
namestring
Display name.
descriptionstring
Returned description value.
categorystring
Returned category value.
authorstring
Returned author value.
files[].namestring
Display name.
files[].urlstring
Resource URL.
points.minnumber
Returned points min value.
points.maxnumber
Returned points max value.
flagstring
Returned flag value.
tiebreakEligibleboolean
Returned tiebreak eligible value.
sortWeightnumber | null | undefined
Returned sort weight value.

V1 challenge entries do not include hidden, releaseTime, instancerConfig, adminBotConfig, or file size.

GET Admin challenge detail

GET /api/[v2,v1]/admin/challs/:id

Auth
Required
Gate
None
Permissions
challsRead
Captcha
No captcha
Rate limit
No rate limit

This route reads one challenge with admin fields. The admin panel uses it when someone opens the challenge editor.

For new clients, V2 is usually the best fit. V1 returns the older admin challenge fields and remains available for existing integrations.

Path parameters

id requiredstring
Unique identifier.

Path parameters

id requiredstring
Unique identifier.

Response fields

idstring
Unique identifier.
namestring
Display name.
descriptionstring
Returned description value.
categorystring
Returned category value.
authorstring
Returned author value.
files[].namestring
Display name.
files[].urlstring
Resource URL.
files[].sizenumber | null
Size in bytes.
points.minnumber
Returned points min value.
points.maxnumber
Returned points max value.
flagstring
Returned flag value.
tiebreakEligibleboolean
Returned tiebreak eligible value.
sortWeightnumber | null | undefined
Returned sort weight value.
instancerConfigobject | null | undefined
Returned instancer config value.
adminBotConfigobject | null | undefined
Returned admin bot config value.
hiddenboolean
Returned hidden value.
releaseTimenumber | null | undefined
Returned release time value.
scoringobject | object | null | undefined
Returned scoring value.

Response fields

idstring
Unique identifier.
namestring
Display name.
descriptionstring
Returned description value.
categorystring
Returned category value.
authorstring
Returned author value.
files[].namestring
Display name.
files[].urlstring
Resource URL.
points.minnumber
Returned points min value.
points.maxnumber
Returned points max value.
flagstring
Returned flag value.
tiebreakEligibleboolean
Returned tiebreak eligible value.
sortWeightnumber | null | undefined
Returned sort weight value.

V1 challenge entries do not include hidden, releaseTime, instancerConfig, adminBotConfig, or file size.

PUT Create or update challenge

PUT /api/[v2,v1]/admin/challs/:id

Auth
Required
Gate
None
Permissions
challsWrite
Captcha
No captcha
Rate limit
No rate limit

This route creates a new challenge or updates an existing one. Fields left out of data keep their current values. Setting instancerConfig or adminBotConfig to null clears that integration config.

After a challenge changes, the leaderboard is recalculated. The active instancer provider validates instancerConfig, and the active admin bot provider validates adminBotConfig before saving a new revision.

Path parameters

id requiredstring
Unique identifier.

Request body

data requiredobject
Request body field for data.

Path parameters

id requiredstring
Unique identifier.

Request body

data requiredobject
Request body field for data.

Response fields

idstring
Unique identifier.
namestring
Display name.
descriptionstring
Returned description value.
categorystring
Returned category value.
authorstring
Returned author value.
files[].namestring
Display name.
files[].urlstring
Resource URL.
files[].sizenumber | null
Size in bytes.
points.minnumber
Returned points min value.
points.maxnumber
Returned points max value.
flagstring
Returned flag value.
tiebreakEligibleboolean
Returned tiebreak eligible value.
sortWeightnumber | null | undefined
Returned sort weight value.
instancerConfigobject | null | undefined
Returned instancer config value.
adminBotConfigobject | null | undefined
Returned admin bot config value.
hiddenboolean
Returned hidden value.
releaseTimenumber | null | undefined
Returned release time value.
scoringobject | object | null | undefined
Returned scoring value.

Response fields

idstring
Unique identifier.
namestring
Display name.
descriptionstring
Returned description value.
categorystring
Returned category value.
authorstring
Returned author value.
files[].namestring
Display name.
files[].urlstring
Resource URL.
points.minnumber
Returned points min value.
points.maxnumber
Returned points max value.
flagstring
Returned flag value.
tiebreakEligibleboolean
Returned tiebreak eligible value.
sortWeightnumber | null | undefined
Returned sort weight value.

V1 does not include hidden state, scheduled release time, instancer config, admin bot config, or file sizes.

DELETE Delete a solve

DELETE /api/v2/admin/challs/:challengeId/solves/:userId

Auth
Required
Gate
None
Permissions
challsSolveWrite
Captcha
No captcha
Rate limit
No rate limit

This route removes one solve for a specific team and challenge. The challenge and team remain in place, and the leaderboard is recalculated after the solve is removed.

Path parameters

challengeId requiredstring
Challenge identifier.
userId requiredstring
Team identifier.

Response#

A successful request returns 200 goodChallengeSolveDelete with no data.

DELETE Delete a challenge

DELETE /api/v1/admin/challs/:id

Auth
Required
Gate
None
Permissions
challsWrite
Captcha
No captcha
Rate limit
No rate limit

This legacy V1 route removes a challenge and its solves. There is no V2 delete route. V2 admin clients remove solves directly and update challenge data through create or update challenge.

The leaderboard is recalculated after the challenge is removed.

Path parameters

id requiredstring
Unique identifier.

Response#

A successful request returns 200 goodChallengeDelete with no data.

POST Upload files

POST /api/[v2,v1]/admin/upload

Auth
Required
Gate
None
Permissions
challsWrite
Captcha
No captcha
Rate limit
No rate limit

This route uploads challenge files. Files are deduplicated by SHA 256, so uploading the same bytes again returns the existing URL.

V2 sends multipart/form-data with one or more files fields. V1 accepts JSON with base64 data URIs and remains available for older admin clients.

Request body

files requiredtransform
Request body field for files.

Request body

files requiredobject[]
Request body field for files.

Response fields

namestring
Display name.
urlstring
Resource URL.
sizenumber | null
Size in bytes.

Response fields

namestring
Display name.
urlstring
Resource URL.

V1 upload responses do not include file size.

POST Query uploads

POST /api/[v2,v1]/admin/upload/query

Auth
Required
Gate
None
Permissions
challsRead
Captcha
No captcha
Rate limit
No rate limit

This route lets the admin panel check whether files already exist by SHA 256 before uploading them. A null URL means the file has not been uploaded yet.

For new clients, V2 is usually the best fit because it also returns nullable file size. V1 only returns the nullable URL.

Request body

uploads requiredobject[]
Request body field for uploads.

Request body

uploads requiredobject[]
Request body field for uploads.

Response fields

sha256string
Returned sha256 value.
namestring
Display name.
urlstring | null
Resource URL.
sizenumber | null
Size in bytes.

Response fields

sha256string
Returned sha256 value.
namestring
Display name.
urlstring | null
Resource URL.

GET List teams

GET /api/v2/admin/users

Auth
Required
Gate
None
Permissions
usersWrite
Captcha
No captcha
Rate limit
No rate limit

This route shows teams for the admin panel. Query parameters control pagination, sorting, and name or email search.

Filter teams is available when a UI also needs status or division filters.

Query parameters

limit requirednumber
Maximum number of records to return.
offset requirednumber
Number of records to skip before returning results.
searchstring
Search string.
sortBy"createdAt" | "team" | "email" | "division" | "score" | "solves" | "status"
Query parameter for sort by.
sortOrder"asc" | "desc"
Query parameter for sort order.

Response fields

totalnumber
Total number of matching records.
users[].idstring
Unique identifier.
users[].namestring
Display name.
users[].emailstring | null
Email address.
users[].divisionstring
Division name or filter.
users[].permsnumber
Returned users perms value.
users[].bannedboolean
Returned users banned value.
users[].scorenumber
Current score.
users[].solveCountnumber
Returned users solve count value.
users[].avatarUrlstring | null
Avatar image URL.
users[].countryCodestring | null
Country or region code.
users[].statusTextstring | null
Team status text.
users[].createdAtstring
Creation timestamp.

Each list item includes public profile fields, admin state, cached score data, and creation time.

POST Filter teams

POST /api/v2/admin/users

Auth
Required
Gate
None
Permissions
usersWrite
Captcha
No captcha
Rate limit
No rate limit

This route lists teams with richer filters than the GET route can carry comfortably. The query string still controls pagination, sorting, and text search.

Filter objects can include nullable include and exclude arrays. A field can be omitted when that filter does not apply.

Query parameters

limit requirednumber
Maximum number of records to return.
offset requirednumber
Number of records to skip before returning results.
searchstring
Search string.
sortBy"createdAt" | "team" | "email" | "division" | "score" | "solves" | "status"
Query parameter for sort by.
sortOrder"asc" | "desc"
Query parameter for sort order.

Request body

statusobject
Request body field for status.
divisionobject
Division name or filter.

Response fields

totalnumber
Total number of matching records.
users[].idstring
Unique identifier.
users[].namestring
Display name.
users[].emailstring | null
Email address.
users[].divisionstring
Division name or filter.
users[].permsnumber
Returned users perms value.
users[].bannedboolean
Returned users banned value.
users[].scorenumber
Current score.
users[].solveCountnumber
Returned users solve count value.
users[].avatarUrlstring | null
Avatar image URL.
users[].countryCodestring | null
Country or region code.
users[].statusTextstring | null
Team status text.
users[].createdAtstring
Creation timestamp.

GET Team detail

GET /api/v2/admin/users/:id

Auth
Required
Gate
None
Permissions
challsRead, usersWrite
Captcha
No captcha
Rate limit
No rate limit

This route shows full team details for the admin panel, including solve history. The token needs both usersWrite and challsRead because the response includes challenge solve data.

Path parameters

id requiredstring
Unique identifier.

Response fields

idstring
Unique identifier.
namestring
Display name.
emailstring | null
Email address.
divisionstring
Division name or filter.
permsnumber
Returned perms value.
bannedboolean
Returned banned value.
scorenumber
Current score.
solveCountnumber
Returned solve count value.
avatarUrlstring | null
Avatar image URL.
countryCodestring | null
Country or region code.
statusTextstring | null
Team status text.
createdAtstring
Creation timestamp.
solves[].challengeIdstring
Challenge identifier.
solves[].challengeNamestring
Returned solves challenge name value.
solves[].challengeCategorystring
Returned solves challenge category value.
solves[].createdAtstring
Creation timestamp.

Private account fields appear here, so this route belongs in trusted admin views.

PUT Update team

PUT /api/v2/admin/users/:id

Auth
Required
Gate
None
Permissions
usersWrite
Captcha
No captcha
Rate limit
No rate limit

This route changes admin controlled team state. The current route supports banning and unbanning teams.

Banning removes the team from leaderboard output after recalculation without deleting solves. Unbanning restores its rank after the leaderboard is recalculated. Admin users are protected from changes through this route.

Path parameters

id requiredstring
Unique identifier.

Request body

data requiredobject
Request body field for data.

Response#

A successful request returns 200 goodAdminUserUpdate with no data.

DELETE Delete team

DELETE /api/v2/admin/users/:id

Auth
Required
Gate
None
Permissions
usersWrite
Captcha
No captcha
Rate limit
No rate limit

This route deletes a team account. Admin users are protected from deletion here.

This operation removes the team rather than hiding it from standings. Update team is the better fit when the intent is to ban a team while keeping its record.

Path parameters

id requiredstring
Unique identifier.

Response#

A successful request returns 200 goodAdminUserDelete with no data.

POST Create team token

POST /api/v2/admin/users/:id/token

Auth
Required
Gate
None
Permissions
usersWrite
Captcha
No captcha
Rate limit
No rate limit

This route creates a fresh team token. It helps organizers recover access for a team that has lost its original credential.

The returned token is a credential. This route does not issue tokens for admin users.

Path parameters

id requiredstring
Unique identifier.

Response fields

tokenstring
Returned token value.

GET Pending verifications

GET /api/v2/admin/user-verifications

Auth
Required
Gate
None
Permissions
usersWrite
Captcha
No captcha
Rate limit
No rate limit

This route shows teams that registered with email verification but have not completed the verification step yet.

Pending verification rows include the team name, email, division, creation time, and expiration time. Admins can complete or resend these rows through the related endpoints.

Response fields

verifications[].idstring
Unique identifier.
verifications[].namestring
Display name.
verifications[].emailstring
Email address.
verifications[].divisionstring
Division name or filter.
verifications[].createdAtnumber
Creation timestamp.
verifications[].expiresAtnumber
Expiration timestamp.

POST Complete verification

POST /api/v2/admin/user-verifications/:id/complete

Auth
Required
Gate
None
Permissions
usersWrite
Captcha
No captcha
Rate limit
No rate limit

This route lets an organizer complete a pending email verification manually and create the team. It is useful when the registration has already been verified outside the normal email flow.

Duplicate email and duplicate name checks still apply.

Path parameters

id requiredstring
Unique identifier.

Response fields

userIdstring
Team identifier.

POST Resend verification

POST /api/v2/admin/user-verifications/:id/resend

Auth
Required
Gate
None
Permissions
usersWrite
Captcha
No captcha
Rate limit
No rate limit

This route sends another verification email for an outstanding pending verification row.

If email delivery is not configured, the route returns 404 badEndpoint because there is no provider available to send the message.

Path parameters

id requiredstring
Unique identifier.

Response fields

idstring
Unique identifier.

GET List submissions

GET /api/v2/admin/submissions

Auth
Required
Gate
None
Permissions
challsRead, usersWrite
Captcha
No captcha
Rate limit
No rate limit

This route shows submission audit rows. The table records flag submissions and admin bot job submissions for review and abuse investigation.

Query parameters control pagination, sorting, and lightweight challenge or team search. Filter submissions adds category, division, kind, result, team status, and time filters.

Query parameters

limit requirednumber
Maximum number of records to return.
offset requirednumber
Number of records to skip before returning results.
sortBy"createdAt" | "challenge" | "team" | "ip" | "kind" | "result"
Query parameter for sort by.
sortOrder"asc" | "desc"
Query parameter for sort order.
challengeSearchstring
Query parameter for challenge search.
teamSearchstring
Query parameter for team search.

Response fields

totalnumber
Total number of matching records.
submissions[].idstring
Unique identifier.
submissions[].kind"flag" | "admin_bot"
Response or object kind.
submissions[].challengeIdstring
Challenge identifier.
submissions[].challengeNamestring
Returned submissions challenge name value.
submissions[].challengeCategorystring
Returned submissions challenge category value.
submissions[].userIdstring
Team identifier.
submissions[].userNamestring
Returned submissions user name value.
submissions[].userDivisionstring
Returned submissions user division value.
submissions[].userAvatarUrlstring | null
Returned submissions user avatar url value.
submissions[].userCountryCodestring | null
Returned submissions user country code value.
submissions[].userStatusTextstring | null
Returned submissions user status text value.
submissions[].userBannedboolean
Returned submissions user banned value.
submissions[].ipstring
Returned submissions ip value.
submissions[].result"correct" | "incorrect" | "already_solved" | "queued" | "active_job" | "invalid_input" | "bad_instancer_state"
Returned submissions result value.
submissions[].detailsRecord<string, any>
Returned submissions details value.
submissions[].relatedIdstring | null
Returned submissions related id value.
submissions[].createdAtstring
Creation timestamp.

Each row includes challenge metadata, team metadata, the source IP address, result details, and creation time.

POST Filter submissions

POST /api/v2/admin/submissions

Auth
Required
Gate
None
Permissions
challsRead, usersWrite
Captcha
No captcha
Rate limit
No rate limit

This route lists submission audit rows with richer filters. The query string still controls pagination, sorting, and lightweight text search.

Filter objects can include nullable include and exclude arrays. Date filters are parsed as ISO timestamps, and createdAfter needs to be earlier than createdBefore when both are provided.

Query parameters

limit requirednumber
Maximum number of records to return.
offset requirednumber
Number of records to skip before returning results.
sortBy"createdAt" | "challenge" | "team" | "ip" | "kind" | "result"
Query parameter for sort by.
sortOrder"asc" | "desc"
Query parameter for sort order.
challengeSearchstring
Query parameter for challenge search.
teamSearchstring
Query parameter for team search.

Request body

challengeobject
Request body field for challenge.
teamobject
Request body field for team.
kindobject
Response or object kind.
resultobject
Request body field for result.
teamStatusobject
Request body field for team status.
categoryobject
Request body field for category.
divisionobject
Division name or filter.
createdAfterstring
Request body field for created after.
createdBeforestring
Request body field for created before.

Response fields

totalnumber
Total number of matching records.
submissions[].idstring
Unique identifier.
submissions[].kind"flag" | "admin_bot"
Response or object kind.
submissions[].challengeIdstring
Challenge identifier.
submissions[].challengeNamestring
Returned submissions challenge name value.
submissions[].challengeCategorystring
Returned submissions challenge category value.
submissions[].userIdstring
Team identifier.
submissions[].userNamestring
Returned submissions user name value.
submissions[].userDivisionstring
Returned submissions user division value.
submissions[].userAvatarUrlstring | null
Returned submissions user avatar url value.
submissions[].userCountryCodestring | null
Returned submissions user country code value.
submissions[].userStatusTextstring | null
Returned submissions user status text value.
submissions[].userBannedboolean
Returned submissions user banned value.
submissions[].ipstring
Returned submissions ip value.
submissions[].result"correct" | "incorrect" | "already_solved" | "queued" | "active_job" | "invalid_input" | "bad_instancer_state"
Returned submissions result value.
submissions[].detailsRecord<string, any>
Returned submissions details value.
submissions[].relatedIdstring | null
Returned submissions related id value.
submissions[].createdAtstring
Creation timestamp.

GET Read settings

GET /api/v2/admin/settings

Auth
Required
Gate
None
Permissions
settingsWrite
Captcha
No captcha
Rate limit
No rate limit

This route shows runtime setting overrides and config defaults side by side. Runtime overrides come from the database. Defaults come from config files and environment variables.

Update settings can change or clear runtime overrides without restarting the server.

Response fields

overrides.ctfNamestring | undefined
Returned overrides ctf name value.
overrides.homeContentstring | undefined
Returned overrides home content value.
overrides.startTimenumber | undefined
Returned overrides start time value.
overrides.endTimenumber | undefined
Returned overrides end time value.
overrides.sponsors[].namestring
Display name.
overrides.sponsors[].iconstring
Returned overrides sponsors icon value.
overrides.sponsors[].descriptionstring
Returned overrides sponsors description value.
overrides.sponsors[].urlstring | undefined
Resource URL.
overrides.meta.descriptionstring | undefined
Returned overrides meta description value.
overrides.meta.imageUrlstring | undefined
Returned overrides meta image url value.
overrides.faviconUrlstring | undefined
Returned overrides favicon url value.
overrides.logoLightUrlstring | undefined
Returned overrides logo light url value.
overrides.logoDarkUrlstring | undefined
Returned overrides logo dark url value.
defaults.ctfNamestring | undefined
Returned defaults ctf name value.
defaults.homeContentstring | undefined
Returned defaults home content value.
defaults.startTimenumber | undefined
Returned defaults start time value.
defaults.endTimenumber | undefined
Returned defaults end time value.
defaults.sponsors[].namestring
Display name.
defaults.sponsors[].iconstring
Returned defaults sponsors icon value.
defaults.sponsors[].descriptionstring
Returned defaults sponsors description value.
defaults.sponsors[].urlstring | undefined
Resource URL.
defaults.meta.descriptionstring | undefined
Returned defaults meta description value.
defaults.meta.imageUrlstring | undefined
Returned defaults meta image url value.
defaults.faviconUrlstring | undefined
Returned defaults favicon url value.
defaults.logoLightUrlstring | undefined
Returned defaults logo light url value.
defaults.logoDarkUrlstring | undefined
Returned defaults logo dark url value.

PUT Update settings

PUT /api/v2/admin/settings

Auth
Required
Gate
None
Permissions
settingsWrite
Captcha
No captcha
Rate limit
No rate limit

This route updates runtime setting overrides. A nullable field set to null clears that override and lets the configured default take effect again.

Changing startTime or endTime also queues a leaderboard recalculation so standings match the updated event window.

Request body

data requiredobject
Request body field for data.

Response fields

overrides.ctfNamestring | undefined
Returned overrides ctf name value.
overrides.homeContentstring | undefined
Returned overrides home content value.
overrides.startTimenumber | undefined
Returned overrides start time value.
overrides.endTimenumber | undefined
Returned overrides end time value.
overrides.sponsors[].namestring
Display name.
overrides.sponsors[].iconstring
Returned overrides sponsors icon value.
overrides.sponsors[].descriptionstring
Returned overrides sponsors description value.
overrides.sponsors[].urlstring | undefined
Resource URL.
overrides.meta.descriptionstring | undefined
Returned overrides meta description value.
overrides.meta.imageUrlstring | undefined
Returned overrides meta image url value.
overrides.faviconUrlstring | undefined
Returned overrides favicon url value.
overrides.logoLightUrlstring | undefined
Returned overrides logo light url value.
overrides.logoDarkUrlstring | undefined
Returned overrides logo dark url value.
defaults.ctfNamestring | undefined
Returned defaults ctf name value.
defaults.homeContentstring | undefined
Returned defaults home content value.
defaults.startTimenumber | undefined
Returned defaults start time value.
defaults.endTimenumber | undefined
Returned defaults end time value.
defaults.sponsors[].namestring
Display name.
defaults.sponsors[].iconstring
Returned defaults sponsors icon value.
defaults.sponsors[].descriptionstring
Returned defaults sponsors description value.
defaults.sponsors[].urlstring | undefined
Resource URL.
defaults.meta.descriptionstring | undefined
Returned defaults meta description value.
defaults.meta.imageUrlstring | undefined
Returned defaults meta image url value.
defaults.faviconUrlstring | undefined
Returned defaults favicon url value.
defaults.logoLightUrlstring | undefined
Returned defaults logo light url value.
defaults.logoDarkUrlstring | undefined
Returned defaults logo dark url value.

GET Instancer schema

GET /api/v2/admin/instancer/schema

Auth
Required
Gate
None
Permissions
challsRead
Captcha
No captcha
Rate limit
No rate limit

This route provides the active instancer provider JSON schema and defaults. The challenge editor uses this response to validate instancerConfig before saving a challenge.

When no instancer provider is configured, the route returns 404 badEndpoint.

Response fields

schemaRecord<string, unknown>
Returned schema value.
defaultsRecord<string, unknown>
Returned defaults value.

GET Admin bot status

GET /api/v2/admin/admin-bot/status

Auth
Required
Gate
None
Permissions
challsRead
Captcha
No captcha
Rate limit
No rate limit

This route shows whether the admin bot provider is enabled and which source language the configured provider expects.

When no admin bot provider is configured, the route returns 404 badEndpoint.

Response fields

enabledboolean
Returned enabled value.
configLanguagestring
Returned config language value.

POST Pull admin bot job

POST /api/v2/admin/admin-bot/jobs/pull

Auth
Service
Gate
None
Permissions
No extra permissions
Captcha
No captcha
Rate limit
No rate limit

The admin bot worker calls this service route when it is ready for more work. It receives the oldest queued job. When nothing is waiting, the response has job set to null.

The request is authenticated with the shared admin bot bearer token from adminBot.provider.options.secretKey in rctf.d/.

Response fields

job.idstring
Unique identifier.
job.challengeIdstring
Challenge identifier.
job.configRevisionstring
Returned job config revision value.
job.userIdstring
Team identifier.
job.submittedAtstring
Returned job submitted at value.
job.flagstring
Returned job flag value.
job.inputsRecord<string, string>
Returned job inputs value.
job.instancerInstances[].typestring
Object type.
job.instancerInstances[].hoststring
Returned job instancer instances host value.
job.instancerInstances[].portnumber
Returned job instancer instances port value.
job.instancerInstances[].titlestring | undefined
Returned job instancer instances title value.

GET Admin bot source

GET /api/v2/admin/admin-bot/challenges/:id/source

Auth
Service
Gate
None
Permissions
No extra permissions
Captcha
No captcha
Rate limit
No rate limit

The admin bot worker calls this service route to read the source code saved for a challenge config revision.

The request is authenticated with the shared admin bot bearer token from adminBot.provider.options.secretKey in rctf.d/.

Path parameters

id requiredstring
Unique identifier.

Response fields

sourceCodestring
Returned source code value.
configRevisionstring
Returned config revision value.

POST Complete admin bot job

POST /api/v2/admin/admin-bot/jobs/:id/complete

Auth
Service
Gate
None
Permissions
No extra permissions
Captcha
No captcha
Rate limit
No rate limit

The admin bot worker calls this service route after a job finishes successfully. The request can include logs so organizers can review what happened later.

Logs are optional. When included, the server accepts up to 1048576 characters.

Path parameters

id requiredstring
Unique identifier.

Request body

logsstring
Request body field for logs.

Response fields

okboolean
Returned ok value.

POST Fail admin bot job

POST /api/v2/admin/admin-bot/jobs/:id/fail

Auth
Service
Gate
None
Permissions
No extra permissions
Captcha
No captcha
Rate limit
No rate limit

The admin bot worker calls this service route when a job cannot complete successfully. The request can include logs so organizers can inspect the failure.

Logs are optional. When included, the server accepts up to 1048576 characters.

Path parameters

id requiredstring
Unique identifier.

Request body

logsstring
Request body field for logs.

Response fields

okboolean
Returned ok value.

GET Admin bot queue depth

GET /api/v2/admin/admin-bot/queue-depth

Auth
Service
Gate
None
Permissions
No extra permissions
Captcha
No captcha
Rate limit
No rate limit

The admin bot worker can call this service route to check how many jobs are waiting in the queue.

The request is authenticated with the shared admin bot bearer token from adminBot.provider.options.secretKey in rctf.d/.

Response fields

depthnumber
Returned depth value.

GET List external-auth clients

GET /api/v2/admin/external-auth/clients

Auth
Required
Gate
None
Permissions
usersWrite
Captcha
No captcha
Rate limit
No rate limit

Returns every registered external-auth client. Client secrets are never returned by this route - they are shown exactly once at creation time by Create external-auth client and cannot be retrieved afterward.

The end-user side of the external-auth flow lives at External auth, and the operator walkthrough lives at External apps.

Response fields

idstring
Unique identifier.
namestring
Display name.
redirectUristring
Returned redirect uri value.
createdAtstring
Creation timestamp.
createdBystring | null
Returned created by value.

POST Create external-auth client

POST /api/v2/admin/external-auth/clients

Auth
Required
Gate
None
Permissions
usersWrite
Captcha
No captcha
Rate limit
No rate limit

Registers a new external-auth client. rCTF generates a UUID id and a 32-byte base64url secret. The redirect URI is stored exactly as supplied and is matched byte-for-byte at authorize time - no wildcards, no path normalization.

Warning (The secret is shown exactly once)

The response is the only place where the client secret is ever returned. Store it immediately somewhere the integrator can retrieve it. If it gets lost the client must be deleted and re-created.

Request body

name requiredstring
Display name.
redirectUri requiredstring
Request body field for redirect uri.

Response fields

idstring
Unique identifier.
namestring
Display name.
redirectUristring
Returned redirect uri value.
createdAtstring
Creation timestamp.
createdBystring | null
Returned created by value.
secretstring
Returned secret value.

DELETE Delete external-auth client

DELETE /api/v2/admin/external-auth/clients/:id

Auth
Required
Gate
None
Permissions
usersWrite
Captcha
No captcha
Rate limit
No rate limit

Removes an external-auth client. After this returns, POST /api/v2/external-auth/token exchanges with that clientId always fail with 400 badExternalAuthRequest.

Access tokens that were already minted through this client stay valid. There is no per-app token registry, so per-client revocation is not possible. If you need to invalidate outstanding tokens, rotate the global tokenKey (this invalidates every token in the system).

Unknown client IDs return 400 badExternalAuthRequest.

Path parameters

id requiredstring
Unique identifier.

Response#

A successful request returns 200 goodAdminExternalAuthClientDelete with no data.

Esc

Start typing to search the docs.