API Reference

The pakAG backend is a Next.js 15 App Router API. All endpoints live under /api/* and run on port 3001 in development.


Base URL

http://localhost:3001/api   (development)
https://tolosaerronka.es/api  (production)

Authentication

All endpoints require Authorization: Bearer <access_token> except where noted as Auth required: No.

Obtain an access token via POST /api/auth/login. Tokens expire after 15 minutes (default). Refresh silently with POST /api/auth/refresh, which rotates the refresh token cookie.

Roles: admin | distributor


Error format

Every error response uses a consistent envelope:

{ "error": "Human-readable error message" }

HTTP status codes:

CodeMeaning
400Validation error
401Unauthenticated (missing or invalid token)
403Forbidden (wrong role, or resource not owned)
404Resource not found
409Conflict (duplicate, FK constraint)
500Internal server error

Pagination

Paginated endpoints accept page (default 1) and limit (default 20, max 100) as query parameters and return:

{
  "items": [...],
  "total": 42,
  "page": 1,
  "limit": 20
}

The field name for the array varies per resource (users, packages, logs).


Resources

ResourceBase pathDescription
Auth/api/authLogin, logout, token refresh, password reset, account activation
Users/api/usersUser CRUD (admin), change own password (any role)
Packages/api/packagesPackage lifecycle — create, list, update, delete, status transitions
Routes/api/routesOptimized delivery route creation and management
Stops/api/stopsReorder stops, record arrival times
Logs/api/logsPackage status-change audit log
Tracking/api/trackingPublic package tracking by token

Package status lifecycle

pending → assigned → in_transit → delivered
                               ↘ undelivered
                               ↘ failed

Each transition triggers a status log entry and a tracking email to the recipient. See PATCH /api/packages/updateStatus for allowed transitions per role.


Auth token flow

POST /api/auth/login
  → body: { user, access_token }
  → cookie: refresh_token (HttpOnly)

Authorization: Bearer <access_token>   ← every request

POST /api/auth/refresh   ← when access token expires
  → body: { access_token }
  → cookie: new refresh_token (old one revoked)

POST /api/auth/logout
  → refresh token revoked, cookie cleared