Users
API reference for public profiles, self profiles, profile updates, avatars, email auth, CTFtime auth, and team members.
User routes cover public team profiles and authenticated account settings. V2 includes avatar, country, and status fields. V1 is still used for team members and CTFtime account links.
Public profile routes are available after the CTF starts. Admin tokens with challsRead can read public profiles before that gate opens because profile responses include solve data.
When both V1 and V2 exist for the same action, V2 is usually the best fit for new clients. The V1 account management routes remain useful where there is no V2 route.
Profile data#
Public profiles include the team name, division, score, rank fields, CTFtime ID when linked, and visible solves. V2 also includes avatar URL, country or region code, status text, and bloodIndex on solve rows.
The own profile routes include private account fields as well, such as the team ID, email address, team token, allowed divisions, and admin permission bitmask when present.
Account updates#
Profile updates can change the team name and division. V2 can also update country or region code and status text. Name updates use a per user rate limit bucket.
Email auth may involve a verification email, depending on provider configuration. CTFtime auth and team member management are available through V1 routes.
GET Public profile
GET /api/[v2,v1]/users/:id
- Auth
- Public
- Gate
- Started (bypass challsRead)
- Permissions
- No extra permissions
- Captcha
- No captcha
- Rate limit
- No rate limit
This route returns the public profile for one team. Public profiles are available after the CTF starts, and admin tokens with challsRead can read through that gate.
For new clients, V2 is usually the best fit. It includes avatar URL, country or region code, status text, and bloodIndex on solve rows. V1 remains available for older clients.
Path parameters
id requiredstringResponse fields
namestringctftimeIdstring | null | undefineddivisionstringscorenumberglobalPlacenumber | nulldivisionPlacenumber | nullsolves[].categorystringsolves[].namestringsolves[].pointsnumber | nullsolves[].awardedPointsnumber | nullsolves[].solvesnumber | nullsolves[].idstringsolves[].createdAtnumbersolves[].bloodIndexnumber | nulldynamicScores[].idstringdynamicScores[].pointsnumberdynamicScores[].pointDeltanumberavatarUrlstring | nullcountryCodestring | nullstatusTextstring | nullResponse fields
namestringctftimeIdstring | null | undefineddivisionstringscorenumberglobalPlacenumber | nulldivisionPlacenumber | nullsolves[].categorystringsolves[].namestringsolves[].pointsnumber | nullsolves[].awardedPointsnumber | nullsolves[].solvesnumber | nullsolves[].idstringsolves[].createdAtnumberdynamicScores[].idstringdynamicScores[].pointsnumberdynamicScores[].pointDeltanumberGET Own profile
GET /api/[v2,v1]/users/me
- Auth
- Required
- Gate
- None
- Permissions
- No extra permissions
- Captcha
- No captcha
- Rate limit
- No rate limit
This route returns the authenticated team’s profile, including private account fields. It is useful for account settings, profile screens, and client side session state.
V2 includes the same public profile additions as public profile. V1 returns the older profile fields and remains available for clients that already use it.
Response fields
idstringnamestringemailstring | nullctftimeIdstring | null | undefineddivisionstringscorenumberglobalPlacenumber | nulldivisionPlacenumber | nullsolves[].categorystringsolves[].namestringsolves[].pointsnumber | nullsolves[].awardedPointsnumber | nullsolves[].solvesnumber | nullsolves[].idstringsolves[].createdAtnumbersolves[].bloodIndexnumber | nulldynamicScores[].idstringdynamicScores[].pointsnumberdynamicScores[].pointDeltanumberteamTokenstringallowedDivisionsstring[]permsnumber | nullavatarUrlstring | nullcountryCodestring | nullstatusTextstring | nullResponse fields
idstringnamestringemailstring | nullctftimeIdstring | null | undefineddivisionstringscorenumberglobalPlacenumber | nulldivisionPlacenumber | nullsolves[].categorystringsolves[].namestringsolves[].pointsnumber | nullsolves[].awardedPointsnumber | nullsolves[].solvesnumber | nullsolves[].idstringsolves[].createdAtnumberdynamicScores[].idstringdynamicScores[].pointsnumberdynamicScores[].pointDeltanumberteamTokenstringallowedDivisionsstring[]permsnumber | nullTreat teamToken as a credential. It can be used for account recovery and team scoped auth flows.
PATCH Update profile
PATCH /api/[v2,v1]/users/me
- Auth
- Required
- Gate
- None
- Permissions
- No extra permissions
- Captcha
- No captcha
- Rate limit
- Profile name update bucket. Burst
3and refill window180000ms per user.
This route updates profile fields for the authenticated team. Profile changes recalculate cached user data and trigger a leaderboard update.
V2 can update the name, division, country or region code, and status text. V1 can update the name and division.
Name updates use the shared profile name update bucket. Division updates are checked against the divisions allowed for the team’s current email address.
Request body
namestringdivisionstringcountryCode"AF" | "AX" | "AL" | "DZ" | "AS" | "AD" | "AO" | "AI" | "AQ" | "AG" | "AR" | "AM" | "AW" | "AC" | "AU" | "AT" | "AZ" | "BS" | "BH" | "BD" | "BB" | "BY" | "BE" | "BZ" | "BJ" | "BM" | "BT" | "BO" | "BA" | "BW" | "BV" | "BR" | "IO" | "VG" | "BN" | "BG" | "BF" | "BI" | "KH" | "CM" | "CA" | "IC" | "CV" | "BQ" | "KY" | "CF" | "EA" | "TD" | "CL" | "CN" | "CX" | "CP" | "CC" | "CO" | "KM" | "CK" | "CR" | "HR" | "CU" | "CW" | "CY" | "CZ" | "DK" | "DG" | "DJ" | "DM" | "DO" | "CD" | "EC" | "EG" | "SV" | "GQ" | "ER" | "EE" | "SZ" | "ET" | "EU" | "FK" | "FO" | "FJ" | "FI" | "FR" | "GF" | "PF" | "TF" | "GA" | "GM" | "GE" | "DE" | "GH" | "GI" | "GR" | "GL" | "GD" | "GP" | "GU" | "GT" | "GG" | "GN" | "GW" | "GY" | "HT" | "HM" | "HN" | "HK" | "HU" | "IS" | "IN" | "ID" | "IR" | "IQ" | "IE" | "CQ" | "IM" | "IL" | "IT" | "CI" | "JM" | "JP" | "JE" | "JO" | "KZ" | "KE" | "KI" | "XK" | "KW" | "KG" | "LA" | "LV" | "LB" | "LS" | "LR" | "LY" | "LI" | "LT" | "LU" | "MO" | "MG" | "MW" | "MY" | "MV" | "ML" | "MT" | "MH" | "MQ" | "MR" | "MU" | "YT" | "MX" | "FM" | "MD" | "MC" | "MN" | "ME" | "MS" | "MA" | "MZ" | "MM" | "NA" | "NR" | "NP" | "NL" | "NC" | "NZ" | "NI" | "NE" | "NG" | "NU" | "NF" | "KP" | "MK" | "MP" | "NO" | "OM" | "PK" | "PW" | "PS" | "PA" | "PG" | "PY" | "PE" | "PH" | "PN" | "PL" | "PT" | "PR" | "QA" | "CG" | "RE" | "RO" | "RU" | "RW" | "BL" | "SH" | "KN" | "LC" | "MF" | "PM" | "VC" | "WS" | "SM" | "ST" | "SA" | "SN" | "RS" | "SC" | "SL" | "SG" | "SX" | "SK" | "SI" | "SB" | "SO" | "ZA" | "GS" | "KR" | "SS" | "ES" | "LK" | "SD" | "SR" | "SJ" | "SE" | "CH" | "SY" | "TW" | "TJ" | "TZ" | "TH" | "TL" | "TG" | "TK" | "TO" | "TT" | "TA" | "TN" | "TR" | "TM" | "TC" | "TV" | "UG" | "UA" | "AE" | "GB" | "UN" | "US" | "UM" | "VI" | "UY" | "UZ" | "VU" | "VA" | "VE" | "VN" | "WF" | "EH" | "YE" | "ZM" | "ZW"statusTextstringRequest body
namestringdivisionstringResponse fields
user.namestringuser.emailstring | nulluser.divisionstringuser.avatarUrlstring | nulluser.countryCodestring | nulluser.statusTextstring | nullResponse fields
user.namestringuser.emailstring | nulluser.divisionstringPATCH Update avatar
PATCH /api/v2/users/me/avatar
- Auth
- Required
- Gate
- None
- Permissions
- No extra permissions
- Captcha
- avatarUpload
- Rate limit
- Avatar upload bucket. Burst
2and refill window120000ms per user.
This route uploads, replaces, or removes the team avatar. The request body uses multipart/form-data.
Include an image file as the avatar form field to upload or replace an avatar. Leaving out avatar removes the current avatar when one exists.
The route checks maxAvatarSize, resizes the image to 256 by 256 pixels, converts it to WebP, and can send it through the moderation provider. The active upload provider stores the new image. The previous avatar is deleted when it is replaced.
Request body
avatarcustomcaptchaCodestringResponse fields
urlstring | nullPUT Set email auth
PUT /api/[v2,v1]/users/me/auth/email
- Auth
- Required
- Gate
- None
- Permissions
- No extra permissions
- Captcha
- setEmail
- Rate limit
- No rate limit
This route sets or changes the email address for the authenticated team.
When email delivery is configured, the route sends a verification email and returns 200 goodVerifySent. When email delivery is not configured, the email is updated immediately and the route returns 200 goodEmailSet.
Duplicate emails are not accepted. Email changes also need to keep the team inside its division ACL.
Request body
email requiredstringcaptchaCodestringRequest body
email requiredstringrecaptchaCodestringResponse#
Both success responses return no data. When the route returns 200 goodVerifySent, the verification token can be submitted to verify a token.
DELETE Remove email auth
DELETE /api/v1/users/me/auth/email
- Auth
- Required
- Gate
- None
- Permissions
- No extra permissions
- Captcha
- No captcha
- Rate limit
- No rate limit
This route removes email auth from the authenticated team. It is available in V1.
If removing email auth would leave the team without either email auth or CTFtime auth, the route returns 409 badZeroAuth.
Response#
A successful request returns 200 goodEmailRemoved with no data.
PUT Set CTFtime auth
PUT /api/v1/users/me/auth/ctftime
- Auth
- Required
- Gate
- None
- Permissions
- No extra permissions
- Captcha
- No captcha
- Rate limit
- No rate limit
This route links the authenticated team to a CTFtime team by using a CTFtime auth token. It is available in V1.
When CTFtime auth is not configured, the route returns 404 badEndpoint.
Request body
ctftimeToken requiredstringResponse#
A successful request returns 200 goodCtftimeAuthSet with no data.
DELETE Remove CTFtime auth
DELETE /api/v1/users/me/auth/ctftime
- Auth
- Required
- Gate
- None
- Permissions
- No extra permissions
- Captcha
- No captcha
- Rate limit
- No rate limit
This route removes CTFtime auth from the authenticated team. It is available in V1.
If removing CTFtime auth would leave the team without either email auth or CTFtime auth, the route returns 409 badZeroAuth.
Response#
A successful request returns 200 goodCtftimeRemoved with no data.
GET List team members
GET /api/v1/users/me/members
- Auth
- Required
- Gate
- None
- Permissions
- No extra permissions
- Captcha
- No captcha
- Rate limit
- No rate limit
This route lists informational team member email rows under the authenticated team account. Team member rows do not create separate login identities.
It is available in V1. When userMembers is disabled, the route returns 404 badEndpoint.
Response fields
idstringuseridstringemailstringPOST Add a team member
POST /api/v1/users/me/members
- Auth
- Required
- Gate
- None
- Permissions
- No extra permissions
- Captcha
- No captcha
- Rate limit
- No rate limit
This route adds an informational team member email row under the authenticated team account. Teams can have up to maxMembers member rows.
It is available in V1. When userMembers is disabled, the route returns 404 badEndpoint.
Request body
email requiredstringResponse fields
idstringuseridstringemailstringDELETE Remove a team member
DELETE /api/v1/users/me/members/:id
- Auth
- Required
- Gate
- None
- Permissions
- No extra permissions
- Captcha
- No captcha
- Rate limit
- No rate limit
This route removes a team member email row from the authenticated team account. It is available in V1.
Path parameters
id requiredstringResponse#
A successful request returns 200 goodMemberDelete with no data.