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)GET /api/projects/{project_id}/my-application- Obtener mi propuesta para un proyecto (experto)POST /api/projects/{project_id}/applications/{application_id}/request-revision- Solicitar cambios en una propuesta (empresa). Pasa la propuesta aneeds_revisiony guardafeedback.PUT /api/projects/{project_id}/applications/{application_id}- Re-enviar propuesta modificada (experto). Solo permitido si está enneeds_revision.POST /api/projects/{project_id}/applications/{application_id}/reject- Rechazar propuesta (empresa)POST /api/projects/{project_id}/select/{expert_id}- Seleccionar experto (requiere datos fiscales del experto si es primer proyecto). Nota: Solo permitido si el proyecto está enpublished_curated,published_privateobidding(y estados legacypublished/openpara compatibilidad). Endraftopending_publicationresponde 400 con un mensaje explicativo.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 proyectoGET /api/projects/{project_id}/dispute- Obtener la disputa más reciente del proyecto (empresa/experto/admin)
Contrato API de Disputas
Crear disputa (POST /api/projects/{project_id}/dispute)
Permisos: participante del proyecto (company_id o expert_id).
Request body (campos soportados):
{
"title": "Incumplimiento de entregables",
"reason": "Texto principal de la disputa",
"description": "Alternativa a reason",
"dispute_type": "delivery",
"priority": "high",
"evidence": "Evidencia textual o referencia",
"requested_resolution": "Mediación y ajuste de alcance",
"contact_preference": "email"
}
Reglas de validación relevantes:
- Se requiere
reasonodescription. - Solo se permite una disputa activa por proyecto (
openoin_review). - No se permite crear disputa en proyectos
completedo yadisputed.
Response (201):
{
"message": "Dispute created successfully. Admin will review the case.",
"dispute_id": 123
}
Obtener disputa del proyecto (GET /api/projects/{project_id}/dispute)
Response (200):
{
"id": 123,
"project_id": 77,
"payment_id": 55,
"raised_by": 9,
"status": "open",
"reason": "Texto de disputa",
"evidence": "...",
"requested_resolution": "...",
"resolution": null,
"resolution_action": null,
"resolved_by": null,
"created_at": "2026-02-11T15:45:00",
"resolved_at": null
}
Endpoints admin de disputas
GET /api/admin/disputes- Listado paginado- Query params:
page,size,status,sort_by(created_at|status),sort_order(asc|desc),search
- Query params:
GET /api/admin/disputes/{dispute_id}- Detalle de disputaPUT /api/admin/disputes/{dispute_id}/mediate- Pasar a mediación- Query params:
notes(10..2000)
- Query params:
PUT /api/admin/disputes/{dispute_id}/resolve- Resolver disputa- Query params:
resolution(10..2000),resolution_action
- Query params:
resolution_action soportadas y side effects principales:
resolve_favor_expertorelease_to_expert→ pagoreleased(si estabadisputed|held|pending)resolve_favor_companyorefund_company→ pagorefunded(si estabadisputed|held|pending|released)
En resolución:
- la disputa pasa a
resolved, - el proyecto pasa de
disputedain_progress, - se registran trazas en
project.admin_notescon prefijo[DISPUTE_EVENT], - se envían notificaciones a las partes.
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, capturar y transferir neto al experto vía Connect (o diferir si balance insuficiente) 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 StripePOST /api/payments/confirm-initial/{project_id}- Confirmar pago inicial del proyecto y activar proyectoGET /api/payments/public-key- Obtener clave pública de Stripe (sin autenticación)GET /api/payments/intent/{payment_intent_id}- Obtener detalles de un PaymentIntent desde StripeGET /api/payments/saved-methods- Listar métodos de pago guardados (empresa)DELETE /api/payments/saved-methods/{payment_method_id}- Eliminar método de pago guardadoPOST /api/payments/attach-method- Guardar método de pago tras transacción exitosaPOST /api/payments/retry-transfer/{payment_id}- Reintentar transferencia fallida (admin)GET /api/payments/{payment_id}/receipt- Obtener URL del recibo de 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 ConnectPOST /api/stripe-connect/admin/disconnect/{user_id}- Desconectar cuenta Connect de un experto (admin)
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)
DAC7 — Cumplimiento Normativo
Sistema de previsualización y revisión de datos fiscales para cumplimiento DAC7 (normativa española de declaración de ingresos de plataformas digitales).
Endpoints de Experto
-
GET /api/dac7/expert/dac7-summary- Obtener resumen DAC7 del experto para un año fiscal- Query params:
year(requerido) — Año fiscal a consultar - Requiere: Rol experto + datos fiscales completos (
fiscal_data_complete=true) - Respuesta 400: Si los datos fiscales no están completos
- Respuesta:
Dac7SummaryResponsecon datos fiscales, resumen de ingresos y estado de revisión
- Query params:
-
POST /api/dac7/expert/dac7-review- Confirmar revisión DAC7 del experto- Body:
{ "period": 2026, "confirmed": true } - Requiere: Rol experto + datos fiscales completos +
confirmed=true - Respuesta 400: Si
confirmed=falseo datos fiscales incompletos - Respuesta 409: Si ya fue revisado para el mismo período
- Body:
Endpoints de Admin
POST /api/dac7/admin/notify-experts- Notificar a expertos con ingresos sobre revisión DAC7- Body:
{ "year": 2026, "review_deadline": "2027-01-15" } - Requiere: Rol admin
- Comportamiento: Busca expertos con datos fiscales completos e ingresos > 0 en el año dado, envía email de notificación, actualiza
dac7_review_statusanotified - Respuesta:
{ "notified_count": N, "skipped_count": M }
- Body:
Modelo de Datos (Profile)
Campos DAC7 agregados al modelo Profile:
| Campo | Tipo | Descripción |
|---|---|---|
fiscal_type | string | Tipo fiscal: autonomo, empresa, individual |
birth_date | date | Fecha de nacimiento |
vat_number | string | NIF/CIF para empresas |
irpf_rate | integer | Retención IRPF: 0, 7 o 15% |
commercial_registry | string | Registro mercantil (empresas) |
fiscal_data_complete | boolean | Indica si todos los campos fiscales requeridos están completos |
dac7_review_status | string | Estado revisión: pending_review, notified, reviewed |
dac7_review_period | integer | Año del período revisado |
dac7_reviewed_at | datetime | Fecha de confirmación de revisión |
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 IDGET /api/admin/users/{user_id}/profile- Obtener el perfil completo del usuario (incluye campos admin comoverification_notes). Si el usuario tiene múltiples perfiles, prioriza el delactive_role.PUT /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 filtrosGET /api/admin/payments/{payment_id}- Detalle de pago individualPOST /api/admin/payments/{id}/refund- Procesar reembolsoPOST /api/admin/payments/reconcile- Reconciliar pagos stale con estado real de Stripe
Configuración de Comisiones
GET /api/admin/commission-config- Listar todas las configuraciones de comisiónPUT /api/admin/commission-config/bulk- Actualizar configuraciones en loteGET /api/admin/commission-config/{level}- Obtener configuración por nivel de expertoPUT /api/admin/commission-config/{level}- Actualizar configuración por nivel
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.
Manejo de Errores
La API utiliza un contrato de errores estandarizado para todas las respuestas fallidas (4xx, 5xx).
Los errores se devuelven en formato JSON con la siguiente estructura:
{
"detail": {
"code": "ERROR_CODE",
"message": "Mensaje legible para el usuario"
}
}
Para ver la lista completa de códigos de error y su significado, consulta la Documentación de Errores.
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