Dashboard API

Dashboard statistics and analytics endpoints. Aggregates data from multiple services to provide unified views for the frontend dashboard, including machine stats, API key usage, storage metrics, and component analytics.

7 EndpointsAnalyticsStatisticsActivity Feed

Overview

Dashboard Data Sources

  • Machines: Connection status, adapter types
  • API Keys: Usage metrics, active keys
  • Storage: Bucket usage, quotas
  • Components: Status breakdown

Features

  • • Unified overview endpoint
  • • Individual stat endpoints for lazy loading
  • • Recent activity feed
  • • Organization-scoped data

Dashboard Overview

GET/v1/dashboard/overviewAuth Required
Get Dashboard Overview
Get comprehensive dashboard overview for the current user's organization. Returns all dashboard statistics in a single response for initial page load.

Response

Responsejson
{
  "organization_id": "org_abc123",
  "plan_name": "professional",
  "machine_stats": {
    "total_machines": 25,
    "active_machines": 20,
    "inactive_machines": 5,
    "connected_machines": 18,
    "disconnected_machines": 5,
    "connecting_machines": 2,
    "by_adapter": {
      "opcua": 15,
      "modbus": 8,
      "mqtt": 2
    },
    "by_vendor": {
      "Siemens": 10,
      "ABB": 8,
      "Fanuc": 7
    },
    "recently_offline": 0
  },
  "api_key_stats": {
    "total_keys": 5,
    "active_keys": 4,
    "revoked_keys": 1,
    "total_requests_today": 1250,
    "total_requests_this_month": 35000,
    "keys_by_scope": {
      "read": 2,
      "write": 1,
      "admin": 2
    }
  },
  "storage_stats": {
    "total_bytes": 536870912,
    "total_gb": 0.5,
    "total_files": 125,
    "quota_bytes": 10737418240,
    "quota_percentage": 5.0,
    "by_bucket_type": {
      "primary": 268435456,
      "documents": 268435456
    }
  },
  "component_stats": {
    "total_components": 150,
    "by_status": {
      "active": 120,
      "maintenance": 15,
      "retired": 10,
      "unknown": 5
    },
    "by_category": {
      "sensors": 50,
      "actuators": 40,
      "controllers": 30,
      "drives": 30
    }
  },
  "llm_billing_stats": {
    "total_tokens_used": 125000,
    "total_cost": 2.50,
    "requests_this_month": 500
  },
  "recent_activity": [
    {
      "type": "machine_connected",
      "description": "Machine CNC-001 connected",
      "timestamp": "2024-08-26T15:30:00Z"
    },
    {
      "type": "file_uploaded",
      "description": "Manual uploaded to CNC-001",
      "timestamp": "2024-08-26T15:25:00Z"
    }
  ],
  "last_updated": "2024-08-26T15:30:00Z"
}

Try it out

cURLbash
curl -X GET "https://sapienstream.com/api/v1/dashboard/overview" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Individual Statistics

Use these endpoints for lazy loading specific dashboard sections or refreshing individual cards.

GET/v1/dashboard/machine-statsAuth Required
Get Machine Statistics
Get machine statistics for the dashboard. Includes counts by connection status, adapter type, and vendor.

Response

Responsejson
{
  "total_machines": 25,
  "active_machines": 20,
  "inactive_machines": 5,
  "connected_machines": 18,
  "disconnected_machines": 5,
  "connecting_machines": 2,
  "by_adapter": {
    "opcua": 15,
    "modbus": 8,
    "mqtt": 2
  },
  "by_vendor": {
    "Siemens": 10,
    "ABB": 8,
    "Fanuc": 7
  },
  "recently_offline": 0
}

Try it out

cURLbash
curl -X GET "https://sapienstream.com/api/v1/dashboard/machine-stats" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"
GET/v1/dashboard/api-key-statsAuth Required
Get API Key Statistics
Get API key usage statistics for the dashboard. Tracks active keys, request counts, and usage by scope.

Response

Responsejson
{
  "total_keys": 5,
  "active_keys": 4,
  "revoked_keys": 1,
  "total_requests_today": 1250,
  "total_requests_this_month": 35000,
  "keys_by_scope": {
    "read": 2,
    "write": 1,
    "admin": 2
  },
  "top_keys_by_usage": [
    {
      "key_id": "key_abc123",
      "name": "Production API",
      "requests_today": 500
    }
  ]
}

Try it out

cURLbash
curl -X GET "https://sapienstream.com/api/v1/dashboard/api-key-stats" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"
GET/v1/dashboard/storage-statsAuth Required
Get Storage Statistics
Get storage usage statistics for the dashboard. Includes total usage, quota, and breakdown by bucket type.

Response

Responsejson
{
  "total_bytes": 536870912,
  "total_gb": 0.5,
  "total_files": 125,
  "quota_bytes": 10737418240,
  "quota_percentage": 5.0,
  "quota_exceeded": false,
  "by_bucket_type": {
    "primary": {
      "bytes": 268435456,
      "files": 75
    },
    "documents": {
      "bytes": 268435456,
      "files": 50
    }
  },
  "recent_uploads": 15
}

Try it out

cURLbash
curl -X GET "https://sapienstream.com/api/v1/dashboard/storage-stats" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"
GET/v1/dashboard/component-statsAuth Required
Get Component Statistics
Get component statistics for the dashboard. Includes counts by status and category.

Response

Responsejson
{
  "total_components": 150,
  "by_status": {
    "active": 120,
    "maintenance": 15,
    "retired": 10,
    "unknown": 5
  },
  "by_category": {
    "sensors": 50,
    "actuators": 40,
    "controllers": 30,
    "drives": 30
  },
  "recently_added": 5,
  "needs_attention": 20
}

Try it out

cURLbash
curl -X GET "https://sapienstream.com/api/v1/dashboard/component-stats" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Activity Feed

GET/v1/dashboard/activityAuth Required
Get Recent Activity
Get recent activity feed for the dashboard. Shows the latest events across machines, files, and system operations.

Parameters

limitinteger

Number of activities to return (default: 10)

Response

Responsejson
{
  "activities": [
    {
      "type": "machine_connected",
      "entity_type": "machine",
      "entity_id": "mach_001",
      "description": "Machine CNC-001 connected",
      "user_id": "user_001",
      "timestamp": "2024-08-26T15:30:00Z"
    },
    {
      "type": "file_uploaded",
      "entity_type": "document",
      "entity_id": "doc_abc123",
      "description": "Operation manual uploaded",
      "user_id": "user_002",
      "timestamp": "2024-08-26T15:25:00Z"
    },
    {
      "type": "component_created",
      "entity_type": "component",
      "entity_id": "comp_001",
      "description": "New sensor TE01 added",
      "user_id": "user_001",
      "timestamp": "2024-08-26T15:20:00Z"
    },
    {
      "type": "api_key_created",
      "entity_type": "api_key",
      "entity_id": "key_def456",
      "description": "New API key 'Production' created",
      "user_id": "user_001",
      "timestamp": "2024-08-26T15:15:00Z"
    }
  ],
  "count": 4,
  "limit": 10
}

Try it out

cURLbash
curl -X GET "https://sapienstream.com/api/v1/dashboard/activity" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Health Check

GET/v1/dashboard/health
Dashboard Service Health Check
Check the health of the dashboard service. Returns available endpoints and service status.

Response

Responsejson
{
  "service": "Dashboard Service",
  "status": "healthy",
  "version": "1.0.0",
  "endpoints": [
    "/dashboard/overview",
    "/dashboard/machine-stats",
    "/dashboard/api-key-stats",
    "/dashboard/storage-stats",
    "/dashboard/component-stats",
    "/dashboard/activity"
  ]
}

Try it out

cURLbash
curl -X GET "https://sapienstream.com/api/v1/dashboard/health" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

Dashboard Loading Example

// Option 1: Load all dashboard data at once (initial page load)
const overviewResponse = await fetch('/v1/dashboard/overview', {
  headers: {
    'Authorization': 'Bearer ' + token
  }
});

const dashboard = await overviewResponse.json();
console.log('Machines:', dashboard.machine_stats.total_machines);
console.log('Storage:', dashboard.storage_stats.total_gb, 'GB');
console.log('Components:', dashboard.component_stats.total_components);

// Option 2: Lazy load individual sections
async function refreshMachineStats() {
  const response = await fetch('/v1/dashboard/machine-stats', {
    headers: {
      'Authorization': 'Bearer ' + token
    }
  });
  const stats = await response.json();
  updateMachineCard(stats);
}

async function refreshActivity() {
  const response = await fetch('/v1/dashboard/activity?limit=20', {
    headers: {
      'Authorization': 'Bearer ' + token
    }
  });
  const { activities } = await response.json();
  updateActivityFeed(activities);
}

// Refresh individual sections periodically
setInterval(refreshMachineStats, 30000);  // Every 30 seconds
setInterval(refreshActivity, 10000);       // Every 10 seconds

React Dashboard Hook

import { useState, useEffect } from 'react';

function useDashboard() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchDashboard() {
      try {
        const response = await fetch('/v1/dashboard/overview', {
          headers: {
            'Authorization': 'Bearer ' + getToken()
          }
        });
        
        if (!response.ok) throw new Error('Failed to fetch dashboard');
        
        const dashboard = await response.json();
        setData(dashboard);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    }

    fetchDashboard();
    
    // Refresh every 60 seconds
    const interval = setInterval(fetchDashboard, 60000);
    return () => clearInterval(interval);
  }, []);

  return { data, loading, error };
}

// Usage in component
function DashboardPage() {
  const { data, loading, error } = useDashboard();

  if (loading) return <DashboardSkeleton />;
  if (error) return <ErrorMessage message={error} />;

  return (
    <div className="grid grid-cols-4 gap-4">
      <MachineStatsCard stats={data.machine_stats} />
      <StorageStatsCard stats={data.storage_stats} />
      <ComponentStatsCard stats={data.component_stats} />
      <ActivityFeed activities={data.recent_activity} />
    </div>
  );
}