API Reference · v1
A real API, not just a UI.
This platform is API-driven: every screen you see is backed by the /api/v1 endpoints documented below. Authentication is a signed, HTTP-only session cookie set at login, and access is enforced server-side by role — the same RBAC model the UI uses to decide what to show.
Authentication
Sign in with POST /api/v1/auth/login. Credentials are verified against scrypt-hashed records (constant-time comparison). On success the server returns the session user and sets an HTTP-only, Secure, SameSite=Lax cookie (hsg_session) — an HMAC-SHA256-signed, stateless token that carries the user's id, role, and facility scope, and expires after 8 hours.
HTTP-only cookie
Not readable from JavaScript — no token handling in the client.
scrypt + timing-safe
Passwords are never stored; hashes compared in constant time.
8-hour signed session
HMAC-SHA256 over the payload; tamper- and expiry-checked on every request.
In production these seed users are replaced by the VA identity provider (VA SSOi / PIV); the session and RBAC contract stays the same. Read-only endpoints below work without signing in (as the guest role).
Roles & permissions
Every endpoint checks a named permission against the caller's role with can(role, permission). This matrix is generated directly from rbac.ts — it is the live source of truth.
| Permission | Admin | PM | HR Specialist | Coordinator | Observer | Guest |
|---|---|---|---|---|---|---|
submissions:read:all Read all facility submissions | · | |||||
surveys:read Read the survey library | · | |||||
surveys:write Manage survey selections | · | · | · | · | ||
jobs:read Read job-architecture mappings | · | · | · | |||
jobs:write Write job-architecture mappings | · | · | · | · | ||
audit:read Read the audit trail | · | |||||
exports:read Generate report exports | · | |||||
submissions:approve Approve facility submissions | · | · | · | · | ||
determinations:read Read pay determinations | · | · | ||||
determinations:write Write pay determinations | · | · | · | · | ||
versions:read Read catalog versions | · | · | ||||
versions:write Publish catalog versions | · | · | · | · | ||
submissions:read:own Read own-facility submissions | · | · | · | · | ||
submissions:write Create / submit facility surveys | · | · | · | · |
Admin holds the admin:all wildcard — every permission above resolves to allowed, including any added later.
Endpoints
All endpoints accept and return JSON. The required permission is enforced on the server — an unauthenticated caller gets 401, an authenticated caller missing the permission gets 403 (with the needed permission named in the body).
Auth
Establish and inspect the signed session. Login sets the cookie; every other call reads it.
/api/v1/auth/login/api/v1/auth/logout/api/v1/auth/sessionData
The platform's records. Reads are role-gated; writes require the listed permission server-side.
/api/v1/submissions/api/v1/submissions/api/v1/determinations/api/v1/determinations/api/v1/versions/api/v1/versions/api/v1/auditOperations
Job-architecture mapping, report exports, and the unauthenticated health probe.
/api/v1/jobs/api/v1/jobs/api/v1/exports/{kind}/api/v1/healthLogin · request
POST /api/v1/auth/login
Content-Type: application/json
{
"email": "hr@va.gov",
"password": "••••••••"
}Login · response
200 OK
Set-Cookie: hsg_session=<signed>; HttpOnly; Secure; SameSite=Lax
{
"user": {
"id": "u-hr",
"email": "hr@va.gov",
"name": "VA HR Specialist (OCHCO)",
"role": "hr_specialist"
}
}Submissions · GET
GET /api/v1/submissions
{
"items": [
{
"id": "sub-…",
"facility": "James A. Haley Veterans' Hospital",
"visn": "VISN 8",
"rnMedian": 96400,
"comparators": 12,
"status": "submitted"
}
],
"scopedTo": null
}Submissions · POST
POST /api/v1/submissions (needs submissions:write)
Content-Type: application/json
{
"facility": "James A. Haley Veterans' Hospital",
"rnMedian": 96400,
"comparators": 12
}
201-style → { "item": { … }, "items": [ … ] }Health · GET (public)
GET /api/v1/health
{
"status": "operational",
"version": "v1",
"ts": 1750000000000,
"services": {
"api": { "ok": true, "detail": "REST API responding" },
"auth": { "ok": true, "detail": "signed-session auth online" },
"store": { "ok": true, "detail": "…", "bucket": "…", "region": "…" }
}
}Try it live
These two calls are read-only and work right now as the guest role — no sign-in required. They hit the real endpoints and render the exact JSON returned.
GET /api/v1/healthPress Send to call the endpoint.
GET /api/v1/auditPress Send to call the endpoint.
Write endpoints require an authenticated role.
Any POST above is gated by the permission shown next to it (for example, submissions:write or determinations:write). Sign in as one of the demo roles to exercise them — the matrix above shows which role gets which capability.
This reference documents the platform's live /api/v1 surface. The Try-it calls invoke the real endpoints; JSON examples are illustrative shapes. In production the seed-user roster is replaced by VA SSOi / PIV, leaving the session and RBAC contract unchanged.