REST API

UniTrack exposes a small HTTP API under /api/v1. The dashboard itself is server-rendered Thymeleaf; the API is for ingestion and account introspection.

1. POST /api/v1/ingest

Accepts a CI upload of test and coverage reports as multipart/form-data. The full field list is documented in Reporting Results.

curl -F project=myapp -F branch=main -F commit=$SHA \
     -F 'junit=@target/surefire-reports/TEST-MyTest.xml;type=text/xml' \
     -F 'jacoco=@target/site/jacoco/jacoco.xml;type=text/xml' \
     http://localhost:8080/api/v1/ingest

Response — 201 Created:

{
  "runId": 42,
  "project": "myapp",
  "tests": 128,
  "failures": 1,
  "skipped": 2,
  "lineCoveragePct": 84.3
}

When unitrack.security.require-ingest-token=true, the request must carry a valid token as Authorization: Bearer <token> (or the X-UniTrack-Token header); otherwise it returns 401.

2. GET /api/v1/gate

CI-consumable quality-gate lookup. A pipeline knows its project name and commit SHA, not UniTrack’s internal run id — this endpoint resolves the latest matching run and returns its gate verdict.

curl "http://localhost:8080/api/v1/gate?project=myapp&commit=$GIT_SHA"

Parameters: project (required); one of commit or branch (required — commit preferred, branch gates the latest run on a branch); optional flag to scope to a component.

{
  "project": "myapp", "branch": "main", "commit": "9af5872", "flag": "default",
  "runId": 42, "status": "FAILED", "passed": false, "coverageDelta": -1.8,
  "rules": [ { "name": "new-failures", "passed": false, "detail": "1 new failure(s): com.x.G a" } ],
  "runPath": "/runs/42"
}

404 if no run matches the project + commit/branch; 400 if neither commit nor branch is given. The unitrack-gate.sh wrapper turns passed into a build exit code so any CI can fail on it.

3. GET /api/v1/me

Returns the authenticated principal — the account behind the current session or API token. Always requires authentication, even in open mode.

curl -H "Authorization: Bearer ut_xxxxxxxx" http://localhost:8080/api/v1/me
{
  "username": "alex",
  "displayName": "Alex Mondshain",
  "email": "[email protected]",
  "role": "ADMIN"
}

4. GET /api/v1/events (live updates)

A Server-Sent-Events stream that pushes a run event each time a run is ingested, so the dashboard can update in place without polling. Connect with an EventSource:

const es = new EventSource('/api/v1/events');
es.addEventListener('run', (e) => {
  const u = JSON.parse(e.data); // { projectId, runId, branch, status, passRatePct, lineCoveragePct, ... }
  // update the matching project card / runs row
});

The stream connects as the current user (or anonymously) and is visibility-filtered per subscriber: a private project’s run events are delivered only to streams that may read it, so they never leak to anonymous or non-member clients. The first message is a connected event.

5. Authentication mechanisms

UniTrack accepts two kinds of credential:

  • Session cookie — after a form login at /login.

  • API token — a personal token, sent as Authorization: Bearer <token> or X-UniTrack-Token: <token>. Tokens are minted on the profile page and stored only as a SHA-256 hash.

For API paths an unauthenticated request returns 401; browser paths redirect to /login. See Accounts & API Tokens.