---
title: "Actividad por evento de un fan (histórico completo + página de filas)"
method: GET
path: "/fan-event-activity/{userId}"
tags: ["Fan Event Activity"]
---

# Actividad por evento de un fan (histórico completo + página de filas)

`GET /fan-event-activity/{userId}`

## Request

- Base URL: `http://localhost:8081`
- URL: `http://localhost:8081/fan-event-activity/{userId}`
- Auth: HTTP bearer

Lectura interna de la vista **Eventos** de la ficha del fan (ticket #59), consumida por la
fachada CRM de nev-api. **Solo JWT de usuario** (`type: access_token`) con rol ADMIN, OWNER o
SUPERADMIN; un token de servicio o STAFF/USER es 403. El alcance es el del JWT
(tenant activo y descendientes autorizados); `x-tenant-id` se ignora.

`history` cubre **toda** la actividad accesible del fan, sin filtros ni paginación. Cada
operación cae en una sola fila (EDITION, EVENT_GROUP, EVENT, SOURCE o UNASSIGNED). Los
importes son céntimos EUR en cadenas decimales. Un importe desconocido nunca es 0: `status`
es PARTIAL o UNKNOWN y `unknownCount` cuenta registros inciertos.
`coverage.reasons` son códigos estables, sin ids. Un consumo cashless de importe desconocido
aporta a su fila y al histórico su `cashless_unknown_reason` (`RAW_RECLASSIFIED_PENDING`,
`ANOMALY_FOREIGN_PROVIDER`, `ANOMALY_NO_CASFID_SHAPE`, `NON_CANONICAL_REFERENCE`,
`METADATA_MISSING`, `IMAGE_FIELD_MISMATCH`, `METADATA_VERSION_MISMATCH`, `SOURCE_DEGRADED`,
`SOURCE_STATE_UNRECOGNIZED`, `METADATA_CONTRADICTION`) o `CASHLESS_AMOUNT_UNKNOWN`.

La respuesta lleva `snapshotToken`: las páginas siguientes y todos los subrecursos lo exigen.
Si la generación de datos o los vínculos cambian, la respuesta es `409 SNAPSHOT_CHANGED`.

**Interruptor versionado** (`src/config/fanEventActivity.ts`): activo en producción y
desarrollo desde 3.38.1. Apagarlo es un PR; apagado, toda ruta responde `404 ACTIVITY_DISABLED`
antes de autenticar.

**Autoridad vigente** (S07): en cada petición, antes de leer datos, se relee sin caché el usuario
del token y su jerarquía. Si el usuario no existe o está borrado, si su rol ya no es el del
token, o si el tenant efectivo ya no está en su tenant ni en sus descendientes, la respuesta es
`401 AUTHORITY_CHANGED` (sin detalle), y se resuelve renovando la sesión. Un token de
suplantación con sesión viva tiene su propia autoridad.

Errores: cuerpo `{code, message, requestId}`. Códigos: 400 INVALID_FILTER / INVALID_PAGE /
INVALID_SNAPSHOT, 401 UNAUTHENTICATED / AUTHORITY_CHANGED, 403 FORBIDDEN, 404 FAN_NOT_FOUND /
ROW_NOT_FOUND / OPERATION_NOT_FOUND, 409 SNAPSHOT_CHANGED / SNAPSHOT_EXPIRED, 422
DATA_INTEGRITY_UNRESOLVED, 429 RATE_LIMITED (con `Retry-After`), 503 ACTIVITY_UNAVAILABLE /
TENANT_HIERARCHY_UNAVAILABLE (con `Retry-After`).

## Path parameters

- `userId` string, required

## Query parameters

- `q` string
- `kind` 'EDITION' | 'EVENT_GROUP' | 'EVENT' | 'SOURCE' | 'UNASSIGNED'
- `year` integer
- `page` integer
- `size` integer
- `snapshotToken` string

## Response `200`

Contrato fan-event-activity-v1 (Overview)

## Other responses

- `400`: INVALID_FILTER, INVALID_PAGE, INVALID_SNAPSHOT
- `401`: UNAUTHENTICATED o AUTHORITY_CHANGED (el token ya no representa la autoridad vigente)
- `403`: FORBIDDEN
- `404`: FAN_NOT_FOUND (inexistente o fuera del alcance
- `409`: SNAPSHOT_CHANGED, SNAPSHOT_EXPIRED
- `429`: RATE_LIMITED
- `503`: ACTIVITY_UNAVAILABLE

---

[API](https://skmtc.dev/nevent/apis/nevent-data-api.md) · [All operations](https://skmtc.dev/nevent/apis/nevent-data-api/llms.txt) · [OpenAPI document](https://skmtc.dev/nevent/apis/nevent-data-api/revisions/81035d32c1c1?raw)
