The Users API covers the full lifecycle of a Sealearn account: creating a user, authenticating them, reading their profile, and updating settings like username, display name, and favorite subjects. All write operations that affect a specific user’s account require a valid JWT token in theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/DerBasilisk/SEA-ServicioEvaluaconAsistida/llms.txt
Use this file to discover all available pages before exploring further.
Authorization: Bearer <token> header. Refer to the Authentication API for how to obtain a token. User documents include gamification fields (XP, level, gems, hearts, streaks, league), cosmetic preferences, duel statistics, and computed virtual fields that the server calculates on the fly.
Endpoints
POST /api/users/register
Creates a new user account. After registration a verification email is dispatched — no JWT token is returned at this stage. The user must verify their email before they can log in via POST /api/users/login.Both
username and email must be globally unique. The username is stored in lowercase and must match ^[a-zA-Z0-9_]{3,20}$.Request body
Unique username. 3–20 characters; letters, digits, and underscores only (
^[a-zA-Z0-9_]{3,20}$). Stored in lowercase.Valid email address. Must be unique across all accounts. Stored in lowercase.
Minimum 6 characters. Hashed with bcrypt (cost factor 12) before storage; never returned in any response.
Responses
| Status | Meaning |
|---|---|
201 | Account created; verification email sent. |
400 | Email or username already in use, or validation failed. |
true on success."Usuario registrado. Revisa tu correo para verificar la cuenta.".Partial user document — no token is included.
POST /api/users/login
Authenticates a user with their email and password. Returns a 7-day JWT token alongside the full user document (including populated achievements, favorite subjects, and live streak data).Login is blocked for accounts whose email has not yet been verified. The API returns
403 in that case. Use POST /api/auth/resend-verification to resend the verification email.Request body
The email address used during registration.
The account password.
Responses
| Status | Meaning |
|---|---|
200 | Authentication successful; token and user data returned. |
401 | Incorrect email or password. |
403 | Account email not yet verified. |
500 | Internal server error. |
true on success.Signed JWT valid for 7 days. Include this value in the
Authorization: Bearer <token> header for authenticated requests.Full user document. See User object reference for all fields.
GET /api/users/me
Returns the complete profile of the currently authenticated user, including populated achievements and favorite subjects, a live heart-refill check, and computed streak data. Use this endpoint to bootstrap the client UI after login or on page load. Requires authentication.Responses
| Status | Meaning |
|---|---|
200 | User document returned. |
401 | Missing, expired, or invalid token. |
404 | User referenced by token no longer exists. |
500 | Internal server error. |
true on success.Full user document with virtual fields and live streak object. See User object reference.
GET /api/users/check-username/:username
Checks whether a given username is available and matches the required format. Useful for real-time validation in registration or username-change forms.Path parameters
The username to check. Must satisfy
^[a-zA-Z0-9_]{3,20}$; otherwise available is false with a reason of "Formato inválido" without querying the database.Responses
| Status | Meaning |
|---|---|
200 | Check completed (see available). |
500 | Internal server error. |
true on success.true if the username is free and format-valid, false otherwise.Only present when
available is false due to format validation: "Formato inválido".PUT /api/users/username
Changes the authenticated user’s username. Usernames can only be changed once every 30 days — the cooldown is tracked via theusernameChangedAt field. The new username is lowercased before storage.
Requires authentication.
Request body
The desired new username. Must match
^[a-zA-Z0-9_]{3,20}$ and be globally unique.Responses
| Status | Meaning |
|---|---|
200 | Username updated successfully. |
400 | Missing or invalid format, cooldown still active, or username already taken. |
401 | Missing, expired, or invalid token. |
500 | Internal server error. |
true on success.PUT /api/users/display-name
Updates the authenticated user’s display name — the name shown in the UI, distinct from the@username. Display names can be changed at any time without a cooldown.
Requires authentication.
Request body
The new display name. Maximum 30 characters. Leading and trailing whitespace is trimmed. Cannot be blank.
Responses
| Status | Meaning |
|---|---|
200 | Display name updated. |
400 | Display name missing, blank, or exceeds 30 characters. |
401 | Missing, expired, or invalid token. |
500 | Internal server error. |
true on success.POST /api/users/toggle-favorite
Adds or removes a subject from the authenticated user’sfavoriteSubjects array. If the subject is already in the array it is removed; if it is absent it is added. Returns the updated full user document with populated subjects.
Requires authentication.
Request body
MongoDB ObjectId of the subject to toggle.
Responses
| Status | Meaning |
|---|---|
200 | Favorite subjects list updated. |
401 | Missing, expired, or invalid token. |
500 | Internal server error. |
true on success.Full updated user document with
favoriteSubjects populated. See User object reference.GET /api/users/verify-email
Validates an email verification token and marks the account as verified. This endpoint is typically reached by clicking the link in the registration email rather than being called programmatically. On success or failure it redirects the browser to the appropriate frontend route — it does not return a JSON body.Query parameters
The 64-character hex verification token included in the registration email.
Behavior
| Condition | Redirect target |
|---|---|
| Token is valid and not expired | FRONTEND_URL/login?verified=true |
token query param is missing | FRONTEND_URL/verify-email?error=missing_token |
| Token not found or expired | FRONTEND_URL/verify-email?error=invalid_or_expired |
| Server error | FRONTEND_URL/verify-email?error=server_error |
POST /api/users/resend-verification
Generates a fresh 24-hour verification token and resends the verification email. Use this when the user’s original verification link has expired.Request body
The email address of the unverified account.
Responses
| Status | Meaning |
|---|---|
200 | Verification email resent successfully. |
400 | Email not provided, or the account is already verified. |
404 | No account found for this email address. |
500 | Internal server error. |
true on success."Correo de verificación reenviado".User object reference
The following describes the shape of thedata object returned by the login, /me, and toggle-favorite endpoints. Virtual fields (xpForNextLevel, xpProgress, currentStreak) are computed server-side and included automatically because the schema is configured with toJSON: { virtuals: true }.
MongoDB ObjectId that uniquely identifies the user.
Unique login handle. Lowercase alphanumeric + underscore, 3–20 characters.
Human-readable display name shown in the UI. Defaults to
username at account creation. Max 30 characters.Lowercase email address. Not returned in unauthenticated contexts.
Account permission level. One of
"student", "admin", or "superadmin". New accounts default to "student".URL or identifier of the user’s avatar image.
null if no avatar has been set.URL or identifier of the user’s profile banner.
null if not set.Total experience points accumulated across all completed lessons and activities. Always
≥ 0.Current level, derived from
xp. Level-up thresholds follow the formula floor(100 × 1.5^(level−1)). Always ≥ 1.In-app currency used to purchase cosmetic items (frames, backgrounds) and refill hearts in the shop. Always
≥ 0.Life system. One heart is consumed per wrong answer; a refill of 1 heart occurs automatically every 30 minutes when below the maximum.
Daily activity streak information resolved at query time against the
Streak collection.Current league tier. One of
"bronze", "silver", "gold", "sapphire", "emerald", "diamond", "master", "champion", or "heroic". Defaults to "bronze".User-configured daily XP target. Allowed values:
10, 20, 30, 50. Defaults to 10.Array of populated
Achievement documents earned by the user. Empty array until the first achievement is unlocked.Reference to the
ShopItem currently equipped as the profile picture frame. null if no frame is active.Reference to the
ShopItem currently equipped as the profile background. null if no background is active.Array of populated
Subject documents the user has marked as favorites. Managed via POST /api/users/toggle-favorite.Aggregated duel performance statistics.
Virtual. XP required to reach the next level, calculated as
floor(100 × 1.5^(level−1)).Virtual. Percentage of XP progress toward the next level,
0–100. Calculated from the XP accumulated since the start of the current level relative to the XP needed to complete it.Virtual. Active streak count based on the embedded
streak.lastActivityDate. Returns streak.current if the last activity was today or yesterday; returns 0 if the streak has lapsed.