Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/sdurutr436/stay-sidekick/llms.txt

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

Stay Sidekick is a fully multi-tenant platform — every company is a completely isolated tenant with its own users, data, apartment inventory, and external integrations. Nothing leaks across tenant boundaries at the query level. A single superadmin account manages the platform at the top level: creating companies, removing them, and switching context freely across any tenant. Within each tenant, a company admin handles day-to-day user management without needing superadmin access.

Roles

Every JWT issued by the platform carries a rol claim and an es_superadmin boolean. The three roles below define what each identity can read and write.
RoleDescription
operativoCan access all operational tools and read company configuration. Cannot modify company settings, manage users, or configure integrations.
adminFull access to company configuration, user management, and integration setup (PMS and AI keys). Cannot manage other companies on the platform.
superadminManages all companies on the platform. Can perform every /api/empresas operation and can target any company’s users by supplying ?empresa_id=.
A superadmin also carries an empresa_id in their token (their home tenant). When operating on users they can override this by appending ?empresa_id=<uuid> to any /api/usuarios endpoint. If the query parameter is omitted, the operation falls back to the superadmin’s own empresa_id.

Company management

All three company routes are restricted to the superadmin role. They are the only way to provision or remove a tenant from the platform.

List companies

GET /api/empresas — Returns all active companies ordered alphabetically by name. Each entry includes id, nombre, and email.

Create company

POST /api/empresas — Creates a new tenant and immediately dispatches a welcome email via Mailgun with the company name, email, and creation timestamp.

Delete company

DELETE /api/empresas/<id> — Permanently removes the company and all its data in cascade: users, apartments, PMS config, AI config, vault templates, generated messages, sync logs, and Google integration.

Create a company

curl -X POST http://localhost/api/empresas \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-CSRF-Token: <csrf_token>" \
  -d '{
    "nombre": "Coastal Stays SL",
    "email": "ops@coastalstays.com"
  }'
Response 201:
{
  "ok": true,
  "empresa": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "nombre": "Coastal Stays SL",
    "email": "ops@coastalstays.com"
  }
}
If a company with the same email already exists the API returns 409 with "Ya existe una empresa con ese email.".
Deleting a company (DELETE /api/empresas/<id>) is irreversible. All tenant data — including all users, apartments, vault templates, and integration credentials — is removed immediately. There is no soft-delete or recovery path. Always confirm the empresa_id before calling this endpoint.

User management

User management routes require at minimum the admin role. All routes resolve the target company from the JWT’s empresa_id claim; superadmins may override this with ?empresa_id=<uuid>.

List users

GET /api/usuarios — Returns all users for the resolved company and the max_usuarios limit configured for that tenant.

Create user

POST /api/usuarios — Creates a user with the given email and rol. The system generates a temporary password that is returned once in the response. The user must change it on first login.

Delete user

DELETE /api/usuarios/<id> — Removes the user from the company. An admin cannot delete their own account.

Change role

PATCH /api/usuarios/<id> — Updates the user’s rol. Accepts a JSON body with the new role value. Valid options: operativo, admin.

Reset a user’s password

PATCH /api/usuarios/<id>/contrasena generates a new temporary password for the target user and returns it in plaintext — the only time it is ever visible. On next login, debe_cambiar_password: true will be set in the JWT response, prompting the user to change it immediately.

Create a user

curl -X POST http://localhost/api/usuarios \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-CSRF-Token: <csrf_token>" \
  -d '{
    "email": "julia@coastalstays.com",
    "rol": "admin"
  }'
Response 201:
{
  "ok": true,
  "usuario": {
    "id": "a1b2c3d4-0000-0000-0000-000000000001",
    "email": "julia@coastalstays.com",
    "rol": "admin",
    "activo": true,
    "created_at": "2025-06-01T09:00:00+00:00"
  },
  "password_temporal": "xK7!mQ2nRpLw"
}
password_temporal is returned once in the creation response and is never stored in plaintext. Share it with the new user through a secure channel. They will be prompted to change it on first login.

Reset a user’s password

curl -X PATCH http://localhost/api/usuarios/a1b2c3d4-0000-0000-0000-000000000001/contrasena \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-CSRF-Token: <csrf_token>"
Response 200:
{
  "ok": true,
  "password_temporal": "pN9#vZ3tYsUx"
}

Change a user’s role

curl -X PATCH http://localhost/api/usuarios/a1b2c3d4-0000-0000-0000-000000000001 \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-CSRF-Token: <csrf_token>" \
  -d '{"rol": "operativo"}'
Response 200:
{
  "ok": true,
  "usuario": {
    "id": "a1b2c3d4-0000-0000-0000-000000000001",
    "email": "julia@coastalstays.com",
    "rol": "operativo",
    "activo": true,
    "created_at": "2025-06-01T09:00:00+00:00"
  }
}

Superadmin cross-company operations

A superadmin can operate on any company’s users without switching context by appending ?empresa_id=<uuid> to any /api/usuarios endpoint.
# List users of a specific company as superadmin
curl -X GET "http://localhost/api/usuarios?empresa_id=3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  -H "Authorization: Bearer $TOKEN"
# Create a user in a specific company as superadmin
curl -X POST "http://localhost/api/usuarios?empresa_id=3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-CSRF-Token: <csrf_token>" \
  -d '{"email": "support@coastalstays.com", "rol": "operativo"}'
Use GET /api/empresas first to obtain the empresa_id UUID of the target tenant, then pass it as a query parameter on any subsequent /api/usuarios call.

User limits

Each company’s configuracion JSONB column stores a max_usuarios value. The GET /api/usuarios response always includes this limit alongside the user list so the frontend can enforce it before attempting a POST /api/usuarios call. Attempting to create a user beyond the limit returns a 422 with a descriptive error message.

Build docs developers (and LLMs) love