Authentication
Cargovision has two separate authentication mechanisms. Use the one that matches the caller, and never substitute one for the other.
JWT sessions
Sign in
A successful sign-in sets an HttpOnly, SameSite=Strict cookie named token that holds the JWT (Secure in production, Path=/, Max-Age of 7 days). Browsers send it automatically. Non-browser clients can read the cookie and send its value as a bearer token instead:
Call GET /v1/user/auth/refresh-token to rotate the token. It requires a valid token and returns a new token cookie.
Accounts
New accounts are created by invitation. Administrators issue invites from the dashboard, and the invite link lets the recipient set a password. Password resets use POST /v1/user/auth/email/forgot-password followed by PUT /v1/user/auth/email/change-password with the emailed token.
Roles
Every user has one of three roles. The API enforces them on every request; the dashboard’s role-based UI is a convenience, not the security boundary.
A missing or invalid token returns 401. A valid token without the required role returns 403.
Cookie-authenticated writes
Requests that change data (POST, PUT, PATCH, DELETE) and authenticate with the token cookie must come from a trusted origin, checked through the Origin or Referer header. Otherwise the API returns 403 with Forbidden: untrusted request origin. Requests that send an Authorization: Bearer header skip this check, so scripts and mobile clients should use the bearer header.
Rate limits
Credential endpoints are rate limited per IP address over a 15-minute window:
Exceeding a limit returns 429. Standard RateLimit-* headers report the remaining budget.
Edge device API keys
Edge devices authenticate with a static key configured on both the API and the device. Send it in the X-API-Key header:
Authorization: Bearer <api-key> is accepted as an alternative. A missing key returns 401 MISSING_API_KEY; a wrong key returns 401 INVALID_API_KEY.
The edge API key grants write access to inspection data. Keep it on the edge device and on servers you control. Never ship it in browser or mobile code.
