Integrations

Client config, analytics, CTFtime, instancer, and admin bot participant routes.

Edit this page View Markdown

Integration routes help the web app and external services coordinate with rCTF. They cover public runtime config, analytics script delivery, CTFtime handoff, per team challenge instances, and participant admin bot jobs.

The admin bot worker service routes use a separate service token and are documented in Admin.

Version choice

Client config is available in both V1 and V2. Newer clients usually want V2 because it includes the current analytics, captcha, logo, archive, and instancer fields. The remaining integration routes are version specific.

Timeline behavior

Instance and participant admin bot routes open after the CTF starts. Admins with challsRead can read through that start gate when they need to review challenges before the event begins.

GET Client config

GET /api/[v2,v1]/integrations/client/config

Edit this page View Markdown
Auth
Public
Gate
None
Permissions
No extra permissions
Captcha
No captcha
Rate limit
No rate limit

This route provides the public runtime settings used by the web app. It includes display settings, event timing, registration state, division names, and public provider settings.

V2 includes the current captcha and analytics fields, logo URLs, archive state, and instancer availability. V1 remains available for older clients and includes the older globalSiteTag and recaptcha fields.

Response fields

meta.descriptionstring
Meta description used for link previews.
meta.imageUrlstring
Preview image URL.
homeContentstring
Markdown content shown on the home page.
sponsors[].namestring
Sponsor name.
sponsors[].iconstring | undefined
Deprecated. Mirrors iconLight (or iconDark when only it is set) for old clients.
sponsors[].iconLightstring | undefined
Sponsor icon URL for light mode; may be absent on data from older versions.
sponsors[].iconDarkstring | undefined
Sponsor icon URL for dark mode; may be absent on data from older versions.
sponsors[].descriptionstring
Sponsor description.
sponsors[].urlstring | undefined
Sponsor link, when present.
flagFormatPlaceholderstring
Placeholder shown in the flag submission box.
analytics.providerstring
Analytics provider name.
analytics.publicOptionsRecord<string, string>
Public, client-safe analytics options.
ctfNamestring
Name of the CTF.
divisionsRecord<string, string>
Division keys mapped to display names.
defaultDivisionstring | null | undefined
Division selected by default, or null when unset.
originstring
Canonical origin of the deployment.
startTimenumber
CTF start time as a Unix timestamp in milliseconds.
endTimenumber
CTF end time as a Unix timestamp in milliseconds.
userMembersboolean
Whether teams may add individual members.
faviconUrlstring | null
Favicon URL, or null when unset.
logoLightUrlstring | null
Light-theme logo URL, or null when unset.
logoDarkUrlstring | null
Dark-theme logo URL, or null when unset.
emailEnabledboolean
Whether email-based auth is enabled.
registrationsEnabledboolean | null
Whether registrations are open, or null when unset.
ctftime.clientIdstring
CTFtime OAuth client ID.
instancerEnabledboolean
Whether the challenge instancer is enabled.
isArchivedboolean
Whether the CTF is archived (read-only).
captcha.providerstring
Captcha provider name.
captcha.publicOptionsRecord<string, string>
Public, client-safe captcha options.
captcha.protectedEndpointsRecord<"register" | "recover" | "setEmail" | "instancerStart" | "instancerExtend" | "avatarUpload" | "adminBotSubmit", boolean>
Which actions require a captcha.

GET Analytics script

GET /api/v2/integrations/analytics/script

Edit this page View Markdown
Auth
Public
Gate
None
Permissions
No extra permissions
Captcha
No captcha
Rate limit
No rate limit

This route proxies the active analytics provider script when analytics are configured. It is intentionally not part of @rctf/types, because it returns JavaScript rather than an rCTF response body.

Response

The response body is the provider JavaScript. The API keeps the fetched script in memory for one hour.

When analytics are not configured, the route responds with 404. Upstream fetch failures respond with 502.

GET Instance status

GET /api/v2/integrations/challs/:id/instance

Edit this page View Markdown
Auth
Required
Gate
Started (bypass challsRead)
Permissions
No extra permissions
Captcha
No captcha
Rate limit
No rate limit

This route gives the authenticated team’s current instance state for a challenge. It is used to show whether the instance is stopped, starting, running, stopping, or in an error state.

When no instancer provider is configured, or when the challenge has no instancer settings, the route returns 404 badEndpoint. Provider errors return 400 badInstancerError with a provider message.

Path parameters

id*string
Challenge ID.

Response fields

status"stopped" | "running" | "starting" | "stopping" | "errored"
Current lifecycle state of the instance.
timeLeftMillisecondsnumber | null
Milliseconds until expiry, or null when not running.
endpoints[].kind"tcp" | "tcp-ssl" | "http" | "https" | "raw"
Exposure protocol.
endpoints[].hoststring
Reachable host name.
endpoints[].portnumber
Reachable port.
endpoints[].titlestring | undefined
Short label for the endpoint, when present.
endpoints[].textstring | undefined
Connection hint shown to players, when present.

endpoints are returned in the order configured for the challenge. Endpoint kinds include tcp, tcp-ssl, http, and https.

PUT Start an instance

PUT /api/v2/integrations/challs/:id/instance

Edit this page View Markdown
Auth
Required
Gate
Started (bypass challsRead)
Permissions
No extra permissions
Captcha
instancerStart
Rate limit
No rate limit

This route asks the instancer provider to start an instance for the authenticated team. If the provider needs time to finish provisioning, the response can report starting before a later status request reports running.

Captcha is checked only when the deployment protects instancerStart.

Path parameters

id*string
Challenge ID.

Request body

captchaCodestring
Checked only when captcha protects this route.

Response fields

status"stopped" | "running" | "starting" | "stopping" | "errored"
Current lifecycle state of the instance.
timeLeftMillisecondsnumber | null
Milliseconds until expiry, or null when not running.
endpoints[].kind"tcp" | "tcp-ssl" | "http" | "https" | "raw"
Exposure protocol.
endpoints[].hoststring
Reachable host name.
endpoints[].portnumber
Reachable port.
endpoints[].titlestring | undefined
Short label for the endpoint, when present.
endpoints[].textstring | undefined
Connection hint shown to players, when present.

PATCH Extend an instance

PATCH /api/v2/integrations/challs/:id/instance

Edit this page View Markdown
Auth
Required
Gate
Started (bypass challsRead)
Permissions
No extra permissions
Captcha
instancerExtend
Rate limit
No rate limit

This route asks the instancer provider to extend the authenticated team’s running instance. The returned status includes the updated remaining time when the provider reports one.

Captcha is checked only when the deployment protects instancerExtend.

Path parameters

id*string
Challenge ID.

Request body

captchaCodestring
Checked only when captcha protects this route.

Response fields

status"stopped" | "running" | "starting" | "stopping" | "errored"
Current lifecycle state of the instance.
timeLeftMillisecondsnumber | null
Milliseconds until expiry, or null when not running.
endpoints[].kind"tcp" | "tcp-ssl" | "http" | "https" | "raw"
Exposure protocol.
endpoints[].hoststring
Reachable host name.
endpoints[].portnumber
Reachable port.
endpoints[].titlestring | undefined
Short label for the endpoint, when present.
endpoints[].textstring | undefined
Connection hint shown to players, when present.

DELETE Stop an instance

DELETE /api/v2/integrations/challs/:id/instance

Edit this page View Markdown
Auth
Required
Gate
Started (bypass challsRead)
Permissions
No extra permissions
Captcha
No captcha
Rate limit
No rate limit

This route asks the instancer provider to stop the authenticated team’s instance. The response reports the latest state returned by the provider.

Path parameters

id*string
Challenge ID.

Response fields

status"stopped" | "running" | "starting" | "stopping" | "errored"
Current lifecycle state of the instance.
timeLeftMillisecondsnumber | null
Milliseconds until expiry, or null when not running.
endpoints[].kind"tcp" | "tcp-ssl" | "http" | "https" | "raw"
Exposure protocol.
endpoints[].hoststring
Reachable host name.
endpoints[].portnumber
Reachable port.
endpoints[].titlestring | undefined
Short label for the endpoint, when present.
endpoints[].textstring | undefined
Connection hint shown to players, when present.

GET Admin bot config

GET /api/v2/integrations/challs/:id/admin-bot/config

Edit this page View Markdown
Auth
Public
Gate
Started (bypass challsRead)
Permissions
No extra permissions
Captcha
No captcha
Rate limit
No rate limit

This route gives participants the released admin bot challenge source and the file extension for that source. Challenge authors can use this to show the exact code participants will write against.

Path parameters

id*string
Challenge ID.

Response fields

sourceCodestring
Admin-bot script source code.
fileExtensionstring
File extension for the script language.

POST Submit admin bot job

POST /api/v2/integrations/challs/:id/admin-bot

Edit this page View Markdown
Auth
Required
Gate
Started (bypass challsRead)
Permissions
No extra permissions
Captcha
adminBotSubmit
Rate limit
Burst 1, refill window 10000 ms per user and challenge.

This route submits an admin bot job for the authenticated team. Participants send values for the input names configured on the challenge.

Only one queued or running job is allowed per user and challenge. When the challenge depends on a running instance, the route returns 400 badInstancerState if the instance is missing, stopped, or expires before the admin bot timeout.

Path parameters

id*string
Challenge ID.

Request body

inputs*record
Admin-bot input values keyed by the config field name.
captchaCodestring
Checked only when captcha protects this route.

Response fields

jobIdstring
ID of the newly submitted job.

GET Admin bot job status

GET /api/v2/integrations/challs/:id/admin-bot/status

Edit this page View Markdown
Auth
Required
Gate
Started (bypass challsRead)
Permissions
No extra permissions
Captcha
No captcha
Rate limit
No rate limit

This route gives the authenticated team’s active admin bot job for a challenge. The job field is null when there is no queued or running job.

Path parameters

id*string
Challenge ID.

Response fields

job.idstring
Admin-bot job ID.
job.status"queued" | "running" | "completed" | "failed"
Current job status.
job.createdAtstring
Job creation time as an ISO 8601 string.
job.queuePositionnumber | null
Position in the queue, or null when not queued.
job.logsstring | null
Captured job logs, or null when none.

GET Admin bot job history

GET /api/v2/integrations/challs/:id/admin-bot/history

Edit this page View Markdown
Auth
Required
Gate
Started (bypass challsRead)
Permissions
No extra permissions
Captcha
No captcha
Rate limit
No rate limit

This route gives the retained completed and failed admin bot jobs for the authenticated team on a challenge. It is useful for showing recent submissions without including the full log body in the list.

Path parameters

id*string
Challenge ID.

Response fields

jobs[].idstring
Admin-bot job ID.
jobs[].status"queued" | "running" | "completed" | "failed"
Current job status.
jobs[].createdAtstring
Job creation time as an ISO 8601 string.
jobs[].hasLogsboolean
Whether logs are available for the job.

GET Admin bot job logs

GET /api/v2/integrations/challs/:id/admin-bot/jobs/:jobId/logs

Edit this page View Markdown
Auth
Required
Gate
Started (bypass challsRead)
Permissions
No extra permissions
Captcha
No captcha
Rate limit
No rate limit

This route gives the retained logs for a completed or failed admin bot job. The logs field is null when logs are not available.

Path parameters

id*string
Challenge ID.
jobId*string
Admin-bot job ID.

Response fields

logsstring | null
Captured job logs, or null when none.

POST CTFtime callback

POST /api/v1/integrations/ctftime/callback

Edit this page View Markdown
Auth
Public
Gate
None
Permissions
No extra permissions
Captcha
No captcha
Rate limit
No rate limit

This V1 route exchanges a CTFtime OAuth code for a short lived CTFtime auth token. That token can then be used with registration, verification, login, or account linking flows.

Request body

ctftimeCode*string
CTFtime OAuth authorization code.

Response fields

ctftimeTokenstring
Opaque token linking the rCTF account to CTFtime.
ctftimeNamestring
CTFtime team name.
ctftimeIdstring
CTFtime team ID.

GET CTFtime leaderboard

GET /api/v1/integrations/ctftime/leaderboard

Edit this page View Markdown
Auth
Required
Gate
None
Permissions
leaderboardRead
Captcha
No captcha
Rate limit
No rate limit

This V1 route provides the leaderboard export expected by CTFtime. It is the rare typed route that returns the body directly instead of using the rCTF response wrapper.

Response

The response body is the raw CTFtime leaderboard.

{
"standings": [
{
"pos": 1,
"team": "otter-sec",
"score": 1200
}
]
}
Field Type Notes
standings { pos: number, team: string, score: number }[] Ordered standings rows.

Type to search.