Telemetry
Telemetry
Every API request can include an optional telemetry object with device and app information. LicenseSeat uses this data to power per-product analytics: DAU/MAU, version adoption, platform distribution, geographic breakdown, and stale device detection.
Telemetry is captured automatically by the official SDKs. If you're building a custom integration, this page describes the telemetry format and what each field is used for.
The Telemetry Object
Include a telemetry key in the JSON body of any POST request:
{
"fingerprint": "mac-a1b2c3d4-e5f6g7h8",
"telemetry": {
"sdk_name": "swift",
"sdk_version": "0.4.0",
"os_name": "macOS",
"os_version": "15.2.0",
"platform": "native",
"device_model": "MacBookPro18,1",
"app_version": "2.1.0",
"app_build": "42",
"device_type": "desktop",
"architecture": "arm64",
"cpu_cores": 10,
"memory_gb": 32,
"locale": "en_US",
"language": "en",
"timezone": "America/New_York",
"screen_resolution": "3456x2234",
"display_scale": 2.0
}
}
Fields
Promoted Columns
These fields are stored as dedicated database columns and are directly queryable in the analytics dashboard:
| Field | Type | Description | Used for |
|---|---|---|---|
sdk_name |
String | SDK identifier: swift, js, cpp, csharp |
SDK distribution |
sdk_version |
String | Version of the LicenseSeat SDK | SDK adoption tracking |
os_name |
String | Operating system name (macOS, iOS, Windows, Linux, Android) |
Platform distribution |
os_version |
String | OS version (e.g., 15.2.0) |
OS distribution |
platform |
String | Runtime environment: native, node, browser, electron, react-native, deno, bun, unity |
Platform analytics |
device_model |
String | Hardware model (e.g., MacBookPro18,1, iPhone15,1) |
Device analytics |
app_version |
String | Host app version | Version adoption charts |
app_build |
String | Host app build number | Build tracking |
device_type |
String | Device form factor: phone, tablet, desktop, watch, tv, server, unknown |
Device type distribution |
architecture |
String | CPU architecture: arm64, x64, x86 |
Architecture distribution |
cpu_cores |
Integer | Number of CPU cores | Hardware segmentation |
memory_gb |
Integer | Total RAM in GB (rounded) | Hardware segmentation |
locale |
String | Full locale (e.g., en_US, pt_BR) |
Localization insights |
language |
String | 2-letter ISO 639-1 code (e.g., en, pt, es) -- extracted from locale |
Language distribution |
Additional Metadata
These fields are stored in the JSONB metadata column:
| Field | Type | Description | SDKs |
|---|---|---|---|
screen_resolution |
String | Screen resolution as WIDTHxHEIGHT |
Swift, JS (browser), C++ |
display_scale |
Number | Display pixel ratio (1.0, 2.0, 3.0) | Swift, JS (browser) |
browser_name |
String | Browser name (Chrome, Safari, Firefox, Edge) | JS (browser only) |
browser_version |
String | Browser version | JS (browser only) |
runtime_version |
String | Runtime version (e.g., .NET 9.0.0, Node 20.11.0) |
JS, C# |
timezone |
String | IANA timezone (e.g., America/New_York) |
All SDKs |
All fields are optional. Send what you have -- partial telemetry is better than none.
Which Endpoints Accept Telemetry
Telemetry is captured on these endpoints:
| Endpoint | Event type |
|---|---|
| Activate | activation |
| Deactivate | deactivation |
| Validate | validation |
| Heartbeat | heartbeat |
Every successful request to these endpoints creates a footprint with the telemetry data, the request IP (for geolocation), and the event type.
How the SDKs Handle It
The official SDKs collect and attach telemetry automatically -- no configuration needed.
Swift SDK
The Swift SDK collects telemetry on every API call:
// Automatic — no code needed.
// The SDK injects telemetry into every POST request.
// What gets collected:
// - sdk_name: "swift"
// - sdk_version: from LicenseSeatConfig.sdkVersion
// - os_name: "macOS", "iOS", "tvOS", "watchOS", "visionOS"
// - os_version: from ProcessInfo.operatingSystemVersion
// - platform: "native"
// - device_model: from sysctlbyname("hw.model")
// - app_version: from CFBundleShortVersionString
// - app_build: from CFBundleVersion
// - device_type: "desktop", "phone", "tablet", "watch", "tv", "headset"
// - architecture: "arm64" or "x64"
// - cpu_cores: from ProcessInfo.processorCount
// - memory_gb: from ProcessInfo.physicalMemory (rounded)
// - locale: from Locale.current.identifier
// - language: 2-letter code from locale
// - timezone: from TimeZone.current.identifier
// - screen_resolution: native pixel resolution
// - display_scale: backingScaleFactor / UIScreen.scale
The SDK also generates a stable device fingerprint automatically (for example, a hardware UUID on macOS and a platform-specific stable identifier on iOS) and sends it as a top-level parameter alongside telemetry. Legacy clients may still use the device_id field name, but fingerprint is the canonical term.
Custom Integrations
If you're building a custom SDK or integration, collect whatever fields are available on your platform and include them in the telemetry object:
import platform
import requests
requests.post(
"https://licenseseat.com/api/v1/products/my-app/licenses/XXXX/validate",
headers={"Authorization": "Bearer pk_live_xxx"},
json={
"fingerprint": get_device_fingerprint(),
"telemetry": {
"sdk_name": "python",
"sdk_version": "0.1.0",
"os_name": platform.system(),
"os_version": platform.release(),
"platform": "native",
"device_type": "desktop",
"architecture": platform.machine(),
"app_version": "1.0.0"
}
}
)
var body = new {
fingerprint = GetDeviceFingerprint(),
telemetry = new {
sdk_name = "csharp",
sdk_version = "0.1.0",
os_name = Environment.OSVersion.Platform.ToString(),
os_version = Environment.OSVersion.Version.ToString(),
platform = "native",
device_type = "desktop",
architecture = RuntimeInformation.ProcessArchitecture.ToString(),
app_version = Assembly.GetExecutingAssembly().GetName().Version.ToString()
}
};
What Powers the Analytics Dashboard
The telemetry data feeds directly into your product's analytics dashboard in LicenseSeat. The dashboard offers 7, 30, and 90 day time range selectors.
KPI Cards
- DAU — Daily Active Users (unique devices today)
- MAU — Monthly Active Users (unique devices this month)
- Unique Devices — Over selected time range
- Total Events — All telemetry events in range
Charts & Distributions
| Section | Metrics | Based on |
|---|---|---|
| Daily Active Devices | Bar chart of unique devices per day | fingerprint counts |
| Geographic Distribution | World map + country breakdown | IP geolocation (automatic) |
| Version Adoption | Donut + stacked area chart | app_version |
| Runtime Environment | OS versions, platforms, device types | os_name, os_version, platform, device_type |
| Hardware | Architecture, CPU cores histogram, memory histogram | architecture, cpu_cores, memory_gb |
LicenseSeat Section
| Metric | Description |
|---|---|
| Seats | Utilization percentage (used/total across all licenses) |
| Stale Devices | Devices with no heartbeat in 7+ days |
| SDK Versions | Distribution of sdk_version values |
| SDK Platforms | Distribution of sdk_name (swift, js, cpp, csharp) |
Geolocation
In addition to the telemetry fields you send, LicenseSeat automatically resolves geolocation from the request IP address. This provides country, city, region, coordinates, and timezone -- no extra work needed from the SDK.
Privacy
If your app needs to comply with GDPR or similar regulations, you can skip telemetry entirely by not including the telemetry key in your requests. The API works the same with or without it.