API Endpoints
Documentación completa de los endpoints de la API de Floutic.
Autenticación
Autenticación Estándar (JWT)
POST /api/auth/register- Registro de usuario (envía email de verificación)POST /api/auth/login- Login y token JWTPOST /api/auth/refresh- Renovar token (rota el refresh token automáticamente)POST /api/auth/logout- Cerrar sesión (puede enviarrefresh_tokenopcional)GET /api/auth/verify- Verificar tokenPOST /api/auth/verify-email- Verificar email usando token de verificaciónPOST /api/auth/send-verification-email- Reenviar email de verificación (requiere autenticación, rate limit: 1 cada 2 minutos)
Autenticación Segura (Recomendado)
POST /api/auth/login_secure- Login seguro con HttpOnly cookies, CSRF protection y session_id únicoPOST /api/auth/refresh_secure- Renovar tokens con validación de session_idPOST /api/auth/logout_secure- Logout seguro con invalidación de tokensGET /api/auth/verify_secure- Verificar sesión válida, devuelve tokens y valida session_idPOST /api/auth/forgot-password- Solicitar recuperación de contraseñaPOST /api/auth/reset-password- Restablecer contraseña con token seguroGET /api/auth/verify_token- Verificar token con autenticaciónPOST /api/auth/verify-email- Verificar email usando token de verificación (no requiere autenticación)POST /api/auth/send-verification-email- Reenviar email de verificación (requiere autenticación, rate limit: 1 cada 2 minutos)POST /api/auth/add-role- Añadir un nuevo rol al usuario autenticado (empresa o experto)POST /api/auth/switch-role- Cambiar el rol activo del usuario autenticado
Gestión de Roles Multiples:
- Los usuarios pueden tener múltiples roles (empresa y/o experto)
- Al registrarse, se pueden seleccionar uno o ambos roles
- El rol activo determina qué dashboard y funcionalidades están disponibles
- Se puede cambiar entre roles en cualquier momento desde el selector de roles
Características de seguridad:
- Cookies HttpOnly con
SameSite=Strictpara aislar ventanas privadas - Sistema de
session_idúnico por ventana - Validación obligatoria de
session_iden todas las peticiones - Protección CSRF con tokens
- Cache Redis para optimización
- Blacklist de tokens en Redis
Usuarios
GET /api/users/me- Obtener información del usuario actual (incluyerolesarray yactive_role)PUT /api/users/me- Actualizar usuario actual (username, is_active)POST /api/users/me/change-password- Cambiar contraseña (requiere contraseña actual)PUT /api/users/me/email- Actualizar email (requiere contraseña actual). Nota: Al cambiar el email, se marca como no verificado y se envía automáticamente un email de verificación al nuevo correo. El usuario debe verificar el nuevo email para completar el cambio.GET /api/users/{id}- Ver perfil público de usuario
Estructura de Usuario:
{
"id": 1,
"email": "usuario@ejemplo.com",
"username": "usuario",
"roles": ["empresa", "experto"], // Array de roles del usuario
"active_role": "empresa", // Rol actualmente activo
"role": "empresa" // Alias para compatibilidad (igual a active_role)
}
Webhooks de Usuario
GET /api/users/me/webhook- Obtener configuración de webhookPUT /api/users/me/webhook- Configurar webhook (URL HTTPS, habilitar/deshabilitar, método de autenticación)GET /api/users/me/webhook/secret- Obtener secreto JWT actualPOST /api/users/me/webhook/secret- Regenerar secreto JWT
Perfiles
GET /api/profiles/{id}- Ver perfil públicoGET /api/profiles/experts/slug/{slug}- Obtener perfil público de experto por slug SEOGET /api/profiles/me- Obtener mi perfil del rol activo actualGET /api/profiles/me/profile- Mi perfil completo (alias de/me)POST /api/profiles/- Crear perfil (empresa/experto/admin) - Requiere que el tipo de perfil esté en los roles del usuarioPUT /api/profiles/{id}- Actualizar perfil
Nota sobre Perfiles Multi-Rol:
-
Cada usuario puede tener un perfil por cada rol que posea
-
Un usuario con roles
["empresa", "experto"]puede tener dos perfiles independientes -
El endpoint
/api/profiles/medevuelve el perfil correspondiente alactive_roledel usuario -
Cada perfil tiene su propia verificación y estado independiente
-
POST /api/profiles/upload- Subir documento (verificación, portfolio, etc.) -
POST /api/profiles/me/picture- Subir imagen de perfil (JPEG, PNG, WebP, max 2MB). Actualiza automáticamente el campoprofile_picturedel perfil. Disponible para expertos y admin.Nota técnica:
- Usa el servicio centralizado
ProfileImageServicepara validación, almacenamiento y normalización de rutas - La imagen se guarda en
uploads/profiles/{user_id}/{filename}y la ruta en BD es/api/uploads/profiles/{user_id}/{filename} - Validación mejorada: Usa Pillow para validar que el archivo sea realmente una imagen válida
- Optimización automática:
- Imágenes mayores a 1024px se redimensionan automáticamente manteniendo aspect ratio
- Optimización de calidad (JPEG: 85, PNG: optimizado, WebP: método 6)
- Conversión automática de imágenes con transparencia a RGB con fondo blanco
- Logging: Registra reducción de tamaño y dimensiones para debugging
- Usa el servicio centralizado
-
GET /api/profiles/experts- Buscar expertos con filtros avanzados -
PUT /api/profiles/{id}/fiscal-data- Actualizar datos fiscales -
GET /api/profiles/me/fiscal-status- Verificar estado de datos fiscales
Perfiles de Admin
Los administradores pueden crear perfiles opcionales para aparecer en la página "Quiénes Somos":
POST /api/profiles/admin/me- Crear perfil de admin (solo para usuarios con rol admin). Todos los campos son opcionales.PUT /api/profiles/admin/me- Actualizar perfil de adminGET /api/profiles/admin/me- Obtener perfil de admin propioGET /api/profiles/admin/slug/{slug}- Obtener perfil de admin por slug (endpoint público, sin autenticación). Usado para la página pública de perfil de miembro del equipo.GET /api/profiles/team- Obtener equipo público (endpoint público, sin autenticación). Retorna todos los perfiles admin conis_visible_in_team=True, ordenados pordisplay_order.
Campos disponibles para perfiles admin:
full_name(string, opcional) - Nombre completo para mostrarteam_role(string, opcional) - Rol en el equipo (CEO, CTO, Product Manager, etc.)bio(string, opcional) - Biografíaprofile_picture(string, opcional) - Ruta de la imagen de perfillocation(string, opcional) - Ubicaciónlinkedin_url(string, opcional) - URL de LinkedIntwitter_url(string, opcional) - URL de Twittergithub_url(string, opcional) - URL de GitHubinstagram_url(string, opcional) - URL de Instagramtiktok_url(string, opcional) - URL de TikTokpersonal_website(string, opcional) - Sitio web personaldisplay_order(integer, opcional) - Orden de visualización en "quienes somos" (menor = primero)is_visible_in_team(boolean, default: false) - Si aparece en la página pública "quienes somos"
Ejemplo de creación de perfil admin:
POST /api/profiles/admin/me
{
"full_name": "Juan Pérez",
"team_role": "CEO",
"bio": "Fundador y CEO de Floutic",
"location": "Madrid, España",
"linkedin_url": "https://linkedin.com/in/juanperez",
"twitter_url": "https://twitter.com/juanperez",
"github_url": "https://github.com/juanperez",
"instagram_url": "https://instagram.com/juanperez",
"tiktok_url": "https://tiktok.com/@juanperez",
"personal_website": "https://juanperez.com",
"display_order": 1,
"is_visible_in_team": true
}
Sistema de Invitaciones de Administradores
Los administradores pueden invitar a nuevos administradores mediante un sistema seguro de invitaciones por email:
Endpoints de Gestión (Requieren autenticación admin)
POST /api/admin/invitations- Crear invitación de administradorGET /api/admin/invitations- Listar invitaciones (con filtros y paginación)GET /api/admin/invitations/{invitation_id}- Obtener detalles de una invitaciónDELETE /api/admin/invitations/{invitation_id}- Cancelar una invitación
Endpoint Público (Aceptar invitación)
POST /api/auth/accept-admin-invitation- Aceptar invitación y crear cuenta de administrador
Campos para crear invitación (POST /api/admin/invitations):
email(string, requerido) - Email del invitadomessage(string, opcional) - Mensaje personalizado para el invitadoexpires_hours(integer, opcional, default: 168) - Horas hasta la expiración (1-720, default 7 días)
Ejemplo de creación de invitación:
POST /api/admin/invitations
{
"email": "nuevo.admin@example.com",
"message": "Te invitamos a unirte al equipo de administradores de Floutic",
"expires_hours": 168
}
Respuesta de creación:
{
"id": 1,
"email": "nuevo.admin@example.com",
"invited_by": 5,
"inviter_username": "admin1",
"message": "Te invitamos a unirte al equipo...",
"expires_at": "2025-12-29T12:00:00Z",
"used": false,
"used_at": null,
"created_at": "2025-12-22T12:00:00Z"
}
Filtros para listar invitaciones (GET /api/admin/invitations):
page(integer, default: 1) - Número de páginasize(integer, default: 20, max: 100) - Tamaño de páginastatus(string: "all"|"pending"|"used"|"expired", default: "all") - Filtrar por estadosearch(string, opcional) - Buscar por email
Campos para aceptar invitación (POST /api/auth/accept-admin-invitation):
token(string, requerido) - Token de invitación (proporcionado en el email)username(string, requerido) - Nombre de usuario (3-50 caracteres, solo letras, números y _)password(string, requerido) - Contraseña (mínimo 8 caracteres)
Características del sistema de invitaciones:
- Los tokens son únicos y se hashean antes de guardarse en la base de datos
- Los tokens expiran después del tiempo especificado (default: 7 días)
- Los tokens son de un solo uso (una vez aceptados, no pueden reutilizarse)
- Se valida que no exista ya un usuario con el email o username antes de crear la cuenta
- El nuevo administrador se crea automáticamente con
email_verified=Trueyis_active=True - Se envía un email con el enlace de invitación que contiene el token
Proyectos
Listado y Búsqueda
GET /api/projects/public- Listar proyectos públicos (marketplace)GET /api/projects/- Listar proyectos (con filtros y paginación)GET /api/projects/my- Mis proyectos (empresa o experto)GET /api/projects/all- Todos los proyectos (admin)GET /api/projects/{project_id}- Ver proyecto específicoGET /api/projects/{project_id}/applications- Aplicaciones de un proyecto
Gestión de Proyectos
POST /api/projects/- Crear proyecto (requiere email verificado, perfil verificado y datos fiscales para primer proyecto)PUT /api/projects/{project_id}- Actualizar proyectoPATCH /api/projects/{project_id}/status- Cambiar estado de proyectoDELETE /api/projects/{project_id}- Eliminar proyecto
Aplicaciones y Selección
POST /api/projects/{project_id}/apply- Aplicar a proyecto (experto)POST /api/projects/{project_id}/select/{expert_id}- Seleccionar experto (requiere datos fiscales del experto si es primer proyecto)POST /api/projects/{project_id}/selection/cancel- Cancelar selección de experto
Validación y Curación
POST /api/projects/{project_id}/submit- Enviar proyecto para validaciónPOST /api/projects/{project_id}/validate- Validar proyecto (admin)POST /api/projects/{project_id}/curate- Curación manual de expertos (admin)POST /api/projects/{project_id}/auto-curate- Curación automática de expertos (admin)GET /api/projects/{project_id}/curation-suggestions- Sugerencias de curación
Otros
POST /api/projects/{project_id}/request-budget- Solicitar presupuesto desde perfil de expertoPOST /api/projects/{project_id}/dispute- Crear disputa en proyecto
Hitos (Milestones)
CRUD de Milestones
POST /api/milestones/- Crear hito (empresa)GET /api/milestones/project/{project_id}- Listar hitos de proyecto (paginado)GET /api/milestones/{milestone_id}- Ver hito específicoPUT /api/milestones/{milestone_id}- Actualizar hito (solo pendientes)DELETE /api/milestones/{milestone_id}- Eliminar hito (solo pendientes)
Entregas de Hitos
La gestión del flujo de trabajo de milestones (completar, aprobar, rechazar) se realiza a través del sistema de entregas:
POST /api/milestones/deliveries/- Crear entrega de hito (experto)GET /api/milestones/deliveries/milestone/{milestone_id}- Listar entregas de un hitoGET /api/milestones/deliveries/project/{project_id}- Listar entregas de un proyectoGET /api/milestones/deliveries/expert/me- Listar entregas del experto actualGET /api/milestones/deliveries/{delivery_id}- Ver entrega específicaPUT /api/milestones/deliveries/{delivery_id}- Actualizar entrega (solo si necesita revisión)PUT /api/milestones/deliveries/{delivery_id}/review- Revisar entrega (aprobar/rechazar/solicitar revisión)
Reseñas (Reviews)
POST /api/reviews/- Crear reseñaGET /api/reviews/user/{user_id}- Reseñas de un usuario (paginado)GET /api/reviews/stats/{user_id}- Estadísticas de reseñas de un usuarioPUT /api/reviews/{review_id}- Actualizar reseñaPUT /api/reviews/{review_id}/respond- Responder a reseñaGET /api/reviews/project/{project_id}- Reseña de un proyectoGET /api/reviews/project/{project_id}/reviewer/{reviewer_id}- Reseña específica por proyecto y revisorGET /api/reviews/{review_id}- Ver reseña específicaDELETE /api/reviews/{review_id}- Eliminar reseña (admin)
Pagos
POST /api/payments/initiate- Crear PaymentIntent del proyecto/hitoPOST /api/payments/release- Liberar pago retenido (Stripe capture)POST /api/payments/release-and-charge-next- Liberar pago actual, transferir neto al experto vía Connect y crear PaymentIntent del siguiente hitoPOST /api/payments/sync-status- Sincronizar estado con Stripe (marcaheld, actualizaheld_atystripe_charge_id)POST /api/payments/refund- Crear reembolsoGET /api/payments/history- Historial de pagos del usuarioGET /api/payments/project/{project_id}- Pagos por proyectoGET /api/payments/{id}- Ver pago específicoPOST /api/payments/webhooks/stripe- Webhook Stripe
Stripe Connect
GET /api/stripe-connect/status- Verificar estado de cuenta Connect del expertoPOST /api/stripe-connect/account-link- Generar enlace de onboarding ExpressPOST /api/stripe-connect/account-update-link- Generar enlace para actualizar información de cuenta Connect
Chat
GET /api/chat/{project_id}- Obtener mensajes del chat (paginado)POST /api/chat/{project_id}- Enviar mensajePUT /api/chat/{project_id}/messages/{message_id}- Editar mensajeGET /api/chat/{project_id}/messages/{message_id}- Obtener mensaje específicoDELETE /api/chat/{project_id}/messages/{message_id}- Eliminar mensajePOST /api/chat/{project_id}/files- Subir archivo al chatGET /api/chat/{project_id}/files/{message_id}- Descargar archivo del chatPOST /api/chat/{project_id}/mark-read- Marcar mensajes como leídos
Notificaciones
GET /api/notifications/- Consultar notificaciones (paginado)POST /api/notifications/mark-read- Marcar notificación como leídaPOST /api/notifications/mark-all-read- Marcar todas como leídasPOST /api/notifications/test- Probar notificaciones (persistencia + WebSocket)POST /api/notifications/webhook/test- Disparar evento de prueba de webhook
WebSocket
WS /api/ws/notifications- Conexión WebSocket para notificaciones en tiempo real
Skills (Habilidades)
GET /api/skills/active- Obtener lista de skills activas (público)GET /api/skills/{slug}- Obtener página de habilidad por slug (público)GET /api/skills/{slug}/experts- Obtener expertos con una habilidad específica (paginado, público)
Dashboard de Experto
GET /api/expert/stats- Estadísticas del experto (aplicaciones, proyectos, ganancias)GET /api/expert/applications- Aplicaciones del experto (paginado)GET /api/expert/available-projects- Proyectos disponibles para el experto (paginado)GET /api/expert/assigned-projects- Proyectos asignados al experto (paginado)GET /api/expert/invitations- Invitaciones a proyectos (paginado)
Administración
Gestión de Usuarios
GET /api/admin/users- Listar usuarios con filtros (rol, estado, verificación, búsqueda)GET /api/admin/users/{user_id}- Obtener usuario por IDPUT /api/admin/users/{user_id}- Actualizar usuario basePUT /api/admin/users/{user_id}/verify- Verificar usuario/perfilPUT /api/admin/users/{user_id}/unverify- Desverificar usuario/perfilPUT /api/admin/users/{user_id}/pre-evaluation- Establecer pre-evaluaciónPOST /api/admin/users/{user_id}/recontact- Recontactar empresaPUT /api/admin/users/{user_id}/reject- Rechazar perfil de usuarioPUT /api/admin/users/{user_id}/resubmit- Reenviar perfil para revisiónPUT /api/admin/users/{user_id}/status- Actualizar estado de usuarioPOST /api/admin/users/{user_id}/deletion-request- Solicitar eliminación de usuario (añadeemp-bajaen GHL)POST /api/admin/users/{user_id}/deletion-confirm- Confirmar eliminación de usuario (remueveemp-baja, añadeemp-baja-confirmadaen GHL)DELETE /api/admin/users/{user_id}- Eliminar usuario definitivamente:- Empresas: Remueve
emp-bajayemp-baja-confirmada, añadeemp-eliminadoen GHL - Expertos: Añade
exp-eliminadoen GHL - Registra evento
user_deletedenghl_sync_log - Si GHL falla, no bloquea la eliminación (solo registra warning)
- Empresas: Remueve
PUT /api/admin/users/{user_id}/change-password- Cambiar contraseña de usuarioPUT /api/admin/users/{user_id}/suspend- Suspender usuarioPUT /api/admin/users/{user_id}/roles- Gestionar roles de usuario (añadir, eliminar, cambiar rol activo)
Gestión de Roles:
- Permite añadir o eliminar roles de un usuario
- Requiere que el usuario tenga al menos un rol
- Si se elimina el rol activo, se asigna automáticamente el primer rol disponible
- Los roles disponibles son:
empresa,experto,admin
Gestión de Perfiles
POST /api/admin/profiles/expert/{user_id}- Crear perfil de experto (genera slug automático)POST /api/admin/profiles/company/{user_id}- Crear perfil de empresaGET /api/admin/profiles- Listar perfiles con filtros
Gestión de Proyectos
GET /api/admin/projects- Listar proyectos con filtrosGET /api/admin/projects/{project_id}- Obtener proyecto completo (admin)
Gestión de Pagos
GET /api/admin/payments- Listar pagos con filtrosPOST /api/admin/payments/{id}/refund- Procesar reembolso
Integración GoHighLevel
GET /api/admin/users/{user_id}/ghl-tags- Etiquetas GHL esperadas vs. actualesGET /api/admin/users/{user_id}/ghl-diagnosis- Diagnóstico completo de sincronización GHLPOST /api/admin/users/{user_id}/ghl-sync-tags- Forzar sincronización manual de tagsGET /api/admin/users/{user_id}/suggest-level- Sugerir nivel de experto basado en lead_scoreGET /api/admin/users/{user_id}/reputation- Métricas de reputación incluyendo lead_score
Valoración Interna
PUT /api/admin/users/{user_id}/internal-rating- Actualizar valoración interna de un usuario- Parámetros:
rating(1.0-5.0),reason(mínimo 10 caracteres) - Crea automáticamente un registro en el historial de cambios
- Sincroniza con GoHighLevel si está habilitado
- Parámetros:
GET /api/admin/users/{user_id}/internal-rating-history- Obtener historial de cambios de valoración- Parámetros opcionales:
limit(1-50, default: 10) - Devuelve: historial ordenado por fecha descendente con valoración anterior/nueva, razón, admin que lo cambió
- Parámetros opcionales:
Ejemplo de respuesta de historial:
{
"user_id": 123,
"history": [
{
"id": 5,
"old_rating": 3.0,
"new_rating": 4.5,
"reason": "Mejora en calidad de entregas",
"changed_by": "admin_username",
"changed_by_id": 1,
"created_at": "2024-12-12T10:30:00"
}
],
"total": 1
}
Métricas y Estadísticas
GET /api/admin/metrics- Métricas básicas del sistema (usuarios, proyectos, ingresos, top expertos/empresas)GET /api/admin/metrics/growth- Métricas con cálculo de crecimiento por período
Parámetros de /api/admin/metrics/growth:
period(string, default: "30d") - Período de comparación:7d,30d,90d,1y
Respuesta de /api/admin/metrics/growth:
{
"period": "30d",
// Valores actuales
"total_revenue": 50000.0,
"active_projects": 15,
"total_users": 250,
"total_projects": 100,
"completion_rate": 65.5,
"average_project_value": 2500.0,
"expert_satisfaction": 4.5,
"company_satisfaction": 4.2,
"dispute_rate": 3.5,
// Crecimientos (porcentaje comparando período actual vs anterior)
"revenue_growth": 12.5,
"projects_growth": 8.0,
"users_growth": 5.5,
"completion_rate_growth": 2.0,
"average_project_value_growth": -1.5,
"expert_satisfaction_growth": 0.3,
"company_satisfaction_growth": 0.5,
"dispute_rate_growth": -0.5,
// Datos adicionales
"monthly_revenue": [
{"month": "2025-02", "revenue": 3000.0, "projects": 2},
{"month": "2025-03", "revenue": 4000.0, "projects": 3}
// ... últimos 12 meses en orden cronológico
],
"project_types": {"private": 30, "curated": 70},
"project_statuses": {
"draft": 5, "pending_publication": 3, "published_private": 10,
"published_curated": 15, "bidding": 8, "assigned": 12,
"in_progress": 10, "in_review": 5, "completed": 25, "disputed": 7
}
}
Cálculo de crecimiento:
- Compara el período actual con el período inmediatamente anterior
- Ejemplo:
30dcompara últimos 30 días vs los 30 días anteriores - Si no hay datos en el período anterior, se muestra
100%si hay datos actuales, o0%si no hay datos
Integraciones
GoHighLevel
POST /api/integrations/ghl/contact- Sincronizar contacto con GHL (admin)POST /api/integrations/ghl/opportunity- Crear oportunidad en GHL (admin)POST /api/integrations/ghl/tag- Añadir tags a contacto en GHL (admin)GET /api/integrations/ghl/status/{contact_id}- Estado de contacto en GHL (admin)GET /api/integrations/ghl/sync-logs- Historial de sincronizaciones (admin)
Webhooks Externos
POST /api/webhooks/ghl- Recibir webhooks de GoHighLevel
Testing (Solo en desarrollo)
POST /api/v1/testing/reset-e2e- Reiniciar base de datos al estado demo (protegido porENABLE_TEST_RESET_ENDPOINT)
Prácticas de Seguridad Backend
Prevención de Inyección SQL
- Uso estricto de ORM: Preferir métodos nativos de SQLAlchemy (
User.roles.contains("admin")) sobre SQL crudo. - Bind Parameters: Si es necesario usar
text(), SIEMPRE utilizar.bindparams()para pasar valores. - Prohibido: Interpolación de strings (f-strings) dentro de consultas SQL.
Validación de Archivos (Uploads)
- Magic Numbers: No confiamos en la extensión del archivo. Se utiliza
python-magicpara inspeccionar los primeros bytes del archivo y determinar su tipo MIME real. - Tipos Permitidos: Lista blanca estricta (Imágenes, PDF, DOCX, ZIP).
- Bloqueo: Archivos ejecutables o scripts renombrados (ej.
malware.sh.jpg) son rechazados automáticamente.
Protección de Datos en Logs
- Scrubbing Automático: Un middleware intercepta errores 500 y ofusca automáticamente claves sensibles (
password,token,secret,credit_card) en el cuerpo del request antes de enviarlo a los logs (OpenObserve). - Prevención: Evita que credenciales de usuario queden registradas en texto plano en caso de crash del servidor.
Documentación Interactiva
Para documentación completa e interactiva con ejemplos, visita:
- Swagger UI: https://api.haorp.es/docs
- ReDoc: https://api.haorp.es/redoc
Notas Importantes
- Todos los endpoints requieren autenticación excepto los marcados como "público"
- Los endpoints de administración requieren que el usuario tenga el rol
adminen su array deroles - Los endpoints de experto requieren que
active_roleseaexperto - Los endpoints de empresa requieren que
active_roleseaempresacon perfil verificado - Los usuarios pueden tener múltiples roles y cambiar entre ellos usando
/api/auth/switch-role - La paginación está disponible en la mayoría de endpoints de listado
- Los filtros y ordenación están disponibles según el endpoint