Referencia API
URL base para todos los endpoints: /api/* (backend-js, puerto 3001 en desarrollo).
Todos los endpoints autenticados requieren cabecera Authorization: Bearer <access_token>, salvo donde se indique lo contrario. Los errores siempre devuelven { "error": "message string" }.
[!NOTE] Las formas de request y response se verificaron desde los DTOs, tipos de repository y tipos del cliente frontend. Los defaults de paginacion y respuestas de endpoints solo-admin marcados como Needs verification no estan cubiertos por clientes frontend.
Formato de respuesta de error
Todos los endpoints devuelven errores estructurados:
{ "error": "Human-readable error message" }Codigos HTTP usados: 400 (validacion), 401 (no autenticado), 403 (rol prohibido), 404 (no encontrado), 409 (conflicto), 500 (error de servidor).
Endpoints de auth
POST /api/auth/login
Publico. Autentica al usuario, emite access token y define la cookie refresh token.
Request body
{ "email": "user@example.com", "password": "secret" }Response 200
{
"user": {
"id": 1,
"name": "Maria Garcia",
"email": "user@example.com",
"role": "distributor",
"is_active": true
},
"access_token": "<JWT>"
}Define Set-Cookie: refresh_token=...; HttpOnly; SameSite=Lax (dev) / SameSite=None; Secure (prod).
POST /api/auth/refresh
Usa la cookie refresh token. Rota el token y emite un access token nuevo.
Request: sin body, la cookie se envia automaticamente.
Response 200
{ "access_token": "<new JWT>" }Define una cookie refresh_token nueva. El token anterior se revoca.
POST /api/auth/logout
Revoca el refresh token actual y borra la cookie.
Request: sin body.
Response 200
{ "message": "Logged out" }GET /api/auth/me
Devuelve el perfil del usuario autenticado. Requiere Bearer token.
Response 200
{
"id": 1,
"name": "Maria Garcia",
"email": "user@example.com",
"role": "distributor",
"is_active": true,
"created_at": "2025-01-15T10:30:00.000Z"
}POST /api/auth/forgotPassword
Publico. Dispara un email de reset de password. Siempre devuelve exito para evitar enumeracion de emails.
Request body
{ "email": "user@example.com" }Response 200
{ "message": "If that email is registered, a reset link has been sent." }PATCH /api/auth/changePwd
Endpoint publico basado en token. Tiene dos modos segun el body.
Modo 1 - solo verificar token (sin new_password):
{ "reset_pwd_token": "<token>" }Response 200: { "valid": true }
Modo 2 - definir password nuevo:
{ "reset_pwd_token": "<token>", "new_password": "newSecret123" }Response 200: { "message": "Password changed successfully" }
new_password debe tener al menos 6 caracteres. El token se revoca tras usarlo.
POST /api/auth/activateAccount
Basado en token. Activa una cuenta recien creada y define su password.
Request: ?token=<activate_account_token> (query param) - Needs verification sobre la division exacta entre body y query param.
Endpoints de usuarios (solo admin)
Todos los endpoints de este grupo requieren role: admin.
POST /api/users/create
Crea un usuario nuevo y envia un email de activacion.
Request body
{ "name": "Jon Doe", "email": "jon@example.com", "role": "distributor" }role debe ser "admin" o "distributor". El usuario se crea inactivo; el email de activacion se envia al email indicado.
Response 201 - Needs verification para la forma exacta; se espera el objeto de usuario creado.
GET /api/users/list
Query params
| Param | Tipo | Default | Descripcion |
|---|---|---|---|
page | number | 1 | Numero de pagina |
limit | number | 20 | Maximo 100 |
role | "admin" | "distributor" | - | Filtrar por rol |
is_active | "true" | "false" | - | Filtrar por estado activo |
Response 200 - Needs verification para la forma exacta del envelope de paginacion.
GET /api/users/getById?id=<number>
Response 200 - objeto usuario. 404 si no existe.
PATCH /api/users/update
Request body - Needs verification sobre campos permitidos; esperado { name?, email?, role?, is_active? }.
DELETE /api/users/remove?id=<number>
Elimina usuario. Un usuario no puede eliminarse a si mismo.
Response 200 o 403 si intenta autoeliminarse.
PATCH /api/users/changeMyPwd
Cualquier rol autenticado. Cambia la password propia.
Request body
{ "current_password": "oldSecret", "new_password": "newSecret123" }Response 200
{ "message": "Password updated successfully" }Endpoints de paquetes
POST /api/packages/create - admin
Crea un paquete, geocodifica la direccion, genera un tracking token y envia un email de tracking.
Request body
{
"packageInfo": {
"recipient_name": "Ane Etxeberria",
"recipient_email": "ane@example.com",
"assigned_to": null,
"created_by": 1,
"status": "pending",
"weight_kg": 2.5,
"description": "Fragile"
},
"address_info": {
"street": "Kale Nagusia 12",
"city": "Tolosa",
"postal_code": "20400"
}
}assigned_to puede ser null (sin asignar) o un ID de usuario valido. description es opcional.
Response 201 - Needs verification para la forma exacta del paquete.
GET /api/packages/list - admin
Query params - Needs verification para el set completo de filtros y envelope de paginacion.
GET /api/packages/getById?id=<number> - admin
Response 200 - PackageWithAddress:
{
"id": 42,
"tracking_code": "PAK-20260001",
"recipient_name": "Ane Etxeberria",
"recipient_email": "ane@example.com",
"weight_kg": 2.5,
"description": "Fragile",
"status": "pending",
"estimated_delivery": "2026-05-01",
"address_id": 7,
"assigned_to": null,
"created_by": 1,
"created_at": "2026-04-26T10:00:00.000Z",
"updated_at": "2026-04-26T10:00:00.000Z",
"street": "Kale Nagusia 12",
"city": "Tolosa",
"postal_code": "20400",
"latitude": 43.1298,
"longitude": -2.0773,
"country": "Espana"
}GET /api/packages/getMyPackages - distributor
Devuelve todos los paquetes asignados al repartidor autenticado.
Response 200 - array de PackageWithAddress.
PATCH /api/packages/updateStatus - distributor
Actualiza el estado de uno o varios paquetes. Debe enviarse exactamente uno de package_id o package_ids.
Request body (individual)
{ "package_id": 42, "new_status": "in_transit" }Request body (batch)
{ "package_ids": [42, 43, 44], "new_status": "delivered" }new_status debe ser un estado valido: "pending" | "assigned" | "in_transit" | "delivered" | "undelivered" | "failed".
Response 200 - un PackageWithAddress (actualizacion individual) o PackageWithAddress[] (batch).
Dispara insercion de log de estado y efectos secundarios de email (ver Modelo de dominio).
PATCH /api/packages/update?id=<number> - admin
Actualiza informacion del paquete y direccion. Needs verification para campos permitidos.
DELETE /api/packages/delete?id=<number> - admin
Response 200 - Needs verification.
GET /api/packages/getDailySummary - admin
Devuelve un conteo de paquetes por estado para hoy.
Response 200 - Needs verification para la forma exacta; esperado { pending: n, assigned: n, ... }.
Endpoints de rutas y paradas
POST /api/routes/create - admin
Crea una ruta de entrega optimizada para un repartidor en una fecha dada.
Request body
{ "user_id": 3, "date": "2026-05-02", "package_ids": [10, 11, 12] }datedebe estar en formatoYYYY-MM-DDy ser al menos manana.package_idsno puede estar vacio, no debe contener duplicados y todos deben ser IDs de paquete validos.
Response 200 - Needs verification para la forma exacta del envelope ruta+paradas.
GET /api/routes/getByUserAndDate - admin
Query params: user_id, date - Needs verification.
GET /api/routes/getMyDaily - distributor
Devuelve la ruta y paradas de hoy para el repartidor autenticado.
Response 200
{
"route": { "id": 5, "route_date": "2026-04-26", "status": "in_progress" },
"stops": [
{
"id": 21,
"stop_order": 1,
"estimated_arrival": "09:30:00",
"actual_arrival": "09:28:00",
"package": {
"id": 42,
"recipient_name": "Ane Etxeberria",
"status": "delivered",
"address": {
"street": "Kale Nagusia 12",
"city": "Tolosa",
"lat": 43.1298,
"lng": -2.0773
}
}
}
]
}PATCH /api/routes/updateStatus/:id - admin o distributor (acotado)
Request body
{ "status": "in_progress" }status debe ser "in_progress" o "completed".
Response 200
{ "message": "Route status updated" }GET /api/routes/continueFromPast - distributor
Comprueba si el repartidor tiene una ruta pasada con paradas pendientes.
Response 200
{
"pending": {
"route_id": 3,
"route_date": "2026-04-25",
"status": "in_progress",
"pending_count": 2,
"route_count": 5
}
}pending es null si no existe ruta pasada pendiente.
POST /api/routes/continueFromPast - distributor
Migra paradas pendientes de la ultima ruta pasada pendiente a la ruta de hoy.
Request: sin body.
Response 200
{
"route_id": 6,
"new_route_date": "2026-04-26",
"migrated_stops": 2
}PATCH /api/stops/reorder - admin
Reordena paradas dentro de una ruta. Needs verification para la forma del body.
PATCH /api/stops/updateArrival - distributor
Registra la hora real de llegada a una parada.
Request body
{ "stop_id": 21 }Response 200
{
"id": 21,
"route_id": 5,
"package_id": 42,
"stop_order": 1,
"estimated_arrival": "09:30:00",
"actual_arrival": "09:28:00"
}Endpoints de logs
GET /api/logs/listByPackage - admin
Query params: packageId (required), page, limit.
Response 200
{
"logs": [
{
"id": 1,
"packageId": 42,
"oldStatus": "assigned",
"newStatus": "in_transit",
"changedBy": 3,
"notes": null,
"changedAt": "2026-04-26T09:00:00.000Z"
}
],
"total": 1,
"page": 1,
"limit": 20
}GET /api/logs/listAll - admin
Lista todos los logs de estado de todos los paquetes. Needs verification para filtros y envelope de paginacion.
Endpoint de tracking (publico)
GET /api/tracking/:trackingToken
Publico. No requiere auth. El token es una cadena hex de 32 bytes.
Response 200
{
"tracking_code": "PAK-20260001",
"recipient_name": "Ane Etxeberria",
"status": "in_transit",
"estimated_delivery": "2026-05-01",
"address": {
"street": "Kale Nagusia 12",
"city": "Tolosa",
"postal_code": "20400"
},
"last_update": "2026-04-26T09:00:00.000Z"
}El token caduca tras TRACKING_EXPIRES_DAYS dias (default 30). Devuelve 404 si el token es desconocido o ha caducado.