### Updated Device Schema and Example Source: https://hubble.com/docs/api-specification/update-device Defines the JSON schema for an updated device, including fields for name, ID, creation timestamp, tags, and most recent packet data (satellite and terrestrial). Provides an example payload conforming to this schema. ```json { "name": "string", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "created_ts": 0, "tags": { "_env": "production" }, "most_recent_packet": { "satellite": { "timestamp": 0, "location": { "latitude": 0, "longitude": 0 } }, "terrestrial": { "timestamp": 0, "location": { "latitude": 0, "longitude": 0 } } } } ``` -------------------------------- ### List Key Scopes API Request Example (C#) Source: https://hubble.com/docs/api-specification/list-key-scopes Example of how to call the 'List Key Scopes' API endpoint using C# HttpClient. This code sends a GET request and handles the response, ensuring success before reading the content. ```csharp var client = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Get, "https://hubble.com/api/org/:org_id/key_scopes"); request.Headers.Add("Accept", "application/json"); request.Headers.Add("Authorization", "Bearer "); var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); Console.WriteLine(await response.Content.ReadAsStringAsync()); ``` -------------------------------- ### Success Response Schema and Example for Devices Source: https://hubble.com/docs/api-specification/batch-update-devices Defines the schema for a successful response when retrieving device information. It includes details like device name, ID, creation timestamp, tags, and most recent packet metadata for satellite and terrestrial connections. The example shows the expected JSON structure. ```json { "devices": [ { "name": "string", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "created_ts": 0, "tags": { "_env": "production" }, "most_recent_packet": { "satellite": { "timestamp": 0, "location": { "latitude": 0, "longitude": 0 } }, "terrestrial": { "timestamp": 0, "location": { "latitude": 0, "longitude": 0 } } } } ] } ``` ```json { "devices": [ { "id": "6ea53e36-b7fb-429f-8c2e-d536cab71089", "name": "Device 1", "created_ts": 1609459200, "tags": { "location": "warehouse-a" }, "most_recent_packet": {} }, { "id": "7fb64f47-c8gc-530g-9d3f-e647dbc8219a", "name": "Device 2", "created_ts": 1609459200, "tags": { "location": "warehouse-b" }, "most_recent_packet": {} } ] } ``` -------------------------------- ### Packets Schema and Example Source: https://hubble.com/docs/api-specification/retrieve-organization-packets Defines the structure for packet data, including location, device information, and network type. Provides an example of a JSON payload for a successful packet retrieval. ```json { "packets": [ { "location": { "latitude": 0, "longitude": 0, "altitude": 0, "horizontal_accuracy": 0, "vertical_accuracy": 0, "timestamp": 0 }, "device": { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "tags": { "_env": "production" }, "payload": "string", "rssi": 0, "timestamp": 0, "counter": 0, "sequence_number": 0 }, "network_type": "TERRESTRIAL" } ] } ``` -------------------------------- ### Execute Billing Usage Request in C# Source: https://hubble.com/docs/api-specification/get-billing-usage Example implementation using HttpClient to perform an authenticated GET request to the Hubble billing usage endpoint. ```csharp var client = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Get, "https://api.hubble.com/api/org/:org_id/billing/usage"); request.Headers.Add("Accept", "application/json"); request.Headers.Add("Authorization", "Bearer "); var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); Console.WriteLine(await response.Content.ReadAsStringAsync()); ``` -------------------------------- ### GET /devices Source: https://hubble.com/docs/api-specification/register-new-devices Retrieves a list of provisioned devices with their associated configurations, including protocol settings, EID rotation, and tags. ```APIDOC ## GET /devices ### Description Retrieves the list of provisioned devices. Each device object contains metadata, protocol configuration, and EID rotation settings. ### Method GET ### Endpoint /devices ### Response #### Success Response (200) - **devices** (array) - List of device objects - **device_id** (uuid) - Primary UUID identifier - **name** (string) - Assigned device name - **created_ts** (int64) - Unix timestamp of creation - **tags** (object) - User-defined key/value pairs - **protocol** (object) - Protocol configuration - **eid_rotation** (object) - EID rotation configuration #### Response Example { "devices": [ { "device_id": "6ea53e36-b7fb-429f-8c2e-d536cab71089", "name": "sensor-001", "created_ts": 1734567890, "tags": { "_env": "production" }, "protocol": { "terrestrial": { "version": 0 } }, "eid_rotation": { "counter_source": "EPOCH_TIME" }, "key": "YWJjZGVmZw==" } ] } ``` -------------------------------- ### Delete Device API Request Examples Source: https://hubble.com/docs/api-specification/delete-device Examples of how to call the Delete Device API endpoint using various programming languages and tools. This includes setting up the HTTP request, including necessary headers like Authorization, and handling the response. ```csharp var client = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Delete, "https://api.hubble.com/api/org/:org_id/devices/:device_id"); request.Headers.Add("Accept", "application/json"); request.Headers.Add("Authorization", "Bearer "); var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); Console.WriteLine(await response.Content.ReadAsStringAsync()); ``` ```curl curl -X DELETE https://api.hubble.com/api/org/:org_id/devices/:device_id \ -H "Authorization: Bearer " \ -H "Accept: application/json" ``` ```dart import 'package:http/http.dart' as http; import 'dart:convert'; Future deleteDevice(String orgId, String deviceId, String token) async { final url = Uri.parse('https://api.hubble.com/api/org/$orgId/devices/$deviceId'); final response = await http.delete( url, headers: { 'Authorization': 'Bearer $token', 'Accept': 'application/json', }, ); if (response.statusCode == 200) { print('Device deleted successfully: ${response.body}'); } else { print('Failed to delete device. Status code: ${response.statusCode}, Body: ${response.body}'); } } ``` ```go package main import ( "fmt" "net/http" "io/ioutil" ) func main() { orgID := "your_org_id" deviceID := "your_device_id" token := "your_token" url := fmt.Sprintf("https://api.hubble.com/api/org/%s/devices/%s", orgID, deviceID) client := &http.Client{} req, err := http.NewRequest("DELETE", url, nil) if err != nil { fmt.Printf("Error creating request: %s\n", err) return } req.Header.Add("Authorization", "Bearer "+token) req.Header.Add("Accept", "application/json") resp, err := client.Do(req) if err != nil { fmt.Printf("Error sending request: %s\n", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Printf("Error reading response body: %s\n", err) return } if resp.StatusCode == http.StatusOK { fmt.Printf("Device deleted successfully: %s\n", string(body)) } else { fmt.Printf("Failed to delete device. Status code: %d, Body: %s\n", resp.StatusCode, string(body)) } } ``` ```http DELETE /api/org/:org_id/devices/:device_id HTTP/1.1 Host: api.hubble.com Authorization: Bearer Accept: application/json ``` ```java import okhttp3.*; import java.io.IOException; public class DeleteDevice { public static void main(String[] args) { String orgId = "your_org_id"; String deviceId = "your_device_id"; String token = "your_token"; String url = "https://api.hubble.com/api/org/" + orgId + "/devices/" + deviceId; OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(url) .delete() .addHeader("Authorization", "Bearer " + token) .addHeader("Accept", "application/json") .build(); try (Response response = client.newCall(request).execute()) { if (response.isSuccessful()) { System.out.println("Device deleted successfully: " + response.body().string()); } else { System.out.println("Failed to delete device. Status code: " + response.code() + ", Body: " + response.body().string()); } } catch (IOException e) { e.printStackTrace(); } } } ``` ```javascript async function deleteDevice(orgId, deviceId, token) { const url = `https://api.hubble.com/api/org/${orgId}/devices/${deviceId}`; try { const response = await fetch(url, { method: 'DELETE', headers: { 'Authorization': `Bearer ${token}`, 'Accept': 'application/json', }, }); if (response.ok) { const data = await response.text(); // Or response.json() if the API returns JSON on success console.log('Device deleted successfully:', data); } else { const errorData = await response.text(); // Or response.json() console.error('Failed to delete device:', response.status, errorData); } } catch (error) { console.error('Error deleting device:', error); } } // Example usage: // deleteDevice('your_org_id', 'your_device_id', 'your_token'); ``` ```kotlin import okhttp3.*; import java.io.IOException; fun deleteDevice(orgId: String, deviceId: String, token: String) { val url = "https://api.hubble.com/api/org/$orgId/devices/$deviceId" val client = OkHttpClient() val request = Request.Builder() .url(url) .delete() .addHeader("Authorization", "Bearer $token") .addHeader("Accept", "application/json") .build() client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { e.printStackTrace() println("Failed to delete device: ${e.message}") } override fun onResponse(call: Call, response: Response) { response.use { if (it.isSuccessful) { println("Device deleted successfully: ${it.body?.string()}") } else { println("Failed to delete device. Status code: ${it.code}, Body: ${it.body?.string()}") } } } }) } ``` ```php ``` ```powershell $orgId = "your_org_id" $deviceId = "your_device_id" $token = "your_token" $url = "https://api.hubble.com/api/org/$orgId/devices/$deviceId" $headers = @{ "Authorization" = "Bearer $token" "Accept" = "application/json" } $response = Invoke-WebRequest -Uri $url -Method DELETE -Headers $headers if ($response.StatusCode -eq 200) { Write-Host "Device deleted successfully: $($response.Content)" } else { Write-Host "Failed to delete device. Status code: $($response.StatusCode), Response: $($response.Content)" } ``` ```python import requests def delete_device(org_id, device_id, token): url = f"https://api.hubble.com/api/org/{org_id}/devices/{device_id}" headers = { "Authorization": f"Bearer {token}", "Accept": "application/json" } response = requests.delete(url, headers=headers) if response.status_code == 200: print(f"Device deleted successfully: {response.text}") else: print(f"Failed to delete device. Status code: {response.status_code}, Response: {response.text}") # Example usage: # delete_device('your_org_id', 'your_device_id', 'your_token') ``` ```rust use reqwest::Error; #[tokio::main] async fn main() -> Result<(), Error> { let org_id = "your_org_id"; let device_id = "your_device_id"; let token = "your_token"; let url = format!("https://api.hubble.com/api/org/{}/devices/{}", org_id, device_id); let client = reqwest::Client::new(); let response = client.delete(&url) .header("Authorization", format!("Bearer {}", token)) .header("Accept", "application/json") .send() .await?; if response.status().is_success() { let body = response.text().await?; println!("Device deleted successfully: {}", body); } else { let status = response.status(); let body = response.text().await?; println!("Failed to delete device. Status code: {}, Response: {}", status, body); } Ok(()) } ``` ```shell curl -X DELETE https://api.hubble.com/api/org/:org_id/devices/:device_id \ -H "Authorization: Bearer " \ -H "Accept: application/json" ``` ```swift import Foundation func deleteDevice(orgId: String, deviceId: String, token: String) { guard let url = URL(string: "https://api.hubble.com/api/org/(orgId)/devices/(deviceId)") else { return } var request = URLRequest(url: url) request.httpMethod = "DELETE" request.setValue("Bearer (token)", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Accept") let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error deleting device: \(error.localizedDescription)") return } guard let httpResponse = response as? HTTPURLResponse else { print("Invalid response") return } if httpResponse.statusCode == 200 { if let data = data, let responseString = String(data: data, encoding: .utf8) { print("Device deleted successfully: \(responseString)") } } else { if let data = data, let errorString = String(data: data, encoding: .utf8) { print("Failed to delete device. Status code: \(httpResponse.statusCode), Response: \(errorString)") } else { print("Failed to delete device. Status code: \(httpResponse.statusCode)") } } } task.resume() } // Example usage: // deleteDevice(orgId: "your_org_id", deviceId: "your_device_id", token: "your_token") ``` -------------------------------- ### GET /websites/hubble/devices Source: https://hubble.com/docs/api-specification/list-devices Retrieves a list of devices associated with the Hubble project. Supports pagination using a continuation token. ```APIDOC ## GET /websites/hubble/devices ### Description Retrieves a list of devices. The response includes a `Continuation-Token` header for paginating through results. ### Method GET ### Endpoint /websites/hubble/devices ### Query Parameters - **continuation_token** (string) - Optional - A token to indicate how to continue paging. ### Response #### Success Response (200) - **devices** (array) - An array of device objects. - **name** (string) - Required - Assigned name for the device (<= 250 characters). - **id** (string) - Required - Primary UUID identifier for a registered device. - **created_ts** (integer) - Required - An UTC second-precision timestamp formatted as an integer. - **tags** (object) - Required - User-defined key/value pairs for device organization (up to 10 tags). - `_env` (string) - Platform tag indicating environment (`production` or `sandbox`). - *property name* (string) - Custom tags with key length up to 32 characters and value length up to 128 characters. - **most_recent_packet** (object) - Most recent packet metadata for different network types (updated periodically). - **satellite** (object) - Nullable - Satellite packet data. - **timestamp** (double) - Unix timestamp of a recent satellite packet. - **location** (object) - Location data from a recent satellite packet. - **latitude** (double) - Required - Latitude in Decimal Degrees (>= -90 and <= 90). - **longitude** (double) - Required - Longitude in Decimal Degrees (>= -180 and <= 180). - **terrestrial** (object) - Nullable - Terrestrial packet data. - **timestamp** (double) - Unix timestamp of a recent terrestrial packet. - **location** (object) - Location data from a recent terrestrial packet. - **latitude** (double) - Required - Latitude in Decimal Degrees (>= -90 and <= 90). - **longitude** (double) - Required - Longitude in Decimal Degrees (>= -180 and <= 180). #### Response Example (200) ```json { "devices": [ { "name": "string", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "created_ts": 0, "tags": { "_env": "production" }, "most_recent_packet": { "satellite": { "timestamp": 0, "location": { "latitude": 0, "longitude": 0 } }, "terrestrial": { "timestamp": 0, "location": { "latitude": 0, "longitude": 0 } } } } ] } ``` #### Error Response (400) - **code** (integer) - The HTTP status code. - **description** (string) - A description for the error. - **name** (string) - A short name for the error (e.g., `Bad Request`). #### Response Example (400) ```json { "code": 400, "description": "The request could not be understood by the server due to malformed syntax.", "name": "Bad Request" } ``` #### Error Response (500) - **code** (integer) - The HTTP status code. - **description** (string) - A description for the error. - **name** (string) - A short name for the error (e.g., `Unknown`). #### Response Example (500) ```json { "code": 500, "description": "An unknown error has occurred.", "name": "Unknown" } ``` ``` -------------------------------- ### Internal Server Error Response Schema and Examples Source: https://hubble.com/docs/api-specification/batch-update-devices Outlines the schema for an 'Internal Server Error' response (HTTP 500). Similar to other errors, it contains code, description, and name fields. The provided examples illustrate the structure for a generic internal error and a specific 'Unknown' error. ```json { "code": 0, "description": "string", "name": "Bad Request" } ``` ```json { "code": 500, "description": "An unknown error has occurred.", "name": "Unknown" } ``` -------------------------------- ### GET /websites/hubble/devices Source: https://hubble.com/docs/openapi.yaml Retrieves a list of devices, with options for filtering, sorting, and pagination. ```APIDOC ## GET /websites/hubble/devices ### Description Retrieves a list of devices, with options for filtering, sorting, and pagination. ### Method GET ### Endpoint /websites/hubble/devices ### Parameters #### Query Parameters - **limit** (integer) - Optional - A limit for the page size of devices. Minimum: 10, Maximum: 1000, Default: 250. - **filter_created_ts** (string) - Optional - Filter devices by creation timestamp (e.g., filter_created_ts=between:1000:2000). Timestamps are in seconds since the Unix epoch. The only supported filtering operator currently is `between`. - **filter_most_recent_packet_ts** (string) - Optional - Filter devices by most recent packet timestamp (e.g., filter_most_recent_packet_ts=between:1000:2000). Timestamps are in seconds since the Unix epoch. The most recent packet value is only updated periodically. The only supported filtering operator currently is `between`. - **sort_field** (string) - Optional - Field to sort devices by. Enum: created_ts, most_recent_packet_ts. - **sort_ascending** (boolean) - Optional - Sort order (true for ascending, false for descending). Default: true. - **continuation_token** (string) - Optional - A token to indicate how to continue paging. ### Request Example ```json { "example": "" } ``` ### Response #### Success Response (200) - **devices** (array) - A list of device objects. - **device_id** (string) - The unique identifier for the device. - **created_ts** (string) - The timestamp when the device was created. - **most_recent_packet_ts** (string) - The timestamp of the most recent packet received from the device. #### Response Example ```json { "devices": [ { "device_id": "dev_123xyz", "created_ts": "2023-10-26T10:00:00Z", "most_recent_packet_ts": "2023-10-27T09:00:00Z" } ] } ``` #### Error Response - **400** - Bad Request - **500** - Internal Server Error ``` -------------------------------- ### GET /websites/hubble/devices Source: https://hubble.com/docs/api-specification/batch-update-devices Retrieves a list of devices associated with the Hubble project. Supports filtering and sorting based on device properties. ```APIDOC ## GET /websites/hubble/devices ### Description Retrieves a list of devices associated with the Hubble project. The response includes detailed information about each device, including its name, ID, creation timestamp, tags, and the most recent packet metadata for satellite and terrestrial network types. ### Method GET ### Endpoint /websites/hubble/devices ### Parameters #### Query Parameters - **limit** (integer) - Optional - The maximum number of devices to return. - **offset** (integer) - Optional - The number of devices to skip before starting to collect the result set. ### Request Example ``` GET /websites/hubble/devices?limit=10&offset=0 ``` ### Response #### Success Response (200) - **devices** (array) - An array of device objects. - **name** (string) - Assigned name for the device (max 250 characters). - **id** (string) - Primary UUID identifier for a registered device. - **created_ts** (integer) - An UTC second-precision timestamp formatted as an integer. - **tags** (object) - User-defined key/value pairs for device attribution (max 10 tags). - **_env** (string) - Hubble-defined tag indicating environment (`production` or `sandbox`). - ***property name*** (string) - Custom tags with key length up to 32 characters and value length up to 128 characters. - **most_recent_packet** (object) - Most recent packet metadata for different network types (updated periodically). - **satellite** (object | null) - Satellite packet metadata. - **timestamp** (double) - Unix timestamp of a recent satellite packet. - **location** (object) - Location data from a recent satellite packet. - **latitude** (double) - Latitude in Decimal Degrees (>= -90 and <= 90). - **longitude** (double) - Longitude in Decimal Degrees (>= -180 and <= 180). - **terrestrial** (object | null) - Terrestrial packet metadata. - **timestamp** (double) - Unix timestamp of a recent terrestrial packet. - **location** (object) - Location data from a recent terrestrial packet. - **latitude** (double) - Latitude in Decimal Degrees (>= -90 and <= 90). - **longitude** (double) - Longitude in Decimal Degrees (>= -180 and <= 180). #### Response Example (200) ```json { "devices": [ { "id": "6ea53e36-b7fb-429f-8c2e-d536cab71089", "name": "Device 1", "created_ts": 1609459200, "tags": { "location": "warehouse-a", "_env": "production" }, "most_recent_packet": { "satellite": { "timestamp": 1678886400.0, "location": { "latitude": 34.0522, "longitude": -118.2437 } }, "terrestrial": { "timestamp": 1678886460.0, "location": { "latitude": 34.0523, "longitude": -118.2438 } } } } ] } ``` #### Error Response (400) - **code** (integer) - The HTTP status code (e.g., 400). - **description** (string) - A description for the error. - **name** (string) - The name of the error (e.g., "Bad Request"). #### Response Example (400) ```json { "code": 400, "description": "The request could not be understood by the server due to malformed syntax.", "name": "Bad Request" } ``` #### Error Response (500) - **code** (integer) - The HTTP status code (e.g., 500). - **description** (string) - A description for the error. - **name** (string) - The name of the error (e.g., "Unknown"). #### Response Example (500) ```json { "code": 500, "description": "An unknown error has occurred.", "name": "Unknown" } ``` ``` -------------------------------- ### Build the Application Source: https://hubble.com/docs/guides/device-integration/quick-start-terrestrial/freertos Executes the build process for the application using the make command pointing to the project's Makefile. ```bash make -C /path/to/your/application/Makefile ``` -------------------------------- ### Device Provisioning JSON Schemas and Examples Source: https://hubble.com/docs/api-specification/register-new-devices JSON payloads for provisioning devices with varying configurations such as EPOCH_TIME or DEVICE_UPTIME based EID rotation, and unencrypted protocol settings. ```json { "devices": [ { "device_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "created_ts": 0, "tags": { "_env": "production" }, "protocol": { "terrestrial": { "version": 0 } }, "eid_rotation": { "counter_source": "EPOCH_TIME", "pool_size": 16 }, "network_id": 0, "key": "string" } ] } ``` ```json { "devices": [ { "device_id": "6ea53e36-b7fb-429f-8c2e-d536cab71089", "name": "sensor-001", "created_ts": 1734567890, "tags": { "_env": "production" }, "protocol": { "terrestrial": { "version": 0 } }, "eid_rotation": { "counter_source": "EPOCH_TIME" }, "key": "YWJjZGVmZw==" } ] } ``` ```json { "devices": [ { "device_id": "7fb53e36-b7fb-429f-8c2e-d536cab71090", "name": "uptime-sensor", "created_ts": 1734567891, "tags": { "_env": "production" }, "protocol": { "terrestrial": { "version": 0 } }, "eid_rotation": { "counter_source": "DEVICE_UPTIME", "pool_size": 128 }, "key": "YWJjZGVmZw==" } ] } ``` ```json { "devices": [ { "device_id": "6ea53e36-b7fb-429f-8c2e-d536cab71089", "name": "static-tag", "created_ts": 1734567893, "tags": { "_env": "production" }, "protocol": { "terrestrial": { "version": 1 } }, "network_id": 1234567 } ] } ``` -------------------------------- ### Validate API Key Implementation in C# Source: https://hubble.com/docs/api-specification/validate-api-key Example implementation using the C# HttpClient library to perform a GET request to the validation endpoint. It demonstrates setting the Authorization header with a Bearer token and handling the response. ```csharp var client = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Get, "https://api.hubble.com/api/org/:org_id/check"); request.Headers.Add("Accept", "application/json"); request.Headers.Add("Authorization", "Bearer "); var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); Console.WriteLine(await response.Content.ReadAsStringAsync()); ``` -------------------------------- ### Create Device via C# HttpClient Source: https://hubble.com/docs/api-specification/register-new-devices Demonstrates how to perform a POST request to the Hubble API to register new devices. It uses HttpClient with Bearer token authorization and a JSON payload. ```csharp var client = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Post, "https://api.hubble.com/api/v2/org/:org_id/devices"); request.Headers.Add("Accept", "application/json"); request.Headers.Add("Authorization", "Bearer "); var content = new StringContent("{\n \"n_devices\": 1,\n \"encryption\": \"AES-256-CTR\",\n \"names\": [\n \"my-device\"\n ]\n}", null, "application/json"); request.Content = content; var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); Console.WriteLine(await response.Content.ReadAsStringAsync()); ``` -------------------------------- ### Sequence Counter Get (C) Source: https://hubble.com/docs/guides/device-integration/quick-start-terrestrial/bare-metal Retrieves a 10-bit sequence counter for cryptographic operations. The default implementation uses a RAM-based counter. Custom implementations can use non-volatile storage for persistence across resets. The counter increments and wraps around at 1023. ```c uint16_t hubble_sequence_counter_get(void); // Example: Custom Implementation with Non-Volatile Storage (NVS) #define CONFIG_HUBBLE_NETWORK_SEQUENCE_NONCE_CUSTOM uint16_t hubble_sequence_counter_get(void) { static uint16_t counter = 0; static bool initialized = false; if (!initialized) { /* Load from non-volatile storage on first call */ counter = your_nvs_read_u16("hubble_seq"); initialized = true; } uint16_t current = counter; counter = (counter + 1) & HUBBLE_BLE_MAX_SEQ_COUNTER; /* 0x3FF = 1023 */ /* Persist periodically or on significant changes */ your_nvs_write_u16("hubble_seq", counter); return current; } ``` -------------------------------- ### Fetch Device Metrics with HttpClient in C# Source: https://hubble.com/docs/api-specification/get-device-metrics Example implementation showing how to retrieve device metrics from the Hubble API using C# HttpClient with Bearer token authentication. ```csharp var client = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Get, "https://api.hubble.com/api/org/:org_id/device_metrics"); request.Headers.Add("Accept", "application/json"); request.Headers.Add("Authorization", "Bearer "); var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); Console.WriteLine(await response.Content.ReadAsStringAsync()); ``` -------------------------------- ### GET /api/org/:org_id/billing/usage Source: https://hubble.com/docs/api-specification/get-billing-usage Retrieve the most recent billing usage data for a specific organization. Requires the 'read-billing-usage' scope. ```APIDOC ## GET /api/org/:org_id/billing/usage ### Description Retrieve the most recent billing usage for your organization. This endpoint returns usage metrics such as Daily or Monthly Active Devices. ### Method GET ### Endpoint https://api.hubble.com/api/org/:org_id/billing/usage ### Parameters #### Path Parameters - **org_id** (uuid) - Required - Your organization ID ### Request Example ```json { "Authorization": "Bearer " } ``` ### Response #### Success Response (200) - **usage** (array) - List of usage records - **usage_timestamp** (date-time) - Start of the bucket in ISO 8601 format - **usage_type** (string) - The type of usage (e.g., 'Daily Active Devices', 'Monthly Active Devices') - **usage_value** (integer) - The usage value for this type and timestamp #### Response Example ```json { "usage": [ { "usage_timestamp": "2024-07-29T15:51:28.071Z", "usage_type": "Daily Active Devices", "usage_value": 0 } ] } ``` ```