Skip to main content

Documentation 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.

The Friends API powers Sealearn’s social layer. Users can discover other learners by username, send and manage friend requests, inspect anyone’s public profile, and see how their friends stack up in a weekly XP leaderboard. Every endpoint in this group requires a valid JWT — attach the token as a Bearer value in the Authorization header of every request.
All routes are mounted under /api/friends and protected by the verificarToken middleware. Requests without a valid token receive 401 Unauthorized.

The Friendship Model

A Friendship document is created whenever one user sends a friend request to another. Its status field tracks the lifecycle of the relationship.
FieldTypeDescription
_idObjectIdUnique document ID — used when accepting or rejecting a request.
requesterObjectId → UserThe user who sent the request.
recipientObjectId → UserThe user who received the request.
status"pending" | "accepted" | "rejected"Current state of the friendship.
createdAtDateTimestamp of when the request was first sent (auto-managed by Mongoose timestamps).
updatedAtDateTimestamp of the last status change.
A compound unique index on { requester, recipient } prevents duplicate requests between the same pair. If a previously rejected friendship exists and a new request is sent, the server re-uses the existing document and sets its status back to "pending".

Endpoints

GET /api/friends

Returns the list of accepted friends for the authenticated user. Both sides of each Friendship document are resolved, so it doesn’t matter who originally sent the request. Response fields per friend object:
ok
boolean
required
true on success.
data
array
required
Array of populated User objects.
curl -X GET https://api.sealearn.app/api/friends \
  -H "Authorization: Bearer <token>"
{
  "ok": true,
  "data": [
    {
      "_id": "664a1f2e8b3c2a001e4d8e10",
      "username": "marisolita",
      "displayName": "Marisol",
      "xp": 3420,
      "level": 12,
      "avatar": "https://res.cloudinary.com/sealearn/image/upload/avatars/marisolita.webp",
      "hearts": 5,
      "gems": 80,
      "streak": 7
    }
  ]
}

GET /api/friends/requests

Returns all incoming friend requests that are still in "pending" status for the authenticated user. Only requests where the authenticated user is the recipient are returned.
ok
boolean
required
true on success.
data
array
required
Array of Friendship documents with the requester field populated.
curl -X GET https://api.sealearn.app/api/friends/requests \
  -H "Authorization: Bearer <token>"
{
  "ok": true,
  "data": [
    {
      "_id": "664b3e1c9f0e4b002f5a9d33",
      "status": "pending",
      "requester": {
        "_id": "664a0011ab12cd003e7f1122",
        "username": "codigoninja",
        "displayName": "Código Ninja",
        "avatar": "https://res.cloudinary.com/sealearn/image/upload/avatars/codigoninja.webp",
        "level": 8,
        "xp": 1950
      },
      "createdAt": "2024-05-20T14:32:00.000Z"
    }
  ]
}

GET /api/friends/search

Searches active users by username or displayName. Results are case-insensitive and limited to 8 matches. The query string must be at least 2 characters; shorter values return an empty array immediately. Each result includes a friendStatus field so the client can immediately render the correct call-to-action (add, pending, already friends, etc.).
q
string
required
Search term (minimum 2 characters). Matched against both username and displayName using a case-insensitive regex.
ok
boolean
required
true on success.
data
array
required
Up to 8 matching User objects.
curl -X GET "https://api.sealearn.app/api/friends/search?q=mari" \
  -H "Authorization: Bearer <token>"
{
  "ok": true,
  "data": [
    {
      "_id": "664a1f2e8b3c2a001e4d8e10",
      "username": "marisolita",
      "displayName": "Marisol",
      "avatar": "https://res.cloudinary.com/sealearn/image/upload/avatars/marisolita.webp",
      "level": 12,
      "xp": 3420,
      "friendStatus": null,
      "friendshipId": null,
      "isRequester": false
    }
  ]
}

GET /api/friends/leaderboard

Returns a weekly XP leaderboard that includes the authenticated user and all of their accepted friends. Ranking is based on xpEarned accumulated in the user’s current league room since the week started (Monday 00:00 UTC). Users not yet assigned to a league room for the current week show 0 XP.
ok
boolean
required
true on success.
data
array
required
Sorted array of leaderboard entries, highest XP first.
curl -X GET https://api.sealearn.app/api/friends/leaderboard \
  -H "Authorization: Bearer <token>"
{
  "ok": true,
  "data": [
    {
      "rank": 1,
      "xpEarned": 520,
      "user": {
        "_id": "664a1f2e8b3c2a001e4d8e10",
        "username": "marisolita",
        "displayName": "Marisol",
        "avatar": "https://res.cloudinary.com/sealearn/image/upload/avatars/marisolita.webp",
        "level": 12
      }
    },
    {
      "rank": 2,
      "xpEarned": 310,
      "user": {
        "_id": "664a0011ab12cd003e7f1122",
        "username": "codigoninja",
        "displayName": "Código Ninja",
        "avatar": "https://res.cloudinary.com/sealearn/image/upload/avatars/codigoninja.webp",
        "level": 8
      }
    }
  ]
}

GET /api/friends/profile/:username

Returns the public profile of any user, identified by their username. The response also includes the friendship status between the viewer and the profile owner, enabling the client to show the correct social action button. Achievements, active cosmetic frame, and active background are fully populated.
username
string
required
The target user’s username (case-sensitive, exact match).
ok
boolean
required
true on success.
data
object
required
Public profile object.
curl -X GET https://api.sealearn.app/api/friends/profile/marisolita \
  -H "Authorization: Bearer <token>"
{
  "ok": true,
  "data": {
    "username": "marisolita",
    "displayName": "Marisol",
    "avatar": "https://res.cloudinary.com/sealearn/image/upload/avatars/marisolita.webp",
    "banner": "https://res.cloudinary.com/sealearn/image/upload/banners/ocean.webp",
    "level": 12,
    "xp": 3420,
    "league": "gold",
    "streak": 7,
    "gems": 80,
    "achievements": [],
    "activeFrame": null,
    "activeBackground": null,
    "friendStatus": null,
    "friendshipId": null,
    "isRequester": false
  }
}

POST /api/friends/request

Sends a friend request to another user identified by their username. If the target previously rejected a request from the authenticated user, the existing document is reused and its status is reset to "pending".
username
string
required
The username of the user to befriend. The lookup is case-insensitive.
ok
boolean
required
true on success.
message
string
required
Human-readable confirmation or error detail.
data
object
The newly created (or reactivated) Friendship document.
Error cases:
  • 400username not provided, attempting to add yourself, already friends, or request already pending.
  • 404 — Username not found.
curl -X POST https://api.sealearn.app/api/friends/request \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{ "username": "marisolita" }'
{
  "ok": true,
  "message": "Solicitud enviada a @marisolita",
  "data": {
    "_id": "664b3e1c9f0e4b002f5a9d33",
    "requester": "664a0011ab12cd003e7f1122",
    "recipient": "664a1f2e8b3c2a001e4d8e10",
    "status": "pending",
    "createdAt": "2024-05-20T14:32:00.000Z"
  }
}

PUT /api/friends/request/:id/accept

Accepts a pending incoming friend request. The :id parameter is the _id of the Friendship document, which can be found in the response from GET /api/friends/requests. Only the recipient of the request can call this endpoint.
id
string
required
The _id of the Friendship document to accept.
ok
boolean
required
true on success.
message
string
required
"Solicitud aceptada".
curl -X PUT https://api.sealearn.app/api/friends/request/664b3e1c9f0e4b002f5a9d33/accept \
  -H "Authorization: Bearer <token>"
{ "ok": true, "message": "Solicitud aceptada" }

PUT /api/friends/request/:id/reject

Rejects a pending incoming friend request. Sets the friendship status to "rejected". Only the recipient can call this endpoint.
id
string
required
The _id of the Friendship document to reject.
ok
boolean
required
true on success.
message
string
required
"Solicitud rechazada".
curl -X PUT https://api.sealearn.app/api/friends/request/664b3e1c9f0e4b002f5a9d33/reject \
  -H "Authorization: Bearer <token>"
{ "ok": true, "message": "Solicitud rechazada" }

DELETE /api/friends/:userId

Removes an accepted friendship between the authenticated user and the target. Both directions of the Friendship document are checked, so either party can remove the other.
userId
string
required
The MongoDB _id of the friend to remove.
ok
boolean
required
true on success.
message
string
required
"Amigo eliminado".
curl -X DELETE https://api.sealearn.app/api/friends/664a1f2e8b3c2a001e4d8e10 \
  -H "Authorization: Bearer <token>"
{ "ok": true, "message": "Amigo eliminado" }

Build docs developers (and LLMs) love