Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/JuanSebasSV/healtyhelp/llms.txt

Use this file to discover all available pages before exploring further.

All endpoints on this page require a valid Bearer token belonging to a user with the admin role — except POST /api/admin/accept-invite/:token, which is publicly accessible.
Authorization: Bearer <admin_token>

Statistics

GET /api/admin/stats

Returns platform-wide aggregate counts. Response
{
  "success": true,
  "stats": {
    "totalUsers": 1024,
    "admins": 3,
    "superAdmins": 1,
    "regularUsers": 1020,
    "imagenesPendientes": 7
  }
}
FieldTypeDescription
totalUsersnumberAll registered accounts
adminsnumberUsers with role: "admin" (excludes Super Admin)
superAdminsnumberAccounts flagged isSuperAdmin: true
regularUsersnumberAccounts with role: "user"
imagenesPendientesnumberReview images awaiting moderation

User Management

GET /api/admin/users

Returns all registered users. Passwords are never included. Response
{
  "success": true,
  "count": 42,
  "users": [
    {
      "_id": "664a1f...",
      "name": "Jane Doe",
      "email": "jane@example.com",
      "role": "user",
      "avatar": "https://...",
      "googleId": null,
      "createdAt": "2024-05-19T10:00:00.000Z",
      "isSuperAdmin": false,
      "baneado": false,
      "baneadoHasta": null,
      "baneadoMotivo": "",
      "baneadoEn": null
    }
  ]
}

DELETE /api/admin/users/:id

Permanently deletes a user account. The Super Admin account cannot be deleted. A non-super admin cannot delete other admins. Path Parameters
ParameterTypeDescription
idstringMongoDB ObjectId of the target user
Response
{
  "success": true,
  "message": "Usuario Jane Doe eliminado correctamente"
}
Error cases
StatusReason
400Attempting to delete your own account
403Target is the Super Admin or a fellow admin (non-super caller)
404User not found

PUT /api/admin/users/:id/role

Updates a user’s role. Only the Super Admin can promote to admin or demote another admin. Path Parameters
ParameterTypeDescription
idstringMongoDB ObjectId of the target user
Request Body
role
string
required
Target role. Must be "admin" or "user".
Response
{
  "success": true,
  "message": "Rol de Jane Doe actualizado a admin",
  "user": {
    "_id": "664a1f...",
    "name": "Jane Doe",
    "email": "jane@example.com",
    "role": "admin"
  }
}

PUT /api/admin/users/:id/ban

Bans a user for a fixed number of days or permanently. Path Parameters
ParameterTypeDescription
idstringMongoDB ObjectId of the target user
Request Body
motivo
string
Human-readable ban reason shown to moderators.
dias
number | null
Duration in days. Pass null for a permanent ban.
Response
{
  "success": true,
  "message": "Usuario baneado por 7 días",
  "baneadoHasta": "2025-07-26T14:30:00.000Z"
}
For a permanent ban the message will read "Usuario baneado permanentemente" and baneadoHasta will be null. Example — temporary ban (7 days)
curl -X PUT https://api.healtyhelp.com/api/admin/users/664a1f.../ban \
  -H "Authorization: Bearer <admin_token>" \
  -H "Content-Type: application/json" \
  -d '{ "motivo": "Spam en reseñas", "dias": 7 }'
Example — permanent ban
curl -X PUT https://api.healtyhelp.com/api/admin/users/664a1f.../ban \
  -H "Authorization: Bearer <admin_token>" \
  -H "Content-Type: application/json" \
  -d '{ "motivo": "Violación grave de términos", "dias": null }'
Error cases
StatusReason
400Attempting to ban yourself or the Super Admin
403Non-super admin attempting to ban another admin
404User not found

PUT /api/admin/users/:id/unban

Lifts an existing ban, clearing all ban fields. Path Parameters
ParameterTypeDescription
idstringMongoDB ObjectId of the target user
Response
{
  "success": true,
  "message": "Usuario desbaneado correctamente"
}

GET /api/admin/users/:id/ban

Returns the current ban status for a specific user. Path Parameters
ParameterTypeDescription
idstringMongoDB ObjectId of the target user
Response
{
  "success": true,
  "ban": {
    "baneado": true,
    "baneadoHasta": "2025-07-26T14:30:00.000Z",
    "baneadoMotivo": "Spam en reseñas",
    "baneadoEn": "2025-07-19T14:30:00.000Z",
    "permanente": false
  }
}
FieldTypeDescription
baneadobooleanWhether the user is currently banned
baneadoHastastring | nullISO expiry date, or null if permanent
baneadoMotivostringReason provided at ban time
baneadoEnstring | nullISO date when the ban was applied
permanentebooleantrue when baneado is true and baneadoHasta is null

Admin Invitations

POST /api/admin/invite

Generates a 24-hour single-use invitation link and sends it to the specified email address. The name provided here is stored in the invitation and becomes the display name of the new admin account when the invite is accepted. Request Body
email
string
required
Email address of the person being invited. Must not already be registered.
name
string
required
Display name for the new admin account. Stored in the invitation and used when the account is created.
Response
{
  "success": true,
  "message": "Invitación enviada a newadmin@example.com",
  "expiresAt": "2025-07-20T14:30:00.000Z"
}
Example
curl -X POST https://api.healtyhelp.com/api/admin/invite \
  -H "Authorization: Bearer <admin_token>" \
  -H "Content-Type: application/json" \
  -d '{ "email": "newadmin@example.com", "name": "New Admin" }'
Error cases
StatusReason
400Email is already registered to an existing account

GET /api/admin/invitations

Returns all pending (unused) invitations. Response
{
  "success": true,
  "invitations": [
    {
      "_id": "665c2a...",
      "email": "newadmin@example.com",
      "name": "New Admin",
      "invitedBy": { "_id": "664a1f...", "name": "Super Admin", "email": "super@example.com" },
      "expiresAt": "2025-07-20T14:30:00.000Z",
      "used": false,
      "createdAt": "2025-07-19T14:30:00.000Z"
    }
  ]
}

DELETE /api/admin/invitations/:id

Immediately revokes a pending invitation. The invitation link will no longer be valid. Path Parameters
ParameterTypeDescription
idstringMongoDB ObjectId of the invitation
Response
{
  "success": true,
  "message": "Invitación revocada"
}

POST /api/admin/accept-invite/:token

This endpoint is public — no Bearer token is required.
Accepts an invitation and creates a new admin account. The token is extracted from the invitation URL and has a 24-hour TTL. The display name and email are taken from the invitation record — only a password must be provided. Path Parameters
ParameterTypeDescription
tokenstringRaw invite token from the invitation URL
Request Body
password
string
required
Password for the new admin account. The display name and email are supplied from the invitation record created when the invite was sent.
Response
{
  "success": true,
  "message": "Cuenta de admin creada exitosamente",
  "user": {
    "id": "665d3b...",
    "name": "New Admin",
    "email": "newadmin@example.com",
    "role": "admin"
  }
}
Error cases
StatusReason
400Token is invalid, already used, or expired

Logs

GET /api/admin/logs

Returns a paginated audit trail of all admin actions. Query Parameters
ParameterTypeDefaultDescription
pagenumber1Page number
limitnumber50Results per page
Response
{
  "success": true,
  "logs": [
    {
      "_id": "666e4c...",
      "adminId": { "_id": "664a1f...", "name": "Super Admin", "email": "super@example.com" },
      "action": "BAN_USER",
      "targetUserId": { "_id": "664b2e...", "name": "Jane Doe", "email": "jane@example.com" },
      "metadata": { "motivo": "Spam en reseñas", "dias": 7, "userName": "Jane Doe" },
      "createdAt": "2025-07-19T14:30:00.000Z"
    }
  ],
  "pagination": {
    "total": 200,
    "page": 1,
    "pages": 4
  }
}
Supported action values
ValueTriggered by
BAN_USERPUT /users/:id/ban
UNBAN_USERPUT /users/:id/unban
DELETE_USERDELETE /users/:id
CHANGE_ROLEPUT /users/:id/role
INVITE_ADMINPOST /invite
ADMIN_INVITE_ACCEPTEDPOST /accept-invite/:token
REVOKE_INVITATIONDELETE /invitations/:id
APPROVE_RESENA_IMAGEPUT /imagenes-resenas/:recipeId/:resenaId/aprobar
REJECT_RESENA_IMAGEPUT /imagenes-resenas/:recipeId/:resenaId/rechazar
DELETE_RESENA_IMAGE_HISTORYDELETE /imagenes-resenas/:recipeId/:resenaId
DELETE_RESENA_IMAGE_HISTORY_MASIVODELETE /imagenes-resenas/masivo

Image Moderation

Review images attached to recipe reviews. Each image carries a state of pendiente, aprobada, or rechazada.

GET /api/admin/imagenes-resenas

Returns a paginated list of review images filtered by moderation state. Query Parameters
ParameterTypeDefaultDescription
estadostring"pendiente"Filter by image state: pendiente, aprobada, or rechazada
pagenumber1Page number
limitnumber12Results per page
Response
{
  "success": true,
  "items": [
    {
      "recipeId": "663a0f...",
      "recipeNombre": "Ensalada César",
      "resenaId": "664b2e...",
      "userId": "664a1f...",
      "userName": "Jane Doe",
      "texto": "Deliciosa receta, muy recomendada.",
      "estrellas": 5,
      "createdAt": "2025-07-18T09:00:00.000Z",
      "imagenUrl": "https://res.cloudinary.com/...",
      "imagenPublicId": "healtyhelp/resenas/abc123",
      "imagenEstado": "pendiente"
    }
  ],
  "pagination": {
    "total": 7,
    "page": 1,
    "pages": 1
  }
}

PUT /api/admin/imagenes-resenas/:recipeId/:resenaId/aprobar

Marks a review image as aprobada, making it publicly visible. Path Parameters
ParameterTypeDescription
recipeIdstringMongoDB ObjectId of the recipe
resenaIdstringMongoDB ObjectId of the review
Response
{
  "success": true,
  "message": "Imagen aprobada. Ya es visible para todos."
}

PUT /api/admin/imagenes-resenas/:recipeId/:resenaId/rechazar

Rejects a review image and permanently deletes it from Cloudinary. The image URL and public ID are cleared from the database. Path Parameters
ParameterTypeDescription
recipeIdstringMongoDB ObjectId of the recipe
resenaIdstringMongoDB ObjectId of the review
Response
{
  "success": true,
  "message": "Imagen rechazada y eliminada de Cloudinary."
}
Error cases
StatusReason
400The review has no associated image
404Recipe or review not found

DELETE /api/admin/imagenes-resenas/:recipeId/:resenaId

Removes the image history entry from a review that has already been approved or rejected. Pending images cannot be deleted via this endpoint — use the reject action instead. Path Parameters
ParameterTypeDescription
recipeIdstringMongoDB ObjectId of the recipe
resenaIdstringMongoDB ObjectId of the review
Response
{
  "success": true,
  "message": "Registro eliminado del historial."
}

DELETE /api/admin/imagenes-resenas/masivo

Bulk-deletes image history entries for multiple reviews in a single request. Each item’s image asset is also removed from Cloudinary.
This operation is irreversible. Deleted image records and their associated Cloudinary assets cannot be recovered. Use with caution — only approved or rejected images can be targeted; pending images will be counted as failures.
Request Body
items
array
required
Array of objects identifying the review images to delete.
items[].recipeId
string
required
MongoDB ObjectId of the recipe.
items[].resenaId
string
required
MongoDB ObjectId of the review.
Example Request Body
{
  "items": [
    { "recipeId": "663a0f...", "resenaId": "664b2e..." },
    { "recipeId": "663a0f...", "resenaId": "664c3f..." }
  ]
}
Response
{
  "success": true,
  "ok": 2,
  "fail": 0,
  "message": "2 registros eliminados del historial."
}
FieldTypeDescription
oknumberSuccessfully deleted items
failnumberItems that could not be deleted (not found, wrong state, etc.)

Terms Management

GET /api/admin/terms

Returns the most recently published terms document. Response
{
  "terms": {
    "_id": "667f5d...",
    "version": "2.1.0",
    "content": "# Terms and Conditions\n...",
    "publishedBy": "664a1f...",
    "publishedAt": "2025-06-01T00:00:00.000Z"
  }
}
Returns { "terms": null } if no terms document has been published yet.

PUT /api/admin/terms

Publishes a new version of the Terms & Conditions document.
Publishing a new version immediately resets termsAccepted to false for every user on the platform (except the publishing admin). All users will be prompted to re-accept the terms on their next login.
Request Body
version
string
required
Semantic version string (e.g. "2.2.0"). Must differ from the currently published version.
content
string
required
Full terms document content (plain text or Markdown).
Response
{
  "success": true,
  "terms": {
    "_id": "668a6e...",
    "version": "2.2.0",
    "content": "# Terms and Conditions\n...",
    "publishedBy": "664a1f...",
    "publishedAt": "2025-07-19T15:00:00.000Z"
  }
}
Error cases
StatusReason
400version or content is missing, or version matches the currently active version

Build docs developers (and LLMs) love