Full tracked-user detail
VIEWER+. Same shape `loadTrackedUserDetail` produces for the user-detail page Server Component prefetch — `HydrationBoundary` skips the on-mount refetch because the wire format is byte-identical.
/api/tracked-users/{userId}VIEWER+. Same shape loadTrackedUserDetail produces for the user-detail page Server Component prefetch — HydrationBoundary skips the on-mount refetch because the wire format is byte-identical.
Path Parameters
TrackedUser id (cuid)
Response Body
application/json
curl -X GET "https://loading/api/tracked-users/string"{
"id": "tu_t5u6v7w8",
"externalId": "usr_abc123",
"displayName": "alex@your-app.com",
"projectId": "prj_x9y8z7w6",
"projectName": "Production",
"traits": {
"plan": "pro",
"email": "alex@your-app.com"
},
"sessionCount": 14,
"lastEventAt": "2026-04-26T10:33:04.320Z",
"status": "ONLINE",
"activeTime7d": 184320,
"createdAt": "2026-04-15T11:24:00.000Z",
"customName": null,
"displayNameTraitKey": null,
"projectDisplayNameTraitKey": "email"
}List tracked users, cursor-paginated GET
VIEWER+. Scoped to the caller's active org. Filters: `?search=` (matches `externalId` OR `customName`, case-insensitive), `?projectIds=`, `?statuses=ONLINE,ACTIVE_24H,...`, `?sort=last-seen|sessions|active-time|newest`, `?sortDir=`. Status is derived (not indexable) — when status filter is active the route over-fetches up to 500 rows and applies it in JS.
Update display-name overrides PATCH
ADMIN+. Body fields `customName` and `traitKey` are independently optional; omitted fields stay unchanged, `null` clears the field (falls back through resolver chain), `string` sets the override (trimmed + validated). Implements steps 1–2 of the 4-step resolver chain.