# API REST — Referencia > Base URL: `http://10.82.68.125:8000/api/v1` · Docs interactivos: `http://localhost:8000/docs` Todos los endpoints (excepto `/auth/*`) requieren header: ``` Authorization: Bearer ``` --- ## 🔐 Autenticación ### POST `/auth/register` Crea un usuario nuevo (rol CIUDADANO por defecto). **Request:** ```json { "full_name": "Juan Pérez", "email": "juan@example.com", "password": "secret123" } ``` **Response 201:** ```json { "access_token": "eyJ...", "token_type": "bearer", "role": "CIUDADANO" } ``` ### POST `/auth/login` **Request:** ```json { "email": "demo@celaya.gob.mx", "password": "Celaya2026" } ``` **Response 200:** ```json { "access_token": "eyJ...", "token_type": "bearer", "role": "CIUDADANO" } ``` **Response 401:** `{"detail": "Credenciales inválidas"}` ### POST `/auth/oauth` Login/registro vía OAuth (Google, Facebook, Apple). ```json { "provider": "google", "oauth_id": "abc123", "email": "juan@gmail.com", "full_name": "Juan", "push_token": "..." } ``` ### GET `/me` Devuelve el usuario actual. **Response:** `{ "id": 1, "full_name": "...", "email": "...", "role": "CIUDADANO" }` --- ## 🏠 Domicilios (`/addresses`) ### GET `/addresses/` Lista tus domicilios. **Response:** `[{"id":1, "label":"Casa", "street":"...", "lat":20.5, "lng":-100.8, "route_id":"RUTA-01", "is_default":true}, ...]` ### POST `/addresses/` Crea un domicilio. Si pasas `lat`/`lng`, se asigna ruta automáticamente. ```json { "label": "Casa", "street": "Hidalgo 245", "colony": "Centro", "lat": 20.5215, "lng": -100.8142, "is_default": true } ``` ### PATCH `/addresses/{id}` Actualiza un domicilio. Solo campos modificados. ```json { "is_default": true } ``` ### DELETE `/addresses/{id}` → 204 --- ## ⏰ ETA (`/eta`) ### GET `/eta/address/{id}` — núcleo del sistema **Privacy-by-design:** nunca devuelve coordenadas del camión. **Response 200:** ```json { "status": "EN_CAMINO", "message": "El camión llegará a tu zona entre las 7:20 y 7:35", "eta_minutes": 12, "window_start": "07:20", "window_end": "07:35", "progress": 45.2, "route_name": "Zona Centro - Las Arboledas", "passes_today": true } ``` **Estados posibles:** - `PROGRAMADO` — la ruta aún no empieza hoy - `EN_CAMINO` — el camión va en ruta - `LLEGANDO` — faltan ≤10 minutos - `PASO` — ya pasó por la zona - `NO_SERVICIO` — no aplica hoy ### GET `/eta/schedule/{address_id}` Devuelve días y horario aproximado. ```json { "route_id":"RUTA-01", "route_name":"Zona Centro - Las Arboledas", "days_of_week":["Lunes","Miércoles","Viernes"], "approximate_time":"06:00 - 07:40", "truck_id": 101 } ``` ### POST `/eta/rate` Califica el servicio. ```json { "address_id": 1, "rating": 5, "comment": "Excelente puntualidad" } ``` --- ## 📋 Reportes ciudadanos (`/reports`) ### POST `/reports/` Crea un reporte con folio único. ```json { "address_id": 1, "report_type": "NO_PASO", "description": "El camión no pasó hoy" } ``` **Response 201:** ```json { "id":5, "folio":"MRL-20260523-F6EC92", "status":"PENDIENTE", "report_type":"NO_PASO", "description":"...", "created_at":"...", "address_label":"Casa" } ``` **Tipos:** `NO_PASO` · `RETRASO` · `ACUMULACION` · `OTRO` ### GET `/reports/` Tus reportes (no los de otros usuarios). ### GET `/reports/{id}` Detalle con la etiqueta del domicilio. --- ## 👮 Staff (`/staff`) — solo EMPLEADO o ADMIN ### GET `/staff/dashboard` Métricas motivacionales del empleado. ```json { "employee_name": "Carlos Hernández", "streak_days": 19, "punctuality_pct": 88, "bonus_accumulated_mxn": 950, "next_milestone_days": 11, "next_milestone_mxn": 500, "reports_generated": 5, "motivation_quote": "Tu puntualidad permite que miles de familias planifiquen su día", "rating_label": "BUENO" } ``` ### GET `/staff/schedule` Horario preestablecido con descansos. ### GET `/staff/categories` Las 8 categorías disponibles para reportes operativos. ### POST `/staff/operational-reports` Crea un reporte operativo (folio `OP-...`). ```json { "category": "FALLA_MECANICA", "severity": "MEDIA", "description": "Frenos haciendo ruido", "route_id": "RUTA-01", "truck_id": 12 } ``` **Categorías:** `NO_ARRANQUE` · `FALLA_MECANICA` · `ACCIDENTE` · `OBSTACULO` · `TRAFICO` · `COMBUSTIBLE` · `CLIMA` · `OTRO` ### GET `/staff/operational-reports` Lista tus reportes operativos. --- ## 🛡️ Admin (`/admin`) — solo ADMIN ### GET `/admin/stats` KPIs globales del sistema. ```json { "total_ciudadanos": 185, "total_domicilios": 302, "total_reportes": 280, "reportes_24h": 8, "promedio_calificacion": 4.07, "reportes_por_estado": {"PENDIENTE": 84, "EN_PROCESO": 56, "RESUELTO": 112, "CERRADO": 28}, "reportes_por_tipo": {"NO_PASO": 98, "RETRASO": 84, ...}, "rutas_activas": 15 } ``` ### GET `/admin/reports?status=PENDIENTE&report_type=NO_PASO` Lista TODOS los reportes ciudadanos (no solo los tuyos). Filtros opcionales. ### PATCH `/admin/reports/{id}/status?status=EN_PROCESO` Cambia el estado de un reporte. Estados válidos: `PENDIENTE | EN_PROCESO | RESUELTO | CERRADO`. ### GET `/admin/routes` Lista todas las rutas con su estado actual. ### GET `/admin/users?role=CIUDADANO` Lista usuarios con conteos de domicilios y reportes. ### PATCH `/admin/users/{id}/role?role=EMPLEADO` Cambia el rol de un usuario. Roles: `CIUDADANO | EMPLEADO | ADMIN`. ### GET `/admin/feedback` Últimas 50 calificaciones del servicio. --- ## 🔒 Códigos de respuesta | Código | Significado | |--------|-------------| | 200 | OK | | 201 | Creado | | 204 | Sin contenido (DELETE exitoso) | | 400 | Bad request (validación falló) | | 401 | No autenticado / token inválido | | 403 | Sin permisos para este recurso | | 404 | Recurso no encontrado o no te pertenece | | 500 | Error del servidor | --- ## 🧪 Ejemplos con curl ### Flujo completo: ciudadano → reporte → admin lo resuelve ```bash BASE=http://10.82.68.125:8000/api/v1 # 1. Login ciudadano CTOKEN=$(curl -s -X POST $BASE/auth/login -H "Content-Type: application/json" \ -d '{"email":"demo@celaya.gob.mx","password":"Celaya2026"}' | jq -r .access_token) # 2. Listar domicilios curl -s $BASE/addresses/ -H "Authorization: Bearer $CTOKEN" | jq # 3. Ver ETA del domicilio 1 curl -s $BASE/eta/address/1 -H "Authorization: Bearer $CTOKEN" | jq # 4. Crear reporte REPORT=$(curl -s -X POST $BASE/reports/ -H "Authorization: Bearer $CTOKEN" \ -H "Content-Type: application/json" \ -d '{"address_id":1,"report_type":"NO_PASO","description":"Hoy no pasó"}') echo $REPORT | jq REPORT_ID=$(echo $REPORT | jq -r .id) # 5. Login admin ATOKEN=$(curl -s -X POST $BASE/auth/login -H "Content-Type: application/json" \ -d '{"email":"admin@celaya.gob.mx","password":"Admin2026"}' | jq -r .access_token) # 6. Admin ve TODOS los reportes curl -s $BASE/admin/reports -H "Authorization: Bearer $ATOKEN" | jq '. | length' # 7. Admin cambia el estado a EN_PROCESO curl -s -X PATCH "$BASE/admin/reports/$REPORT_ID/status?status=EN_PROCESO" \ -H "Authorization: Bearer $ATOKEN" | jq # 8. El ciudadano vuelve a consultar y ve el cambio curl -s $BASE/reports/$REPORT_ID -H "Authorization: Bearer $CTOKEN" | jq .status # → "EN_PROCESO" ✓ ```