Skip to content

Latest commit

 

History

History
259 lines (197 loc) · 10 KB

File metadata and controls

259 lines (197 loc) · 10 KB

Activity Reporting Guide

Docs generated by AI

This document explains how to report activity events to the system.

Unified API reference:

  • Scalar API Reference: /api-reference
  • OpenAPI JSON: /api/openapi.json

1. Get an API Token

  1. Open the admin panel: /admin
  2. After signing in, go to the API Token page
  3. Click create Token
  4. Save the full Token shown in the dialog. It is displayed only once.

2. Reporting Endpoint

  • Method: POST
  • URL: /api/activity
  • Authentication: Authorization: Bearer <YOUR_TOKEN>
  • Content Type: application/json

Request Fields

Required fields:

  • generatedHashKey: unique device identifier, obtained after creating a device in admin Device Management
  • process_name: process name, such as VS Code

Optional fields:

  • device: display name for the device, such as MacBook Pro; used only for display and not for unique identification
  • process_title: process title
  • battery_level: current device battery level, from 0 to 100, if supported by the device or browser
  • is_charging: whether the device is charging, as a boolean. The server writes it to metadata.deviceBatteryCharging. Alias isCharging is also supported. If omitted, the previous charging state is preserved during merge.
  • device_type: device type, one of desktop / tablet / mobile
  • push_mode: push mode, one of realtime / active
  • metadata: extended JSON object

metadata.play_source Optional Media Source

Identifies the media source for this report, such as system_media or music_sdk. Admins can configure Media Source Rules for this value:

  • block: hides metadata.media from public feed output without deleting the activity record.
  • rename: overrides the source label shown by the home page hover card.

Legacy media-source blocklists are still supported and are treated as block rules.

metadata.media Optional Now Playing Data

Used to show the currently playing track in Current Status and Recent Activity on the home page. The media block is displayed only when metadata.media.title is present and non-empty.

Field Required Description
title Yes, if you want media to display Track title. The media block is shown only when the trimmed value is non-empty.
singer / artist No Singer or artist. Displayed together with the title when present.
album No Album name, displayed in the hover card when present.
coverDataUrl No Base64 image data URL. When media cover display is enabled, the server stores it and writes back a coverUrl. A plain URL is also accepted by the frontend for compatibility.
coverUrl No Public cover image URL, usually generated by the server after accepting coverDataUrl.
appIconDataUrl / iconDataUrl No Base64 image data URL for the playback app icon. When “Report playback app icon” is enabled, the server stores it and writes back appIconUrl. Aliases such as sourceIconDataUrl, playerIconDataUrl, and programIconDataUrl are also accepted.
appIconUrl / iconUrl No Public playback app icon URL. When present and accepted, the current status music row shows it before the track title.
status No Playback state: playing, paused, or stopped. Boolean aliases isPlaying and isPaused are also accepted.
positionMs No Current playback position in milliseconds. Aliases include elapsedMs, currentMs, and progressMs.
durationMs No Track duration in milliseconds. Aliases include lengthMs and totalMs.
timestamps No Discord-style playback timestamps, for example { "start": 1778017800000, "end": 1778018040000 }. Values may be Unix milliseconds, Unix seconds, or ISO strings.

Example:

"metadata": {
  "play_source": "cloudmusic.exe",
  "media": {
    "title": "Song Title",
    "singer": "Artist Name",
    "album": "Album Name",
    "status": "playing",
    "positionMs": 83000,
    "durationMs": 244000,
    "timestamps": {
      "start": 1778017800000,
      "end": 1778018044000
    }
  }
}

Merge rule for repeated reports from the same process updating the same activity: top-level metadata is shallow-merged. metadata.media is merged as a one-level object with { ...existingMedia, ...incomingMedia }. This means clients may report only part of the media fields, and missing keys are preserved when possible. For example, a client may report title first and report singer later.

Notes:

  • started_at and ended_at do not need to be uploaded. The server manages timestamps automatically.
  • When the same generatedHashKey reports a new event, the server automatically ends the previous unfinished status for that device.
  • push_mode = realtime: offline state is determined automatically by timeout rules.
  • push_mode = active: the activity stays visible for a long time, is not ended automatically by timeout, and shows the last update time.

For the desktop Go Reporter in reporter/go, including polling/heartbeat behavior, review flow, and background running, see reporter/go/README.md.

3. Device Management and GeneratedHashKey

  1. Open the admin panel: /admin
  2. Go to the Device Management tab
  3. Click Add Device to create a device record. You may optionally enter a custom GeneratedHashKey, matching the key generated in Quick Add Activity.
  4. Copy the corresponding GeneratedHashKey from the device list
  5. Include this value as generatedHashKey when reporting from the client

Admin Quick Add Activity on the Web

  • GeneratedHashKey can be left empty. The server will use the reserved device waken-web-admin, displayed as Web Admin Quick Add, so no device needs to be created beforehand.
  • If a key is provided, it must match an enabled device in Device Management. You can also generate a random key in the form, then create a device with the same key in Device Management.

Notes:

  • GeneratedHashKey is the unique device identifier and must remain stable.
  • If a device is revoked, reports using that key are rejected.
  • If a device is bound to a specific Token, reports must use the matching Token.

4. curl Example

curl -X POST "http://localhost:3000/api/activity" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "generatedHashKey": "YOUR_DEVICE_HASH_KEY",
    "device": "MacBook Pro",
    "device_type": "desktop",
    "process_name": "VS Code",
    "process_title": "editing setup-form.tsx",
    "battery_level": 82,
    "is_charging": true,
    "push_mode": "realtime",
    "metadata": {
      "play_source": "manual-test",
      "media": {
        "title": "Example Track",
        "singer": "Example Artist"
      }
    }
  }'

5. Node.js Example

const battery = await navigator.getBattery?.().catch(() => null)
const batteryLevel = battery ? Math.round(battery.level * 100) : undefined
const isCharging = battery ? battery.charging : undefined

await fetch('http://localhost:3000/api/activity', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${token}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    generatedHashKey: deviceHashKey, // required
    device: navigator.platform || 'My PC',
    device_type: 'desktop',
    process_name: 'Chrome',
    process_title: 'Dashboard',
    battery_level: batteryLevel,
    ...(typeof isCharging === 'boolean' ? { is_charging: isCharging } : {}),
    push_mode: 'active', // active push: long-lived display with last update time
    metadata: {
      media: {
        title: 'Example Track',
        singer: 'Example Artist', // optional
      },
    },
  }),
})

6. Responses and Errors

Success response:

  • HTTP 200
  • {"success": true, "data": ...}

Common errors:

  • 401: Token is invalid or disabled
  • 400: required fields are missing, such as generatedHashKey or process_name
  • 403: device does not exist, is revoked, or does not match the current Token binding
  • 500: server error

7. Quick Checklist

If reporting fails, check the following in order:

  1. The Token is the full value, not a truncated value
  2. The Bearer prefix is included
  3. generatedHashKey and process_name are present
  4. The Token is enabled in the admin panel
  5. The device exists and is in the active state in admin Device Management

8. One-Click Integration Config Copy as Base64

The admin Settings page provides a Copy Integration Config as Base64 button.

The copied content includes:

  • Web configuration, such as name, bio, avatar, history window, and text copy
  • Token list, including name, token, and enabled state
  • Reporting URL as reportEndpoint

Other devices can decode the Base64 value into JSON.

Example Node.js decoding:

const decoded = Buffer.from(base64Text, 'base64').toString('utf8')
const config = JSON.parse(decoded)
console.log(config.token.reportEndpoint)
console.log(config.token.items[0]?.token)

9. Admin Export for Used Apps JSON

After signing in as admin, call:

  • Method: GET
  • URL: /api/admin/activity/apps-export

Example response shape:

{
  "success": true,
  "data": {
    "version": 1,
    "exportedAt": "2026-04-01T00:00:00.000Z",
    "groups": {
      "pc": [
        { "appName": "code.exe", "titles": ["project-a"], "lastSeenAt": "2026-04-01T00:00:00.000Z" }
      ],
      "mobile": [
        { "appName": "chrome", "titles": ["home"], "lastSeenAt": "2026-04-01T00:00:00.000Z" }
      ]
    }
  }
}

Notes:

  • Grouping rule: device_type values mobile and tablet are grouped into mobile; everything else is grouped into pc.
  • Each app is unique by process_name. Only the latest 3 titles are kept, deduplicated with newest first.

10. Historical App Record Collection Toggle

The admin Web Settings page provides the toggle Save app records from reported activity for rule selection/export:

  • Disabled: no new history records are added, but existing history data is kept.
  • Enabled: reports enter a buffer and are periodically written to the history table. Redis is preferred; without Redis, the system falls back to direct database writes.