# 📚 Documentación API - Syntria ## 🔐 Autenticación Todos los endpoints (excepto `/api/auth/login` y `/api/auth/register`) requieren autenticación mediante token JWT en el header: ``` Authorization: Bearer {token} ``` --- ## 🔑 AUTH - Autenticación ### 1. Login **POST** `/api/auth/login` Inicia sesión y obtiene el token de acceso. **Body:** ```json { "username": "admin", "password": "admin123" } ``` **Response 200:** ```json { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "bearer", "user": { "id": 1, "username": "admin", "email": "admin@syntria.com", "full_name": "Administrador", "role": "admin", "is_active": true, "created_at": "2025-11-19T00:00:00Z" } } ``` **Errores:** - `401 Unauthorized` - Usuario o contraseña incorrectos --- ### 2. Registro **POST** `/api/auth/register` Crea una nueva cuenta de usuario. **Body:** ```json { "username": "nuevo_usuario", "password": "password123", "email": "usuario@email.com", "full_name": "Usuario Nuevo", "role": "mechanic" } ``` **Response 200:** ```json { "id": 2, "username": "nuevo_usuario", "email": "usuario@email.com", "full_name": "Usuario Nuevo", "role": "mechanic", "is_active": true, "created_at": "2025-11-19T00:00:00Z" } ``` **Errores:** - `400 Bad Request` - Usuario ya existe --- ### 3. Obtener Mi Perfil **GET** `/api/auth/me` Obtiene la información del usuario autenticado. **Headers:** ``` Authorization: Bearer {token} ``` **Response 200:** ```json { "id": 1, "username": "admin", "email": "admin@syntria.com", "full_name": "Administrador", "role": "admin", "is_active": true, "created_at": "2025-11-19T00:00:00Z" } ``` --- ## 👥 USERS - Gestión de Usuarios ### 1. Listar Usuarios (Admin) **GET** `/api/users` Lista todos los usuarios del sistema. **Query Params:** - `skip` (int, default: 0) - Paginación - `limit` (int, default: 100) - Límite de resultados - `active_only` (bool, default: false) - Solo usuarios activos **Headers:** ``` Authorization: Bearer {token} ``` **Response 200:** ```json [ { "id": 1, "username": "admin", "email": "admin@syntria.com", "full_name": "Administrador", "role": "admin", "is_active": true, "created_at": "2025-11-19T00:00:00Z" }, { "id": 2, "username": "mecanico", "email": "mecanico@syntria.com", "full_name": "Mecánico", "role": "mechanic", "is_active": true, "created_at": "2025-11-19T00:00:00Z" } ] ``` **Errores:** - `403 Forbidden` - No tienes permisos (solo admin) --- ### 2. Obtener Usuario por ID (Admin) **GET** `/api/users/{user_id}` Obtiene un usuario específico. **Headers:** ``` Authorization: Bearer {token} ``` **Response 200:** ```json { "id": 2, "username": "mecanico", "email": "mecanico@syntria.com", "full_name": "Mecánico", "role": "mechanic", "is_active": true, "created_at": "2025-11-19T00:00:00Z" } ``` **Errores:** - `403 Forbidden` - No tienes permisos - `404 Not Found` - Usuario no encontrado --- ### 3. Crear Usuario (Admin) **POST** `/api/users` Crea un nuevo usuario. **Headers:** ``` Authorization: Bearer {token} ``` **Body:** ```json { "username": "nuevo_mecanico", "password": "password123", "email": "mecanico2@syntria.com", "full_name": "Mecánico 2", "role": "mechanic" } ``` **Response 200:** ```json { "id": 3, "username": "nuevo_mecanico", "email": "mecanico2@syntria.com", "full_name": "Mecánico 2", "role": "mechanic", "is_active": true, "created_at": "2025-11-19T00:00:00Z" } ``` **Errores:** - `400 Bad Request` - Usuario ya existe o email en uso - `403 Forbidden` - No tienes permisos --- ### 4. Actualizar Usuario (Admin) **PUT** `/api/users/{user_id}` Actualiza información de un usuario. **Headers:** ``` Authorization: Bearer {token} ``` **Body:** ```json { "username": "nuevo_username", "email": "nuevo_email@syntria.com", "full_name": "Nombre Actualizado", "role": "admin" } ``` **Response 200:** ```json { "id": 2, "username": "nuevo_username", "email": "nuevo_email@syntria.com", "full_name": "Nombre Actualizado", "role": "admin", "is_active": true, "created_at": "2025-11-19T00:00:00Z" } ``` **Notas:** - El campo `is_active` NO puede ser modificado por este endpoint - Para cambiar el estado usar `/deactivate` o `/activate` **Errores:** - `400 Bad Request` - Email o username ya en uso - `403 Forbidden` - No tienes permisos - `404 Not Found` - Usuario no encontrado --- ### 5. Inactivar Usuario (Admin) **PATCH** `/api/users/{user_id}/deactivate` Inactiva un usuario (soft delete). **Headers:** ``` Authorization: Bearer {token} ``` **Response 200:** ```json { "message": "Usuario inactivado correctamente", "user_id": 2 } ``` **Errores:** - `400 Bad Request` - No puedes inactivar tu propio usuario - `403 Forbidden` - No tienes permisos - `404 Not Found` - Usuario no encontrado --- ### 6. Activar Usuario (Admin) **PATCH** `/api/users/{user_id}/activate` Reactiva un usuario inactivo. **Headers:** ``` Authorization: Bearer {token} ``` **Response 200:** ```json { "message": "Usuario activado correctamente", "user_id": 2 } ``` **Errores:** - `403 Forbidden` - No tienes permisos - `404 Not Found` - Usuario no encontrado --- ### 7. Cambiar Contraseña de Usuario (Admin) **PATCH** `/api/users/{user_id}/password` Cambia la contraseña de cualquier usuario. **Headers:** ``` Authorization: Bearer {token} ``` **Body:** ```json { "new_password": "nueva_password123" } ``` **Response 200:** ```json { "message": "Contraseña actualizada correctamente" } ``` **Errores:** - `403 Forbidden` - No tienes permisos - `404 Not Found` - Usuario no encontrado --- ### 8. Actualizar Mi Perfil **PUT** `/api/users/me` Actualiza tu propio perfil. **Headers:** ``` Authorization: Bearer {token} ``` **Body:** ```json { "email": "mi_nuevo_email@syntria.com", "full_name": "Mi Nuevo Nombre" } ``` **Response 200:** ```json { "id": 1, "username": "admin", "email": "mi_nuevo_email@syntria.com", "full_name": "Mi Nuevo Nombre", "role": "admin", "is_active": true, "created_at": "2025-11-19T00:00:00Z" } ``` **Errores:** - `400 Bad Request` - Email ya en uso --- ### 9. Cambiar Mi Contraseña **PATCH** `/api/users/me/password` Cambia tu propia contraseña. **Headers:** ``` Authorization: Bearer {token} ``` **Body:** ```json { "current_password": "password_actual", "new_password": "nueva_password123" } ``` **Response 200:** ```json { "message": "Contraseña actualizada correctamente" } ``` **Errores:** - `400 Bad Request` - Contraseña actual incorrecta --- ## 🔑 API TOKENS - Tokens de Acceso API ### Autenticación con API Tokens Además de JWT tokens, puedes usar API tokens persistentes para autenticación. Los API tokens: - Tienen el prefijo `syntria_` - No expiran (hasta que sean revocados) - Se rastrean por último uso - Pueden ser gestionados desde el panel de usuario **Uso:** ```bash curl -H "Authorization: Bearer syntria_xxxxxxxxxxxxx" http://api/inspections ``` ### 1. Listar Mis Tokens **GET** `/api/users/me/tokens` Lista todos tus API tokens. **Headers:** ``` Authorization: Bearer {token} ``` **Response 200:** ```json [ { "id": 1, "description": "Token para integración con sistema externo", "is_active": true, "last_used_at": "2025-11-19T14:30:00Z", "created_at": "2025-11-15T10:00:00Z" } ] ``` **Nota:** El valor del token no se muestra por seguridad. --- ### 2. Generar Nuevo Token **POST** `/api/users/me/tokens` Genera un nuevo API token. **Headers:** ``` Authorization: Bearer {token} ``` **Body:** ```json { "description": "Token para integración con sistema externo" } ``` **Response 200:** ```json { "id": 1, "token": "syntria_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "description": "Token para integración con sistema externo", "is_active": true, "last_used_at": null, "created_at": "2025-11-19T15:00:00Z" } ``` **⚠️ IMPORTANTE:** El token completo solo se muestra una vez. Guárdalo de forma segura. --- ### 3. Revocar Mi Token **DELETE** `/api/users/me/tokens/{token_id}` Revoca (desactiva) uno de tus tokens. **Headers:** ``` Authorization: Bearer {token} ``` **Response 200:** ```json { "message": "Token revocado correctamente", "token_id": 1 } ``` **Errores:** - `404 Not Found` - Token no encontrado --- ### 4. Listar Tokens de Usuario (Admin) **GET** `/api/users/{user_id}/tokens` Lista todos los tokens de un usuario específico. **Headers:** ``` Authorization: Bearer {token} ``` **Response 200:** ```json [ { "id": 1, "description": "Token de producción", "is_active": true, "last_used_at": "2025-11-19T14:30:00Z", "created_at": "2025-11-15T10:00:00Z" } ] ``` **Errores:** - `403 Forbidden` - No tienes permisos (solo admin) --- ### 5. Revocar Token de Usuario (Admin) **DELETE** `/api/users/{user_id}/tokens/{token_id}` Revoca un token de cualquier usuario. **Headers:** ``` Authorization: Bearer {token} ``` **Response 200:** ```json { "message": "Token revocado correctamente", "token_id": 1 } ``` **Errores:** - `403 Forbidden` - No tienes permisos (solo admin) - `404 Not Found` - Token no encontrado --- ## 📋 CHECKLISTS - Plantillas de Inspección ### 1. Listar Checklists **GET** `/api/checklists` Lista todas las plantillas de inspección. **Query Params:** - `skip` (int, default: 0) - `limit` (int, default: 100) - `active_only` (bool, default: false) - Solo activas **Headers:** ``` Authorization: Bearer {token} ``` **Response 200:** ```json [ { "id": 1, "name": "Inspección Pre-Entrega", "description": "Checklist para vehículos antes de entrega", "ai_mode": "off", "scoring_enabled": true, "logo_url": null, "max_score": 100, "is_active": true, "created_at": "2025-11-19T00:00:00Z", "creator_id": 1 } ] ``` --- ### 2. Crear Checklist (Admin) **POST** `/api/checklists` Crea una nueva plantilla de inspección. **Headers:** ``` Authorization: Bearer {token} ``` **Body:** ```json { "name": "Inspección de Mantenimiento", "description": "Checklist para mantenimiento preventivo", "ai_mode": "off", "scoring_enabled": true, "logo_url": null } ``` **Response 200:** ```json { "id": 2, "name": "Inspección de Mantenimiento", "description": "Checklist para mantenimiento preventivo", "ai_mode": "off", "scoring_enabled": true, "logo_url": null, "max_score": 0, "is_active": true, "created_at": "2025-11-19T00:00:00Z", "creator_id": 1 } ``` **Errores:** - `403 Forbidden` - No tienes permisos --- ## ❓ QUESTIONS - Preguntas del Checklist ### 1. Crear Pregunta (Admin) **POST** `/api/questions` Agrega una pregunta a un checklist. **Headers:** ``` Authorization: Bearer {token} ``` **Body:** ```json { "checklist_id": 1, "section": "Motor", "text": "¿El nivel de aceite es correcto?", "type": "pass_fail", "points": 5, "options": null, "order": 1, "allow_photos": true, "max_photos": 3, "requires_comment_on_fail": true } ``` **Response 200:** ```json { "id": 1, "checklist_id": 1, "section": "Motor", "text": "¿El nivel de aceite es correcto?", "type": "pass_fail", "points": 5, "options": null, "order": 1, "allow_photos": true, "max_photos": 3, "requires_comment_on_fail": true, "created_at": "2025-11-19T00:00:00Z" } ``` --- ## 🔍 INSPECTIONS - Inspecciones Realizadas ### 1. Listar Inspecciones **GET** `/api/inspections` Lista las inspecciones realizadas. **Query Params:** - `skip` (int, default: 0) - `limit` (int, default: 100) - `vehicle_plate` (string) - Filtrar por patente - `status` (string) - Filtrar por estado (draft, completed, inactive) - `show_inactive` (bool, default: false) - Mostrar inactivas **Headers:** ``` Authorization: Bearer {token} ``` **Response 200:** ```json [ { "id": 1, "checklist_id": 1, "mechanic_id": 2, "or_number": "OR-12345", "vehicle_plate": "ABC123", "vehicle_brand": "Toyota", "vehicle_model": "Corolla", "vehicle_km": 50000, "client_name": "Juan Pérez", "score": 85, "max_score": 100, "percentage": 85.0, "flagged_items_count": 2, "status": "completed", "started_at": "2025-11-19T10:00:00Z", "completed_at": "2025-11-19T11:00:00Z", "created_at": "2025-11-19T10:00:00Z" } ] ``` --- ### 2. Crear Inspección **POST** `/api/inspections` Inicia una nueva inspección. **Headers:** ``` Authorization: Bearer {token} ``` **Body:** ```json { "checklist_id": 1, "or_number": "OR-12345", "vehicle_plate": "ABC123", "vehicle_brand": "Toyota", "vehicle_model": "Corolla", "vehicle_km": 50000, "client_name": "Juan Pérez" } ``` **Response 200:** ```json { "id": 1, "checklist_id": 1, "mechanic_id": 2, "or_number": "OR-12345", "vehicle_plate": "ABC123", "vehicle_brand": "Toyota", "vehicle_model": "Corolla", "vehicle_km": 50000, "client_name": "Juan Pérez", "score": 0, "max_score": 100, "percentage": 0.0, "flagged_items_count": 0, "status": "draft", "started_at": "2025-11-19T10:00:00Z", "created_at": "2025-11-19T10:00:00Z" } ``` --- ### 3. Completar Inspección **POST** `/api/inspections/{inspection_id}/complete` Marca una inspección como completada y calcula el score. **Headers:** ``` Authorization: Bearer {token} ``` **Response 200:** ```json { "id": 1, "status": "completed", "score": 85, "percentage": 85.0, "flagged_items_count": 2, "completed_at": "2025-11-19T11:00:00Z" } ``` --- ### 4. Inactivar Inspección (Admin) **PATCH** `/api/inspections/{inspection_id}/deactivate` Inactiva una inspección (soft delete). **Headers:** ``` Authorization: Bearer {token} ``` **Response 200:** ```json { "message": "Inspección inactivada correctamente", "inspection_id": 1 } ``` **Errores:** - `403 Forbidden` - No tienes permisos (solo admin) - `404 Not Found` - Inspección no encontrada --- ## 📝 ANSWERS - Respuestas de Inspección ### 1. Crear Respuesta **POST** `/api/answers` Registra una respuesta a una pregunta de inspección. **Headers:** ``` Authorization: Bearer {token} ``` **Body:** ```json { "inspection_id": 1, "question_id": 1, "answer_value": "pass", "answer_text": null, "is_flagged": false, "comments": null, "photos": [] } ``` **Response 200:** ```json { "id": 1, "inspection_id": 1, "question_id": 1, "answer_value": "pass", "answer_text": null, "is_flagged": false, "points_earned": 5, "comments": null, "photos": [], "created_at": "2025-11-19T10:30:00Z" } ``` --- ## 🤖 AI - Análisis con Inteligencia Artificial ### 1. Analizar Foto con IA **POST** `/api/ai/analyze` Analiza una foto usando IA y devuelve sugerencias. **Headers:** ``` Authorization: Bearer {token} Content-Type: application/json ``` **Body:** ```json { "photo_base64": "data:image/jpeg;base64,/9j/4AAQSkZJRg...", "question_text": "¿El nivel de aceite es correcto?", "question_type": "pass_fail", "section": "Motor" } ``` **Response 200:** ```json { "analysis": { "answer_value": "fail", "confidence": 0.85, "explanation": "El nivel de aceite está por debajo del mínimo recomendado", "is_flagged": true, "comments": "Se requiere rellenar aceite urgentemente" }, "model_used": "gpt-4-vision-preview", "timestamp": "2025-11-19T10:30:00Z" } ``` --- ## 📊 Códigos de Estado HTTP - `200 OK` - Solicitud exitosa - `201 Created` - Recurso creado exitosamente - `400 Bad Request` - Datos inválidos o faltantes - `401 Unauthorized` - No autenticado o token inválido - `403 Forbidden` - No tienes permisos para esta acción - `404 Not Found` - Recurso no encontrado - `500 Internal Server Error` - Error del servidor --- ## 🔐 Roles y Permisos ### Admin - ✅ Gestionar usuarios (crear, editar, inactivar, activar) - ✅ Cambiar contraseñas de cualquier usuario - ✅ Ver y revocar tokens API de cualquier usuario - ✅ Gestionar checklists y preguntas - ✅ Ver todas las inspecciones - ✅ Crear inspecciones - ✅ Inactivar inspecciones - ✅ Acceso completo a configuración de IA ### Mechanic (Mecánico) - ✅ Ver sus propias inspecciones - ✅ Crear y completar inspecciones - ✅ Responder preguntas de inspección - ✅ Usar análisis con IA - ✅ Actualizar su propio perfil - ✅ Cambiar su propia contraseña - ✅ Gestionar sus propios tokens API - ❌ No puede gestionar usuarios - ❌ No puede gestionar checklists - ❌ No puede ver tokens de otros usuarios --- ## 💡 Ejemplos de Uso ### Flujo Completo: Crear y Completar Inspección ```bash # 1. Login curl -X POST http://localhost:8000/api/auth/login \ -H "Content-Type: application/json" \ -d '{ "username": "mecanico", "password": "mec123" }' # Guardar el token de la respuesta TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." # 2. Crear inspección curl -X POST http://localhost:8000/api/inspections \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "checklist_id": 1, "or_number": "OR-12345", "vehicle_plate": "ABC123", "vehicle_brand": "Toyota", "vehicle_model": "Corolla", "vehicle_km": 50000, "client_name": "Juan Pérez" }' # Guardar inspection_id de la respuesta INSPECTION_ID=1 # 3. Responder preguntas curl -X POST http://localhost:8000/api/answers \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "inspection_id": '$INSPECTION_ID', "question_id": 1, "answer_value": "pass", "is_flagged": false, "points_earned": 5 }' # 4. Completar inspección curl -X POST http://localhost:8000/api/inspections/$INSPECTION_ID/complete \ -H "Authorization: Bearer $TOKEN" ``` --- ## 🛠️ Testing con Postman 1. Importa la colección de Postman (disponible en `/docs/postman`) 2. Configura la variable de entorno `base_url` a `http://localhost:8000` 3. Ejecuta el request de Login 4. El token se guardará automáticamente en la variable `token` 5. Los demás requests usarán el token automáticamente --- ## 📖 Documentación Interactiva Accede a la documentación interactiva de Swagger: - **Swagger UI**: `http://localhost:8000/docs` - **ReDoc**: `http://localhost:8000/redoc` Puedes probar todos los endpoints directamente desde el navegador.