Skip to main content

Sessions API

All endpoints verified working via curl. Document updated only after curl confirmation.

Base path: /api/v1/sessions. A session is a distinct traces.session_id value for the team (a caller-supplied opaque string set on a trace via POST /api/v1/traces). There is no dedicated sessions table — a session is a grouped aggregate over the traces table. Read-only, any-role, team-scoped. Auth: requireAnyAuth (session cookie or personal API key). Traces with no sessionId are excluded from every session listing.


GET /api/v1/sessions

Lists the team's sessions, newest activity first (ordered by most recent trace startedAt within the session). Query params:

  • from, to — ISO 8601; default window is the last 30 days
  • page — 1-based, default 1
  • limit — default 20, max 100
  • q — optional case-insensitive substring match on session_id
curl -H "Authorization: Bearer $ACRUXCORE_API_KEY" \
"$ACRUXCORE_BASE_URL/sessions"

Response (status 200):

{
"data": [
{
"sessionId": "beta-session-2",
"traceCount": 1,
"totalCostUsd": 0.000009,
"totalTokens": 80,
"firstAt": "2026-07-04T11:00:00.000Z",
"lastAt": "2026-07-04T11:00:00.000Z"
},
{
"sessionId": "alpha-session-1",
"traceCount": 2,
"totalCostUsd": 0.0000414,
"totalTokens": 270,
"firstAt": "2026-07-04T10:00:00.000Z",
"lastAt": "2026-07-04T10:05:00.000Z"
}
],
"total": 2,
"page": 1,
"limit": 20
}

alpha-session-1 above was built from two traces ingested via POST /api/v1/traces (see docs/api/traces/traces.md) sharing the same sessionId; traceCount, totalCostUsd and totalTokens are rollups across those traces, and firstAt/lastAt are the earliest/latest trace startedAt in the session. A trace posted with no sessionId does not appear in any session.


Pagination

curl -H "Authorization: Bearer $ACRUXCORE_API_KEY" \
"$ACRUXCORE_BASE_URL/sessions?limit=1&page=2"

Response (status 200) — same two sessions as above, page 2 of size 1:

{
"data": [
{
"sessionId": "alpha-session-1",
"traceCount": 2,
"totalCostUsd": 0.0000414,
"totalTokens": 270,
"firstAt": "2026-07-04T10:00:00.000Z",
"lastAt": "2026-07-04T10:05:00.000Z"
}
],
"total": 2,
"page": 2,
"limit": 1
}

Substring search (q)

curl -H "Authorization: Bearer $ACRUXCORE_API_KEY" \
"$ACRUXCORE_BASE_URL/sessions?q=beta"

Response (status 200) — only sessions whose id contains "beta" (case-insensitive):

{
"data": [
{
"sessionId": "beta-session-2",
"traceCount": 1,
"totalCostUsd": 0.000009,
"totalTokens": 80,
"firstAt": "2026-07-04T11:00:00.000Z",
"lastAt": "2026-07-04T11:00:00.000Z"
}
],
"total": 1,
"page": 1,
"limit": 20
}

Date filter (from/to)

The default window (no from/to) is the last 30 days. Supplying a from/to outside a session's activity excludes it entirely — there is no partial rollup.

curl -H "Authorization: Bearer $ACRUXCORE_API_KEY" \
"$ACRUXCORE_BASE_URL/sessions?from=2026-08-01T00:00:00Z"

Response (status 200) — both sessions above have traces before 2026-08-01, so none match:

{ "data": [], "total": 0, "page": 1, "limit": 20 }

GET /api/v1/sessions/:id

One session's summary plus its traces (newest-first, capped at 100). NOT date-filtered — from/to query params are ignored on this route; the lookup is purely by session_id within the team.

curl -H "Authorization: Bearer $ACRUXCORE_API_KEY" \
"$ACRUXCORE_BASE_URL/sessions/alpha-session-1"

Response (status 200):

{
"session": {
"sessionId": "alpha-session-1",
"traceCount": 2,
"totalCostUsd": 0.0000414,
"totalTokens": 270,
"firstAt": "2026-07-04T10:00:00.000Z",
"lastAt": "2026-07-04T10:05:00.000Z"
},
"traces": [
{
"id": "86035565-cdfb-430e-9013-1264b232cd6d",
"name": "support-agent-followup",
"sessionId": "alpha-session-1",
"status": "ok",
"startedAt": "2026-07-04T10:05:00.000Z",
"endedAt": "2026-07-04T10:05:01.500Z",
"spanCount": 1,
"totalCostUsd": 0.000018,
"totalTokens": 110,
"tags": []
},
{
"id": "33781375-aefe-4e26-a6ac-4e44598b76aa",
"name": "support-agent-run",
"sessionId": "alpha-session-1",
"status": "ok",
"startedAt": "2026-07-04T10:00:00.000Z",
"endedAt": "2026-07-04T10:00:01.200Z",
"spanCount": 1,
"totalCostUsd": 0.0000234,
"totalTokens": 160,
"tags": ["prod"]
}
]
}

Each trace item carries sessionId and tags (added 2026-07-08) so the payload satisfies the web client's shared TraceTable row shape.

Verified the "not date-filtered" claim: passing a from that excludes both traces from the list view still returns the full detail unchanged:

curl -H "Authorization: Bearer $ACRUXCORE_API_KEY" \
"$ACRUXCORE_BASE_URL/sessions/alpha-session-1?from=2026-08-01T00:00:00Z"

Response (status 200) — identical body to the call above; from/to had no effect.


Error responses

Unknown session_id for the team (status 404):

curl -H "Authorization: Bearer $ACRUXCORE_API_KEY" \
"$ACRUXCORE_BASE_URL/sessions/does-not-exist-session"
{ "error": { "code": "NOT_FOUND", "message": "Session not found." } }

No Authorization header on either route (status 401):

{ "error": { "code": "UNAUTHORIZED", "message": "API key required." } }

Invalid from/to on GET /sessions (status 400):

curl -H "Authorization: Bearer $ACRUXCORE_API_KEY" \
"$ACRUXCORE_BASE_URL/sessions?from=not-a-date"
{ "error": { "code": "VALIDATION_ERROR", "message": "Invalid date" } }

limit above the max of 100 (status 400):

curl -H "Authorization: Bearer $ACRUXCORE_API_KEY" \
"$ACRUXCORE_BASE_URL/sessions?limit=1000"
{ "error": { "code": "VALIDATION_ERROR", "message": "Number must be less than or equal to 100" } }