Skip to main content

Sessions

The portal API is session-based. A caller authenticates once and carries a session cookie; there is no separate API key, and there are no long-lived bearer tokens issued to clients.
These two sit at /api/auth/…, not under the /api/v1/portal/… prefix the employee endpoints use. They are the platform’s own session endpoints, included in this contract because the mobile client needs them.
GET /api/auth/session documents only a 200. Its user is nullable — an unauthenticated caller gets 200 with user: null rather than a 401 — so a client can ask “am I signed in?” without treating the answer as an error. POST /api/auth/logout returns 200 with a literal success: true, or 500.

How a session is established

The mobile client is SSO-only by decision: a mobile app holding a long-lived magic-link session is a materially worse credential story than a token from the identity provider.

Cookies

Session and CSRF cookies are Secure by default. The flag can be disabled only for local development served over plain http://localhost, and never in a deployed environment.

Authorization

Every portal endpoint is self-scoped. There is no id parameter to substitute — the subject is resolved from the session — so the classic IDOR shape does not exist on this surface. Two consequences for clients:
  • A caller with no linked employee record gets 404 from the employee endpoints, not an empty object. The absence of an employment relationship is a distinct state from an empty result.
  • Salary and compensation fields respect the platform’s visibility rules. A masked value is masked in the response body — there is nothing hidden client-side to reveal.

Status codes

The contract uses exactly these:
Tokens and session identifiers never appear in URLs or in Location: headers. If you are building a client, do not put one there either — every proxy, CDN and access log in the chain records them.