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.
/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.
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.
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.
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.
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.
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 CODE | REAL 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. |
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.
summary.sms_sent. Demo range: 84Kโ92K. Orange accent. Delta badge shows MoM direction.summary.active_calls. Demo range: 320โ580. Green accent.summary.video_sessions. Demo range: 48โ140. Blue accent.summary.auth_verifications. Demo range: 14Kโ18K. Teal accent.summary.active_alerts. Demo range: 12โ34. Red accent. negGood:true โ delta badge is inverted (increase = bad).summary.api_latency. Demo range: 28โ95ms. Amber accent. negGood:true โ higher latency = worse.summary.chat_messages. Demo range: 22Kโ31K. Purple accent.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.
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).
| CHANNEL | DISPLAY PATH | LATENCY RANGE (DEMO) | STATUS DISTRIBUTION |
|---|---|---|---|
| SMS API | /api/8x8/sms/health | 15โ310ms | ~71% ok, ~14% warn, ~14% err |
| Voice API | /api/8x8/voice/health | 15โ310ms | Same distribution |
| Video API | /api/8x8/video/health | 15โ310ms | Same distribution |
| Chat Apps | /api/8x8/chat/health | 15โ310ms | WhatsApp / Viber / LINE |
| Auth / OTP | /api/8x8/auth/health | 15โ310ms | Verification + 2FA |
| Contacts API | /api/8x8/contacts/health | 15โ310ms | Contact database management |
| IVR / TTS | /api/8x8/ivr/health | 15โ310ms | Interactive voice response |
| Omni Shield | /api/8x8/fraud/health | 15โ310ms | Fraud 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().
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.
summary.sms_sent. Failure count is randomized in demo (40โ120).summary.active_calls.summary.auth_verifications.summary.active_alerts.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.
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.
8X8-NNNN format. Demo range: 8X8-4400 to 8X8-4428.titles array and the affected account ID from accts. Both are generated from realistic MSP scenarios.open, ack, or resolved. The filter buttons filter by this field.Section 05 shows three side-by-side feed panels at the bottom of the console. Each refreshes on every 30-second cycle.
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.
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.
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.
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.
| LEVEL | CSS CLASS | COLOR | MEANING |
|---|---|---|---|
| S1 | sev-s1 | Red | Critical โ service-impacting, immediate response required. Row highlighted in incident table. |
| S2 | sev-s2 | Orange | High โ significant degradation, respond within SLA window. |
| S3 | sev-s3 | Yellow | Medium โ partial impact, monitor and address in next cycle. |
| S4 | sev-s4 | Neutral | Low โ informational or minor. No immediate action required. |
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.
| CHANNEL | REAL ENDPOINT | METHOD | WHAT 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.8x8.com/connect. Create your account and get API keys at: connect.8x8.com.
connect.8x8.com, navigate to Admin โ API Keys, and generate a key. You will also need your subAccountId โ found in the same section.8x8-api-key and 8x8-subaccount-id in Key Vault. The Function App reads them via Managed Identity.BASE in the script to the Function App URL if it is on a different origin from the HTML file.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.
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.
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.
- 1SMS sent count and delivery rateCall
GET https://sms.8x8.com/api/v1/{subAccountId}/reports?startDate=TODAY&endDate=TODAY. ExtracttotalSentand compute delivery rate fromdelivered/totalSent. - 2Active 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.
- 3Auth verificationsCall the Verify API status endpoint or aggregate from webhook receipts of
verify.successandverify.failedevents logged through the day. - 4Chat 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.
- 5API 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. - 6Active 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/alertsreturns.
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 SCENARIO | DATA SOURCE | THRESHOLD EXAMPLE |
|---|---|---|
| SMS delivery rate degraded | SMS reports API | Delivery rate < 95% in rolling 15-minute window |
| OTP failure rate elevated | Verify webhooks | Failed verifications > 10% of total in last 100 attempts |
| API key rate limit breached | 8x8 API 429 responses | Any 429 from the 8x8 API triggers an S2 alert |
| Carrier route failover | SMS delivery webhooks | Delivery failures on a single carrier route exceed threshold |
| Fraud score threshold exceeded | Omni Shield webhooks | Any Omni Shield event with score > 80 becomes an S1 alert |
| Voice call quality below threshold | Voice API / webhooks | MOS 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.
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.
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.
- โBASE variable set correctly. If the proxy is on a different origin from the HTML file,
BASEmust be set to the full proxy URL (e.g.https://your-funcapp.azurewebsites.net). An emptyBASEmeans 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.
| SYMPTOM | CAUSE | FIX |
|---|---|---|
| Console shows demo data despite proxy being live | apiFetch() caught an error and fell back to generator | Open browser DevTools โ Network tab. Find the proxy request. Check response status and body for the actual error. |
| API CALLS counter stops incrementing | Refresh loop stopped โ likely a JavaScript error | Check browser console (F12) for uncaught exceptions. A render function receiving unexpected data shape can break the loop. |
| Incident table empty after filtering | All incidents have a different status value than expected | Log the alerts array to the console. Verify status values are exactly "open", "ack", or "resolved" โ case sensitive. |
| Fraud feed always empty | Omni Shield webhooks not reaching proxy or not stored | Check proxy webhook receiver logs. Confirm 8x8 Connect Portal has the correct webhook URL for fraud events. |
| SYSTEM shows NOMINAL but data is stale | ftsys element only reflects the refresh loop state, not API health | In production, add logic to set ftsys to DEGRADED if any apiFetch() call returned an error rather than falling back to the generator. |