# getActivityLog — API (TActivityLog)

> Returns the user's activity history within the requested time window, ordered newest-first.
> Import: `import { TActivityLog } from '@smartico/public-api'`
> Search terms: getActivityLog, user, TActivityLog, UserBalanceType, PointChangeSourceType, ActivityLogActivities, ActivityLogMeta, onUpdate, subscription, create_date, user_ext_id, crm_brand_id, type, amount, balance, total_ever, source_type_id

## Signature
```ts
_smartico.api.getActivityLog({
		startTimeSeconds,
		endTimeSeconds,
		from,
		to,
		types,
		src_types,
		onUpdate,
	}: {
		/** Window start in epoch seconds. */
		startTimeSeconds: number;
		/** Window end in epoch seconds. */
		endTimeSeconds: number;
		/** Pagination offset (0-based). */
		from: number;
		/** Pagination ceiling (exclusive); server caps `to - from` at 50. */
		to: number;
		/** Optional — filter by {@link ActivityLogActivities} / `type_id`. */
		types?: number[];
		/** Optional — filter by {@link PointChangeSourceType} / `source_type_id`. */
		src_types?: number[];
		/** Optional push callback; payload is a fixed 10-min / 50-entry refresh on every wallet change (see Subscription model). */
		onUpdate?: (data: TActivityLog[]) => void;
	}): Promise<TActivityLog[]>
```

## Parameters
_None._

## Returns — `Promise<TActivityLog[]>`
Array of `TActivityLog`. Each item:
- `create_date` (number) — Date when the change was created (epoch timestamp in seconds)
- `user_ext_id` (string) — External user ID
- `crm_brand_id` (number) — CRM brand ID
- `type` (UserBalanceType) — Type of balance: Points = 0, Gems = 1, Diamonds = 2
- `amount` (number) — Amount changed (positive or negative)
- `balance` (number) — Current balance after this change
- `total_ever` (number) — Total ever collected (only relevant for type points)
- `source_type_id` (PointChangeSourceType) — Source type ID indicating what triggered this change
- `activity_type_id` (ActivityLogActivities) — Activity kind — see `ActivityLogActivities` (`type` on the wire).
- `context_value_1` (number) — Sub-action for `activity_type_id` (e.g. unlock vs complete, add vs deduct, raffle win vs register).
- `meta` (ActivityLogMeta) — Extra display payload for the row (name, image, position, …) — see `ActivityLogMeta`.
  - `name` (string) — Display name of the source entity (mission, tournament, raffle, …).
  - `image_url` (string)
  - `position` (number)
  - `user_points_balance_before` (number) — Points balance before this row; points rows.
  - `points_requested` (number) — Points the awarding rule asked for; points rows.
  - `user_points_ever` (number) — Total points ever collected after this row; points rows.
  - `amount_requested` (number) — Gems / diamonds the awarding rule asked for; gems / diamonds rows.
  - `balance_before` (number) — Gems / diamonds balance before this row.
  - `affects_level` (boolean) — Whether this row counts toward level progress.
  - `affects_leaderboard` (boolean) — Whether this row counts toward leaderboards.
  - `affects_current_balance` (boolean) — Whether this row moved the spendable balance.
  - `user_initialization` (boolean) — Set on the row that seeds a brand-new user's wallet.
  - `is_recurring` (boolean) — Set on mission rows for repeatable missions.
  - `from_level_id` (number) — Level moved from; level-change rows.
  - `to_level_id` (number) — Level moved to; level-change rows.
  - `from_level_public_meta` (any) — Public meta of the level moved from; level-change rows.
  - `to_level_public_meta` (any) — Public meta of the level moved to; level-change rows.
- `source_entity_name` (string) — Human-readable name of the source entity (mission, tournament, raffle, …).
- `source_entity_id` (number) — Primary id of the source entity (mission / badge / tournament / …).
- `source_reference_id` (number) — More specific id within the source (e.g. level id, draw id, win id).
- `source_root_id` (number) — Root / parent entity id when the source is nested (e.g. raffle id owning a draw).
- `is_wallet_entry` (boolean) — True when the row is a points/gems/diamonds wallet change.

## Behavioral contract
**Preconditions**
- User must be authenticated. Visitor mode is not guarded at the SDK level
 but is not meaningful — activity is per-user.

**Pagination — `from` / `to` are offset + ceiling, not timestamps**
The SDK derives `offset = from`, `limit = min(to - from, 50)` — the server
hard-caps a single response at 50 entries. For infinite scroll, advance
`from` by 50 between calls. Both `startTimeSeconds` and `endTimeSeconds`
are epoch seconds bounding the window the server scans.

**Filtering** — optional server-side filters:
- `types` — `ActivityLogActivities` / `type_id` values (e.g. Points=3, Gems=1)
- `src_types` — `PointChangeSourceType` / `source_type_id` values
Omit both for an unfiltered window.

**Subscription model (`onUpdate`)**
The callback fires when the user's `ach_points_balance`,
`ach_gems_balance`, or `ach_diamonds_balance` changes (i.e. whenever a
wallet event lands). The pushed payload is a FIXED re-fetch of the
**last 10 minutes / first 50 entries** — it does NOT honor the original
call's `startTimeSeconds` / `endTimeSeconds` / `from` / `to` / filters.
Consumers maintaining a long historical view must re-call `getActivityLog` with
their own params after receiving an `onUpdate` notification.

**Refresh**
- The SDK caches results for 30 seconds.
- Push triggers fire only on balance changes; transactions that don't
 alter a balance (theoretical zero-amount entries) won't refresh.

**Visitor mode**: not meaningful (no per-user history available).

**UI guidance**: see [UI Guide — `getActivityLog`](../../docs/ui/user/UIGuide_getActivityLog.md).

## Example
```ts
const now = Math.floor(Date.now() / 1000);
const start = now - 86400 * 30; // 30 days

const log = await window._smartico.api.getActivityLog({
    startTimeSeconds: start,
    endTimeSeconds:   now,
    from: 0,
    to:   50,
    types: [1], // Gems only (ActivityLogActivities.Gems)
    src_types: [11], // Tournament wins only (PointChangeSourceType.Tournament)
    onUpdate: (refreshed) => {
        console.log('[smartico] wallet changed — refreshed payload is last 10 min / 50 entries:', refreshed.length, 'rows');
        // If the consumer is showing a full 30-day view, re-call getActivityLog with the original params here.
    },
});

for (const row of log) {
    const sign = row.amount >= 0 ? '+' : '';
    console.log('[smartico] activity row — render with', row.type === 0 ? 'points' : row.type === 1 ? 'gems' : 'diamonds', 'icon, color by sign:', sign + row.amount, 'balance after:', row.balance, 'source:', row.source_type_id);
}
```

### Example response (REAL shape)
> Where this real payload differs from the typed Returns above (TS interface vs raw wire), the REAL shape is the runtime truth.
```json
[
  {
    "create_date": 1785955065,
    "user_ext_id": "test12562034",
    "crm_brand_id": 31,
    "type": 0,
    "amount": 150,
    "balance": 5372,
    "total_ever": 5372,
    "source_type_id": 12,
    "activity_type_id": 3,
    "context_value_1": 1,
    "meta": {
      "user_points_balance_before": 5222,
      "user_points_ever": 5372,
      "affects_level": true,
      "points_requested": 150,
      "affects_leaderboard": true,
      "affects_current_balance": true
    },
    "source_reference_id": 675,
    "source_root_id": 675,
    "is_wallet_entry": true
  }
]
```

## Errors
See this method's TSDoc / the mutation pages for `err_code` handling.

## Related
- `TActivityLog`
- `ActivityLogActivities`
- `PointChangeSourceType`
