HOME โ€บ OPERATIONS โ€บ 8x8 CPaaS OPERATIONS CONSOLE โ€” KB
stack-8x8.html ยท 8x8 CPaaS
KNOWLEDGE BASE // OPERATIONS // 8x8 CPaaS
8x8 CPaaS Operations Console
Complete reference for understanding, configuring, and integrating the 8x8 CPaaS Operations Console โ€” a unified dashboard for SMS, Voice, Video, Authentication, Chat Apps, and Omni Shield fraud monitoring. Covers the data architecture, all five dashboard sections, and the full build guide for wiring live 8x8 APIs via a proxy layer.
OPERATIONS 8x8 CPaaS DEMO MODE โ€” NOT LIVE SMS ยท VOICE ยท VIDEO ยท AUTH OMNI SHIELD FRAUD
FILE
stack-8x8.html
DATA SOURCE
Demo generators โ€” no live API
SECTIONS
5 โ€” KPIs ยท Channels ยท Alerts ยท Incidents ยท Feeds
REFRESH
30 seconds (simulated)
REAL API BASE
sms.8x8.com / developer.8x8.com
01
WHAT THIS TOOL DOES

The 8x8 CPaaS Operations Console is a single-file HTML dashboard that provides a unified view of the 8x8 Communications Platform as a Service stack โ€” SMS messaging, voice calls, video sessions, OTP authentication, chat app messaging (WhatsApp/Viber/LINE), and Omni Shield fraud detection. It is designed for MSP operations teams managing clients who use 8x8 CPaaS for customer communications.

The dashboard gives operators a single screen to monitor channel health across all 8x8 API services, track active alerts and incident severity, view call detail records, and watch the Omni Shield fraud detection feed in real time. It refreshes every 30 seconds and includes a footer status bar showing API call count and system state.

CURRENT STATE โ€” DEMO ONLY As shipped, this console runs entirely on randomly generated data. There is no live connection to any 8x8 API. The proxy endpoints referenced in the code (/api/8x8/summary, /api/8x8/alerts, etc.) are custom placeholder paths โ€” they are not real 8x8 API routes. See Section 03 for the full wiring status breakdown before deploying this to production.
02
ARCHITECTURE & DATA FLOW

The console is a self-contained single HTML file with no framework dependencies. Chart.js is not used โ€” all rendering is pure DOM manipulation. The data engine runs client-side and follows a try/catch fetch pattern: attempt to call the proxy, fall back to the generator function on any failure.

REFRESH CYCLE

On load and every 30 seconds, the refresh() function fires a Promise.all of six apiFetch() calls. Each call targets a proxy endpoint and accepts a generator function as its fallback. If the fetch succeeds, the returned JSON is used. If it fails for any reason โ€” network error, 404, timeout โ€” the generator runs and produces randomized demo data instead. This means the console always renders successfully regardless of whether any API is connected.

REFRESH LOOP โ€” SIX PARALLEL CALLS
const [summary, alerts, events, cdrs, channels, fraud] = await Promise.all([ apiFetch(BASE+'/api/8x8/summary', genSummary), // KPIs apiFetch(BASE+'/api/8x8/alerts', genAlerts), // Alert strip + incident table apiFetch(BASE+'/api/8x8/events', genEvents), // Platform event feed apiFetch(BASE+'/api/8x8/cdr', genCDR), // Call detail records Promise.resolve(genChannels()), // Channel health โ€” always generated apiFetch(BASE+'/api/8x8/fraud', genFraud), // Omni Shield fraud feed ]);
BASE URL

The BASE constant is set to an empty string ''. All proxy calls are therefore relative to the page's own origin โ€” the dashboard and the proxy must be served from the same domain. When deploying, set BASE to the base URL of your Azure Function proxy if it is on a different origin.

CHANNEL HEALTH IS ALWAYS GENERATED Unlike the other five endpoints, channel health data is always produced by genChannels() and never attempted via apiFetch(). The proxy paths stored in the channel objects (/api/8x8/sms/health, etc.) are display labels only โ€” they are shown in the UI but never called. When wiring live data, you will need to replace the Promise.resolve(genChannels()) call with a real fetch to get live channel status.
03
WIRING STATUS โ€” READ BEFORE DEPLOYING

The proxy endpoints used in this console are custom aggregation paths. They do not correspond to any native 8x8 API endpoint. The real 8x8 CPaaS API is organized around individual channel operations (send an SMS, initiate a call, verify an OTP) โ€” it does not have a native "summary", "alerts", or "fraud feed" endpoint. Those operational views need to be constructed by aggregating multiple API responses in your proxy layer.

PROXY PATH IN CODEREAL 8x8 API EXISTS?HOW TO BUILD IT
/api/8x8/summary No native endpoint Aggregate from multiple calls: SMS delivery stats from GET /api/v1/{subAccountId}/reports, active call count from Voice API, video session count from JaaS / Video Interaction API, OTP verification count from Verify API. Your proxy must compose these into a single summary object.
/api/8x8/alerts No native alerts endpoint 8x8 CPaaS does not have an operational alerts API. Alerts must be constructed from anomaly detection logic in your proxy โ€” e.g. SMS delivery rate below threshold, API error rate elevated, high OTP failure rate. This is custom business logic, not a vendor endpoint.
/api/8x8/events Webhooks, not polling 8x8 delivers events via webhooks (outbound HTTP POST to your endpoint). To populate this feed, your proxy needs to receive and store incoming webhooks from 8x8, then serve the recent event log via GET. This is a different integration pattern than the other endpoints.
/api/8x8/cdr Closest to real API CDR data is available via the 8x8 Analytics API and the Connect Portal export. The closest real endpoint depends on your 8x8 product tier โ€” check the Analytics section of developer.8x8.com/connect for your account's available reporting endpoints.
/api/8x8/fraud No native feed endpoint Omni Shield is 8x8's fraud detection platform. It operates via real-time webhooks that fire on fraud events, not a polling endpoint. Your proxy needs to receive and store Omni Shield webhook payloads and serve them as a feed โ€” similar to the events endpoint above.
Channel health paths
/api/8x8/sms/health etc.
Display labels only โ€” never called These paths exist only as display labels in the UI. They are stored in the channel objects but genChannels() is always used โ€” no fetch is attempted. For live channel health, add a fetch call and map real API error rates or status page data to the ok/warn/err status values.
WHAT THIS MEANS FOR PRODUCTION This console cannot be "switched to live mode" by simply pointing it at real 8x8 API keys. The proxy layer must be built first to aggregate, transform, and serve data in the shape the console expects. The proxy is the integration work โ€” not the console itself. The console is already complete and does not need modification. See the Config Guide (C1โ€“C6) for the full build plan.
04
KPI STRIP

Seven KPI tiles run across the top of the console. They are rendered by renderKPIs() on every refresh and animate from their previous value to the new value over 700ms using the anim() function. Each tile has a colored top accent, icon, label, value, subtext, and a delta badge showing direction of change.

๐Ÿ“จ SMS Sent
Total SMS messages dispatched today across all accounts. Source: summary.sms_sent. Demo range: 84Kโ€“92K. Orange accent. Delta badge shows MoM direction.
๐Ÿ“ž Active Calls
Current concurrent voice sessions. Source: summary.active_calls. Demo range: 320โ€“580. Green accent.
๐ŸŽฅ Video Sessions
Live video meetings in progress. Source: summary.video_sessions. Demo range: 48โ€“140. Blue accent.
๐Ÿ” Auth Verifications
2FA/OTP verifications completed today. Source: summary.auth_verifications. Demo range: 14Kโ€“18K. Teal accent.
๐Ÿšจ Active Alerts
Count of open incidents. Source: summary.active_alerts. Demo range: 12โ€“34. Red accent. negGood:true โ€” delta badge is inverted (increase = bad).
โšก API Latency
Average API response time in milliseconds. Source: summary.api_latency. Demo range: 28โ€“95ms. Amber accent. negGood:true โ€” higher latency = worse.
๐Ÿ’ฌ Chat App Msgs
Messages sent across WhatsApp, Viber, and LINE. Source: summary.chat_messages. Demo range: 22Kโ€“31K. Purple accent.
DELTA BADGE LOGIC The delta badge compares the current value against the previous cycle's value stored in prev[key]. For most KPIs, an increase is positive (green up arrow). For active_alerts and api_latency, the negGood flag is set to true โ€” these fields show a red badge on increase and green on decrease.
05
CHANNEL HEALTH PANEL

The channel health panel shows the operational status of all eight 8x8 API services. Each row shows the service name, its proxy path (as a display label), a latency reading, and a status indicator. Status is one of ok (green), warn (amber), or err (red).

CHANNELDISPLAY PATHLATENCY RANGE (DEMO)STATUS DISTRIBUTION
SMS API/api/8x8/sms/health15โ€“310ms~71% ok, ~14% warn, ~14% err
Voice API/api/8x8/voice/health15โ€“310msSame distribution
Video API/api/8x8/video/health15โ€“310msSame distribution
Chat Apps/api/8x8/chat/health15โ€“310msWhatsApp / Viber / LINE
Auth / OTP/api/8x8/auth/health15โ€“310msVerification + 2FA
Contacts API/api/8x8/contacts/health15โ€“310msContact database management
IVR / TTS/api/8x8/ivr/health15โ€“310msInteractive voice response
Omni Shield/api/8x8/fraud/health15โ€“310msFraud detection platform

The path column is a UI display label only โ€” these paths are never fetched. Channel health status and latency are generated fresh on every refresh cycle by genChannels().

06
PLATFORM STATUS CARDS

Platform cards appear to the right of the channel health panel and show aggregate status for the major 8x8 product categories. They are rendered by renderPlatCards() using data from the summary object. Each card shows a delivery rate, uptime percentage, and a count of active sessions.

SMS Platform
Shows SMS sent count and delivery failure count. Source: summary.sms_sent. Failure count is randomized in demo (40โ€“120).
Voice Platform
Active call count and concurrent session capacity. Source: summary.active_calls.
Authentication
OTP verification count and failure rate. Source: summary.auth_verifications.
Platform API
APIs healthy count (hardcoded "7/8" in demo) and active alert count. Source: summary.active_alerts.
07
ALERT STRIP

Section 03 of the console shows a horizontal scrolling strip of recent alert badges rendered by renderAlertStrip(). Each badge shows the incident ID, severity, and a truncated title. Clicking an alert badge could scroll to the incident table โ€” this interaction is present in the source but can be wired to open a detail view.

Alerts are drawn from the full alerts array returned by the /api/8x8/alerts proxy call (or genAlerts() in demo). The strip shows a subset of the most recent alerts. The same data populates the full incident queue table in Section 04.

Demo alert titles include realistic operational scenarios: SMS delivery rate degradation, WhatsApp throughput spikes, OTP failure rate elevation by region, fraud score threshold breaches, IVR timeout spikes, carrier route failovers, and 2FA bypass attempts.

08
INCIDENT QUEUE

Section 04 is the full incident table, rendered by renderTable(). It shows all incidents from the alerts dataset and supports four filter states: ALL, OPEN, ACK, and RESOLVED. The active filter is highlighted and the row count updates dynamically.

ID
Incident identifier in 8X8-NNNN format. Demo range: 8X8-4400 to 8X8-4428.
SEV
Severity level: S1 (critical), S2 (high), S3 (medium), S4 (low). S1 rows have red background highlight. S2 orange. S3 yellow. S4 neutral.
TITLE / ACCOUNT
Incident title from the titles array and the affected account ID from accts. Both are generated from realistic MSP scenarios.
CHANNEL
The 8x8 service affected: SMS API, Voice API, Video API, Chat Apps, Auth API, IVR, or Contacts API.
STATUS
open, ack, or resolved. The filter buttons filter by this field.
AGE
Time since incident created. Shown as seconds, minutes, or hours based on the generated age value.
ASSIGNED
Engineer or team name. Demo values: NOC Team, A. Patel, S. Kim, Auto-Remediation, J. Carter, Unassigned.
09
LIVE FEEDS

Section 05 shows three side-by-side feed panels at the bottom of the console. Each refreshes on every 30-second cycle.

PLATFORM EVENT FEED

Rendered by renderEvents() from the /api/8x8/events proxy (or genEvents()). Shows a timestamped log of platform operations: bulk SMS dispatches, outbound calls via Voice API, OTP verifications, video session initiations, API key rotations, SMS delivery failures, number masking calls, fraud alert suppressions, RCS messages, and IVR traversals. Each event has a channel tag (sms, voice, auth, video, admin) that determines its color coding.

RECENT CALL RECORDS (CDR)

Rendered by renderCDR() from the /api/8x8/cdr proxy (or genCDR()). Shows call detail records with: call ID, direction (inbound/outbound), from/to numbers, duration in seconds, and status (completed/failed/busy/no-answer). In production this would be wired to the 8x8 Analytics API or CDR export endpoint.

OMNI SHIELD ยท FRAUD FEED

Rendered by renderFraud() from the /api/8x8/fraud proxy (or genFraud()). Shows the 4โ€“7 most recent fraud detection events with a threat description, carrier/origin metadata, and a numeric fraud score (0โ€“100). Higher scores indicate higher threat confidence. Demo scenarios include smishing attempts, OTP flooding, toll fraud patterns, grey route traffic anomalies, velocity check triggers, robocall signature matches, and CLI spoofing.

OMNI SHIELD INTEGRATION NOTE In production, Omni Shield delivers fraud events via webhooks โ€” not a polling GET endpoint. Your proxy will need to receive POST webhooks from 8x8, store recent events, and serve them via a GET endpoint that the dashboard polls. This is a different integration pattern than the SMS or Voice APIs which support polling.
11
DATA MODEL

The proxy must return objects matching these shapes exactly. The rendering functions consume these shapes directly with no transformation layer โ€” field names are hardcoded throughout the render functions.

SUMMARY OBJECT
{ sms_sent: number, // total SMS today active_calls: number, // concurrent voice sessions video_sessions: number, // live video meetings auth_verifications: number, // OTP verifications today active_alerts: number, // open incident count api_latency: number, // avg response ms chat_messages: number, // WhatsApp/Viber/LINE msgs delivery_rate: string, // e.g. "98.7" (percent) uptime: string, // e.g. "99.97" (percent) }
ALERT OBJECT (array)
{ id: string, // e.g. "8X8-4401" title: string, // alert description account: string, // e.g. "acct-corp-001" channel: string, // "SMS API" | "Voice API" | "Video API" etc. sev: string, // "S1" | "S2" | "S3" | "S4" status: string, // "open" | "ack" | "resolved" age: string, // e.g. "12m" | "2h" | "45s" assignee: string, // engineer name or "Unassigned" }
FRAUD EVENT OBJECT (array)
{ msg: string, // threat description e.g. "SMISHING attempt blocked" sub: string, // carrier/origin detail e.g. "Carrier: T-Mobile US" score: number, // fraud confidence 0โ€“100 }
12
SEVERITY REFERENCE
LEVELCSS CLASSCOLORMEANING
S1sev-s1RedCritical โ€” service-impacting, immediate response required. Row highlighted in incident table.
S2sev-s2OrangeHigh โ€” significant degradation, respond within SLA window.
S3sev-s3YellowMedium โ€” partial impact, monitor and address in next cycle.
S4sev-s4NeutralLow โ€” informational or minor. No immediate action required.
13
REAL 8x8 API REFERENCE

These are the actual 8x8 CPaaS API endpoints your proxy will call. All authentication uses an API key obtained from the 8x8 Connect Portal (Admin โ†’ API Keys). The key is passed as a request header.

AUTHENTICATION
// All 8x8 CPaaS API calls require: x-8x8-c2c-api-key: YOUR_API_KEY // header name for SMS/Chat APIs // OR for some endpoints: Authorization: Basic {base64(subAccountId:apiKey)} // Obtain your API key and subAccountId from: https://connect.8x8.com โ†’ Admin โ†’ API Keys
CHANNELREAL ENDPOINTMETHODWHAT TO EXTRACT
SMS โ€” Send https://sms.8x8.com/api/v1/{subAccountId}/single POST Send individual SMS. Response includes requestId for delivery tracking.
SMS โ€” Delivery Status https://sms.8x8.com/api/v1/{subAccountId}/status/{requestId} GET Delivery status for a sent message. Use to calculate delivery rate for the summary KPI.
SMS โ€” Reports https://sms.8x8.com/api/v1/{subAccountId}/reports GET Aggregate delivery stats for a time period. Primary source for sms_sent and delivery rate.
Voice API See developer.8x8.com/connect/docs/voice Various Outbound calls, IVR, number masking, TTS. Active call count requires webhook-based session tracking.
Video Interaction See developer.8x8.com/vi-overview Various Video session APIs. Active session count requires webhook-based session tracking.
Verify / OTP https://verify.8x8.com/api/v1/send POST Send OTP. Use webhook callbacks or polling /status to track verification count.
Contacts API https://connect.8x8.com/api/v1/contacts GET/POST Contact database management. Read contacts for CRM integration.
Webhooks (all channels) Configured in 8x8 Connect Portal POST (inbound) Delivery receipts, inbound messages, OTP callbacks, Omni Shield fraud events. Your proxy receives these.
DEVELOPER PORTAL Full API reference, authentication guides, webhook configuration, and SDK documentation: developer.8x8.com/connect. Create your account and get API keys at: connect.8x8.com.
CONFIGURATION GUIDE
C1
PREREQUISITES
8x8 CPaaS Account
An active 8x8 CPaaS account with API access enabled. Log in to connect.8x8.com, navigate to Admin โ†’ API Keys, and generate a key. You will also need your subAccountId โ€” found in the same section.
Channels to Monitor
Determine which 8x8 channels your client uses โ€” not all accounts have Voice, Video, and Verify enabled. Only wire the proxy endpoints for channels your account has access to. The others can remain as demo generators.
Webhook Endpoint
For events, fraud feed, and delivery receipts, you need a publicly accessible HTTPS endpoint to receive 8x8 webhook POSTs. This is part of the proxy layer โ€” see C2.
Azure Function Proxy
The 8x8 API key must never appear in browser-side code. Route all API calls through the Azure Function proxy built during Stage 1. Store 8x8-api-key and 8x8-subaccount-id in Key Vault. The Function App reads them via Managed Identity.
SharePoint or Web Host
The HTML file must be served over HTTPS. SharePoint document library is the standard deployment target. Set BASE in the script to the Function App URL if it is on a different origin from the HTML file.
C2
BUILD THE PROXY LAYER

Unlike the other stack consoles that wrap a single vendor's API, the 8x8 proxy must do two distinct things: actively fetch data from polling endpoints, and passively receive and store incoming webhooks. Both are required for a fully live console.

POLLING ROUTES โ€” EXPOSE THESE FROM YOUR PROXY
// The dashboard calls these routes โ€” your proxy must serve them GET /api/8x8/summary โ†’ aggregate: SMS reports + active call count + OTP count GET /api/8x8/alerts โ†’ custom: computed from anomaly thresholds (see C4) GET /api/8x8/events โ†’ serve stored webhook log (see C2 webhook section) GET /api/8x8/cdr โ†’ query 8x8 reports API for recent call records GET /api/8x8/fraud โ†’ serve stored Omni Shield webhook log
WEBHOOK RECEIVER โ€” YOUR PROXY MUST ACCEPT THESE

Configure these webhook URLs in the 8x8 Connect Portal (Settings โ†’ Webhooks). Your Function App or proxy server must expose POST endpoints for each and persist the payloads for the polling GET endpoints above to serve.

// Configure in 8x8 Connect Portal โ†’ Webhooks POST /webhooks/8x8/delivery โ†’ SMS delivery receipts POST /webhooks/8x8/inbound โ†’ inbound messages (reply SMS, WhatsApp etc) POST /webhooks/8x8/events โ†’ platform events (call started, session ended etc) POST /webhooks/8x8/fraud โ†’ Omni Shield fraud detections // Store to in-memory ring buffer or lightweight DB (Cosmos DB, Redis) // GET /api/8x8/events serves the last N items from the ring buffer
C3
WIRE SUMMARY ENDPOINT

The summary endpoint aggregates multiple 8x8 API calls into the single object the KPI strip expects. Your proxy handles all the fan-out โ€” the dashboard only sees one clean object.

  • 1
    SMS sent count and delivery rateCall GET https://sms.8x8.com/api/v1/{subAccountId}/reports?startDate=TODAY&endDate=TODAY. Extract totalSent and compute delivery rate from delivered/totalSent.
  • 2
    Active calls8x8 Voice API does not expose a native active-call-count endpoint. Track session state via webhooks (call.started / call.ended) and maintain a counter in your proxy's state store.
  • 3
    Auth verificationsCall the Verify API status endpoint or aggregate from webhook receipts of verify.success and verify.failed events logged through the day.
  • 4
    Chat messagesWhatsApp, Viber, and LINE message counts are available from the 8x8 Connect Portal analytics API if your account tier includes reporting. Alternatively track via inbound/outbound message webhooks.
  • 5
    API latencyMeasure the round-trip time of a lightweight ping to the SMS status endpoint from your proxy and return that as api_latency. This is the most meaningful latency signal for MSP operational monitoring.
  • 6
    Active alertsReturn the count of currently open items in your proxy's alert store (computed in C4). This must be consistent with what GET /api/8x8/alerts returns.
C4
WIRE ALERTS & INCIDENTS

The alerts endpoint is the most custom piece of this integration. 8x8 does not have a native operational alerts API โ€” your proxy must implement alert generation logic based on thresholds applied to the data it collects.

ALERT SCENARIODATA SOURCETHRESHOLD EXAMPLE
SMS delivery rate degradedSMS reports APIDelivery rate < 95% in rolling 15-minute window
OTP failure rate elevatedVerify webhooksFailed verifications > 10% of total in last 100 attempts
API key rate limit breached8x8 API 429 responsesAny 429 from the 8x8 API triggers an S2 alert
Carrier route failoverSMS delivery webhooksDelivery failures on a single carrier route exceed threshold
Fraud score threshold exceededOmni Shield webhooksAny Omni Shield event with score > 80 becomes an S1 alert
Voice call quality below thresholdVoice API / webhooksMOS score or packet loss reported below SLA floor

Each alert object your proxy generates must match the alert data shape documented in Section 11. Assign severity (S1โ€“S4), set initial status to open, and store with a creation timestamp for the age calculation.

C5
WIRE CHANNEL HEALTH

Channel health is the only data source currently hard-wired to always use the generator. To wire live channel status, replace the Promise.resolve(genChannels()) line in the master refresh() call with a real apiFetch() call.

REPLACE THIS LINE IN refresh()
// Current โ€” always generated: Promise.resolve(genChannels()) // Replace with: apiFetch(BASE+'/api/8x8/channels', genChannels)

Your proxy's /api/8x8/channels endpoint should measure actual API response times for each channel by making lightweight test calls (e.g. a status ping to the SMS API), then return an array of channel objects with latency in milliseconds and status set to ok, warn, or err based on the response. The name, icon, and path fields are display-only and do not need to change.

C6
VERIFY & TROUBLESHOOT
  • โœ“
    BASE variable set correctly. If the proxy is on a different origin from the HTML file, BASE must be set to the full proxy URL (e.g. https://your-funcapp.azurewebsites.net). An empty BASE means the dashboard and proxy are on the same origin.
  • โœ“
    All proxy endpoints return valid JSON. The apiFetch() function falls back silently to the demo generator on any error. If your proxy is returning HTML error pages instead of JSON, the console will show demo data with no error indication. Check the browser Network tab to confirm each proxy endpoint is returning JSON with a 200 status.
  • โœ“
    API key stored in Key Vault, not in proxy code. Verify the Function App's Application Settings show the Key Vault reference string (@Microsoft.KeyVault(...)), not the actual key value. If the raw key is visible in App Settings, the Key Vault reference did not resolve โ€” check Managed Identity access policies.
  • โœ“
    Webhooks configured in 8x8 Connect Portal. Navigate to Settings โ†’ Webhooks and confirm all four webhook URLs point to your proxy's public HTTPS endpoint. 8x8 webhooks require HTTPS โ€” HTTP will be rejected.
  • โœ“
    KPI strip shows real numbers after first refresh. In demo mode values are in the 80Kโ€“92K range for SMS. In live mode the numbers should reflect your actual account volume. A live SMS count of 0 with active accounts is a signal the reports API call failed or the date range is wrong.
  • โœ“
    Footer shows real latency. In demo mode, LAST FETCH shows 60โ€“200ms (the artificial delay). In live mode it should reflect your actual proxy response time. Values above 2000ms indicate proxy performance issues.
  • โœ“
    Channel health feed updating. If channel health always shows the same latency and status distribution as demo mode, the Promise.resolve(genChannels()) line has not been replaced with a live fetch yet โ€” see C5.
TROUBLESHOOTING
SYMPTOMCAUSEFIX
Console shows demo data despite proxy being liveapiFetch() caught an error and fell back to generatorOpen browser DevTools โ†’ Network tab. Find the proxy request. Check response status and body for the actual error.
API CALLS counter stops incrementingRefresh loop stopped โ€” likely a JavaScript errorCheck browser console (F12) for uncaught exceptions. A render function receiving unexpected data shape can break the loop.
Incident table empty after filteringAll incidents have a different status value than expectedLog the alerts array to the console. Verify status values are exactly "open", "ack", or "resolved" โ€” case sensitive.
Fraud feed always emptyOmni Shield webhooks not reaching proxy or not storedCheck proxy webhook receiver logs. Confirm 8x8 Connect Portal has the correct webhook URL for fraud events.
SYSTEM shows NOMINAL but data is staleftsys element only reflects the refresh loop state, not API healthIn production, add logic to set ftsys to DEGRADED if any apiFetch() call returned an error rather than falling back to the generator.