Creator Device Breakdown
Visitor device-type breakdown for the authenticated creator's bio page (mobile / tablet / desktop / unknown). All segments returned, sorted by count descending.
GET /api/v1/creators/analytics/devices โ ๐ Bearer ยท Rate limit: 60 req / minute
Returns all device types observed for sessions on the creator's bio page within the window โ typically mobile, desktop, tablet, plus unknown for sessions where UA parsing didn't land on a definite type. No LIMIT โ all distinct buckets are returned (typically 3-4 rows).
Device value comes from server-side UA parse. Set at session-create time by UAParser on the request User-Agent: 'mobile' / 'tablet' / fallback 'desktop'. Sessions where parsing yielded no device type are null, and the SQL COALESCE(device, 'unknown') puts them in an "unknown" bucket.
No LIMIT and no top-N cap. The SQL just GROUP BY device ORDER BY count DESC โ every distinct device value lands in the response. In practice this is 3-4 rows, but if a future UA parse introduces new buckets they'll show up here.
Request
Query parameters
| Param | Type | Default | Notes |
|---|---|---|---|
days | integer | 30 | Lookback window. Capped at 365. |
Headers
| Header | Required | Notes |
|---|---|---|
Authorization: Bearer <accessToken> | โ | JwtAuthGuard. |
Response
200 OK โ ApiResponseOf<CreatorDevicesDto>
{
"success": true,
"data": {
"segments": [
{ "name": "mobile", "count": 1200, "percentage": 67 },
{ "name": "desktop", "count": 480, "percentage": 27 },
{ "name": "tablet", "count": 90, "percentage": 5 },
{ "name": "unknown", "count": 30, "percentage": 2 }
]
}
}Item fields (segments[])
| Field | Type | Notes |
|---|---|---|
name | string | Device type โ mobile / tablet / desktop / unknown. |
count | number | Session count. |
percentage | number | Whole-number percentage of total. |
Errors
Same as overview.
Side effects
JwtAuthGuard+ThrottleGuard.getBioPageId(userId).analyticsDb.$queryRaw:SELECT COALESCE(device, 'unknown') as name, COUNT(*)::int as count FROM "AnalyticsSession" WHERE "bioPageId" = $bioPageId::uuid AND "startedAt" >= $since GROUP BY device ORDER BY count DESC- Compute
percentageper row; return.
Code samples
curl 'https://api.bio.re/api/v1/creators/analytics/devices?days=30' \
-H "Authorization: Bearer $ACCESS_TOKEN"type DeviceSegment = { name: string; count: number; percentage: number };
async function getDevices(accessToken: string, days = 30): Promise<{ segments: DeviceSegment[] }> {
const res = await fetch(
`https://api.bio.re/api/v1/creators/analytics/devices?days=${days}`,
{ headers: { Authorization: `Bearer ${accessToken}` } },
);
const json = await res.json();
if (!res.ok || !json.success) throw new Error(json?.error?.message ?? 'Failed');
return json.data;
}Try it
Authorization
bearer In: header
Query Parameters
Response Body
application/json
application/json
application/json
curl -X GET "https://loading/api/v1/creators/analytics/devices"{
"success": true,
"data": {
"segments": [
{
"name": "mobile",
"count": 1200,
"percentage": 66.7
}
]
}
}{
"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"
}
}{
"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
| Source | Path | Lines |
|---|---|---|
| Controller | apps/api-core/src/modules/analytics/creator-analytics.controller.ts | 100โ116 (devices) |
| DTO (response) | apps/api-core/src/modules/analytics/dto/analytics-client-response.dto.ts | 129โ132 (CreatorDevicesDto), 116โ125 (item shape) |
| Prisma model | packages/prisma-analytics/prisma/schema.prisma | AnalyticsSession.device (line 72), index @@index([device, startedAt]) (94) |
Creator Geo Distribution
Top 20 visitor countries for the authenticated creator's bio page. Country names from GeoIP at session-create; sessions with unknown country fall under "Unknown".
Creator Daily Trend
Per-day views and clicks for the creator's bio page. Bucketed via Postgres date_trunc('day', enteredAt). Days with no traffic are absent โ fill gaps client-side.