BIO.RE
Analytics

Identify Session After Login

Bind the current authenticated userId to a previously-anonymous session id. Idempotent. Lets analytics correlate pre-login traffic with the resulting account.

PATCH /api/v1/analytics/session/:id/identify — 🔑 Bearer

Sets AnalyticsSession.userId for an existing session. Call this once, right after login or signup completes — the session was created anonymously (likely before the user authenticated), and this pulls the user identity onto it so all the prior pageviews in that session can be attributed correctly.

Idempotent and overwrite-friendly. The service does a flat update({ where: { id }, data: { userId } }) — calling it twice with the same userId is a no-op. Calling it with a different userId overwrites the previous one, so don't share session ids across users (a logout-then-login on the same anonymous session would reattribute prior views to the second user).

No 404 / 401 cross-checks. The service silently swallows update failures (update.catch(() => {})). If the session id doesn't exist or the DB rejects the write, the response is still 200 { ok: true } — you can't programmatically detect a bad id. The auth check (@CurrentUser('id') requires a valid bearer) is the only real gate.

userId comes from the JWT, not the body. The endpoint reads userId via @CurrentUser('id') — there is no way to identify a session as someone else. To unbind, you'd need a separate endpoint (none today). To re-identify after logout, the new session should be created fresh.

Request

Path parameters

ParamTypeRequiredNotes
idstring (UUID)Session id from POST /analytics/session. Not validated server-side — bad ids no-op.

Headers

HeaderRequiredNotes
Authorization: Bearer <accessToken>Global JwtAuthGuard. The user from this token is bound to the session.

No body.

Response

200 OKApiResponseOf<IdentifySessionResultDto>

{ "success": true, "data": { "ok": true } }

Errors

HTTPReason
401Missing / invalid bearer token.

The endpoint has no documented 404 or 400 paths — bad session ids and DB failures collapse to a successful response.

Side effects

  1. Decode bearer (global JwtAuthGuard); userId = req.user.id.
  2. analyticsDb.analyticsSession.update({ where: { id }, data: { userId } }).catch(() => {}). Single SQL UPDATE; failures swallowed.
  3. Return { ok: true }.

No throttle on this endpoint. The class registers @UseGuards(ThrottleGuard) but this handler has no @Throttle() decorator and the guard returns true when no decorator is present. In practice clients should call it at most once per session (right after auth completes), so a missing throttle is fine.

Code samples

curl -X PATCH https://api.bio.re/api/v1/analytics/session/ses-uuid/identify \
  -H "Authorization: Bearer $ACCESS_TOKEN"
async function identifySession(
  accessToken: string,
  sessionId: string,
): Promise<void> {
  await fetch(`https://api.bio.re/api/v1/analytics/session/${sessionId}/identify`, {
    method: 'PATCH',
    headers: { Authorization: `Bearer ${accessToken}` },
  }).catch(() => {});
}
// Run this once, immediately after a successful login/signup.
// The session was started anonymously when the page first loaded.
async function onLoginSuccess(accessToken: string) {
  const sessionId = window.__ANALYTICS_SESSION_ID__; // captured from createSession()
  if (!sessionId) return;
  await identifySession(accessToken, sessionId);
  // No need to re-fire; the binding persists for the lifetime of the session.
}

Try it

PATCH
/api/v1/analytics/session/{id}/identify
AuthorizationBearer <token>

In: header

Path Parameters

id*string

Response Body

application/json

application/json

curl -X PATCH "https://loading/api/v1/analytics/session/string/identify"
{
  "success": true,
  "data": {
    "ok": true
  }
}
{
  "success": false,
  "error": {
    "code": "AUTH_UNAUTHORIZED",
    "message": "Invalid credentials",
    "i18nKey": "auth.login.invalid_credentials",
    "i18nVars": {
      "field": "email"
    },
    "details": [
      {
        "message": "email must be an email"
      }
    ],
    "correlationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}

Source

SourcePathLines
Controllerapps/api-core/src/modules/analytics/analytics.controller.ts179–188 (identifySession)
DTO (response)apps/api-core/src/modules/analytics/dto/analytics-client-response.dto.ts50–53 (IdentifySessionResultDto)
Serviceapps/api-core/src/modules/analytics/traffic-tracking.service.ts215–220 (identifyUser — single UPDATE, silent fail)
Prisma modelpackages/prisma-analytics/prisma/schema.prismaAnalyticsSession.userId line 49 (application-level FK to main DB User)
Throttle behaviorapps/api-core/src/common/guards/throttle.guard.ts43–48 (no decorator → return true)

On this page