There are two separate login flows, issuing two structurally different tokens — a staff token can't be used on renter-portal routes and vice versa.
POST /api/auth/staff/login
{ "email": "...", "password": "..." }
→ { "accessToken": "...", "user": {...} }
POST /api/auth/renter/login
{ "email": "...", "password": "..." }
→ { "accessToken": "...", "renter": {...} }Pass the token back on every request as Authorization: Bearer <token>. Tokens expire after 8 hours.
Every account belongs to a tenant (your organization). You never send a tenant ID yourself — it's embedded in your token and applied automatically to every request, so you only ever see your own organization's data.
All endpoints are prefixed with /api. In this environment: https://bizerp-gnj.onrender.com/api
Standard REST — JSON in, JSON out. List endpoints return a plain array (no pagination wrapper yet). Errors return a standard NestJS error shape:
{ "statusCode": 400, "message": "...", "error": "Bad Request" }