1House Global API Documentation

Analytics

Event tracking, search, and reporting

Track user events, search content, and access platform analytics.

Analytics & Search

Comprehensive event tracking, full-text search across all content, and advanced reporting for data-driven insights.

Overview

The Analytics Service provides:

  • Event tracking
  • Search functionality
  • User activity timelines
  • Dashboard analytics
  • Leaderboards — peak concurrency, gifting, and top viewers
  • Funnel analysis

Base Paths:

  • Analytics: /v1/analytics
  • Search: /v1/search

Event Tracking

Track Single Event

POST /v1/analytics/track

Try it out:

{
  "eventName": "page.view",
  "eventType": "navigation",
  "metadata": {
    "page": "/dashboard",
    "referrer": "/login",
    "device": "mobile"
  }
}

Track Bulk Events

POST /v1/analytics/track/bulk
{
  "events": [
    {
      "eventName": "button.click",
      "eventType": "interaction",
      "metadata": { "button": "buy_now" }
    },
    {
      "eventName": "form.submit",
      "eventType": "conversion",
      "metadata": { "form": "signup" }
    }
  ]
}

Get User Events

GET /v1/analytics/events
ParameterTypeDescription
pagenumberPage number
limitnumberResults per page
eventTypestringFilter by type
startDatedatetimeStart date
endDatedatetimeEnd date
{
  "success": true,
  "status": 200,
  "data": [
    {
      "id": "event_123",
      "userId": "user_456",
      "eventName": "trade.created",
      "eventType": "trading",
      "metadata": {
        "tradeId": "trade_789",
        "symbol": "EUR/USD"
      },
      "timestamp": "2025-10-21T12:00:00.000Z"
    }
  ],
  "pagination": {...}
}

Search All Content

GET /v1/search
ParameterTypeRequiredDescription
qstringYesSearch query
typestringNoFilter by type (post, course, trade, user)
pagenumberNoPage number
limitnumberNoResults per page

Example:

# Development
curl "https://api-gateway.dev.1houseglobalservices.com/v1/search?q=EUR/USD&type=post" \
  -H "X-API-Key: your-development-api-key" \
  -H "Authorization: Bearer your-jwt-token"

# Production
curl "https://api-gateway.prod.1houseglobalservices.com/v1/search?q=EUR/USD&type=post" \
  -H "X-API-Key: your-production-api-key" \
  -H "Authorization: Bearer your-jwt-token"
{
  "success": true,
  "status": 200,
  "data": {
    "results": [
      {
        "type": "post",
        "id": "post_123",
        "title": "EUR/USD Analysis",
        "excerpt": "...EUR/USD breaking resistance at 1.0950...",
        "url": "/posts/post_123",
        "score": 0.95,
        "createdAt": "2025-10-21T10:00:00.000Z"
      },
      {
        "type": "course",
        "id": "course_456",
        "title": "EUR/USD Trading Masterclass",
        "excerpt": "Learn to trade EUR/USD like a pro",
        "url": "/courses/course_456",
        "score": 0.87,
        "createdAt": "2025-01-15T00:00:00.000Z"
      }
    ],
    "totalResults": 45
  },
  "pagination": {
    "page": 1,
    "limit": 10,
    "total": 45,
    "pages": 5
  }
}

Get Search Suggestions

GET /v1/search/suggestions?q=eur
{
  "success": true,
  "status": 200,
  "data": [
    "EUR/USD",
    "EUR/USD trading strategies",
    "EUR/USD analysis",
    "EUR/GBP",
    "European Central Bank"
  ]
}

Get Search History

GET /v1/search/history
{
  "success": true,
  "status": 200,
  "data": [
    {
      "query": "EUR/USD analysis",
      "resultCount": 45,
      "searchedAt": "2025-10-21T12:00:00.000Z"
    }
  ]
}

Dashboard Analytics (Admin)

Get Dashboard Data

GET /v1/analytics/dashboard
ParameterTypeDescription
periodstring7d, 30d, 90d, 1y
{
  "success": true,
  "status": 200,
  "data": {
    "overview": {
      "totalUsers": 12500,
      "activeUsers": 3456,
      "newUsers": 234,
      "totalRevenue": 45678.00
    },
    "traffic": {
      "pageViews": 156789,
      "uniqueVisitors": 8901,
      "averageSessionDuration": 420
    },
    "engagement": {
      "postsCreated": 456,
      "commentsPosted": 1234,
      "reactionsGiven": 5678
    },
    "trading": {
      "tradesCreated": 789,
      "tradesWon": 512,
      "winRate": 64.89
    },
    "education": {
      "coursesCompleted": 234,
      "lessonsWatched": 3456,
      "totalWatchTime": 123456
    }
  }
}

Leaderboards

Four rankings behind one call: the educators with the most people watching at the same moment, who gave and received the most Keys, and who watched the most.

GET /v1/analytics/leaderboards

One payload, two audiences

1hstream's Leaderboard tab reads this endpoint with the viewer's own JWT. The management dashboard reads GET /v1/admin/analytics/leaderboards, which takes the same parameters and returns the same shape. Both are assembled by the same code, so the two surfaces can never disagree about who is winning.

Query Parameters:

ParameterTypeDescription
periodstring24h, 7d (default), 30d, 90d
startDatestringISO 8601. Overrides period
endDatestringISO 8601
platformstringios, android, web. Omit for every surface
contentTypestringlivestream, meeting, lesson, video, story. Narrows the watch-derived boards
limitnumberRows per board (default 10, max 50)

What peak concurrency actually counts

peakConcurrent is the most watch sessions open at the same moment, not the total number of people who passed through. It is counted per session rather than per user, because two tabs are two streams being served — which is what the number is for when sizing a broadcast. A session that started before the window opened still counts toward the window it overlaps.

Try it out:

Example Response:

{
  "success": true,
  "status": 200,
  "data": {
    "period": {
      "key": "30d",
      "startDate": "2026-02-01T00:00:00.000Z",
      "endDate": "2026-03-03T00:00:00.000Z"
    },
    "filters": { "platform": null, "contentType": null, "limit": 10 },
    "partial": false,
    "unavailable": [],
    "totals": {
      "platformPeakConcurrent": 1284,
      "platformPeakAt": "2026-02-18T21:04:00.000Z",
      "giftedKeys": 48210,
      "gifts": 3129,
      "gifters": 812,
      "giftRecipients": 46
    },
    "topConcurrentEducators": [
      {
        "rank": 1,
        "educatorId": "68f2c1a4e9b21c0012aa77d1",
        "peakConcurrent": 412,
        "peakAt": "2026-02-18T21:04:00.000Z",
        "watchSecs": 1840233,
        "sessions": 5120,
        "uniqueViewers": 3104,
        "name": "Leo Diaz",
        "username": "leodiaz",
        "slug": "leo-diaz",
        "avatar": "https://cdn.1house.tv/educators/leo.jpg"
      }
    ],
    "topGifters": [
      {
        "rank": 1,
        "userId": "68f2c1a4e9b21c0012aa8814",
        "keys": 2400,
        "gifts": 118,
        "counterparties": 12,
        "lastGiftAt": "2026-03-02T18:22:11.000Z",
        "name": "Jane Ruiz",
        "username": "janer",
        "slug": null,
        "avatar": null
      }
    ],
    "topGifted": [
      {
        "rank": 1,
        "userId": "68f2c1a4e9b21c0012aa77d1",
        "keys": 9120,
        "gifts": 640,
        "counterparties": 388,
        "lastGiftAt": "2026-03-02T20:11:04.000Z",
        "name": "Leo Diaz",
        "username": "leodiaz",
        "slug": "leo-diaz",
        "avatar": "https://cdn.1house.tv/educators/leo.jpg"
      }
    ],
    "topViewers": [
      {
        "rank": 1,
        "userId": "68f2c1a4e9b21c0012aa9002",
        "watchSecs": 184320,
        "sessions": 212,
        "contentCount": 31,
        "contentTypes": ["livestream", "meeting"],
        "lastWatchedAt": "2026-03-02T22:40:00.000Z",
        "name": "Marcus Hall",
        "username": "mhall",
        "slug": null,
        "avatar": null
      }
    ],
    "lastUpdated": "2026-03-03T09:12:44.000Z"
  }
}

Board Fields:

BoardRanked byKey fields
topConcurrentEducatorspeakConcurrentpeakAt, watchSecs, sessions, uniqueViewers
topGifterskeys givengifts, counterparties (distinct recipients)
topGiftedkeys receivedgifts, counterparties (distinct senders)
topViewerswatchSecssessions, contentCount, contentTypes

Check `partial` before trusting an empty board

The gifting boards are built from the Keys ledger in the wallet service. If that service cannot be reached, those two boards come back empty with partial: true and unavailable: ["gifting"] — which is not the same as nobody having gifted anything. Render the difference rather than showing an empty list.

Gifts count every surface

A gift is a completed Keys transfer stamped as one, whichever surface produced it: livestream tips, educator gifts and SafeHouse meeting tips all land on the same board. Admin transfers and wallet funding are excluded — they are not somebody choosing to give their Keys away.

Caching: responses are cached for 120 seconds. lastUpdated says when the payload was built.

User Activity

Get Activity Timeline

GET /v1/analytics/user/activity
ParameterTypeDescription
daysnumberNumber of days (default: 30)
{
  "success": true,
  "status": 200,
  "data": [
    {
      "date": "2025-10-21",
      "events": 45,
      "breakdown": {
        "page.view": 20,
        "trade.created": 3,
        "post.created": 2,
        "course.viewed": 5
      }
    }
  ]
}

Get User Statistics

GET /v1/analytics/user/stats
{
  "success": true,
  "status": 200,
  "data": {
    "totalEvents": 1234,
    "eventsThisWeek": 89,
    "eventsThisMonth": 345,
    "mostCommonEvents": [
      { "eventName": "page.view", "count": 567 },
      { "eventName": "trade.created", "count": 89 }
    ],
    "engagement": {
      "posts": 12,
      "comments": 45,
      "reactions": 123
    },
    "trading": {
      "trades": 34,
      "winRate": 67.65
    },
    "education": {
      "coursesEnrolled": 5,
      "lessonsCompleted": 89
    }
  }
}

Funnel Analysis (Admin)

Analyze Conversion Funnel

POST /v1/analytics/funnel
{
  "eventSequence": [
    "page.view.pricing",
    "button.click.signup",
    "form.submit.signup",
    "payment.completed"
  ],
  "startDate": "2025-10-01",
  "endDate": "2025-10-21"
}
{
  "success": true,
  "status": 200,
  "data": {
    "funnel": [
      {
        "step": "page.view.pricing",
        "count": 1000,
        "percentage": 100,
        "dropoff": 0
      },
      {
        "step": "button.click.signup",
        "count": 450,
        "percentage": 45,
        "dropoff": 55
      },
      {
        "step": "form.submit.signup",
        "count": 380,
        "percentage": 38,
        "dropoff": 7
      },
      {
        "step": "payment.completed",
        "count": 234,
        "percentage": 23.4,
        "dropoff": 14.6
      }
    ],
    "conversionRate": 23.4,
    "totalUsers": 1000
  }
}

Aggregated Analytics (Admin)

Get Event Aggregates

GET /v1/analytics/aggregate
ParameterTypeDescription
groupBystringday, week, month
eventTypestringFilter by event type
eventNamestringFilter by event name
startDatedatetimeStart date
endDatedatetimeEnd date

Get Event Counts by Type

GET /v1/analytics/events/types
{
  "success": true,
  "status": 200,
  "data": [
    { "eventType": "trading", "count": 456 },
    { "eventType": "education", "count": 789 },
    { "eventType": "navigation", "count": 1234 },
    { "eventType": "engagement", "count": 567 }
  ]
}
GET /v1/analytics/events/popular
{
  "success": true,
  "status": 200,
  "data": [
    { "eventName": "page.view", "count": 12345 },
    { "eventName": "trade.created", "count": 456 },
    { "eventName": "course.viewed", "count": 789 }
  ]
}

Common Events to Track

  • page.view - Page view
  • section.scroll - Scrolled to section
  • exit.intent - User about to leave

Engagement

  • button.click - Button clicked
  • form.submit - Form submitted
  • video.play - Video started
  • video.complete - Video finished

Trading

  • trade.created - New trade
  • trade.viewed - Trade idea viewed
  • market.searched - Symbol searched

Education

  • course.viewed - Course page view
  • lesson.started - Lesson playback started
  • lesson.completed - Lesson finished
  • course.enrolled - User enrolled

Conversion

  • signup.started - Signup form opened
  • signup.completed - Account created
  • payment.initiated - Checkout started
  • payment.completed - Purchase made

Client-Side Tracking

// Tracking utility
class AnalyticsTracker {
  constructor(apiKey, token) {
    this.apiKey = apiKey;
    this.token = token;
    this.queue = [];
    this.flushInterval = 10000;  // 10 seconds
    
    setInterval(() => this.flush(), this.flushInterval);
  }

  track(eventName, eventType, metadata = {}) {
    this.queue.push({
      eventName,
      eventType,
      metadata,
      timestamp: new Date().toISOString()
    });

    // Flush if queue gets large
    if (this.queue.length >= 10) {
      this.flush();
    }
  }

  async flush() {
    if (this.queue.length === 0) return;

    const events = [...this.queue];
    this.queue = [];

    await fetch('/v1/analytics/track/bulk', {
      method: 'POST',
      headers: {
        'X-API-Key': this.apiKey,
        'Authorization': `Bearer ${this.token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ events })
    });
  }
}

// Usage
const tracker = new AnalyticsTracker(apiKey, token);

// Track page view
tracker.track('page.view', 'navigation', { page: '/dashboard' });

// Track button click
document.getElementById('tradeBtn').addEventListener('click', () => {
  tracker.track('button.click', 'interaction', { button: 'create_trade' });
});

// Track form submit
form.addEventListener('submit', () => {
  tracker.track('form.submit', 'conversion', { form: 'signup' });
});
  • Indicators - Indicator access, granted and revoked from the backoffice
  • Wallet - Keys and the ledger the gifting boards are built from
  • Search API - Advanced search features
  • Reporting - Generate reports
  • Events - Event schema reference