# Kubyk Documentation > Source: https://kubyk-docs.integration.kebormed.com/ > This file contains the complete documentation content for AI agent consumption. > Last generated: 2026-03-27T14:17:16.407Z ## Table of Contents - [Getting Started](#getting-started) - [What is Kubyk?](#what-is-kubyk) - [Who Uses Kubyk](#who-uses-kubyk) - [Choose Your Route](#choose-your-route) - [Definitions & Glossary](#definitions-glossary) - [Portal User Guide](#portal-user-guide) - [Signing In & Your Account](#signing-in-your-account) - [Dashboard](#dashboard) - [User Management](#user-management) - [Datasource Management](#datasource-management) - [Device Management](#device-management) - [Groups](#groups) - [Data & Analytics](#data-analytics) - [My Devices](#my-devices) - [My Data](#my-data) - [Mobile Companion App](#mobile-companion-app) - [Messages](#messages) - [The Bench](#the-bench) - [Experiment](#experiment) - [Profile & Security](#profile-security) - [About](#about) - [Platform Tips](#platform-tips) - [Solution Routes](#solution-routes) - [Builder Route](#builder-route) - [Integrator Route](#integrator-route) - [Understanding Datasources](#understanding-datasources) - [Overview & Decision Guide](#overview-decision-guide) - [Standard Datasource](#standard-datasource) - [Custom (Remote)](#custom-remote) - [Cloud Datasource](#cloud-datasource) - [Setup Guides](#setup-guides) - [BLE Device Integration](#ble-device-integration) - [Cloud API Integration](#cloud-api-integration) - [OAuth Cloud Providers](#oauth-cloud-providers) - [Custom Remote Parser](#custom-remote-parser) - [API Reference](#api-reference) - [Overview](#overview) - [Device Endpoints](#device-endpoints) - [SDKs & Examples](#sdks-examples) - [Overview](#overview) - [cURL](#curl) - [Python](#python) - [JavaScript/Node.js](#javascript-node-js) - [Arduino/ESP32](#arduino-esp32) - [Go](#go) - [Architecture](#architecture) - [System Overview](#system-overview) - [Data Flow](#data-flow) - [Security Model](#security-model) - [Troubleshooting & FAQ](#troubleshooting-faq) - [Data & Compliance](#data-compliance) - [Troubleshooting & FAQ](#troubleshooting-faq) - [Getting Help](#getting-help) --- ## Getting Started ### What is Kubyk? Kubyk is the self-serve digital health platform: a complete, regulated foundation for connected health products. It gives you everything out of the box: admin portals for managing devices and users, a mobile companion app for BLE data relay, data visualization, built-in messaging, compliance-ready documentation, and secure cloud APIs. Whether you're prototyping a proof of concept or deploying at clinical scale, Kubyk provides the entire infrastructure so you can focus on your solution, not the plumbing. --- ### Who Uses Kubyk ### Students Bioengineering, biomedical engineering, and healthcare technologies students - Build a working prototype for your capstone project, not just a PowerPoint - Create a portfolio piece that demonstrates real device connectivity - Develop a project you can take into a startup after graduation - Showcase your work to medical device manufacturers for job opportunities ### Startups Teams building digital health solutions - Go from idea to working pilot in weeks, not months - Get compliance-ready infrastructure from day one - Build investor-ready demos with real data flowing - Focus on your device innovation, not backend plumbing ### Researchers Academics running digital health studies - Set up IRB-ready data collection infrastructure - Run multi-site studies with centralized data management - Document your methodology with generated reports - Connect custom research devices or consumer wearables ### Developers Engineers integrating systems and building parsers - Integrate device firmware with cloud data ingestion - Build custom parsers for proprietary data formats - Connect legacy systems and existing data pipelines - Implement BLE gateway apps that relay to Kubyk ### Enterprise Medical device manufacturers, digital health companies, CDMOs, hospitals & CROs - Build cloud infrastructure for connected medical devices - Launch digital therapeutics and pharma companion apps - Manage multiple product lines under one platform - Scale compliant infrastructure across global markets --- ### Choose Your Route ### Builder Route _Build your own device_ Connect custom hardware, prototypes, or proof-of-concept devices directly to Kubyk. For teams building their own devices. **Estimated Time:** 30 min **Datasource Types:** Standard, Custom Remote ### Integrator Route _Combine devices to create your solution_ Build solutions using any combination of datasource types: commercially available BLE devices using standard protocols, Cloud integrations from consumer wearable platforms, or your own custom hardware. **Estimated Time:** 15 min **Datasource Types:** Standard, Custom Remote, Cloud --- ### Definitions & Glossary **2FA (Two-Factor Authentication)** A security method requiring two forms of verification: your password (something you know) and a code from an authenticator app (something you have). Managed by administrators from the User Details page. **BLE (Bluetooth Low Energy)** A wireless communication protocol used by health-monitoring devices to transmit data over short distances with minimal power consumption. Kubyk supports BLE connectivity for Standard and Custom datasources. **Chart Recipe** A saved visualization configuration built in The Bench's Chart Builder. A recipe defines panels, series, chart types, colors, and axis assignments for displaying device data as interactive charts. Recipes can be applied in the Experiment page. **Data Session** A timestamped batch of measurements sent by a device. Each session contains one or more parameter values and is grouped by the time it was received by the platform. **SSE (Server-Sent Events)** A protocol that allows the server to push real-time updates to the browser. Kubyk uses SSE for live notifications, such as unread message counts. **SSO (Single Sign-On)** An authentication method that lets you use one set of credentials to access multiple applications. Kubyk uses Keycloak-based SSO — you sign in once and are authenticated across the platform. **Organization** Your isolated workspace in Kubyk. All users, devices, datasources, and data belong to your organization. Each organization is completely isolated from others. **Admin** A portal user with full access to all resources: users, devices, datasources, data, messages, and settings. Admins can switch between Admin View and User View, allowing them to also interact with the system as a standard user (e.g., collect their own data). Organizations can have more than one Admin. **Standard User** A portal user who can view and interact with devices, data, and messages, but cannot manage other users or system settings. **Data Viewer** A read-only portal user who sees anonymized data instead of real names. **HCP (Healthcare Provider)** A clinician user type available on Scale tier. HCPs have a dedicated portal to monitor assigned patients and manage clinical alerts. **Patient** An end-user type available on Scale tier. Patients have a dedicated portal to view their own device data and communicate with their HCPs. **Datasource** A reusable blueprint that defines what parameters (fields) your devices will track. You add a datasource first, then add devices based on it. Each device inherits the same parameter definitions automatically. **Device** A physical or virtual device registered in Kubyk and based on a datasource. Devices have unique serial numbers and security certificates. **Group** An organizational unit (Lab+/Scale) that controls visibility. Users in a group can only see other users and devices within the same group. **Identifier** An anonymized label (e.g., A1, B2, C3) used in place of a user's real name whenever their data is displayed to other authorized users, adding an extra layer of identity protection. **Parameter** A data field that defines what a datasource is designed to track (e.g., heartRate, steps, temperature). Parameters can be numeric, non-numeric, or file-based. Kubyk provides a predefined library of common parameters organized by category, and you can also create custom parameters for specialized measurements. Custom parameters will be saved for reuse across datasources. **KAI** Kubyk's built-in AI assistant available in the portal. KAI can help with portal setup and customization, and provide guidance. --- ## Portal User Guide ### Signing In & Your Account ## System Requirements | Requirement | Details | |---|---| | Browser | Chrome, Firefox, Safari, or Edge (latest two versions) | | Screen | Desktop, tablet, or mobile — the portal is fully responsive | | Network | Stable internet connection (HTTPS) | | Authentication | Credentials provided by your organization (SSO via Keycloak) | ## Portal Layout - **Sidebar (left):** Navigation links filtered by your role. Collapse it with the toggle at the top for more screen space. A Help link at the bottom opens external documentation. - **Top bar:** Theme switcher (light/dark mode), Admin View Mode toggle (Admin only), and user dropdown menu (Profile, About, Sign Out). - **Content area:** The active page with its controls, data, and forms. On mobile devices, the sidebar becomes a hamburger menu that slides in as an overlay. ## Role-Based Navigation Each role sees a different set of sidebar links: **Admin:** Home, Users, Devices, Data, Datasources, Messages, Bench, Experiment **Standard User:** Home, My Devices, My Data, Messages **Data Viewer:** Home, Data, Messages If you cannot see a menu item described in this guide, it is restricted to a different role. Contact your administrator if you need access. ## Signing In & Your Account **Step 1: Receive Your Invitation** Kubyk uses an invitation-only model. Your Admin will create your account and you'll receive an email with the subject "Update your account". 1. Check your email (including spam/junk folder) for an email titled "Update your account" 2. Click the link in the email to set your password (the link expires in 12 hours) 3. If you did not expect this email, you can safely ignore it **Step 2: Sign In** Once you have set your password, navigate to your portal URL and sign in. 1. Enter the email address your invitation was sent to 2. Enter the password you created via the setup link **Step 3: Set Up Your Profile** Complete your profile to help your team identify you. 1. Go to your profile (click your avatar in the top-right) 2. Update your display name and phone number 3. Your email address cannot be changed. Contact your Admin if needed 4. If you are an Admin, you can switch between Admin View and User View via the header toggle. User View lets you interact with the system as a standard user (e.g., view your own devices and collect data) **Account Actions:** - **Edit Profile:** Click your avatar → Profile. Update your name and phone number. - **View Legal:** Access Privacy Policy and Terms of Service from the Settings page. - **Sign Out:** Click your avatar → Sign Out. --- ### Dashboard The Dashboard is your landing page after signing in. It provides a quick overview of your organization's activity. ## Welcome Banner A personalized greeting at the top: - **Admin:** "Welcome back, [First Name]" with your Organization ID badge (click to copy). - **Standard User:** "Welcome, [First Name]" with your Customer ID badge. - **Viewer:** "Welcome, [First Name]" (no ID badge). ## Metrics Cards Role-specific stat cards at a glance: | Role | Cards Displayed | |---|---| | Admin | Total Devices, Active Users, Data Points | | Standard User | Personal device count, health data metrics | | Viewer | Anonymized dataset counts | ## Companion App Card (Admin & Standard User) Required for Bluetooth device connectivity. Two buttons let you request an install link: - **iOS (TestFlight)** — Sends you a TestFlight invitation link. - **Android (App Tester)** — Sends you an App Tester invitation link. The Companion App is required only if your devices use Bluetooth connectivity. Cloud and direct-to-cloud devices do not need the app. ## News Feed An Industry News carousel displays recent healthcare technology articles with title, summary, source, publication date, and a Read link. Auto-advances with Previous/Next navigation. ## Feedback Form Report issues or suggest improvements directly from the dashboard: 1. Select a **Type**: General Feedback, Bug Report, or Support Request 2. Enter a **Subject** 3. Write your **Message** 4. Click **Submit** ## Project Header (Admin) Admins see an editable project header at the top of the dashboard with the organization name and description. Click the pencil icon to edit. Standard Users and Viewers see it in read-only mode. --- ### User Management Admins can add, view, edit, and delete portal users. Each user is assigned a role that determines their permissions. ## User Types & Permissions | Type | Can Do | Restrictions | |---|---|---| | Admin | Full access: manage users, devices, datasources, data, messages, settings | None | | Standard User | View and interact with devices, data, and messages | Cannot manage other users or system settings | | Data Viewer | Read-only access to anonymized data | Cannot modify anything | ## Browsing the User List Use the filter bar above the table to find specific users: | Filter | Type | Options | |---|---|---| | Search | Text input | Search by name or email | | User Type | Dropdown | Admin User, Standard User, Data Viewer | | Status | Multi-select | Active, Pending, Locked | | Last Login Date | Date range | Calendar picker (auto-closes on end date) | Click **Clear** to reset all filters. Sortable column headers toggle ascending/descending. Pagination supports 10, 25, or 50 rows per page. ## Adding a User **Step 1: Navigate to Users** Go to the Users section from the main navigation sidebar. **Step 2: Click "Add User"** Click the Add User button in the top-right corner of the users list. **Step 3: Fill in User Details** Enter the required information for the new user. 1. Select User Role: Admin User, Standard User, or Data Viewer 2. Organization Name (pre-filled with your current organization) 3. First Name and Last Name (required, max 32 characters) 4. Email Address (required, max 254 characters, must be unique) 5. Username (required, 3-32 characters, letters/numbers/dots/hyphens/underscores, must be unique) 6. Phone (optional, numbers only, max 24 characters) 7. Identifier (required for Admin and Standard User roles): a unique alphanumeric code used to display data without personal information (max 16 characters). Hidden for Data Viewers. 8. Note: you can have multiple Admins. This is useful when your team is small and more than one person needs full access **Step 4: Review and Confirm** Review the details and click Add User. The user will receive an email prompting them to set their password. ## Editing a User 1. Click a user row to open their details page. 2. Click **Edit**. 3. Modify role, name, phone, or identifier. Email cannot be changed after creation. 4. Click **Save Changes**. ## User Details Page Click any user row to view their full profile: - **Contact Information:** Name, email, username, phone. - **Organization:** Organization name and user role. - **Account Activity:** Account status, creation date, last login. - **Security Settings:** 2FA toggle, account locked/inactive alerts with action buttons. **Admin actions:** Edit, Password Reset, Resend Activation, Unlock, Activate/Inactivate, Delete. > **Warning:** Inactivating or deleting a user is permanent and removes their access immediately. ## Bulk Import (CSV) To add multiple users at once: 1. Click the **Import** button on the Users page 2. Select a **User Type** for all imported users 3. Click **Download Template** to get a pre-formatted CSV 4. Fill in user data: First Name, Last Name, Email, Phone (optional), Identifier 5. Drag and drop or browse to upload the CSV 6. Click **Upload** to import ## User Capabilities Matrix | Capability | Admin | Standard | Viewer | |---|---|---|---| | View Dashboard | Yes | Yes | Yes | | Manage Users | Yes | No | No | | Manage Devices | Yes | No | No | | Manage Datasources | Yes | No | No | | View Organization Data | Yes | No | Yes (read-only) | | View Personal Devices | Via User View | Yes | No | | View Personal Data | Via User View | Yes | No | | Send Messages | Yes | Yes | Yes | | Edit Profile | Yes | Yes | Yes | | Access Bench & Experiment | Yes | No | No | --- ### Datasource Management A datasource is a blueprint that defines what data your devices will collect. You must add a datasource before adding devices. ## Adding a Datasource **Step 1: Navigate to Datasources** Go to the Datasources section from the main navigation sidebar. **Step 2: Click "Add Datasource"** Click the Add Datasource button. **Step 3: Choose Datasource Type** Select the type that matches your data source. 1. Standard Datasource: platform-managed processing for standard data collection (simplest) 2. Custom Datasource: bring your own processing logic. On Lab, this uses Remote deployment (your API). Lab+ and higher tiers also support Local deployment (your container hosted by Kubyk) 3. Cloud Datasource: OAuth connection to platforms like Fitbit, Withings, and Dexcom. Fitbit and Withings support real user authorization. Dexcom provides sandbox access for development. Production access to real CGM data requires a Dexcom commercial agreement. 4. For Standard and Custom datasources, select a connectivity type: Cloud (WiFi/Cellular), Bluetooth (BLE), or Both. Cloud datasources skip this step as connectivity is handled by the OAuth provider **Step 4: Name Your Datasource** Give it a descriptive name. Use a naming convention like "DeviceType-Version" (e.g., "ActivityTracker-v1"). **Step 5: Add Parameters** Define the data fields your devices will send. 1. Browse the predefined parameter library organized by category (Cardiac, Respiratory, Metabolic, Temperature, Classification). Select the parameters your device will track 2. To add a custom parameter not in the library, click "Add Parameter". Enter a name, choose a type (numeric, or non-numeric), and optionally set a unit 3. Custom parameters will be saved for reuse across future datasources. Saved parameters appear under the "Custom" category in the library 4. A parameter key is auto-generated from the display name (e.g., "Heart Rate" becomes "heart_rate") **Step 6: Save** Click Add Datasource to save. You can now create devices based on this datasource blueprint. ## Datasource Details Page Click a datasource row to view its details: - **Metric Cards:** Parameters (total count), Devices (connected count), Remote Action (Enabled/Disabled), and Created (date). - **Connected Devices:** Paginated list of devices using this datasource, with an Add Device button (non-cloud datasources only). - **BLE Integration Info:** For Bluetooth-enabled datasources, shows standard Bluetooth SIG service UUIDs. - **Parameters:** Full list of configured parameters with name, key, unit, and type. > **Deletion Restriction:** A datasource cannot be deleted while devices are still connected to it. The delete button is disabled until all devices are removed or reassigned. ## Cloud Provider Setup (Cloud Datasources) For Cloud datasources, the setup uses a multi-step wizard: 1. **Select Provider** — Choose from available providers (Fitbit, Dexcom, Withings). 2. **Copy Redirect URL** — Copy the provided URL and register it in the provider's developer portal. 3. **Copy Notification URL** — For providers that require it (e.g., Fitbit), copy and register the webhook notification URL. 4. **Select API Endpoint** — Choose from available authorization endpoints. 5. **Enter Credentials** — Provide the Client ID and Client Secret from the provider's developer console. 6. **Provider-Specific Fields** — Some providers require additional configuration (e.g., Fitbit requires a Subscriber Verification Code). Each provider card includes a **Developer Portal** link that opens the provider's console in a new tab. ## Parameter Types Parameters come in three types: **Numeric** (e.g., heart rate in bpm), **Non-numeric** (e.g., classification labels), and **File** (binary uploads — accepted formats: MP3, MP4, JPEG, PNG). File parameters are used with the File Upload tool in The Bench. You can choose from a predefined library organized by category (Cardiac, Metabolic, Respiratory, Temperature, Classification, Custom) or create your own. Each parameter has a unique key auto-generated from its name. Custom parameters are saved for reuse across datasources. --- ### Device Management Add, configure, and manage your devices. Each device is based on a datasource and is ready to send data. ## Browsing the Device List The page shows stats cards (Active, Total, Inactive Devices) and a filter bar: | Filter | Type | Description | |---|---|---| | Search | Text input | Search by device name or serial number | | Device Activity | Dropdown | Active in Last 24h, Inactive in Last 24h | | Datasource | Dropdown | Filter by assigned datasource | | Date Range | Date picker | Select start and end dates | The device table columns are: Device (name + serial), Datasource, Created, and Active Last 24h (green/red indicator). On mobile, the table switches to a compact card layout. ## Adding a Device **Step 1: Navigate to Devices** Go to the Devices section from the main navigation sidebar. **Step 2: Click "Add Device"** Click the Add Device button. **Step 3: Enter Device Information** Fill in the required fields. 1. Device Name (descriptive, e.g., "Activity Tracker Prototype #1") 2. Serial Number (unique identifier, e.g., "POC-WB-001"). You can type one manually or click Generate 3. Select a Datasource to link this device to. Cloud-type datasources are not shown in this list — cloud devices are connected from the My Devices page instead 4. Software Version: track firmware version for debugging and updates **Step 4: Save and Configure** Your device is now Active and ready to receive data. If your device uses direct-to-cloud connectivity, download the security certificate for API authentication. 1. Go to Device Details → Security Certificate section 2. Download the certificate ZIP containing three files: private key, public key, and TLS certificate 3. Configure your device firmware with these certificates for mTLS authentication 4. Note: certificates are for API (mTLS) data ingestion only. BLE devices send data through the mobile companion app and do not require certificates ## Editing a Device 1. Open the device details page by clicking a device row. 2. Click **Edit Device**. 3. Modify the Device Name or Software Version. Serial number and datasource cannot be changed after creation. 4. Click **Save Changes**. ## Device Details Page Click any device row to view its full details: - **Metric Cards:** Last Active (e.g., "5 hours ago" or "Never") and Total Data Sessions. - **Device Info:** Name, datasource (with type badge), status (Active/Inactive), serial number (with copy button), software version, parameter badges, and timestamps. - **Action Buttons:** View Data (primary), Edit Device (outline), Delete (destructive). ## Security Certificates Expand the Security Certificate section on the device details page. Click Download Certificate to get a ZIP containing: - `{serial}-private.key` — Private key (keep secure) - `{serial}-public.key` — Public key - `{serial}-certificate.crt` — TLS certificate ## API Integration The device details page provides ready-to-use code examples: - **Step 1 — Authenticate:** Pre-filled cURL command using your security certificate to obtain an access token. - **Step 2 — Send Data:** Pre-filled cURL and JavaScript examples with your device's serial number and parameters. ## Device Onboarding Flow 1. Create Datasource (define parameters & connectivity) 2. Register Device (assign to datasource + serial number) 3. Download Certificate (install on device) 4. Send Data via API (authenticate + POST to /device/data) 5. View in Data Page (tables & graphs) ## Removing a Device 1. Open the device details page. 2. Click **Delete**. 3. Confirm in the dialog: "Are you sure you want to delete this device? This action cannot be undone." > **Warning:** Deleting a device is permanent. All associated data sessions will be removed. --- ### Groups **Step 1: Navigate to Groups** Go to the Groups section from the main navigation sidebar. **Step 2: Click "Add Group"** Click the Add Group button. **Step 3: Enter Group Details** Provide a name and optional description for the group. **Step 4: Add Members** After creating the group, add users to it. 1. Open the group details page 2. Click "Add Members" 3. Search for users by name or username 4. Filter by user type if needed 5. Select users and confirm --- ### Data & Analytics The Data page provides organization-wide analytics. Two tabs at the top let you switch perspectives: ## Device View Browse data by device with metrics cards, searchable device list, expandable panels with parameter selection, table/graph toggle, and date range filtering. 1. Use the **Search** bar and **Datasource** filter to find specific devices. 2. Click a device row to expand its data panel. 3. Select a **Parameter** from the dropdown. 4. Toggle between **Table** and **Graph** view. 5. Use the **Date Range** picker to narrow the time window. 6. Click **Export** to download as CSV. 7. Click the **settings icon** to navigate to the device details page. ## User View Browse data by user with the same visualization options. Select a user, then a device and parameter to view data. ## Table View vs Graph View - **Table View:** Rows of individual data points with parameter name, value, and timestamp. Supports pagination. - **Graph View:** Time-series line chart showing values over time. ## Exporting Data Click Export to download filtered data as CSV. The file contains columns for parameter key, value, start timestamp, and end timestamp — suitable for spreadsheets or data analysis tools. ## Data Sessions Data arrives in sessions — batches of measurements sent by a device at a specific time. Each session contains one or more parameter values. The Total Data Sessions metric on the device details page shows how many batches a device has sent. > **Data Viewer Access:** Data Viewers have read-only access to the Data page. You can browse, filter, and export, but you cannot modify or delete any data. --- ### My Devices The My Devices page shows the devices assigned to you personally (Standard User). ## Your Device List Shows the same columns as the admin device list (name, datasource, creation date, activity status) but scoped to your devices only. Use search and filters to find specific devices. Pagination supports 10, 25, or 50 per page. **Device status:** - **Active** (green) — The device has sent data within the last 24 hours. - **Inactive** (red) — No data received in the last 24 hours. ## Pending Cloud Connections If your organization uses Cloud datasources (e.g., Fitbit, Withings), you may see a Pending Connections section: 1. Click **Connect** next to the provider name. 2. Sign in and grant Kubyk access on the provider's authorization page. 3. You are redirected back. The connection status updates automatically. Cloud connections allow Kubyk to pull your health data from third-party platforms. You must authorize each provider individually. ## Cloud Device Management For cloud-connected devices, a **Disconnect** button lets you revoke the cloud service authorization. Non-cloud devices do not have a delete option from this page. --- ### My Data View and analyze your personal health data collected from your devices (Standard User). ## Filtering Your Data - **Device:** Select one of your devices from the dropdown. - **Parameter:** Choose which measurement to view (e.g., Heart Rate). - **Date Range:** Narrow the time window. Click Clear to reset. ## Viewing & Exporting Toggle between Table view (individual data points with pagination) and Graph view (time-series chart). Metrics cards summarize your data at a glance. Click Export to download filtered data as CSV. --- ### Mobile Companion App ### Mobile Companion App The Kubyk mobile companion app acts as a Bluetooth relay: it connects to your BLE device, receives data, and forwards it to Kubyk Cloud. A companion app is only needed for devices using Bluetooth connectivity. > **When do I need the mobile app?:** Only when your device connects via **Bluetooth (BLE)** or **Both (WiFi + BLE)** mode. Direct-to-Cloud devices (WiFi/Cellular) do not require the mobile app. Administrator You are responsible for setting up the physical device and assigning it to a user. Complete these steps before a standard user can collect data. > If the device was already registered in the portal with its correct serial number, the app auto-matches it after you select the datasource. You'll see a green Matched indicator and can skip directly to user association. If you skip the user association step, the session is saved as device test data and is not linked to any user health record. > **Bluetooth range required:** The administrator must be physically near the device, within Bluetooth range, when scanning and completing the setup. This is a one-time setup step per device. After the device is assigned, the standard user can connect and collect data independently from their own app. Standard User Before you can collect data from a Bluetooth device, your administrator must complete the setup steps above and assign the device to your account. > All data collected during your sessions is automatically synced to your account on the web portal. You can sign in at any time to view your readings, history, and any alerts set by your administrator. --- ### Messages The Messages page provides a thread-based communication system for all users in your organization. If you have unread messages, a green badge shows the count on the sidebar menu item. ## Messages Interface The page uses a dual-panel layout: - **Thread List (Left):** Search, thread title, creator name, and timestamp. Threads with unread messages show a green dot. - **Conversation (Right):** Message bubbles with sender avatars, names, and timestamps. Your messages appear on the right (blue), others appear on the left (gray). ## Starting a New Conversation 1. Click **New Thread** at the bottom of the thread list 2. **Select Recipients:** Search for users and check boxes next to their names 3. Click **Continue** 4. **Enter Title:** Type a descriptive thread title 5. Click **Create Thread** The new thread opens immediately in the conversation panel. ## Sending a Message 1. Click the text input at the bottom of the conversation panel 2. Type your message 3. Click the **Send** button (arrow icon) or press Enter ## Unread Indicators - **Sidebar badge:** A green count badge on the Messages menu item. - **Thread dot:** A green dot next to threads with unread messages. Messages are marked as read when you open the thread. --- ### The Bench The Bench is a developer playground for building chart visualizations, generating test data, and uploading files. It is accessible only to Admin users. It has three tabs: **Chart Builder**, **Simulated Data**, and **File Upload**, plus an **Open Terminal** button. ## Chart Builder Create reusable visualization "recipes" — saved configurations that define how device data is displayed as charts. **Building a Recipe:** 1. Enter a **Recipe Title** at the top. 2. Select a **Device** from the dropdown to load its available parameters. 3. Optionally enable **Merge to Single Chart** to combine all panels into one chart. **Adding Panels:** Each recipe contains one or more panels (separate chart areas). 1. Click **Add Panel** to create a new panel. 2. Give the panel a label. 3. Within a panel, click **Add Series** to add a data line. 4. For each series, configure: - **Parameter** — Select from the device's available parameters. - **Chart Type** — Line, Area, Bar, or Scatter. - **Color** — Pick a color using the color picker. - **Y-Axis** — Left (L) or Right (R), for dual-axis charts. 5. Add multiple series to overlay different parameters on the same panel. **Live Preview:** The right side shows a chart preview rendered with Apache ECharts. Click **Fetch & Render** to load actual device data. **Saving and Loading Recipes:** - Click **Save** to persist. If a recipe with the same title exists, an overwrite confirmation dialog appears. - Click **Recipes** to open saved recipes, where you can load (play icon) or delete (trash icon). - Click **New** to start a fresh recipe. ## Simulated Data Generate simulated device readings for testing without physical hardware. > **Warning:** Simulated data is written directly to the selected device's data stream and cannot be distinguished from real readings. Use dedicated test devices. **Generating:** 1. Select a **Device** from the dropdown. 2. Check the **parameters** you want to generate data for. For each, enter the number of data points (1–10,000). 3. Set a **Start Date** and **End Date**. 4. Review the **Summary** card showing parameter counts, intervals, device name, and total rows. 5. Click **Generate & Send**. A progress bar shows: requests sent / total (with failure count), estimated time remaining, and points sent. Click **Cancel Generation** at any time. > **Rate Limit:** All data counts against a 120 requests per minute rate limit. Large batches may trigger a 429 error. **CSV Alternative:** 1. Click **Download Template** to get a CSV with headers matching selected parameters. 2. Fill in your values manually. 3. Click **Upload CSV** to send the data. ## File Upload Upload files to device parameters configured for file-type data. 1. Select a **Device** from the dropdown. 2. Select a **File Parameter** (only file-type parameters shown). 3. **Serial Number** and **Parameter Key** auto-populate (read-only). 4. Click **Choose file**. Accepted formats and maximum file size are displayed. 5. The portal auto-computes the file's **SHA-256** hash. 6. Click **Upload File**. ## Terminal Click **Open Terminal** in the Bench header to open a floating terminal overlay. Features: - Mac-style title bar with close, minimize, and maximize dots. - Draggable and resizable window. - Command input with a `$` prompt. Type commands and press Enter. - Scrollable output area with formatted text and table output. --- ### Experiment The Experiment page is a sandbox for previewing beta features. Currently hosts the **Recipe Viewer** — a tool for applying chart recipes to live device data (Admin only). ## Recipe Viewer 1. **Select a Device** — Choose from the dropdown (shows name, serial number, datasource). 2. **Select a Recipe** — Choose from saved recipes (shows title, panel/parameter count). 3. **Set a Date Range** — Quick buttons: **1h**, **6h**, **12h**, **24h**, **7d**, **30d**, or custom date picker. 4. Click **Refresh** to fetch data and render the chart. ## Chart Display Supports Line, Area, Bar, and Scatter chart types, dual Y-axis (left and right), single merged chart or multi-panel grid layout, and responsive resizing. **States:** - **No selection:** Dashed border placeholder — "Select a device and recipe to view charts." - **Loading:** Centered spinner. - **Error:** Red-bordered card — "Failed to fetch parameter data. Try refreshing." > **Tip:** Don't have any recipes yet? Head to The Bench to create one using the Chart Builder. --- ### Profile & Security Navigate to Profile from the user dropdown menu in the top-right corner. ## Your Profile - **Avatar:** Displays your initials (first letter of first name + first letter of last name). Below it, your username with @ prefix (e.g., @john.smith). - **Name and Role:** Full name and role badge (Admin User, Standard User, or Data Viewer). Role is set by an administrator and cannot be changed from this page. - **Edit:** Click Edit to modify First Name, Last Name, or Phone. Email is read-only — contact your administrator if it needs to be updated. - **Change Password:** In the Security section, click Change Password. A password reset email is sent to your registered address. > **Two-Factor Authentication:** 2FA settings are managed by your administrator from the User Details page, not from your personal profile. --- ### About Navigate to About from the user dropdown menu in the top-right corner. ## Support - **Email:** support@kebormed.com - **Help & FAQ:** External link to the documentation portal. ## System Info - **Version:** Current portal version number. - **Powered by KeborMed.** ## Legal - **Privacy Policy** (external link) - **Terms of Service** (external link) --- ### Platform Tips Tips for getting the most out of the Kubyk portal. ## Theme Switching Click the sun/moon icon in the top bar to toggle between light and dark mode. Your preference is saved. ## Pagination Choose 10, 25, or 50 items per page on list pages. Navigate with Previous/Next buttons. ## Sortable Columns Click a sortable column header for ascending order, click again for descending. The sorted column is indicated visually. ## Sidebar Collapse Click the toggle at the top of the sidebar to minimize it to icons only for more screen space. ## Mobile Responsiveness The sidebar becomes a hamburger menu, tables switch to card layouts, and forms stack fields vertically. All features remain accessible. ## Organization Switching If you belong to multiple organizations, use the selector in the top bar. Your role may differ across organizations. ## Admin View Mode Toggle Admins can switch between Admin View and User View using the toggle in the top navigation bar. User View shows the Standard User experience (My Devices, My Data) — useful for previewing what your users see. ## Signing Out 1. Click your name or avatar in the top-right corner. 2. Select **Sign Out** from the dropdown menu. 3. Your session is cleared and you are redirected to the login page. > **Tip:** Always sign out when using a shared or public computer. --- ## Solution Routes ### Builder Route **Step 1: Add a Datasource** Define what data your device will send and how Kubyk should process it 1. Go to Datasources → Add Datasource 2. Choose Standard Datasource (simplest) or Custom Datasource (your own algorithms and AI, running in your cloud). Cloud Datasource is available for the Integrator route. 3. Name it and select parameters from the predefined library or create custom parameters (numeric, non-numeric, or file). Custom parameters will be saved for reuse 4. For Custom datasources, provide your API Endpoint and API Key/Secret so Kubyk can forward data to your service. **Step 2: Add a Device** Register your physical device in Kubyk 1. Go to Devices → Add Device 2. Give it a name and unique serial number 3. Link it to the datasource you created **Step 3: Download Certificates** Download security credentials for API authentication 1. Open Devices → Your Device → Security Certificate 2. Download device certificate and private key 3. Configure your firmware with these credentials **Step 4: Send Data** Make your first API call to ingest data 1. Each device you register comes with a pre-filled template of API requests in Device Details → API Integration. Use it as the base for your firmware implementation 2. Include your certificate for TLS client authentication 3. Send JSON with device serial number and data payload (timestamps and values). **Step 5: View Your Data** Confirm your data appears and looks correct 1. Go to Data → Devices → Your Device 2. See your time-series measurements in the table 3. Switch to Graph view to see your data visualized over time --- ### Integrator Route **Step 1: Choose Your Datasource Mix** Decide which types of data sources your solution needs. You can use one type, or combine several. 1. Add a Standard datasource for commercially available hardware that uses standard BLE profiles or HTTPS. No custom firmware required on your end. 2. Add a Custom datasource if you are building your own device with proprietary data formats or a custom backend integration. 3. Add a Cloud datasource to pull data from consumer wearable platforms like Fitbit or Withings via OAuth. This is entirely optional and only relevant if a cloud integration adds value to your solution. 4. There is no required combination. Use whichever types fit your study or product. **Step 2: Add Devices for Each Datasource** For each datasource you added, register the corresponding devices. 1. Go to Devices and add each device, selecting the datasource it belongs to. 2. Standard and Custom devices are registered with a serial number. 3. Cloud datasources automatically create a device entry once a user authorizes their account. No manual registration needed. 4. All devices appear in the same list regardless of type. **Step 3: Authorize Cloud Accounts (if applicable)** If your solution includes Cloud datasources, users will need to connect their wearable accounts. Skip this step entirely if you have no cloud integrations. 1. When a Cloud datasource is added, all relevant users see a connection prompt in the portal automatically. 2. Users click Connect and sign in with their own provider credentials (Fitbit, Withings, etc.). 3. Once authorized, data begins syncing. No further configuration is needed. **Step 4: View Unified Data** All data, regardless of source type, flows into the same Data view. 1. Go to Data to see readings from all your devices and datasources in one place. 2. Switch between Device view and User view depending on how you want to explore the data. 3. Filter by user, device, or date range to focus on specific streams. --- ## Understanding Datasources ### Overview & Decision Guide **Standard Datasource:** Platform-managed processing where Kubyk handles everything. Your device sends structured JSON directly to Kubyk's cloud, and Kubyk stores, parses and visualizes it. **Custom Datasource:** Your datasource action runs in YOUR cloud. Your device delivers raw data to Kubyk, which then retrieves the processed results after your processing completes. You maintain full control over the processing logic in your own infrastructure. **Cloud Datasource:** OAuth connection to third-party platforms like Fitbit, Withings, or Dexcom. Users authorize access and Kubyk syncs their data. Note: some providers (like Dexcom) require a sandbox environment for development. Real user data access requires a separate commercial agreement with the provider. --- ### Standard Datasource ## Standard Datasource Platform-managed processing where Kubyk handles everything. Your device sends structured JSON directly to Kubyk's cloud, and Kubyk stores, parses and visualizes it. **Setup Time:** 15-20 minutes | **Complexity:** Low **Data Flow:** Your Device → HTTPS/TLS → Kubyk Cloud → Data View **When to Use:** - Your device can make HTTPS requests (WiFi/cellular) - Your payload is already in a structured JSON format - You want the simplest setup with no custom backend **Technical Requirements:** - Device with network connectivity (WiFi, cellular, Ethernet) - Ability to store and use X.509 certificates - JSON payload formatting capability **Common Gotchas:** - Certificate path issues on embedded devices - Timestamp format mismatches (use Unix timestamps in milliseconds) - Field name typos vs. datasource configuration **Example:** Activity tracker sending heart rate and steps values every minute --- ### Custom (Remote) ## Custom Datasource Your datasource action runs in YOUR cloud. Your device delivers raw data to Kubyk, which then retrieves the processed results after your processing completes. You maintain full control over the processing logic in your own infrastructure. **Setup Time:** 30-60 minutes (including endpoint setup) | **Complexity:** Medium **Data Flow:** Your Device → Kubyk Cloud → Your Cloud for Processing → Kubyk Fetch → Data View **When to Use:** - You need custom processing logic you want to keep in your infrastructure - You have proprietary algorithms or decryption that can't be shared - You want to integrate an existing backend service **Technical Requirements:** - A publicly accessible HTTPS endpoint - API key for authentication - Your endpoint must return data in Kubyk's expected format **Common Gotchas:** - API endpoint availability and uptime - Response format must match Kubyk's schema **Example:** Backend with proprietary signal processing that Kubyk polls for results --- ### Cloud Datasource ## Cloud Datasource OAuth connection to third-party platforms like Fitbit, Withings, or Dexcom. Users authorize access and Kubyk syncs their data. Note: some providers (like Dexcom) require a sandbox environment for development. Real user data access requires a separate commercial agreement with the provider. **Setup Time:** 10-15 minutes (after developer account setup) | **Complexity:** Low **Data Flow:** Consumer Device → OAuth → Provider Cloud → Kubyk → Data View **When to Use:** - Integrating commercial consumer health devices - You don't control the device firmware - Building remote monitoring applications (Scale tier required for production) **Technical Requirements:** - Developer account with the cloud provider - OAuth credentials (Client ID, Client Secret) - Configure redirect URLs in provider's developer portal **Common Gotchas:** - OAuth redirect URL configuration - Scope permissions for the data you need - Rate limiting from providers **Example:** Withings scale syncing weight data for a wellness research study --- ## Setup Guides ### BLE Device Integration Implement the Kubyk BLE protocol in your device firmware to send data via the mobile companion app. **Prerequisites:** - Device with Bluetooth Low Energy (BLE) capability - Datasource created with Bluetooth connectivity enabled - Kubyk mobile companion app installed on a smartphone ### 1. Advertise Kubyk Service UUID Your device must advertise the Kubyk BLE service so the mobile app can discover and connect to it. Add this service UUID to your device's advertisement packet. ```text // Kubyk BLE Service UUIDs serviceUuid = 'C0B1C000-0000-1000-8000-00805F9B34FB' Control(Command) Characteristic: characteristicUuid = 'C0B1C001-0000-1000-8000-00805F9B34FB' Notification Characteristic: characteristicUuid = 'C0B1C002-0000-1000-8000-00805F9B34FB' ``` ### 2. Implement Handshake Protocol The mobile app controls data streaming by writing to the Control characteristic. Your firmware should listen for these commands. ```text // Control Commands (written by mobile app) 0x02 = Start streaming (begin sending data) 0x03 = Stop streaming (pause data transmission) // Your firmware should: 1. Wait for 0x02 before sending any data 2. Begin notifications on Data Characteristic 3. Stop sending when 0x03 is received ``` ### 3. Format Payload Data If a reading generates one value for heart rate and one for spo2, then the format for this is: ```json { "values": [ { "parameterKey": "heart_rate_2", "value": 75, "timestamp": 1690196955000 }, { "parameterKey": "spo2_2", "value": 98, "timestamp": 1690196955000 } ] } ``` In hex, this is: ```text 7b2276616c756573223a5b7b22706172616d657465724b6579223a2268656172 745f726174655f32222c2276616c7565223a37352c2274696d657374616d7022 3a313639303139363935353030307d2c7b22706172616d657465724b6579223a 2273706f325f32222c2276616c7565223a39382c2274696d657374616d70223a 313639303139363935353030307d5d7d ``` ### 4. Send Notifications Use BLE notifications on the Data Characteristic to stream measurement data. The mobile app will receive, package, and forward this data to Kubyk Cloud. ## Troubleshooting **Q: Device not appearing in app scan** A: Verify your device is advertising the Kubyk Service UUID (C0B1C000-...). Check that BLE is enabled and the device is in range. **Q: Data not appearing in portal** A: Confirm the mobile app shows "Connected" status, check that parameter order in payload matches datasource configuration, and verify the device is registered in the portal. --- ### Cloud API Integration Send measurement data from your device directly to Kubyk Cloud. **Prerequisites:** - Device with network connectivity (WiFi, cellular, or Ethernet) - Datasource created and device registered in the portal - Security certificate downloaded from Device Details → Security Certificate ### 1. Endpoint POST /api/device/data ### 2. Authentication Devices authenticate using mTLS (mutual TLS) with X.509 client certificates. Each device receives a unique certificate pair when registered in the portal. Download both files from Device Details → Security Certificate in the portal: • device-cert.crt: client certificate (proves device identity) • device-key.key: private key (never share this) Include both when making requests. The server validates the certificate against its CA to identify and authorize the device. --- ### OAuth Cloud Providers Connect to consumer health platforms like Fitbit, Withings, and Dexcom via OAuth authorization. Provider behavior varies: Fitbit and Withings support real user account authorization, while Dexcom provides sandbox access during development. **Prerequisites:** - Developer account with the target platform (Fitbit, Withings, Dexcom, etc.) - OAuth credentials (Client ID and Client Secret) from the provider - Cloud datasource created with the appropriate provider selected - For Dexcom: access is sandbox-only during development. Real patient CGM data requires a commercial API agreement with Dexcom (a business/legal step, not a technical one) > **Dexcom Sandbox Access:** Dexcom works differently from Fitbit and Withings in the Lab tier. Rather than real users authorizing their personal Dexcom accounts, you connect to the Dexcom Sandbox, a fully functional test environment that streams synthetic CGM data (glucose readings, trend arrows, alert events) in the exact same format as real device data. What you CAN do with Dexcom sandbox: • Build your complete Dexcom integration end-to-end • Test data parsing, parameter mapping, and alert thresholds • Demonstrate a live CGM data stream without anyone wearing a device • Validate your solution is production-ready What you CANNOT do: • Have real users sign in with their personal Dexcom accounts • Receive actual glucose readings from people wearing Dexcom CGMs The path to real data: Accessing live patient CGM data requires a commercial data sharing agreement with Dexcom. This is a business/legal milestone, not a technical prerequisite for building. Everything you build in Lab with sandbox data transfers directly to production once that agreement is in place. ### 1. Create Developer Account Register for a developer account with your chosen provider. This typically involves agreeing to their API terms and creating an "app" in their developer console. ### 2. Configure Redirect URLs In your provider's developer portal, add Kubyk's OAuth callback URL to the allowed redirect URIs. This enables the authorization flow to complete. ```text // Add this redirect URL to your provider's developer portal: https://datasource-oauth2-auth.kubyk.rnd.kebormed.com/login/oauth2/code/{provider} // Example for Withings: https://datasource-oauth2-auth.kubyk.rnd.kebormed.com/login/oauth2/code/withings // Example for Fitbit: https://datasource-oauth2-auth.kubyk.rnd.kebormed.com/login/oauth2/code/fitbit ``` ### 3. Enter Credentials in Kubyk In your Cloud datasource settings, enter the Client ID and Client Secret from your provider's developer console. Kubyk encrypts and securely stores these credentials. ### 4. User Completes Authorization For Fitbit and Withings: the real user logs into their account and approves Kubyk's access. For Dexcom sandbox: the flow completes against the sandbox and begins streaming synthetic CGM data automatically. Once authorized, data syncs on the configured schedule. ## Troubleshooting **Q: Redirect URL mismatch error** A: The redirect URL in your provider settings must exactly match Kubyk's callback URL, including https:// and any trailing slashes. **Q: Data not syncing after authorization** A: Check that the required data scopes are enabled in your provider's app settings. Some data types require explicit permission. **Q: Authorization expired** A: OAuth tokens expire periodically. Users may need to re-authorize if too much time has passed. Kubyk attempts automatic token refresh. **Q: I want to pull real users' Dexcom CGM data** A: Accessing live patient glucose data from Dexcom requires a commercial data sharing agreement with Dexcom. This is a business and legal step between your organization and Dexcom, separate from anything you do in Kubyk. The good news: everything you build in Lab using Dexcom sandbox data is production-ready. Once your commercial agreement is in place, you switch from sandbox to production credentials and your integration works immediately. --- ### Custom Remote Parser Configure Kubyk to call your external endpoint for custom data processing. When a device sends raw data to Kubyk via a Custom Remote datasource, Kubyk forwards each raw payload to your endpoint, and your endpoint returns the parsed measurements. **Prerequisites:** - A publicly accessible HTTPS endpoint that can receive POST requests - Datasource created with "Custom Remote" type (External deployment: Remote) ## Authentication Kubyk authenticates requests to your endpoint using the X-KBM-Secret header. Your endpoint should validate this header value against the secret you configured. **Header Example:** ``` X-KBM-Secret: your-configured-secret ``` If no secret was configured, the header is still sent but with an empty value. ## How It Works Device → Kubyk Cloud → POST to your endpoint → Your response → Kubyk stores parsed data 1. A device sends raw data to Kubyk (via BLE relay or direct cloud upload) 2. Kubyk identifies the datasource as a Custom Remote type 3. For each RawDeviceData parameter value in the session, Kubyk sends a POST request to your configured endpoint 4. Your endpoint processes the raw data (decrypt, decode, run algorithms, etc.) and returns structured measurements 5. Kubyk stores the returned measurements and displays them in the portal ## Configuration | Field | Required | Description | |---|---|---| | datasourceKey | Yes | The key of the datasource this remote action is linked to | | endpoint | Yes | Your publicly accessible HTTPS URL that will receive the data | | secret | No | A shared secret Kubyk sends in every request for authentication | ## Request **Method:** POST **Headers:** | Header | Value | |---|---| | Content-Type | application/json | | X-KBM-Secret | The secret you configured (if set) | **Body:** ```json { "parameterKey": "RawDeviceData", "value": "A34F001E9C0198FF...", "unit": "raw", "timestamp": 1738232100000 } ``` **Fields:** | Field | Type | Description | |---|---|---| | parameterKey | string | Always "RawDeviceData" for Custom Remote datasources | | value | dynamic | The raw data payload sent by the device (typically a hex or base64 string) | | unit | string | Unit of measure (if set on the parameter) | | timestamp | long | Unix timestamp in milliseconds | ## Response ```json { "reference": "optional-reference-id", "values": [ { "parameterKey": "heart_rate", "value": 82, "timestamp": 1738232100000 }, { "parameterKey": "spo2", "value": 97.5, "timestamp": 1738232100000 }, { "parameterKey": "quality", "value": "OK", "timestamp": 1738232100000 } ] } ``` | Field | Type | Required | Description | |---|---|---|---| | reference | string | No | Optional reference ID for grouping measurements. Auto-generated if omitted | | values | array | Yes | Array of parsed measurement values | | values[].parameterKey | string | Yes | Must match a parameter key defined in the datasource | | values[].value | dynamic | Yes | The parsed value: numeric for numeric parameters, string for non-numeric | | values[].timestamp | long | No | Unix timestamp in milliseconds. Falls back to session timestamp if omitted | | values[].startTimestamp | long | No | Start of the measurement window (for range-based data) | | values[].endTimestamp | long | No | End of the measurement window (for range-based data) | | values[].unitMeasure | string | No | Unit override (e.g., "bpm", "mg/dL") | | values[].notes | string | No | Optional notes for this measurement | ## Error Handling - If your endpoint returns a non-success HTTP status (4xx, 5xx), Kubyk logs the failure and no measurements are stored for that raw data value - Your endpoint should return responses within a reasonable timeout - If your endpoint is unreachable, the raw data is still stored in Kubyk but no parsed measurements are generated ## Key Points - Your device sends raw data using the parameter key RawDeviceData. Kubyk only forwards values with this key to your endpoint - Parameter keys in your response must exactly match the parameter keys defined in the datasource configuration - Numeric parameters expect numeric values; non-numeric parameters expect string values - Each raw data value results in a separate POST request to your endpoint - Kubyk does not retry failed requests --- ## API Reference ### Overview ## Authentication Devices authenticate using mTLS (mutual TLS) with X.509 client certificates. Each device receives a unique certificate pair when registered in the portal. **Base URL:** `https://device-api-your_customer_ID.lab.kubyk.dev` ## Error Format ```json { "code": "device_not_found_error", "traceId": "abc123def456" } ``` | Status | Code | Description | |---|---|---| | 400 | invalid_argument_error | Invalid request payload or parameters | | 401 | not_authenticated_error | Missing or invalid device authentication token | | 404 | device_not_found_error | Device serial number not found in the system | ## Important Notes - Timestamps: All timestamps are Unix timestamps in milliseconds (not ISO 8601 strings). Example: 1769887730071 - Parameter Keys: The parameterKey values in the data payload must exactly match the parameter keys configured in the datasource definition (e.g., heart_rate, steps, temperature) - Serial Number: The serialNumber field must exactly match the serial number registered in the portal - Data Types: Parameter values in the value field are numeric (integer or floating-point) --- ### Device Endpoints ### 1. Send Device Data The primary endpoint for uploading measurement data from devices to Kubyk. `POST /api/device/data` **Response:** 200 OK **Request Fields:** | Field | Type | Required | Description | |---|---|---|---| | serialNumber | string | true | The device's unique serial number as registered in the portal | | organizationId | integer | true | The organization the device belongs to | | organizationUserId | integer | false | The associated user ID (if data is linked to a user) | | data | object | true | Container for measurement values | | data.values | array | true | Array of measurement objects | | data.values[].timestamps | long | true | Unix timestamp in milliseconds for this measurement | | data.values[].parameterKey | string | true | Parameter key matching the datasource configuration (e.g., heart_rate, steps) | | data.values[].value | number | true | The measurement value | | timestamp | long | true | Unix timestamp in milliseconds for the overall session | | completedAt | long | false | Unix timestamp in milliseconds when the session completed | | generatedAt | long | false | Unix timestamp in milliseconds when the data was generated on device | | dataType | string | false | Data type identifier (empty string for standard data) | | metadata | string | false | Optional metadata string | **Response Fields:** | Field | Type | Required | Description | |---|---|---|---| | sessionId | string | true | Unique identifier for the created data session | | reference | string | true | Reference identifier for the ingested data | **Request Body:** ```json { "serialNumber": "POC50HRM1", "data": { "values": [ { "timestamps": 1769887730071, "parameterKey": "heart_rate", "value": 18.41947750991033 }, { "timestamps": 1769887730071, "parameterKey": "rr_interval", "value": 630.0 } ] }, "timestamp": 1769887730071, "dataType": "" } ``` **Response Body:** ```json { "sessionId": "abc123-def456-ghi789", "reference": "ref_1234567890" } ``` **cURL Example:** ```bash curl --location 'https://device-api-your_customer_ID.lab.kubyk.dev/api/device/data' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_TOKEN' \ --data '{ "serialNumber": "POC50HRM1", "data": { "values": [ { "timestamps": 1769887730071, "parameterKey": "heart_rate", "value": 82.0 }, { "timestamps": 1769887730071, "parameterKey": "steps", "value": 3421 } ] }, "timestamp": 1769887730071, "dataType": "" }' ``` ### 2. Check Device Exists Verify if a device is registered in Kubyk by its serial number. `GET /api/device/{serialNumber}/exists` **Response:** 200 OK **Path Parameters:** | Field | Type | Required | Description | |---|---|---|---| | serialNumber | string | true | The device serial number to look up | **Response Body:** ```json { "exists": true } ``` ### 3. Validate Device Validate a device's attributes against the Kubyk registration. `POST /api/device/validate` **Response:** 200 OK **Request Fields:** | Field | Type | Required | Description | |---|---|---|---| | serialNumber | string | true | Device serial number | | softwareVersion | string | true | Current firmware/software version | **Response Fields:** | Field | Type | Required | Description | |---|---|---|---| | associatedOrganizationId | integer | null | true | The organization ID the device is associated with, or null if not associated | | invalidAttributes | string[] | true | List of attribute names that failed validation (empty if all valid) | **Request Body:** ```json { "serialNumber": "POC50HRM1", "softwareVersion": "1.2.0" } ``` **Response Body:** ```json { "associatedOrganizationId": 42, "invalidAttributes": [] } ``` ### 4. Self-Register Device with Software List Register a new device and receive a certificate package for future authentication. `POST /api/device/register/software-list` **Response:** 200 OK **Request Fields:** | Field | Type | Required | Description | |---|---|---|---| | datasourceKey | string | true | The key of the datasource this device is based on | | name | string | true | Descriptive device name | | serialNumber | string | true | Unique device serial number | | installedSoftwareList | array | true | List of currently installed software | | installedSoftwareList[].softwareKey | string | true | Software/firmware identifier | | installedSoftwareList[].firmwareInstalledAtTimestamp | long | false | Unix timestamp (ms) when firmware was installed | | createWithIdentity | boolean | false | Whether to create the device with an identity token | **Request Body:** ```json { "datasourceKey": "heart-rate-monitor-v1", "name": "Activity Tracker Prototype #1", "serialNumber": "POC-WB-001", "installedSoftwareList": [ { "softwareKey": "firmware-main", "firmwareInstalledAtTimestamp": 1738232100000 } ], "createWithIdentity": true } ``` **Response Body:** ```json Binary zip file (application/octet-stream) containing device certificates. ``` **Error Responses:** 400 Bad Request, 404 Not Found ### 5. Device Heartbeat / Telemetry Send a heartbeat from the device and check if any software updates are required. `POST /api/device/{serialNumber}/heartbeat` **Path Parameters:** | Field | Type | Required | Description | |---|---|---|---| | serialNumber | string | true | Device serial number | ### 6. Download Firmware Binary Download a firmware binary file by its software key. `GET /api/device/firmware/{key}/binary` **Response:** 200 OK **Path Parameters:** | Field | Type | Required | Description | |---|---|---|---| | key | string | true | The firmware/software key | **Response Body:** ```json Binary file (application/octet-stream). ``` ### 7. Log Device Firmware Event Log a firmware-related event for a device. `POST /api/device/{serialNumber}/firmware/{existingFirmwareKey}/event` **Path Parameters:** | Field | Type | Required | Description | |---|---|---|---| | serialNumber | string | true | Device serial number | | existingFirmwareKey | string | true | The firmware key the event relates to | **Request Fields:** | Field | Type | Required | Description | |---|---|---|---| | deviceEventType | integer (enum) | true | The type of firmware event | | metadata | string | false | Optional metadata about the event | **Request Body:** ```json { "deviceEventType": 1, "metadata": "optional metadata string" } ``` **Error Responses:** 404 Not Found ## Legacy Endpoints ### Ingest Device Data `POST /api/tenant-admin/parameter-values` Send measurement data from a registered device to Kubyk. This is the primary endpoint for device data ingestion. **Authentication:** mTLS Certificate (device-cert.crt + device-key.key) **Request Body:** | Field | Type | Required | Description | |---|---|---|---| | values | array | true | Array of measurement objects, each containing a parameterKey and value | | timestamp | number | true | Unix timestamp in milliseconds (e.g., 1738232100000) | | parameterKey | string | true | Unique identifier for the parameter being measured | **Response Codes:** - `200`: Data ingested successfully - `400`: Invalid request payload or malformed JSON - `401`: Certificate authentication failed - `404`: Device not found - `429`: Rate limit exceeded **Example Request:** ```json { "values": [ { "parameterKey": "heart_rate", "value": 82, "timestamp": 1738232100000 } ], "timestamp": 1738232100000, "parameterKey": "heart_rate" } ``` **Example Response:** ```json { "success": true, "recordId": "rec_1234567890", "timestamp": "2025-01-30T10:15:00.123Z" } ``` ### Get Device Data `GET /api/tenant-admin/devices/{deviceId}/data` Retrieve historical measurement data for a specific device with optional date range filtering. **Authentication:** Bearer Token (Portal User) **Tier:** Lab++ **Query Parameters:** | Param | Type | Required | Description | |---|---|---|---| | from | string | false | Start date (ISO 8601) | | to | string | false | End date (ISO 8601) | | limit | number | false | Max records to return (default: 100) | | offset | number | false | Pagination offset | **Response Codes:** - `200`: Data retrieved successfully - `401`: Authentication required - `403`: Not authorized to access this device - `404`: Device not found **Example Response:** ```json { "deviceId": "POC-WB-001", "records": [ { "recordId": "rec_123", "timestamp": "2025-01-30T10:15:00Z", "measurements": { "heartRate": 82 } } ], "pagination": { "total": 1250, "limit": 100, "offset": 0 } } ``` ### List Devices `GET /api/tenant-admin/devices` Retrieve a list of all devices registered in your organization. **Authentication:** Bearer Token (Portal User) **Query Parameters:** | Param | Type | Required | Description | |---|---|---|---| | datasourceId | string | false | Filter by datasource | **Response Codes:** - `200`: Devices retrieved successfully - `401`: Authentication required **Example Response:** ```json { "devices": [ { "id": "dev_123", "name": "Activity Tracker POC", "serialNumber": "POC-WB-001", "status": "active", "datasourceId": "ds_456", "lastSeen": "2025-01-30T10:15:00Z" } ], "total": 5 } ``` --- ## SDKs & Examples ### Overview ## SDKs & Examples Code examples in multiple languages Use these examples to quickly integrate with Kubyk. All examples show how to send measurement data using mTLS certificate authentication. > **Certificate Paths:** Store your certificates securely. On embedded devices, you may need to embed them as byte arrays rather than reading from files. --- ### cURL ## cURL Example ```bash curl --location --insecure 'https://device-api-your_customer_ID.lab.kubyk.dev/api/device/data' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_TOKEN' \ --data '{ "serialNumber": "POC50HRM1", "data": { "values": [ { "timestamps": 1769887730071, "parameterKey": "heart_rate", "value": 18.41947750991033 } ] }, "timestamp": 1769887730071, "dataType": "" }' ``` --- ### Python ## Python Example ```python import requests import json url = "https://device-api-your_customer_ID.lab.kubyk.dev/api/device/data" headers = { "Content-Type": "application/json", "Authorization": "Bearer YOUR_TOKEN", } payload = { "serialNumber": "POC50HRM1", "data": { "values": [ { "timestamps": 1769887730071, "parameterKey": "heart_rate", "value": 18.41947750991033, } ] }, "timestamp": 1769887730071, "dataType": "", } response = requests.post( url, headers=headers, json=payload, verify=False, # equivalent to --insecure ) print(response.status_code) print(response.text) ``` --- ### JavaScript/Node.js ## Node.js Example ```javascript const https = require("https"); const data = JSON.stringify({ serialNumber: "POC50HRM1", data: { values: [ { timestamps: 1769887730071, parameterKey: "heart_rate", value: 18.41947750991033, }, ], }, timestamp: 1769887730071, dataType: "", }); const options = { hostname: "device-api-your_customer_ID.lab.kubyk.dev", path: "/api/device/data", method: "POST", headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(data), Authorization: "Bearer YOUR_TOKEN", }, rejectUnauthorized: false, }; const req = https.request(options, (res) => { let body = ""; res.on("data", (chunk) => { body += chunk; }); res.on("end", () => { console.log(res.statusCode); console.log(body); }); }); req.on("error", (err) => { console.error(err); }); req.write(data); req.end(); ``` --- ### Arduino/ESP32 ## Arduino/ESP32 Example ```arduino #include #include const char* WIFI_SSID = "YOUR_WIFI_SSID"; const char* WIFI_PASS = "YOUR_WIFI_PASSWORD"; const char* HOST = "device-api-your_customer_ID.lab.kubyk.dev"; const int PORT = 443; const char* PATH = "/api/device/data"; const char* TOKEN = "YOUR_TOKEN"; void setup() { Serial.begin(115200); WiFi.begin(WIFI_SSID, WIFI_PASS); while (WiFi.status() != WL_CONNECTED) { delay(300); Serial.print("."); } Serial.println("\nWiFi connected"); WiFiClientSecure client; client.setInsecure(); if (!client.connect(HOST, PORT)) { Serial.println("Connection failed"); return; } String body = "{" "\"serialNumber\":\"POC50HRM1\"," "\"data\":{\"values\":[{\"timestamps\":1769887730071," "\"parameterKey\":\"heart_rate\",\"value\":18.41947750991033}]}," "\"timestamp\":1769887730071,\"dataType\":\"\"" "}"; client.print(String("POST ") + PATH + " HTTP/1.1\r\n"); client.print(String("Host: ") + HOST + "\r\n"); client.print("Content-Type: application/json\r\n"); client.print("Authorization: Bearer "); client.print(TOKEN); client.print("\r\n"); client.print("Content-Length: "); client.print(body.length()); client.print("\r\n\r\n"); client.print(body); while (client.connected()) { String line = client.readStringUntil('\n'); if (line == "\r") break; } String response = ""; while (client.available()) { response += client.readString(); } Serial.println(response); client.stop(); } void loop() {} ``` --- ### Go ## Go Example ```go package main import ( "bytes" "crypto/tls" "fmt" "io" "net/http" "time" ) func main() { url := "https://device-api-your_customer_ID.lab.kubyk.dev/api/device/data" token := "YOUR_TOKEN" body := []byte(`{ "serialNumber": "POC50HRM1", "data": { "values": [ { "timestamps": 1769887730071, "parameterKey": "heart_rate", "value": 18.41947750991033 } ] }, "timestamp": 1769887730071, "dataType": "" }`) tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client := &http.Client{Transport: tr, Timeout: 30 * time.Second} req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(body)) if err != nil { panic(err) } req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+token) resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() respBody, _ := io.ReadAll(resp.Body) fmt.Println("Status:", resp.Status) fmt.Println(string(respBody)) } ``` --- ## Architecture ### System Overview ## Architecture System design and data flow Security Model - mTLS for device authentication - Per-device unique certificates - TLS 1.3 encryption in transit - Organization isolation Data Flow - Real-time ingestion - Automatic data validation - Configurable data retention - Export in multiple formats --- ### Data Flow ### Data Flow Understanding how data moves through Kubyk from device to visualization. 1 Ingestion Device sends HTTPS POST request with mTLS certificate to /api/tenant-admin/parameter-values endpoint 2 Validation Kubyk validates certificate, checks device status, and validates payload structure against datasource configuration 3 Processing For Custom datasources, your parser is invoked. For Standard, data is stored directly 4 Storage Data is encrypted at rest and stored in your organization's isolated database partition 5 Visualization Data appears in portal within seconds - view as tables, charts, or export for analysis --- ### Security Model ### Security Model Kubyk uses mutual TLS (mTLS) for device authentication - a zero-trust security model where both client and server verify each other's identity. Certificate Lifecycle - 1. Generate certificates in Device Details → Security Certificate - 2. Download device-cert.cert and device-key.key - 3. Embed in device firmware securely - 4. Certificates expire after 1 year by default Security Features - TLS 1.3 with strong cipher suites - Per-device unique certificate pairs - Certificate revocation on device deletion - AES-256 encryption at rest > **Certificate Security:** Never commit certificates to version control. Store the private key securely on your device and protect it from extraction. --- ## Troubleshooting & FAQ ### Data & Compliance ## Data & Compliance > **Important:** In Lab and Lab+, you must use **test data or de-identified data only**. Do not use real patient health information (PHI) unless you are in a properly contracted and validated production environment with suitable compliance frameworks in place. > **Kubyk Scale:** For production deployments with real patient data, upgrade to Kubyk Scale. This tier includes the compliance infrastructure and BAA required for PHI handling. --- ### Troubleshooting & FAQ ## Frequently Asked Questions **Q: How do I add a device to the system?** A: Go to Devices → Add Device. Fill in the device name, serial number, and select a datasource. Your device is immediately Active. Download the security certificate from Device Details for API authentication. **Q: What are the requirements for data transmission?** A: Devices need: (1) a valid mTLS certificate pair, for direct-to-cloud devices, (2) JSON payload with deviceId, timestamp (Unix timestamp in milliseconds), and data object matching your datasource parameters. **Q: Is there a limit to data transmission?** A: There are rate limits to prevent abuse, but normal device data transmission is not restricted. If you hit rate limits, you'll receive HTTP 429 responses. Contact support if you need higher limits. **Q: Can I view and analyze data in the portal?** A: Yes. Go to Data → Devices (for device-centric view) or Data → Users (for user-centric view). You can view data as tables or graphs, filter by date range, and export in CSV format. **Q: How do I troubleshoot connectivity issues?** A: Check: (1) Certificates are valid and correctly configured, (2) JSON payload format matches datasource parameters, (3) use the cURL example from Device Details → API Integration tab to test. **Q: How do I add additional users?** A: Go to Users → Add User. Enter their name, email, and select a role (Admin, Standard User, or Data Viewer). They'll receive an invitation email. Check your tier's user limit if you get an error. **Q: I've reached my device or user limits. What do I do?** A: Your current tier has capacity limits (Lab: 5 devices/9 users, Lab+: 15/20, Scale: 25/50). To add more, upgrade your tier from the Account → Billing page, or remove unused resources. **Q: My portal has crashed or is unresponsive. What do I do?** A: Try: (1) Refresh your browser, (2) clear cache and cookies, (3) try a different browser, (4) check your internet connection. If the issue persists, contact support through the Help section or your account representative. **Q: How do I reach Kubyk support?** A: Use the escalation path: (1) Check docs and troubleshooting, (2) Ask KAI in the portal, (3) Use the in-app feedback button, (4) Lab+ and Scale customers have priority support with guaranteed response times. **Q: Will I get a notification when I approach my limits?** A: Yes. The portal displays warnings when you're nearing your device or user limits. You'll see banners on relevant pages and KAI will proactively notify you. **Q: I can't see certain menu items (Users, Devices, Datasources, Bench, Experiment)** A: Your sidebar navigation is filtered by your role. Admin-only pages are not visible to Standard Users or Data Viewers. If you need access, ask your organization's administrator to update your role. **Q: Authentication or session issues** A: If redirected to the login page unexpectedly, your session has expired — sign in again. If your account is locked after multiple failed login attempts, contact your administrator to unlock it. For 2FA issues, contact your administrator to reset your 2FA settings. **Q: Simulated data mixed with real data** A: If you used the Simulated Data tool in The Bench, those data points are indistinguishable from real device readings. There is no automated way to remove simulated data. Prevention: use dedicated test devices for simulated data generation to keep production devices clean. **Q: I can't create or edit records** A: Only Admins can create or edit users, devices, and datasources. Standard Users can manage their own profile but not organization resources. Some fields like email, serial number, and datasource assignment are read-only after creation. ## Troubleshooting **Q: No data in Data → Devices** A: Verify the device is Active, the URL and fields are correct, TLS certificates are valid, and that time filters cover your test timestamps. **Q: No data in Data → Users** A: Verify a Cloud datasource is linked to that user and that synchronization is configured correctly. **Q: Errors from cURL or scripts** A: Check HTTP status codes and messages, validate JSON structure, and confirm authentication configuration. **Q: Portal UI issues** A: Refresh the browser, try another browser, check your network/VPN, and use the Help section for contact details. **Q: Which datasource type should I use?** A: Standard for sample JSON devices, Custom Remote if you need custom processing in your own cloud, Cloud for consumer devices like Fitbit. Custom Local (Kubyk-hosted containers) is available on Lab+ and higher tiers. --- ### Getting Help ### Getting Help Multiple ways to get assistance when you're stuck. 1 Check Docs & Troubleshooting Most questions are answered in our documentation and troubleshooting guides 2 Ask KAI Our AI assistant in the portal can answer questions about your specific setup and data 3 In-App Feedback Send us questions or ideas directly through the feedback button in your portal 4 Priority Support Lab+ and Scale customers have access to dedicated support with guaranteed response times ---