---
language: "en"
---
# ClearBlade IoT Core

ClearBlade IoT Core is a fully managed service for securely connecting and managing IoT devices, from a few to millions. Ingest data from connected devices and build rich applications that integrate with cloud services.

## [How-to guides](https://docs.clearblade.com/iotcore/how-to-guides.md)

How to create a new ClearBlade IoT Core new application, including:

* [Creating registries and devices](https://docs.clearblade.com/iotcore/creating-registries-and-devices.md)

* [Sending data using MQTT](https://docs.clearblade.com/iotcore/publishing-over-mqtt.md)

## [Reference](https://docs.clearblade.com/iotcore/reference.md)

How to call into the ClearBlade IoT Core APIs for real-time integration

## [Resources](https://docs.clearblade.com/iotcore/resources.md)

Information to put the service into your business

---
language: "en"
---
# Admin and regional API differences

## Admin API

### Calling admin API

The URL, systemKey, and token this endpoint requires are obtained differently than others. To get those, do the following:

1. Click the Select project drop-down at the top of the IoT Core UI.

2. Click the Edit icon (pencil) next to the desired project.

3. Go to the SERVICE ACCOUNTS tab.

4. If a service account already exists, select it and choose DOWNLOAD CREDENTIALS. If a service account does not exist, create it and select DOWNLOAD CREDENTIALS.

5. A JSON file will be downloaded to your local machine. Open the file with an editor. Use the systemKey, token, and URL from the file as needed below.

### Admin APIs

#### [projects.locations.registries](https://docs.clearblade.com/iotcore/projects-locations-registries.md)

[Create](https://docs.clearblade.com/iotcore/create.md)

[Delete](https://docs.clearblade.com/iotcore/delete.md)

[List](https://docs.clearblade.com/iotcore/list.md)

#### [policy](https://docs.clearblade.com/iotcore/policy.md)

[queryGrantableRoles](https://docs.clearblade.com/iotcore/querygrantableroles.md)

[getIamPolicy](https://docs.clearblade.com/iotcore/getiampolicy.md)

[setIamPolicy](https://docs.clearblade.com/iotcore/setiampolicy.md)

[testIamPermissions](https://docs.clearblade.com/iotcore/testiampermissions.md)

#### [miscellaneous](https://docs.clearblade.com/iotcore/miscellaneous.md)

[Get registry credentials](https://docs.clearblade.com/iotcore/getregistrycredentials.md)

[Get project credentials](https://docs.clearblade.com/iotcore/getprojectcredentials.md)

[Update project credentials](https://docs.clearblade.com/iotcore/updateprojectcredentials.md)

## Regional API

### Calling regional API

You can find the URL, SystemKey, and token required in the call by clicking API Keys (key icon) at the top-right of the Registry Details page:  
![Screenshot from 2025-11-20 06-46-53-20251120-144653.png](https://docs.clearblade.com/__attachments/a_f85096a00866da65a81fba66fbd97212a69a0be3ccc0e68766a89fa7940cb104/Screenshot%20from%202025-11-20%2006-46-53-20251120-144653.png?cb=e2f52456f2d412bffacbf23e82803c14)

The URL, System Key and Token\* for calling Regional APIs are found in the Registry API Keys section:  
![image-20251120-183435.png](https://docs.clearblade.com/__attachments/a_7a16ca0b961af5bd1f668c6b79a5ef078b41f1d00aa3d0dbc5977a3d652422b5/image-20251120-183435.png?cb=630ac21917fd1014e7f8b08df5db5afc)

### Regional APIs

#### [projects.locations.registries](https://docs.clearblade.com/iotcore/projects-locations-registries.md)

[Bind](https://docs.clearblade.com/iotcore/binddevicetogateway.md)

[Get](https://docs.clearblade.com/iotcore/get.md)

[Patch](https://docs.clearblade.com/iotcore/patch.md)

[Unbind](https://docs.clearblade.com/iotcore/unbinddevicefromgateway.md)

#### [projects.locations.registries.devices](https://docs.clearblade.com/iotcore/projects-locations-registries-devices.md)

[Create](https://docs.clearblade.com/iotcore/create-projects-locations-registries-devices.md)

[Delete](https://docs.clearblade.com/iotcore/delete-projects-locations-registries-devices.md)

[Get](https://docs.clearblade.com/iotcore/get-projects-locations-registries-devices.md)

[List](https://docs.clearblade.com/iotcore/list-projects-locations-registries-devices.md)

[Modify](https://docs.clearblade.com/iotcore/modifycloudtodeviceconfig-projects-locations-regis.md)

[Patch](https://docs.clearblade.com/iotcore/patch-projects-locations-registries-devices.md)

[Send command](https://docs.clearblade.com/iotcore/sendcommandtodevice-projects-locations-registries-.md)

#### [projects.locations.registries.devices.configVersions](https://docs.clearblade.com/iotcore/projects-locations-registries-devices-configversio.md)

[List](https://docs.clearblade.com/iotcore/list-project-locations-registies-devices-configver.md)

#### [projects.locations.registries.devices.states](https://docs.clearblade.com/iotcore/projects-locations-registries-devices-states.md)

[List](https://docs.clearblade.com/iotcore/list-projects-locations-registies-devices-states.md)

#### [projects.locations.registries.devices: cloudiotdevice](https://docs.clearblade.com/iotcore/projects-locations-registries-devices-cloudiotdevi.md)

[Configuration](https://docs.clearblade.com/iotcore/getconfig-project-locations-registries-devices.md)\*

[Publish event](https://docs.clearblade.com/iotcore/publishevent-projects-locations-registries-devices.md)\*

[Set state](https://docs.clearblade.com/iotcore/setstate-projects-locations-registries-devices.md)\*

### Credentials for APIs called by devices

\*The marked APIs are ones called by devices rather than users. For those, note the following:

1. In IoT Core **Enterprise** the token shown under API Keys CANNOT be used to call those APIs. Instead, the value of the **ClearBlade-UserToken** header MUST be a JWT specific to the device generated as shown [here](https://docs.clearblade.com/iotcore/using-json-web-tokens.md). Pay attention to the claims required for HTTP calls when generating the JWT.

2. In IoT Core **Standard** the value of the **ClearBlade-UserToken** header can EITHER be the JWT or the token found under API Keys. The JWT is recommended for security.

---
language: "en"
---
# All concepts

## [ClearBlade IoT Core overview](https://docs.clearblade.com/iotcore/clearblade-iot-core-overview.md)

[Understand key concepts, service components, and data flow.](https://docs.clearblade.com/iotcore/clearblade-iot-core-overview.md)

## [Device security](https://docs.clearblade.com/iotcore/device-security.md)

[Learn about device security and get recommendations.](https://docs.clearblade.com/iotcore/device-security.md)

## [MQTT and HTTP protocols](https://docs.clearblade.com/iotcore/protocols-mqtt-and-http.md)

[Compare the two ClearBlade IoT Core protocol bridges.](https://docs.clearblade.com/iotcore/protocols-mqtt-and-http.md)

## [Devices, configuration, and state](https://docs.clearblade.com/iotcore/devices-configuration-and-state.md)

[Get an overview of ClearBlade IoT Core's logical devices, and understand the relationship between device configuration and device state.](https://docs.clearblade.com/iotcore/devices-configuration-and-state.md)

---
language: "en"
---
# Support

* [Getting support](https://docs.clearblade.com/iotcore/getting-support.md)
* [Troubleshooting IoT Core MQTT Device Connection Issues](https://docs.clearblade.com/iotcore/troubleshooting-iot-core-mqtt-device-connection-issues.md)
* [Status](https://docs.clearblade.com/iotcore/status.md)

---
language: "en"
---
# Authenticating applications

This page explains how to use user-managed service accounts and their private keys to authenticate an application to the ClearBlade IoT Core API.

You can use applications to administer registries and devices.

## Authenticating using service accounts

We require a Google service account only when you create a project. This talks to Google Pub/Sub, Cloud Logs, and Cloud Monitoring.

A [user-managed service account](https://cloud.google.com/iam/docs/service-accounts#user-%0Amanaged_service_accounts) is a Google account type that represents an application. User-managed service accounts are primarily used for server-to-API authentication.

This page does not describe service accounts created and owned by Google to manage roles and permissions for different services. For example, when you first enable a project's ClearBlade IoT Core API, a new [service account](https://cloud.google.com/iam/docs/service-accounts#google-managed_service_accounts) is automatically assigned a role to enable publishing to Pub/Sub topics. For details, see [Creating a device registry](https://docs.clearblade.com/iotcore/creating-registries-and-devices.md).

ClearBlade IoT Core uses two authentication types. When authenticating devices to ClearBlade IoT Core, you use [private/public key pairs](https://docs.clearblade.com/iotcore/creating-key-pairs.md) and [JSON Web Tokens](https://docs.clearblade.com/iotcore/using-json-web-tokens.md).

You need a service account to call the [getRegistryCredentials endpoint](https://docs.clearblade.com/iotcore/getregistrycredentials.md). You need credentials from a service account to:

1. Call [registriesCreate](https://docs.clearblade.com/iotcore/create.md), [registriesList](https://docs.clearblade.com/iotcore/list.md), and [registriesDelete](https://docs.clearblade.com/iotcore/delete.md). Once you have a service account, you can download those credentials to call these APIs.

2. Call `getRegistryCredentials`. Once you have a registry's credentials, you can use them to call all other APIs. E.g., [registriesGet](https://docs.clearblade.com/iotcore/get.md), [registriesPatch](https://docs.clearblade.com/iotcore/patch.md), [devicesList](https://docs.clearblade.com/iotcore/list-projects-locations-registries-devices.md), etc.

The SDKs handle calling `getRegistryCredentials`, so you just have to supply a service account's credentials.

The system key, token, and URL (registry keys) are from getRegistryCredentials. They can call the getRegistryCredentials API, and those credentials are used to talk to the registry and its regional APIs.

You can access the API page by going to the registry list, clicking a registry, and clicking the key icon on the top right.

This API keys page calls getRegistryCredentials:  
![image-20240129-183019.png](https://docs.clearblade.com/__attachments/a_c2f69b8b5f2109544c809f3add3421453477fb1465f975cc603a0b52f3f92836/image-20240129-183019.png?cb=c7fd4783f339118bf7b4bf6a7d64e320)

---
language: "en"
---
# bindDeviceToGateway

Associates the device with the gateway.  
Note: This is a [regional API](https://docs.clearblade.com/iotcore/admin-and-regional-api-differences.md#RegionalAPI).

You can find the URL, SystemKey, and token required in the call by clicking API Keys (key icon) at the top-right of the Registry Details page. Use the Registry Keys section.

## HTTP request

`POST {URL}/api/v/4/webhook/execute/{SystemKey}/cloudiot`

### Query parameters

|                                                                 Parameters                                                                  ||
|----------|-----------------------------------------------------------------------------------------------------------------------------------|
| `parent` | `string` The registry name. For example, `projects/example-project/locations/us-central1/registries/my-registry` OR `my-registry` |
| `method` | `string` Value must be `bindDeviceToGateway`                                                                                      |

### Header parameters

|                                           Parameters                                           ||
|------------------------|------------------------------------------------------------------------|
| `ClearBlade-UserToken` | See the note at the start of this document on where to find the token. |

### Request body

The request body contains data with this structure:  

|             JSON representation             |
|---------------------------------------------|
| { "gatewayId": string, "deviceId": string } |

|                                                                               Fields                                                                               ||
|-------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
| `gatewayId` | `string` The `gatewayId` value can be the device numeric ID or the user-defined device identifier.                                                    |
| `deviceId`  | `string` The device to associate with the specified gateway. The `deviceId` value can be the device numeric ID or the user-defined device identifier. |

### Response status codes

| Code | Meaning |
|------|---------|
| 200  | Success |

### Response body

If successful, the response body will be empty.

#### Example curl

`curl 'https://us-central1.clearblade.com/api/v/4/webhook/execute/aae9b9b30c8aa4e49081c7eeb9bb07/cloudiot?method=bindDeviceToGateway&parent=test-reg' -X POST -H 'ClearBlade-UserToken: {Token}' -d '{"gatewayId": "test-gateway-1", "deviceId": "test-dev-1"}'`

Using the instructions at the start of this document, replace the following: `https://us-central1.clearblade.com` with your URL. `aae9b9b30c8aa4e49081c7eeb9bb07` with your SystemKey. {Token} with your token.

Set the `gatewayId` and `deviceId` values appropriately.

---
language: "en"
---
# BindDeviceToGatewayResponse

Response for `registries.bindDeviceToGateway`.

---
language: "en"
---
# ClearBlade IoT Core overview

## Key concepts

Internet of Things (IoT)

A collective term for the physical objects connected to the internet (directly or indirectly) that can exchange data without user involvement.

[Device](https://docs.clearblade.com/iotcore/devices-configuration-and-state.md)

A Thing in the Internet of Things. It is a processing unit capable of connecting to the internet and exchanging data with the cloud. Devices are often called smart devices or connected devices. They communicate telemetry and state data.

Telemetry

All event data (for example, environment measurements) sent from devices to the cloud. This data is called telemetry event data. You can use [Google Cloud Smart Analytics](https://cloud.google.com/solutions/smart-analytics) to analyze it.

[Device state](https://docs.clearblade.com/iotcore/getting-device-state.md)

An arbitrary, user-defined data blob that describes the device's current status. Device state data can be structured or unstructured. It flows only in the device-to-cloud direction.

[Device configuration](https://docs.clearblade.com/iotcore/devices-configuration-and-state.md#Devices,configuration,andstate-Deviceconfiguration)

An arbitrary, user-defined data blob used to modify a device's settings. Configuration data can be structured or unstructured. It flows only in the cloud-to-device direction.

[Device registry](https://docs.clearblade.com/iotcore/devices-configuration-and-state.md#Devices,configuration,andstate-Deviceregistries)

A device container with shared properties. You register a device with a service (like ClearBlade IoT Core) to manage it.

Device manager

The service you use to monitor device health and activity, update device configurations, and manage credentials and authentication.

[MQTT](https://docs.clearblade.com/iotcore/protocols-mqtt-and-http.md)

An industry-standard IoT protocol (Message Queue Telemetry Transport). [MQTT](http://mqtt.org/faq) is a publish/subscribe (Pub/Sub) messaging protocol.

## Components

ClearBlade IoT Core's main components are the device manager and protocol bridges.

* A device manager registers devices with the service so you can monitor and configure them.

* MQTT and HTTP protocol bridges are used by devices to connect to the Google Cloud Platform.

Device telemetry data is forwarded to a Google Cloud [Pub/Sub](https://cloud.google.com/pubsub) topic, which can be used to trigger Google [Cloud Functions](https://cloud.google.com/functions). You can also perform streaming analysis with Google Cloud [Dataflow](https://cloud.google.com/dataflow) or custom analysis with your subscribers.

## Quotas and limits

ClearBlade IoT Core enforces [quotas and limits](https://docs.clearblade.com/iotcore/quotas-and-limits.md) on a per-project basis.

---
language: "en"
---
# ClearBlade maintenance windows

Occasionally, ClearBlade will perform maintenance during a weekly maintenance window. Planned maintenance will be scheduled and published at [status.clearblade.com](http://status.clearblade.com/). We encourage all ClearBlade users to subscribe.

## Maintenance frequency

ClearBlade will perform scheduled maintenance once a month at most. All planned maintenance will be documented on ClearBlade's [status page](http://status.clearblade.com/), and planned maintenance events will be announced seven days before their occurrence.

## Maintenance windows

To better meet the needs of the regions serviced, ClearBlade provides regional maintenance windows. ClearBlade will use these instead of the current global window where possible. The regional windows are:

* US-Central1: 23:00 - 24:00 CT (Central Time) / 5:00 - 6:00 UTC

* Europe-West1: 23:00 - 24:00 CET (Central European Time) / 22:00 - 23:00 UTC

* Asia-East1: 23:00 - 24:00 CST (China Standard Time) / 15:00 - 16:00 UTC

* Global Window: 15:00 - 16:00 UTC (Coordinated Universal Time)

---
language: "en"
---
# cloudiot

* [projects.locations.registries](https://docs.clearblade.com/iotcore/projects-locations-registries.md)
* [projects.locations.registries.devices](https://docs.clearblade.com/iotcore/projects-locations-registries-devices.md)
* [projects.locations.registries.devices.configVersions](https://docs.clearblade.com/iotcore/projects-locations-registries-devices-configversio.md)
* [projects.locations.registries.devices.states](https://docs.clearblade.com/iotcore/projects-locations-registries-devices-states.md)
* [BindDeviceToGatewayResponse](https://docs.clearblade.com/iotcore/binddevicetogatewayresponse.md)
* [GatewayListOptions](https://docs.clearblade.com/iotcore/gatewaylistoptions.md)
* [ListDeviceConfigVersionsResponse](https://docs.clearblade.com/iotcore/listdeviceconfigversionsresponse.md)
* [ListDevicesResponse](https://docs.clearblade.com/iotcore/listdevicesresponse.md)
* [ListDeviceStatesResponse](https://docs.clearblade.com/iotcore/listdevicestatesresponse.md)
* [LogLevel](https://docs.clearblade.com/iotcore/loglevel.md)
* [SendCommandToDeviceResponse](https://docs.clearblade.com/iotcore/sendcommandtodeviceresponse.md)
* [UnbindDeviceFromGatewayResponse](https://docs.clearblade.com/iotcore/unbinddevicefromgatewayresponse.md)

## API

bookmark_border

Registers and manages IoT devices that connect to the Google Cloud Platform.

### REST resource: [v1.projects.locations.registries](https://docs.clearblade.com/iotcore/projects-locations-registries.md)

|                                                                                                   Methods                                                                                                    ||
|----------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------|
| [bindDeviceToGateway](https://docs.clearblade.com/iotcore/binddevicetogateway.md)         | `POST /v1/{parent=projects/*/locations/*/registries/*}:bindDeviceToGateway` Associates the device with the gateway                           |
| [create](https://docs.clearblade.com/iotcore/create.md)                                   | `POST /v1/{parent=projects/*/locations/*}/registries` Creates a device registry                                                              |
| [delete](https://docs.clearblade.com/iotcore/delete.md)                                   | `DELETE /v1/{name=projects/*/locations/*/registries/*}` Deletes a device registry configuration                                              |
| [get](https://docs.clearblade.com/iotcore/get.md)                                         | `GET /v1/{name=projects/*/locations/*/registries/*}` Gets a device registry configuration                                                    |
| [getIamPolicy](https://docs.clearblade.com/iotcore/getiampolicy.md)                       | `POST /v1/{resource=projects/*/locations/*/registries/*}:getIamPolicy` Gets the resource's access control policy                             |
| [list](https://docs.clearblade.com/iotcore/list.md)                                       | `GET /v1/{parent=projects/*/locations/*}/registries` Lists device registries                                                                 |
| [patch](https://docs.clearblade.com/iotcore/patch.md)                                     | `PATCH /v1/{deviceRegistry.name=projects/*/locations/*/registries/*}` Updates a device registry configuration                                |
| [setIamPolicy](https://docs.clearblade.com/iotcore/setiampolicy.md)                       | `POST /v1/{resource=projects/*/locations/*/registries/*}:setIamPolicy` Sets the access control policy on the specified resource              |
| [testIamPermissions](https://docs.clearblade.com/iotcore/testiampermissions.md)           | `POST /v1/{resource=projects/*/locations/*/registries/*}:testIamPermissions` Returns permissions that a caller has on the specified resource |
| [unbindDeviceFromGateway](https://docs.clearblade.com/iotcore/unbinddevicefromgateway.md) | `POST /v1/{parent=projects/*/locations/*/registries/*}:unbindDeviceFromGateway` Deletes the association between the device and the gateway   |

### REST resource: [v1.projects.locations.registries.devices](https://docs.clearblade.com/iotcore/projects-locations-registries-devices.md)

|                                                                                                                                          Methods                                                                                                                                          ||
|---------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [create](https://docs.clearblade.com/iotcore/create-projects-locations-registries-devices.md)                          | `POST /v1/{parent=projects/*/locations/*/registries/*}/devices` Creates a device in a device registry                                                                                        |
| [delete](https://docs.clearblade.com/iotcore/delete-projects-locations-registries-devices.md)                          | `DELETE /v1/{name=projects/*/locations/*/registries/*/devices/*}` Deletes a device                                                                                                           |
| [get](https://docs.clearblade.com/iotcore/get-projects-locations-registries-devices.md)                                | `GET /v1/{name=projects/*/locations/*/registries/*/devices/*}` Gets a device's details                                                                                                       |
| [list](https://docs.clearblade.com/iotcore/list-projects-locations-registries-devices.md)                              | `GET /v1/{parent=projects/*/locations/*/registries/*}/devices` List devices in a device registry                                                                                             |
| [modifyCloudToDeviceConfig](https://docs.clearblade.com/iotcore/modifycloudtodeviceconfig-projects-locations-regis.md) | `POST /v1/{name=projects/*/locations/*/registries/*/devices/*}:modifyCloudToDeviceConfig` Modifies the device's configuration, which is eventually sent from the ClearBlade IoT Core servers |
| [patch](https://docs.clearblade.com/iotcore/patch-projects-locations-registries-devices.md)                            | `PATCH /v1/{device.name=projects/*/locations/*/registries/*/devices/*}` Updates a device                                                                                                     |
| [sendCommandToDevice](https://docs.clearblade.com/iotcore/sendcommandtodevice-projects-locations-registries-.md)       | `POST /v1/{name=projects/*/locations/*/registries/*/devices/*}:sendCommandToDevice` Sends a command to the specified device                                                                  |

### REST resource: [v1.projects.locations.registries.devices.configVersions](https://docs.clearblade.com/iotcore/projects-locations-registries-devices-configversio.md)

|                                                                                                                      Methods                                                                                                                      ||
|------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [list](https://docs.clearblade.com/iotcore/list-project-locations-registies-devices-configver.md) | `GET /v1/{name=projects/*/locations/*/registries/*/devices/*}/configVersions` Lists the device configuration's last few versions in descending order (i.e., newest first) |

### REST resource: [v1.projects.locations.registries.devices.states](https://docs.clearblade.com/iotcore/projects-locations-registries-devices-states.md)

|                                                                                                             Methods                                                                                                             ||
|----------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|
| [list](https://docs.clearblade.com/iotcore/list-projects-locations-registies-devices-states.md) | `GET /v1/{name=projects/*/locations/*/registries/*/devices/*}/states` Lists the device state's last few versions in descending order (i.e., newest first) |

---
language: "en"
---
# cloudiotdevice

* [projects.locations.registries.devices: cloudiotdevice](https://docs.clearblade.com/iotcore/projects-locations-registries-devices-cloudiotdevi.md)

Registers and manages IoT devices that connect to the Google Cloud Platform.

## REST Resource: [v1.projects.locations.registries.devices](https://docs.clearblade.com/iotcore/projects-locations-registries-devices-cloudiotdevi.md)

|                                                                                              Methods                                                                                               ||
|--------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|
| [getConfig](https://docs.clearblade.com/iotcore/getconfig-project-locations-registries-devices.md)        | `GET /v1/{name=projects/*/locations/*/registries/*/devices/*}/config` Gets the device's configuration.             |
| [publishEvent](https://docs.clearblade.com/iotcore/publishevent-projects-locations-registries-devices.md) | `POST /v1/{name=projects/*/locations/*/registries/*/devices/*}:publishEvent` Publishes a device's telemetry event. |
| [setState](https://docs.clearblade.com/iotcore/setstate-projects-locations-registries-devices.md)         | `POST /v1/{name=projects/*/locations/*/registries/*/devices/*}:setState` Sets the device's state.                  |

---
language: "en"
---
# Concepts

* [All concepts](https://docs.clearblade.com/iotcore/all-concepts.md)
* [ClearBlade IoT Core overview](https://docs.clearblade.com/iotcore/clearblade-iot-core-overview.md)
* [Device security](https://docs.clearblade.com/iotcore/device-security.md)
* [MQTT and HTTP protocols](https://docs.clearblade.com/iotcore/protocols-mqtt-and-http.md)
* [Devices, configuration, and state](https://docs.clearblade.com/iotcore/devices-configuration-and-state.md)
* [Identity and Access Management (IAM)](https://docs.clearblade.com/iotcore/identity-and-access-management-iam.md)
* [Topics Overview (MQTT and Google PubSub)](https://docs.clearblade.com/iotcore/topics-overview-mqtt-and-google-pubsub.md)

---
language: "en"
---
# Load balancer configuration

ClearBlade provides a default HAProxy configuration to allow customers to do their TLS termination for MQTT device connections.

The default load balancer using HAProxy runs on a Google Cloud compute instance group. To install this load balancer, you need the appropriate permissions to create compute instances and configure their network traffic.

The Terraform scripts to run are available [here](https://github.com/ClearBlade/iot-core-external-proxy). Unpack the scripts on a local compute instance.

---
language: "en"
---
# Configuring devices

With ClearBlade IoT Core, you can control a device by modifying its configuration. A device configuration is an arbitrary, user-defined data blob. After a configuration has been applied to a device, the device can report its state to ClearBlade IoT Core.

Device configuration works differently in the MQTT and HTTP bridges. See below for details.

For more information, see [Devices, configuration, and state](https://docs.clearblade.com/iotcore/devices-configuration-and-state.md).

## Limits

Configuration updates are limited to 1 update per second per device. However, for best results, device configuration should be updated much less often --- at most, once every 10 seconds.

## Protocol differences

### MQTT

Devices using MQTT can subscribe to a special MQTT topic for configuration updates:

    /devices/{device-id}/config

When a device subscribes to the configuration topic, the MQTT bridge responds with an MQTT SUBACK message, which contains the config topic's granted QoS (0 or 1) or 128 if an error occurs.

After initially subscribing, the device receives the latest configuration in a message's payload. It will receive additional configuration updates as they are pushed to ClearBlade IoT Core.

#### Retrieving configuration updates on a device over MQTT code samples

##### Node.js

    // const deviceId = `myDevice`;
    // const registryId = `myRegistry`;
    // const region = `us-central1`;
    // const algorithm = `RS256`;
    // const privateKeyFile = `./rsa_private.pem`;
    // const serverCertFile = `./roots.pem`;
    /**
     * @see https://clearblade.atlassian.net/wiki/spaces/IC/pages/2210299905/Retargeting+Devices#Production-URL-%2F-URLs for a full URL list
     */
    // const mqttBridgeHostname = `us-central1-mqtt.clearblade.com`;
    // const mqttBridgePort = 8883;
    // const messageType = `events`;
    // const numMessages = 5;

    // The mqttClientId is a unique string that identifies this device. For ClearBlade
    // IoT Core, it must be in the format below.
    const mqttClientId = `projects/${projectId}/locations/${region}/registries/${registryId}/devices/${deviceId}`;

    // With ClearBlade IoT Core, the username field is ignored, however it must be
    // non-empty. The password field is used to transmit a JWT to authorize the
    // device. The "mqtts" protocol causes the library to connect using SSL, which
    // is required for Cloud IoT Core.
    const connectionArgs = {
      host: mqttBridgeHostname,
      port: mqttBridgePort,
      clientId: mqttClientId,
      username: "unused",
      password: createJwt(projectId, privateKeyFile, algorithm),
      protocol: "mqtts",
      secureProtocol: "TLSv1_2_method",
      ca: [readFileSync(serverCertFile)],
    };

    // Create a client, and connect to the ClearBlade MQTT bridge.
    const iatTime = parseInt(Date.now() / 1000);
    const client = mqtt.connect(connectionArgs);

    // Subscribe to the /devices/{device-id}/config topic to receive config updates.
    // Config updates are recommended to use QoS 1 (at least once delivery)
    client.subscribe(`/devices/${deviceId}/config`, { qos: 1 });

    // Subscribe to the /devices/{device-id}/commands/# topic to receive all
    // commands or to the /devices/{device-id}/commands/<subfolder> to just receive
    // messages published to a specific commands folder; we recommend you use
    // QoS 0 (at most once delivery)
    client.subscribe(`/devices/${deviceId}/commands/#`, { qos: 0 });

    // The MQTT topic that this device will publish data to. The MQTT topic name is
    // required to be in the format below. The topic name must end in 'state' to
    // publish state and 'events' to publish telemetry. This differs from the
    // device registry's Cloud Pub/Sub topic.
    const mqttTopic = `/devices/${deviceId}/${messageType}`;

    client.on("connect", (success) => {
      console.log("connect");
      if (!success) {
        console.log("Client not connected...");
      } else if (!publishChainInProgress) {
        publishAsync(mqttTopic, client, iatTime, 1, numMessages, connectionArgs);
      }
    });

    client.on("close", () => {
      console.log("close");
      shouldBackoff = true;
    });

    client.on("error", (err) => {
      console.log("error", err);
    });

    client.on("message", (topic, message) => {
      let messageStr = "Message received: ";
      if (topic === `/devices/${deviceId}/config`) {
        messageStr = "Config message received: ";
      } else if (topic.startsWith(`/devices/${deviceId}/commands`)) {
        messageStr = "Command message received: ";
      }

      messageStr += Buffer.from(message, "base64").toString("ascii");
      console.log(messageStr);
    });

    client.on("packetsend", () => {
      // Logging packet send is very verbose
    });

    // Once all the messages have been published, the connection to ClearBlade
    // IoT Core will be closed, and the process will exit. See the publishAsync method.

##### Python

    import paho.mqtt.client as mqtt
    import datetime
    import ssl
    import jwt

    def create_jwt(project_id, private_key_file, algorithm):
        """Creates a JWT (https://jwt.io) to establish an MQTT connection.
        Args:
         project_id: The cloud project ID this device belongs to
         private_key_file: A path to a file containing an RSA256 or
                 ES256 private key.
         algorithm: The encryption algorithm to use (RS256 or ES256)
        Returns:
            A JWT generated from the given project_id and private key, which
            expires in 20 minutes. After 20 minutes, your client will be
            disconnected, and a new JWT must be generated.
        Raises:
            ValueError: If the private_key_file does not contain a known key.
        """

        token = {
            # The time that the token was issued at
            "iat": datetime.datetime.now(tz=datetime.timezone.utc),
            # The time the token expires.
            "exp": datetime.datetime.now(tz=datetime.timezone.utc) + datetime.timedelta(minutes=20),
            # The audience field should always be set to the GCP project id.
            "aud": project_id,
        }

        # Read the private key file.
        with open(private_key_file, "r") as f:
            private_key = f.read()

        print(
            "Creating JWT using {} from private key file {}".format(
                algorithm, private_key_file
            )
        )

        return jwt.encode(token, private_key, algorithm=algorithm)

    def error_str(rc):
        """Convert a Paho error to a human readable string."""
        return "{}: {}".format(rc, mqtt.error_string(rc))

    def on_connect(unused_client, unused_userdata, unused_flags, rc):
        """Callback for when a device connects."""
        print("on_connect", mqtt.connack_string(rc))

        # After a successful connect, reset backoff time and stop backing off.
        global should_backoff
        global minimum_backoff_time
        should_backoff = False
        minimum_backoff_time = 1

    def on_disconnect(unused_client, unused_userdata, rc):
        """Paho callback for when a device disconnects."""
        print("on_disconnect", error_str(rc))

        # Since a disconnect occurred, the next loop iteration will wait with
        # exponential backoff.
        global should_backoff
        should_backoff = True

    def on_publish(unused_client, unused_userdata, unused_mid):
        """Paho callback when a message is sent to the broker."""
        print("on_publish")

    def on_message(unused_client, unused_userdata, message):
        """Callback when the device receives a message on a subscription."""
        payload = str(message.payload.decode("utf-8"))
        print(
            "Received message '{}' on topic '{}' with Qos {}".format(
                payload, message.topic, str(message.qos)
            )
        )

    def get_client(
        project_id,
        cloud_region,
        registry_id,
        device_id,
        private_key_file,
        algorithm,
        ca_certs,
        mqtt_bridge_hostname,
        mqtt_bridge_port,
    ):
        """Create our MQTT client.

        The client_id is a unique string that identifies this device.
        For ClearBlade IoT Core, it must be in the format below.
        """
        client_id = "projects/{}/locations/{}/registries/{}/devices/{}".format(
            project_id, cloud_region, registry_id, device_id
        )
        print("Device client_id is '{}'".format(client_id))

        client = mqtt.Client(client_id=client_id)

        # With ClearBlade IoT Core, the username field is ignored, and the
        # password field is used to transmit a JWT to authorize the device.
        client.username_pw_set(
            username="unused", password=create_jwt(project_id, private_key_file, algorithm)
        )

        # Enable SSL/TLS support.
        client.tls_set(ca_certs=ca_certs, tls_version=ssl.PROTOCOL_TLSv1_2)

        # Register message callbacks. https://eclipse.org/paho/clients/python/docs/
        # describes additional callbacks that Paho supports. In this example, the
        # callbacks just print to standard out.
        client.on_connect = on_connect
        client.on_publish = on_publish
        client.on_disconnect = on_disconnect
        client.on_message = on_message

        # Connect to the MQTT bridge.
        client.connect(mqtt_bridge_hostname, mqtt_bridge_port)

        # This is the topic on which the device will receive configuration updates.
        mqtt_config_topic = "/devices/{}/config".format(device_id)

        # Subscribe to the config topic.
        client.subscribe(mqtt_config_topic, qos=1)

        # The topic on which the device will receive commands.
        mqtt_command_topic = "/devices/{}/commands/#".format(device_id)

        # Subscribe to the commands topic, QoS 1 enables message acknowledgment.
        print("Subscribing to {}".format(mqtt_command_topic))
        client.subscribe(mqtt_command_topic, qos=0)

        return client

    get_client(
        "YOUR_PROJECT_ID",
        "us-central1",
        "YOUR_REGISTRY_ID",
        "YOUR_DEVICE_ID",
        "YOUR_DEVICE_PRIVATE_KEY_FILE",
        "RS256",
        "DigiCertGlobalRootCA.crt.pem",
        "us-central1-mqtt.clearblade.com",
        8883
    )

### HTTP

Devices must explicitly [request new configurations](https://docs.clearblade.com/iotcore/publishing-over-http.md#Updatingdeviceconfiguration) if you're using the [HTTP bridge](https://docs.clearblade.com/iotcore/publishing-over-http.md).

#### Retrieving configuration updates on a device over HTTP code samples

##### Node.js

    import fetch from 'node-fetch';

    /**
     *
     * @see https://clearblade.atlassian.net/wiki/spaces/IC/pages/2202697766/Authenticating+applications for information on how to obtain your registry's urlBase, systemKey, and authToken
     *
     * @param {string} urlBase
     * @param {string} systemKey
     * @param {string} authToken
     * @param {string} deviceName
     * @param {number} version
     */
    const getConfig = async (urlBase, systemKey, authToken, deviceName, version) => {
      const res = await fetch(
        `${urlBase}/api/v/4/webhook/execute/${systemKey}/cloudiotdevice_devices?name=${encodeURIComponent(
          deviceName
        )}&localVersion=${version}`,
        {
          method: 'GET',
          headers: {
            'ClearBlade-UserToken': authToken
          }
        }
      );
      const data = await res.json();
      console.log('Received config', data);
    };

##### Python

    # see https://clearblade.atlassian.net/wiki/spaces/IC/pages/2202697766/Authenticating+applications

    import requests
    import urllib.parse

    def get_config(urlBase, systemKey, authToken, deviceName, version):
      url = f"{urlBase}/api/v/4/webhook/execute/{systemKey}/cloudiotdevice_devices"
      headers = { "ClearBlade-UserToken": authToken }
      params = { "name": urllib.parse.quote(deviceName), "localVersion": version }
      response = requests.get(url=url, headers=headers, params=params)
      if response.status_code == 200:
        return response.json()
      else:
        return response.text

    # To obtain the 3 params below see https://clearblade.atlassian.net/wiki/spaces/IC/pages/2202697766/Authenticating+applications
    # urlBase named 'URL'
    # systemKey named 'System Key'
    # authToken named 'Token'
    urlBase = "URL_FOR_YOUR_REGISTRY"
    systemKey = "SYSTEM_KEY_FOR_YOUR_REGISTRY"
    authToken = "TOKEN_FOR_YOUR_REGISTRY"
    deviceName = "your-device-name"
    version = "LOCAL_CONFIG_VERSION_OF_YOUR_DEVICE"
    config_resp = get_config(urlBase, systemKey, authToken, deviceName, version)
    print(config_resp)

## Updating and reverting device configuration

### Console

#### Update the device configuration

1. Go to the ClearBlade IoT Core console's [Registries](https://iot.clearblade.com/iot-core/app/registries) page.

2. Click the registry ID that contains the device.

3. In the left registry menu, click Devices.

4. Click the device ID whose configuration you want to update.

5. Click the ellipsis (⋮) at the top-right of the page, then select Update device.

6. Select the configuration's format (text, Base64) and paste the data in the configuration box.

7. Click SEND TO DEVICE.

See [Protocol differences](https://docs.clearblade.com/iotcore/configuring-devices.md#Configuringdevices-Protocoldifferences) for how devices receive the new configuration.

#### Revert the device configuration to a previous version

1. Go to the Google Cloud console's Registries page.

2. Click the registry ID that contains the device whose configuration you want to revert.

3. In the left registry menu, click Devices.

4. Click the device ID whose configuration you wish to revert.

5. Click CONFIGURATION \& STATE. Use the checkboxes to display configuration history, state history, or both. By default, both are shown.

6. Click a row to get the full configuration or state data in JSON and the timestamp and version.

7. Click COMPARE to compare the configuration data with the state data. This view can help you debug configurations and ensure devices have acknowledged specific configuration versions if you use MQTT (the HTTP bridge does not support configuration acknowledgments).

8. Click the version you want to revert to. Select Text in the Format list to see a text version of the configuration details.

9. Click Revert, ensure you've selected the correct version, then click Revert.

### API

To update or revert device configuration via the API, use the device [modifyCloudToDeviceConfig](https://docs.clearblade.com/iotcore/modifycloudtodeviceconfig-projects-locations-regis.md) method, specifying the new or previous configuration in the `config` field. You can specify a configuration when [creating a device](https://docs.clearblade.com/iotcore/create-projects-locations-registries-devices.md) and then use `modifyCloudToDeviceConfig` to change it later.

#### Updating a device's configuration code samples

##### Node.js

    // const cloudRegion = 'us-central1';
    // const deviceId = 'my-device';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    // const data = 'test-data';
    // const version = 0;

    import { DeviceManagerClient } from '@clearblade/iot';

    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function modifyCloudToDeviceConfig() {
      // Construct request
      const formattedName = iotClient.devicePath(projectId, cloudRegion, registryId, deviceId);

      const binaryData = Buffer.from(data).toString('base64');
      const request = {
        name: formattedName,
        versionToUpdate: version,
        binaryData: binaryData
      };

      const [response] = await iotClient.modifyCloudToDeviceConfig(request);
      console.log('Success:', response);
    }

    modifyCloudToDeviceConfig();

##### C#

    if (bPatchDeviceConfig)
    {
        logger.LogInformation("Update configuration of a device");

        // While running this sample, it is assumed that device with name
        // "Sample-New-Device" exists

        string name = "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry/devices/Sample-New-Device";

        var result = await mClient.GetDevice(4, name);
        if (!result.Item1 || (result.Item2 == null))
            logger.LogError("Failed to get a device configuration");
        else
        {
            logger.LogInformation("Successfully obtained the device configuration");

            // Use the obtained information
            string updateMask = "metadata";
            string pubKey = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5P0Z4OUD5PSjri8xexGo\n6eQ39NGyQbXamIgWAwvnAs/oDRVqEejE2nwDhnpykaCGLkuDEN0LPd2wF+vC2Cq3\nY3YvkJh71IkjuAjMZQ+00CXdezfCjmTtEpMCNA3cV+G1g6uIcdEpHKs0YHfC9CFQ\nrjkc7tl3idmcQLngIov/gsFY7D1pbOgkCVVcZCRLgsdFfhCUYwYCvdEVJP3w+5mG\nybvmhNRbbFG7eG3+hmZoOg0h3f6r2fqgSx6l0+Z3D77SRT6lBEHvGDlxb08ASeuE\n0SJAc6PdAKd3FDqdZok4z1qJsgMqtU/ZGJJG54pNECWmhoOar+aQmmqnZ6kGQ5cn\nEwIDAQAB\n-----END PUBLIC KEY-----\n";
            result.Item2.credentials.Add(new core.Models.Credential
            {
                expirationTime = "",
                publicKey = new PublicKey
                {
                    format = "RSA_PEM",
                    key = pubKey
                }
            });

            result = await mClient.PatchDevice(4, name, updateMask, result.Item2);

            if (!result.Item1 || (result.Item2 == null))
                logger.LogError("Failed to update a device configuration");
        }
    }

##### Python

    import os
    import base64
    from clearblade.cloud import iot_v1

    def modify_cloud_to_device_config():
      project_id = 'YOUR_PROJECT_ID'
      cloud_region = 'us-central1'
      registry_id = 'your-registry-id'
      device_id = 'your-device-id'
      
      client = iot_v1.DeviceManagerClient()

      device_path = client.device_path(project_id, cloud_region, registry_id, device_id)

      # versionToUpdate MUST be the latest version. Setting this to 0 implies the latest version
      # since actual versions start with 1. If versionToUpdate is NOT 0 or the latest version, an
      # error is thrown.
      versionToUpdate = 0
      data = b"test-config-data"

      request = iot_v1.ModifyCloudToDeviceConfigRequest(
        name=device_path,
        version_to_update=versionToUpdate,
        binary_data=base64.b64encode(data)
      )

      client.modify_cloud_to_device_config(request=request)

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    modify_cloud_to_device_config()

##### Go

    // setConfig sends a configuration change to a device.
    func setConfig(w io.Writer, projectID string, region string, registryID string, deviceID string, configData string) (*iot.DeviceConfig, error) {
        ctx := context.Background()
        service, err := iot.NewService(ctx)

        if err != nil {
            return nil, err
        }

        req := iot.ModifyCloudToDeviceConfigRequest{
            BinaryData: b64.StdEncoding.EncodeToString([]byte(configData)),
        }

        path := fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", projectID, region, registryID, deviceID)
        response, err := service.Projects.Locations.Registries.Devices.ModifyCloudToDeviceConfig(path, &req).Do()
        if err != nil {
            return nil, err
        }

        fmt.Fprintf(w, "Config set!\nVersion now: %d\n", response.Version)

        return response, nil
    }

## Reviewing device configuration

### Console

1. Go to the Google Cloud console's Registries page.

2. Click the registry ID that contains the device whose configuration you want to update.

3. In the left registry menu, click Devices.

4. Click the device ID whose configuration you want to update.

5. Click CONFIGURATION \& STATE. Use the checkboxes to display configuration history, state history, or both. By default, both are shown.

6. Click a row to get the full configuration or state data in JSON and the timestamp and version.

7. Click COMPARE to compare the configuration data with the state data. This view can help you debug configurations and ensure devices have acknowledged specific configuration versions if you use MQTT (the HTTP bridge does not support configuration acknowledgments).

To review device configuration via the API, use a device [configVersions.list](https://docs.clearblade.com/iotcore/list-project-locations-registies-devices-configver.md) request.

#### Review a device's configuration code samples

##### Node.js

    // const cloudRegion = 'us-central1';
    // const deviceId = 'my-device';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    import { DeviceManagerClient } from '@clearblade/iot';

    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function listDeviceConfigVersions() {
      // Construct request
      const devicePath = iotClient.devicePath(projectId, cloudRegion, registryId, deviceId);

      const [response] = await iotClient.listDeviceConfigVersions({
        name: devicePath
      });
      const configs = response.deviceConfigs;

      if (configs.length === 0) {
        console.log(`No configs for device: ${deviceId}`);
      } else {
        console.log('Configs:');
      }

      for (let i = 0; i < configs.length; i++) {
        const config = configs[i];
        console.log('Config:', config, '\nData:\n', config.binaryData.toString('utf8'));
      }
    }

    listDeviceConfigVersions();

##### C#

    if (bGetDeviceConfig)
    {
        logger.LogInformation("Get configuration of a device");

        // While running this sample, it is assumed that a device with name
        // "Sample-New-Device" exists and the version is updated to "2"

        string name = "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry/Devices/Sample-New-Device";
        string localVersion = "2";

        var result = await mClient.GetDeviceConfig(4, name, localVersion);
        if (!result.Item1 || (result.Item2 == null))
            logger.LogError("Failed to get a device configuration");
        else
        {
            logger.LogInformation("Successfully obtained the device configuration");

            // Use the obtained information
        }
    }

##### Python

    import os
    from clearblade.cloud import iot_v1

    def list_device_config_versions():
      project_id = 'YOUR_PROJECT_ID'
      cloud_region = 'us-central1'
      registry_id = 'your-registry-id'
      device_id = 'your-device-id'
      
      client = iot_v1.DeviceManagerClient()

      device_path = client.device_path(project_id, cloud_region, registry_id, device_id)

      request = iot_v1.ListDeviceConfigVersionsRequest(
        name=device_path,
        numVersions=0
      )

      response = client.list_device_config_versions(request=request)
      configs = response.device_configs

      if (len(configs) == 0):
        print(f"No configs for device: {device_id}")
      else:
        print("Configs:")
      
      for config in configs:
        if config.binary_data is None:
          print(f"version: {config.version}\n\tdata: {None}")
        else:  
          print(f"version: {config.version}\n\tcloudUpdateTime: {config.cloud_update_time}\n\tdata: {config.binary_data}")

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    list_device_config_versions()

##### Go

    // getDeviceConfigs retrieves and lists device configurations.
    func getDeviceConfigs(w io.Writer, projectID string, region string, registryID string, device string) ([]*iot.DeviceConfig, error) {
        ctx := context.Background()
        service, err := iot.NewService(ctx)

        if err != nil {
            return nil, err
        }

        path := fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", projectID, region, registryID, device)
        response, err := service.Projects.Locations.Registries.Devices.ConfigVersions.List(path).Do()
        if err != nil {
            return nil, err
        }

        for _, config := range response.DeviceConfigs {
            fmt.Fprintf(w, "%d : %s\n", config.Version, config.BinaryData)
        }

        return response.DeviceConfigs, nil
    }

---
language: "en"
---
# Configuring devices and getting state

* [Configuring devices](https://docs.clearblade.com/iotcore/configuring-devices.md)
* [Getting device state](https://docs.clearblade.com/iotcore/getting-device-state.md)

---
language: "en"
---
# create

Creates a device registry.  
Note: This is an [admin API](https://docs.clearblade.com/iotcore/admin-and-regional-api-differences.md#Admin-API).

The URL, systemKey, and token this endpoint requires are obtained differently than others. To get those, do the following:

1. Click the Select project drop-down at the top of the IoT Core UI.

2. Click the edit icon ( ![image-20250820-160436.png](https://docs.clearblade.com/__attachments/a_9b7d8364ae867f0ff83c6351a4d816d301aa04b5c2407e71befbde2f8288822f/97d2813b-e223-4c01-9e8f-747a3b32fa53?cb=3fa3c2b962369c28ecd287dd3a331f4c) ) next to the desired project.

3. Go to the SERVICE ACCOUNTS tab.

4. If a service account already exists, select it and choose DOWNLOAD CREDENTIALS. If a service account does not exist, create it and select DOWNLOAD CREDENTIALS.

5. A JSON file will be downloaded to your local machine. Open the file with an editor. Use the systemKey, token, and URL from the file as needed below.

## HTTP request

`POST {url}/api/v/4/webhook/execute/{systemKey}/cloudiot`

### Query parameters

|                                                      Parameters                                                      ||
|----------|------------------------------------------------------------------------------------------------------------|
| `parent` | `string` The project and cloud region path. For example, `projects/example-project/locations/us-central1`. |

### Header parameters

|                                           Parameters                                           ||
|------------------------|------------------------------------------------------------------------|
| `ClearBlade-UserToken` | See the note at the start of this document on where to find the token. |

### Request body

The request body contains a [DeviceRegistry](https://docs.clearblade.com/iotcore/projects-locations-registries.md#Resource:DeviceRegistry) instance.

### Response status codes

| Code | Meaning |
|------|---------|
| 200  | Success |

### Response body

If successful, the response body contains a newly created [DeviceRegistry](https://docs.clearblade.com/iotcore/projects-locations-registries.md#Resource:DeviceRegistry) instance.

#### Example curl

`curl 'https://iot.clearblade.com/api/v/4/webhook/execute/aae9b9b30c8aa4e49081c7eeb9bb07/cloudiot?parent=projects/iot-core-test-363819/locations/us-central1' -H 'ClearBlade-UserToken: {token}' -d '{ "id": "two", "eventNotificationConfigs": [], stateNotificationConfig": {}, "mqttConfig": {}, "httpConfig": {}, "logLevel": "NONE", "credentials": [] }'`

Using the instructions at the start of this document, replace the following: `https://iot.clearblade.com` with your URL. `aae9b9b30c8aa4e49081c7eeb9bb07` with your systemKey. {token} with your token.

This example's body contains a registry object with name and id "two." Replace the registry object with your own.

---
language: "en"
---
# create: projects.locations.registries.devices

Creates a device in a device registry.  
Note: This is a [regional API](https://docs.clearblade.com/iotcore/admin-and-regional-api-differences.md#RegionalAPI).

You can find the URL, SystemKey, and token required in the call by clicking API Keys (key icon) at the top-right of the Registry Details page. Use the Registry Keys section.

## HTTP request

`POST {URL}/api/v/4/webhook/execute/{SystemKey}/cloudiot_devices`

### Query parameters

None

### Header parameters

|                                           Parameters                                           ||
|------------------------|------------------------------------------------------------------------|
| `ClearBlade-UserToken` | See the note at the start of this document on where to find the token. |

### Request body

The request body contains a [device](https://docs.clearblade.com/iotcore/projects-locations-registries-devices.md#Resource:Device) instance.

### Response status codes

| Code | Meaning |
|------|---------|
| 200  | Success |

### Response body

If successful, the response body contains a newly created [device](https://docs.clearblade.com/iotcore/projects-locations-registries-devices.md#Resource:-Device) instance.

#### Example curl

`curl 'https://us-central1.clearblade.com/api/v/4/webhook/execute/aae9b9b30c8aa4e49081c7eeb9bb07/cloudiot_devices' -X POST -H 'ClearBlade-UserToken: {Token}' -d '{"id": "test-device-1", "credentials": [], "config": {}, "metadata": {}, "logLevel": "LOG_LEVEL_UNSPECIFIED"}'`

Using the instructions at the start of this document, replace the following: `https://us-central1.clearblade.com` with your URL. `aae9b9b30c8aa4e49081c7eeb9bb07` with your SystemKey. {Token} with your token.

The item `id` is required in the body. If other items are not provided, they will have default values in the created device. Set the values of `id` and other items appropriately.

---
language: "en"
---
# Creating, configuring, and managing gateways

## Creating or editing a gateway

After you create a gateway, you can't change it to a non-gateway device. Ensure you've [created a registry and a device key pair](https://docs.clearblade.com/iotcore/creating-registries-and-devices.md) before completing the steps below.

### Console

#### Create a new gateway

1. Go to the [Registries](https://iot.clearblade.com/iot-core/app/registries) page. Click a registry ID.

2. On the Registry details page, select **Gateways** , then click the '**+** ' icon (top-right) to create a new gateway.

   ![image-20250828-171151.png](https://docs.clearblade.com/__attachments/a_b01cfe108ae7c9c95a71b2b8bdc26623dde3a2592e96981abf2d5587001fbd60/image-20250828-171151.png?cb=15821c2742a3ac9d63cc1fc03d7b590f)

   ![image-20250828-203846.png](https://docs.clearblade.com/__attachments/a_975799d3ea96b069155d7c8f1092679d2e220fc087725c28eb33142198c331d7/image-20250828-203846.png?cb=27bed1831467cebf41486cf392a8cb87)

<!-- -->

3. Enter a gateway ID that describes the gateway and helps you identify it. **This field cannot be edited later**.

4. For Gateway communication, select **Allow** or **Block**. The latter allows you to block communication when needed, such as when a gateway or one or more devices bound to it are not functioning properly. You'll most likely want to allow communication when creating the gateway. When a gateway is blocked, all devices bound to it are blocked from communicating with ClearBlade IoT Core.

5. Select the public key format that matches this gateway's key pair. Paste the certificate or key in the Public key value field. You can also set the key's expiration date.

6. Select the [authentication method](https://docs.clearblade.com/iotcore/non-gateway-device-authentication.md) to use for devices bound to the gateway.

7. Use the Key and Value fields to add optional [gateway metadata](https://docs.clearblade.com/iotcore/devices-configuration-and-state.md#Devicemetadata), such as a serial number.

8. Click Submit to create the gateway or Update to save changes to an existing gateway.

#### Edit an existing gateway

1. Go to the [Registries](https://iot.clearblade.com/iot-core/app/registries) page.

2. Click the gateway's registry ID.

3. Click Registry details.

4. Select **Gateways**.

5. Click the gateway's ID you want to edit.

6. Click edit icon ( ![image-20240429-185348.png](https://docs.clearblade.com/__attachments/a_bc2c765fbf4214e78a1a763518f1bcc2ac1e761ccd4cfefa97680d6d31729243/9cfbb092-9b8f-4f6d-b5f1-59691d26b44d?cb=7b0ed0726913d8d57bf1d16a8b5e91d2) ) at the top of the page.

   ![image-20250828-171633.png](https://docs.clearblade.com/__attachments/a_8921270ae6d5bce7c6c0326e04d60b2811a1ebf42ac155c003bb0b93600f78af/image-20250828-171633.png?cb=31205dee2a1d965697d4d3bc0197096b)

To add a key to an existing gateway, click Add public key on the Device details page.

### API

Use these methods to create or edit a gateway:

* Device [create](https://docs.clearblade.com/iotcore/create-projects-locations-registries-devices.md) method to add gateways to registries

* Device [patch](https://docs.clearblade.com/iotcore/patch-projects-locations-registries-devices.md) method to edit existing gateways

#### Creating or editing a gateway code samples

##### Node.js

    // const cloudRegion = 'us-central1';
    // const deviceId = 'my-unauth-device';
    // const gatewayId = 'my-gateway';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    // const gatewayAuthMethod = 'ASSOCIATION_ONLY';
    import { DeviceManagerClient } from '@clearblade/iot';

    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function createDevice() {
      // Construct request
      const regPath = iotClient.registryPath(projectId, cloudRegion, registryId);

      console.log('Creating gateway:', gatewayId);

      let credentials = [];

      // if public key format and path are specified, use those
      if (publicKeyFormat && publicKeyFile) {
        credentials = [
          {
            publicKey: {
              format: publicKeyFormat,
              key: readFileSync(publicKeyFile).toString()
            }
          }
        ];
      }

      const device = {
        id: gatewayId,
        credentials: credentials,
        gatewayConfig: {
          gatewayType: 'GATEWAY',
          gatewayAuthMethod: gatewayAuthMethod
        }
      };

      const request = {
        parent: regPath,
        device
      };

      const [response] = await iotClient.createDevice(request);
      console.log('Created device:', response);
    }

    createDevice();

##### C#

    {
        logger.LogInformation("Create a new gateway");

        string id = "Sample-New-Gateway";
        string name = "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry/Devices/Sample-New-Gateway";

        String keyText = File.ReadAllText("path/to/key");

        var credentials = new List<DeviceCredential>
        {
            new DeviceCredential()
            {
                PublicKey = new PublicKeyCredential()
                {
                    Key = keyText,
                    Format = "ES256_PEM"
                },
            }
        };

        var gatewayConfig = new GatewayConfig()
        {
            GatewayType = "GATEWAY",
            GatewayAuthMethod = "ASSOCIATION_ONLY"
        };

        var result = await mClient.CreateDevice(4, id, name, credentials, gatewayConfig);
        if (!result.Item1 || (result.Item2 == null))
            logger.LogError("Failed to create new device");
        else
        {
            logger.LogInformation("Successfully created new device");

            // The result.Item2 object can be used to refer to newly created device
        }
    }

##### Python

    import os
    import io
    from clearblade.cloud import iot_v1

    def create_gateway():
      project_id = 'YOUR_PROJECT_ID'
      cloud_region = 'us-central1'
      registry_id = 'your-registry-id'
      device_id = 'your-device-id'
      gateway_id = 'your-gateway-id'
      public_key_file = 'path/to/ec_public.pem'
      algorithm = 'ES256'
      
      # Check that the gateway doesn't already exist
      exists = False
      client = iot_v1.DeviceManagerClient()

      parent = client.registry_path(project_id, cloud_region, registry_id)

      listDevicesRequest = iot_v1.ListDevicesRequest(parent=parent)
      devices = list(client.list_devices(request=listDevicesRequest))

      for device in devices:
        if device.id == gateway_id:
          exists = True
        print(
          "Device: {} : {} : {} : {}".format(
            device.id, device.num_id, device.config, device.gateway_config
          )
        )

      with io.open(public_key_file) as f:
        public_key = f.read()

      if algorithm == "ES256":
        public_key_format = iot_v1.PublicKeyFormat.ES256_PEM
      else:
        public_key_format = iot_v1.PublicKeyFormat.RSA_X509_PEM

      # TODO: Auth type
      gateway = iot_v1.Device(
        name=gateway_id,
        credentials=[{
          "publicKey": { "format": public_key_format, "key": public_key }
        }],
        gateway_config={
          "gatewayType": "GATEWAY",
          "gatewayAuthMethod": "ASSOCIATION_ONLY",
        }
      )

      if not exists:
        createDeviceRequest = iot_v1.CreateDeviceRequest(
          parent=parent,
          device=gateway
        )
        res = client.create_device(request=createDeviceRequest)
        print("Created Gateway {}".format(res))
      else:
        print("Gateway exists, skipping")

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    create_gateway()

##### Go

    // getDevice retrieves a specific device and prints its details.
    func createGateway(w io.Writer, projectID string, region string, registryID string, gatewayID string, gatewayAuthMethod string, publicKeyPath string) (*iot.Device, error) {
        ctx := context.Background()
        service, err := iot.NewService(ctx)
        if err != nil {
            return nil, err
        }

        keyBytes, err := ioutil.ReadFile(publicKeyPath)
        if err != nil {
            return nil, err
        }

        gateway := &cloudiot.Device{
            Id: gatewayID,
            Credentials: []*cloudiot.DeviceCredential{
                {
                    PublicKey: &cloudiot.PublicKeyCredential{
                        Format: "RSA_X509_PEM",
                        Key:    string(keyBytes),
                    },
                },
            },
            GatewayConfig: &cloudiot.GatewayConfig{
                GatewayType:       "GATEWAY",
                GatewayAuthMethod: gatewayAuthMethod,
            },
        }

        parent := fmt.Sprintf("projects/%s/locations/%s/registries/%s", projectID, region, registryID)
        response, err := service.Projects.Locations.Registries.Devices.Create(parent, gateway).Do()
        if err != nil {
            return nil, err
        }

        fmt.Fprintln(w, "Successfully created gateway:", gatewayID)

        return response, nil
    }

See [Creating or editing a device](https://docs.clearblade.com/iotcore/creating-registries-and-devices.md#Creatingoreditingadevice) to learn how to create the devices you'll use with the gateway.

## Configuring the gateway and getting state

With ClearBlade IoT Core, you can control a gateway by modifying its configuration, like any other device. See [Configuring devices](https://docs.clearblade.com/iotcore/configuring-devices.md) to learn how to configure a gateway over the MQTT or HTTP bridge.

After a configuration has been applied to a gateway, the gateway can report its [state](https://docs.clearblade.com/iotcore/getting-device-state.md) to ClearBlade IoT Core. You can compare the gateway's state and its most recent configuration to ensure it's functioning properly.

## Binding or unbinding a device

You can authenticate non-gateway devices to ClearBlade IoT Core by binding them to the gateway. Binding creates an association between the devices and the gateway that ClearBlade IoT Core checks to authenticate the devices.

Binding is required when using the HTTP bridge. Note that BINDING is distinct from [ATTACHING](https://docs.clearblade.com/iotcore/using-gateways-with-the-mqtt-bridge.md#Attaching-devices-to-a-gateway).

### Console

1. Go to the [Registries](https://iot.clearblade.com/iot-core/app/registries) page.

2. Click the gateway's registry ID.

3. Click Gateways, then click the gateway's ID.

4. On the Gateway details page, click Bound devices.

   ![image-20250828-171948.png](https://docs.clearblade.com/__attachments/a_b87dfbb58eb6cef5968b189a80abd6aaeab781e8395ae046d108f3927feb1686/image-20250828-171948.png?cb=35254f83b402f9af4313474fdd6ae287)
5. Click **BIND DEVICES**.

6. Select the devices you want to bind to the gateway, then click **BIND**.

   ![image-20250828-172114.png](https://docs.clearblade.com/__attachments/a_e602d5b07619e32b184146a7cde78cc57e9d50e266007d439b903546bcc82934/image-20250828-172114.png?cb=5e863b9e86673ae510b68731f82bee41)
7. To unbind a device, select the device in the Gateway details page, and click Unbind device and Unbind to confirm.

### API

Use these methods to bind a device to or unbind a device from a gateway:

* Registries [BindDeviceToGateway](https://docs.clearblade.com/iotcore/binddevicetogateway.md) method to bind devices to gateways

* Registries [UnbindDeviceFromGateway](https://docs.clearblade.com/iotcore/unbinddevicefromgateway.md) method to unbind devices from gateways

#### Binding a device to or unbinding a device from a gateway code samples

##### Node.js

    // const cloudRegion = 'us-central1';
    // const deviceId = 'my-unauth-device';
    // const gatewayId = 'my-gateway';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    import { DeviceManagerClient } from '@clearblade/iot';

    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function bindDeviceToGateway() {
      // Construct request
      const regPath = iotClient.registryPath(projectId, cloudRegion, registryId);

      const bindRequest = {
        parent: regPath,
        deviceId: deviceId,
        gatewayId: gatewayId
      };

      console.log(`Binding device: ${deviceId}`);

      await iotClient.bindDeviceToGateway(bindRequest);

      console.log(`Bound ${deviceId} to`, gatewayId);
    }

    bindDeviceToGateway();

##### C#

    if (bBindUnBindDevice)
    {
        logger.LogInformation("Get configuration of a device");

        // While running this sample, it is assumed that device with name
        // "Sample-New-Device" exists and Gateway with name "TestGateway" exists
        // "Sample-New-Registry" is the registry name

        // Sample - Bind Device
        var result = await mClient.BindDeviceToGateway(4, "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry", "TestGateway", "Sample-New-Device");
        if (!result)
        {
            logger.LogError("Failed To Bind Device");
        }
        else
        {
            // Actual test - UnBind Device
            result = await mClient.UnBindDeviceFromGateway(4, "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry", "TestGateway", "Sample-New-Device");
            if (!result)
                logger.LogError("Failed to unbind a device");
            else
                logger.LogInformation("Successfully bind device");

        }
    }

##### Python

    import os
    from clearblade.cloud import iot_v1

    def bind_device_to_gateway():
      project_id = 'YOUR_PROJECT_ID'
      cloud_region = 'us-central1'
      registry_id = 'your-registry-id'
      device_id = 'your-device-id'
      gateway_id = 'your-gateway-id'
      client = iot_v1.DeviceManagerClient()

      parent = client.registry_path(project_id, cloud_region, registry_id)

      request = iot_v1.BindDeviceToGatewayRequest(
        parent=parent,
        gatewayId=gateway_id,
        deviceId=device_id
      )
      res = client.bind_device_to_gateway(request=request)

      print("Device Bound! {}".format(res))

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    bind_device_to_gateway()

##### Go

    // bindDeviceToGateway creates an association between an existing device and gateway.
    func bindDeviceToGateway(w io.Writer, projectID string, region string, registryID string, gatewayID string, deviceID string) (*iot.BindDeviceToGatewayResponse, error) {
        ctx := context.Background()
        service, err := iot.NewService(ctx)

        if err != nil {
            return nil, err
        }
        parent := fmt.Sprintf("projects/%s/locations/%s/registries/%s", projectID, region, registryID)
        bindRequest := &iot.BindDeviceToGatewayRequest{
            DeviceId:  deviceID,
            GatewayId: gatewayID,
        }

        response, err := service.Projects.Locations.Registries.BindDeviceToGateway(parent, bindRequest).Do()

        if err != nil {
            return nil, fmt.Errorf("BindDeviceToGateway: %v", err)
        }

        if response.HTTPStatusCode/100 != 2 {
            return nil, fmt.Errorf("BindDeviceToGateway: HTTP status code not 2xx\n %v", response)
        }

        fmt.Fprintf(w, "Bound %s to %s", deviceID, gatewayID)

        return response, nil
    }

## Listing all devices bound to a gateway

### Console

1. Go to the [Registries](https://iot.clearblade.com/iot-core/app/registries) page. Click the gateway's registry ID.

2. Click Gateways, then click the gateway's ID.

3. On the Gateway details page, click **BOUND DEVICES**.

### API

Use the devices [list](https://docs.clearblade.com/iotcore/list-projects-locations-registries-devices.md) method and specify a gateway ID to list all devices bound to the gateway.

#### Listing all devices bound to the gateway code samples

##### Node.js

    // const cloudRegion = 'us-central1';
    // const gatewayId = 'my-gateway';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    import { DeviceManagerClient } from '@clearblade/iot';
    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function listDevices() {
      // Construct request
      const parentName = iotClient.registryPath(projectId, cloudRegion, registryId);
      const [response] = await iotClient.listDevices({
        parent: parentName,
        gatewayListOptions: { associationsGatewayId: gatewayId }
      });
      const devices = response;

      if (devices.length > 0) {
        console.log('Current devices bound to gateway: ', gatewayId);
      } else {
        console.log('No devices bound to this gateway.');
      }

      for (let i = 0; i < devices.length; i++) {
        const device = devices[i];
        console.log(`\tDevice: ${device.numId}: ${device.id}`);
      }
    }

    listDevices();

##### C#

    {
        logger.LogInformation("Obtain list of devices for a particular registry and gateway");

        // While running this sample, it is assumed that gateway with name
        // "associated-gateway" exists

        GatewayListOptionsModel gatewayListOptions = new GatewayListOptionsModel()
        {
            AssociationsGatewayId = "associated-gateway",
        };
        var result = await mClient.GetDevicesList(4, "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry", gatewayListOptions);
        if (!result.Item1)
            logger.LogError("Failed to get list of devices");
        else
        {
            logger.LogInformation("Succeeded in getting the list of Devices");

            // Use the list
        }
    }

##### Python

    import os
    from clearblade.cloud import iot_v1

    def list_bound_devices():
      project_id = 'YOUR_PROJECT_ID'
      cloud_region = 'us-central1'
      registry_id = 'your-registry-id'
      gateway_id = 'your-gateway-id'

      client = iot_v1.DeviceManagerClient()

      path = client.registry_path(project_id, cloud_region, registry_id)

      request = iot_v1.ListDevicesRequest(
        parent=path,
        gatewayListOptions={ "associationsGatewayId": gateway_id }
      )
      
      devices = list(client.list_devices(request=request))

      found = False
      for device in devices:
          found = True
          print("Device: {} : {}".format(device.num_id, device.id))

      if not found:
          print("No devices bound to gateway {}".format(gateway_id))

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    list_bound_devices()

##### Go

    // listDevicesForGateway lists the devices that are bound to a gateway.
    func listDevicesForGateway(w io.Writer, projectID string, region string, registryID, gatewayID string) ([]*iot.Device, error) {
        // Authorize the client using Application Default Credentials.
        // See https://g.co/dv/identity/protocols/application-default-credentials
        ctx := context.Background()
        service, err := iot.NewService(ctx)
        if err != nil {
            return nil, err
        }
        parent := fmt.Sprintf("projects/%s/locations/%s/registries/%s", projectID, region, registryID)
        response, err := service.Projects.Locations.Registries.Devices.List(parent).GatewayListOptionsAssociationsGatewayId(gatewayID).Do()

        if err != nil {
            return nil, fmt.Errorf("ListDevicesForGateway: %v", err)
        }

        if len(response.Devices) == 0 {
            fmt.Fprintln(w, "\tNo devices found")
            return response.Devices, nil
        }

        fmt.Fprintf(w, "Devices for %s:\n", gatewayID)
        for _, gateway := range response.Devices {
            fmt.Fprintf(w, "\t%s\n", gateway.Id)
        }

        return response.Devices, nil
    }

## Listing all gateways in a registry

### Console

1. Go to the [Registries](https://iot.clearblade.com/iot-core/app/registries) page.

2. Click a registry ID.

3. On the Registry details page, select **Gateways** to see a list of the registry's gateways.

### API

Use the device [list](https://docs.clearblade.com/iotcore/list-projects-locations-registries-devices.md) method to list a registry's gateways.

#### Listing a registry's gateways code samples

##### Node.js

    // const cloudRegion = 'us-central1';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    import { DeviceManagerClient } from '@clearblade/iot';
    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function listDevices() {
      // Construct request
      const registryPath = iotClient.registryPath(projectId, cloudRegion, registryId);

      console.log('Current gateways in registry:');
      const [response] = await iotClient.listDevices({
        parent: registryPath,
        fieldMask: { paths: ['config', 'gateway_config'] },
        gatewayListOptions: {
          gatewayType: 'GATEWAY'
        }
      });
      const devices = response;

      devices.forEach((device) => {
        console.log('----\n', device);
      });
    }

    listDevices();

##### C#

    {
        logger.LogInformation("Obtain list of gateways in a registry");

        GatewayListOptionsModel gatewayListOptions = new GatewayListOptionsModel()
        {
            GatewayType = core.Enums.GatewayTypeEnum.GATEWAY,
        };

        var result = await mClient.GetDevicesList(4, "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry", gatewayListOptions);
        if (!result.Item1)
            logger.LogError("Failed to get list of devices");
        else
        {
            logger.LogInformation("Succeeded in getting the list of gateways");

            // Use the list
        }
    }

##### Python

    import os
    from clearblade.cloud import iot_v1

    def list_gateways():
      project_id = 'YOUR_PROJECT_ID'
      cloud_region = 'us-central1'
      registry_id = 'your-registry-id'

      client = iot_v1.DeviceManagerClient()

      path = client.registry_path(project_id, cloud_region, registry_id)
      mask = "config,gateway_config"

      request = iot_v1.ListDevicesRequest(
        parent=path,
        # fieldMask=mask
      )
      
      devices = list(client.list_devices(request=request))

      for device in devices:
        print(device.id)
        if device.gateway_config is not None:
          print(f"gateway_config: {device.gateway_config}")
          if device.gateway_config['gatewayType'] == 1:
            print("Gateway ID: {}\n\t{}".format(device.id, device))

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    list_gateways()

##### Go

    // listGateways lists all the gateways in a specific registry.
    func listGateways(w io.Writer, projectID string, region string, registryID string) ([]*iot.Device, error) {
        ctx := context.Background()
        service, err := iot.NewService(ctx)
        if err != nil {
            return nil, err
        }

        parent := fmt.Sprintf("projects/%s/locations/%s/registries/%s", projectID, region, registryID)
        response, err := service.Projects.Locations.Registries.Devices.List(parent).GatewayListOptionsGatewayType("GATEWAY").Do()

        if err != nil {
            return nil, fmt.Errorf("ListGateways: %v", err)
        }

        if len(response.Devices) == 0 {
            fmt.Fprintln(w, "No gateways found")
            return response.Devices, nil
        }

        fmt.Fprintln(w, len(response.Devices), "devices:")
        for _, gateway := range response.Devices {
            fmt.Fprintf(w, "\t%s\n", gateway.Id)
        }

        return response.Devices, nil
    }

## Deleting devices bound to a gateway

To delete a device bound to a gateway, you first unbind the device from all gateways it's bound to, then delete it from the registry.

### Console

1. [Unbind the device](https://docs.clearblade.com/iotcore/creating-configuring-and-managing-gateways.md#Bindingorunbindingadevice) from every gateway it's bound to.

2. In the Device details page, click Delete.

### API

After [unbinding the device](https://docs.clearblade.com/iotcore/creating-configuring-and-managing-gateways.md#Bindingorunbindingadevice) from all gateways it's bound to, use the device [delete](https://docs.clearblade.com/iotcore/delete-projects-locations-registries-devices.md) method to delete the device.

#### Deleting a device bound to a gateway code samples

##### Node.js

    // const cloudRegion = 'us-central1';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    import { DeviceManagerClient } from '@clearblade/iot';

    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function deleteDevice() {
      // Construct request
      const devPath = iotClient.devicePath(projectId, cloudRegion, registryId, deviceId);

      const [responses] = await iotClient.deleteDevice({ name: devPath });
      console.log('Successfully deleted device', responses);
    }

    deleteDevice();

##### C#

    {
        logger.LogInformation("Unbind the device");

        var unbindResult = await mClient.UnBindDeviceFromGateway(4, "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry", "TestGateway", "Sample-New-Device");
        if (!unbindResult)
            logger.LogError("Failed to unbind a device");
        else
            logger.LogInformation("Successfully unbind device");

        logger.LogInformation("Delete the device");

        string id = "Sample-New-Device";
        string name = "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry/Devices/Sample-New-Device";

        var deleteResult = await mClient.DeleteDevice(4, id, name);
        if (!deleteResult.Item1 || (deleteResult.Item2 == null))
            logger.LogError("Failed to delete device");
        else
        {
            logger.LogInformation("Successfully deleted the device");
        }
    }

##### Python

    import os
    from clearblade.cloud import iot_v1

    def delete_device():
      project_id = 'YOUR_PROJECT_ID'
      cloud_region = 'us-central1'
      registry_id = 'your-registry-id'
      device_id = 'your-device-id'
      
      print("Delete device")
      client = iot_v1.DeviceManagerClient()

      device_path = client.device_path(project_id, cloud_region, registry_id, device_id)

      request = iot_v1.DeleteDeviceRequest(name=device_path)

      return client.delete_device(request=request)

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    delete_device()

##### Go

    // deleteDevice deletes a device from a registry.
    func deleteDevice(w io.Writer, projectID string, region string, registryID string, deviceID string) (*iot.Empty, error) {
        ctx := context.Background()
        service, err := iot.NewService(ctx)
        if err != nil {
            return nil, err
        }

        path := fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", projectID, region, registryID, deviceID)
        response, err := service.Projects.Locations.Registries.Devices.Delete(path).Do()
        if err != nil {
            return nil, err
        }

        fmt.Fprintf(w, "Deleted device: %s\n", deviceID)

        return response, nil
    }

## Deleting a gateway

To delete a gateway, you first unbind its devices and then delete the gateway from the registry.

### Console

1. [Unbind all devices from the gateway](https://docs.clearblade.com/iotcore/creating-configuring-and-managing-gateways.md#Bindingorunbindingadevice).

2. Go back to the Gateway details page and click Delete.

### API

After [unbinding all devices](https://docs.clearblade.com/iotcore/creating-configuring-and-managing-gateways.md#Bindingorunbindingadevice) from the gateway, use the device [delete](https://docs.clearblade.com/iotcore/delete-projects-locations-registries-devices.md) method to delete the gateway, specifying the gateway's ID you want to delete.

#### Deleting a gateway code samples

##### Node.js

    // const cloudRegion = 'us-central1';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    import { DeviceManagerClient } from '@clearblade/iot';

    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function deleteDevice() {
      // Construct request
      const devPath = iotClient.devicePath(projectId, cloudRegion, registryId, deviceId);

      const [responses] = await iotClient.deleteDevice({ name: devPath });
      console.log('Successfully deleted device', responses);
    }

    deleteDevice();

##### C#

    {
        logger.LogInformation("Unbind the device");

        var unbindResult = await mClient.UnBindDeviceFromGateway(4, "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry", "TestGateway", "Sample-New-Device");
        if (!unbindResult)
            logger.LogError("Failed to unbind a device");
        else
            logger.LogInformation("Successfully unbind device");

        logger.LogInformation("Delete the device");

        string id = "Sample-New-Device";
        string name = "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry/Devices/Sample-New-Device";

        var deleteResult = await mClient.DeleteDevice(4, id, name);
        if (!deleteResult.Item1 || (deleteResult.Item2 == null))
            logger.LogError("Failed to delete device");
        else
        {
            logger.LogInformation("Successfully deleted the device");
        }
    }

##### Python

    import os
    from clearblade.cloud import iot_v1

    def delete_gateway():
      project_id = 'YOUR_PROJECT_ID'
      cloud_region = 'us-central1'
      registry_id = 'your-registry-id'
      gateway_id = 'your-gateway-id'
      
      print("Delete gateway")
      client = iot_v1.DeviceManagerClient()

      device_path = client.device_path(project_id, cloud_region, registry_id, gateway_id)

      request = iot_v1.DeleteDeviceRequest(name=device_path)

      return client.delete_device(request=request)

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    delete_gateway()

##### Go

    // deleteDevice deletes a device from a registry.
    func deleteDevice(w io.Writer, projectID string, region string, registryID string, deviceID string) (*iot.Empty, error) {
        ctx := context.Background()
        service, err := iot.NewService(ctx)
        if err != nil {
            return nil, err
        }

        path := fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", projectID, region, registryID, deviceID)
        response, err := service.Projects.Locations.Registries.Devices.Delete(path).Do()
        if err != nil {
            return nil, err
        }

        fmt.Fprintf(w, "Deleted device: %s\n", deviceID)

        return response, nil
    }

## What's next

* Use the [MQTT](https://docs.clearblade.com/iotcore/using-gateways-with-the-mqtt-bridge.md) or [HTTP](https://docs.clearblade.com/iotcore/using-gateways-with-the-http-bridge.md) bridge to send messages and configuration data between the devices and ClearBlade IoT Core.

---
language: "en"
---
# Creating a Google Cloud service account key

A service account is required to migrate and run the IoT Core service. These instructions allow you to create a service account with the necessary permissions:

1. Select your desired project area.

2. Open the IAM \& Admin Cloud services from the flyout menu.

   ![Screen Shot 2022-09-03 at 9.52.12 AM.png](https://docs.clearblade.com/__attachments/a_db50cf18d6c3bb7bacdb37431b9d58367cb4f6706f98a6b629d4260b3eac99fb/Screen%20Shot%202022-09-03%20at%209.52.12%20AM.png?cb=6ae017d6910969617779f5d85622ee47)

3. Select Service Accounts in the left menu.

   ![Screen Shot 2022-09-03 at 9.47.11 AM.png](https://docs.clearblade.com/__attachments/a_a03e6af4de850b7614691eb9acb3f567584b0a8775391557b9f7fac0968240f0/Screen%20Shot%202022-09-03%20at%209.47.11%20AM.png?cb=1c69816bc09ea92d500e81689d8d2d6f)

4. Click CREATE SERVICE ACCOUNT from the top menu bar.

   ![Screen Shot 2022-09-03 at 9.47.20 AM.png](https://docs.clearblade.com/__attachments/a_e7c920363bf318bafbaee8c16df22e1aecfd216da212c569f4a95526b7786838/Screen%20Shot%202022-09-03%20at%209.47.20%20AM.png?cb=66ed070355ae266b5d0ec00d51c5ac10)

5. Complete the account details.

   1. Service Account Name: ClearBlade IoT Core Service Account

   2. Account description: This account is used by ClearBlade IoT Core service to flow MQTT-based device message data into the Google Pub/Sub offering. It additionally integrates with Cloud Logging and Cloud Monitoring services.

   3. Click CREATE AND CONTINUE.

6. ![Screen Shot 2022-09-03 at 9.55.57 AM.png](https://docs.clearblade.com/__attachments/a_3ca737e772895250cd2434cfb1dce99e29857a751f0e714d1e97c6df2dd9c6f2/Screen%20Shot%202022-09-03%20at%209.55.57%20AM.png?cb=680e0eb04ad2e4b6318f74ccea05bf13)
7. Grant these roles to the service account:

   1. Pub/Sub Editor:

      1. This role is needed to allow ClearBlade IoT Core to publish messages into Google Cloud Pub/Sub topics. This role is needed for normal operations.

      2. This role is needed to allow the ClearBlade IoT Core console to browse and create new topics in Google Pub/Sub to send events and status updates. This role is needed for normal operations.

   2. Logs Writer: This role is required for ClearBlade IoT Core to send data directly into the Google Cloud Logging service. This role is needed for normal operations.

   3. Monitoring Metric Writer: This role is required for ClearBlade IoT Core to send metrics into the Google Cloud Monitoring service. This role is needed for normal operations.

   4. Monitoring Viewer: This role is required for ClearBlade IoT Core to view metrics in the Google Cloud Monitoring service. This role is needed for normal operations.

8. Click CONTINUE.

   ![image-20260805-225730.png](https://docs.clearblade.com/__attachments/a_299644052a3a2c56e2a18bf31facf2d790c61ef56c40f6da10ed829b6f231285/image-20260805-225730.png?cb=74091ad0789ac5574cf5036e497fe048)

9. Leave the field to grant users access to the service account blank.Click DONE to complete the service account creation.

   ![Screen Shot 2022-09-03 at 10.09.27 AM.png](https://docs.clearblade.com/__attachments/a_952f2ca4911d887a65c64b5aeb785a1378649b49b2fdb39e31a776c9e3586fa7/Screen%20Shot%202022-09-03%20at%2010.09.27%20AM.png?cb=528c2c75eba5bc2d5a616e9d6c520371)

10. Select the newly created account by clicking the email hyperlink.

    ![Screen Shot 2022-09-03 at 10.10.51 AM.png](/__attachments/a_9e1aa236658b03c9f3c3fe916b8904fc245ebd5288ee7bd5b9292449f8dc6f65/Screen%20Shot%202022-09-03%20at%2010.10.51%20AM.png?cb=bc6ffeb6362bb25803e9f672a785d638)

11. On the Service Account Page, select KEYS from the top button bar.

    ![Screen Shot 2022-09-03 at 10.12.02 AM.png](/__attachments/a_97329e734629000e8c99eac852ad501de4a6cf778a087de531baf6ac8a12a95b/Screen%20Shot%202022-09-03%20at%2010.12.02%20AM.png?cb=c9307c69c6064e23f0120eaf8bd07a25)

12. Click ADD KEY → Create new key.

    ![Screen Shot 2022-09-03 at 10.12.51 AM.png](/__attachments/a_5ac24de0b012d92b848c32967bae70ff10f6ac187c041a670e61b48c382fc2db/Screen%20Shot%202022-09-03%20at%2010.12.51%20AM.png?cb=1714a95feb4f6ce7502999894b3da07d)

13. Choose JSON as the key type and click CREATE.

    ![Screen Shot 2022-09-03 at 10.13.36 AM.png](/__attachments/a_28704e6615907cb64517bd517b9e5cf094409875d50407b0c00f4aa72bea8b85/Screen%20Shot%202022-09-03%20at%2010.13.36%20AM.png?cb=e99be0cfe30eeae6812f3383c3320506)

14. A new .json key file is downloaded to your device.

    ![Screen Shot 2022-09-03 at 10.14.38 AM.png](/__attachments/a_3f1c31a8bbb76a73b9e7ea737a29084f2bb6f69e40abbfd965c690a6a4d1f5d6/Screen%20Shot%202022-09-03%20at%2010.14.38%20AM.png?cb=95fc2efa0bc9f9bc1c765166f40303d5)

---
language: "en"
---
# Creating key pairs

This page explains how to generate public/private key pairs using [OpenSSL](https://www.openssl.org/) command-line tools.

## Device authentication

ClearBlade IoT Core uses public key (or asymmetric) authentication:

* The device uses a private key to sign a [JSON Web Token (JWT)](https://docs.clearblade.com/iotcore/using-json-web-tokens.md). The token is passed to ClearBlade IoT Core as proof of the device's identity.

* The service uses the device's public key (uploaded before the JWT is sent) to verify the device's identity.

ClearBlade IoT Core supports the RSA and elliptic curve algorithms. For details on key formats, see [Public key format](https://docs.clearblade.com/iotcore/device-security.md#Devicesecurity-Publickeyformat).

## Generating an RSA key

You can generate a 2048-bit RSA key pair with these commands:

    openssl genpkey -algorithm RSA -out rsa_private.pem -pkeyopt rsa_keygen_bits:2048
    openssl rsa -in rsa_private.pem -pubout -out rsa_public.pem

These commands create this public/private key pair:

* `rsa_private.pem`: The private key that must be securely stored on the device and used to sign the authentication JWT.

* `rsa_public.pem`: The public key that must be stored in ClearBlade IoT Core and used to verify the authentication JWT's signature.

### Generating an RSA key with a self-signed X.509 certificate

The certificate must meet [specific requirements](https://docs.clearblade.com/iotcore/verifying-device-credentials.md) if you validate keys against registry-level certificates. One of these requirements is that the certificate uses the X.509 standard.

To generate a 2048-bit RSA private key and a self-signed X.509 certificate with an SHA-256 signature, run this command:

    openssl req -x509 -nodes -newkey rsa:2048 -keyout rsa_private.pem -out rsa_cert.pem -subj "/CN=unused"

You can replace the `-subj` argument with an actual certificate subject and use that certificate. Alternatively, you can omit `-subj` and supply the certificate information when prompted (ClearBlade IoT Core does not verify the subject).

By default, X.509 certificates expire 30 days after creation. Add the `-days <n>` flag at creation time to set the number of days until the certificate expires. If you try to create or update a device with an expired certificate or try to connect a device to a registry and the certificate has expired, ClearBlade IoT Core returns an error.

## Generating elliptic curve keys

You can use these commands to generate a P-256 elliptic curve key pair:

    openssl ecparam -genkey -name prime256v1 -noout -out ec_private.pem
    openssl ec -in ec_private.pem -pubout -out ec_public.pem

These commands create this public/private key pair:

* `ec_private.pem`: The private key that must be securely stored on the device and used to sign the authentication JWT.

* `ec_public.pem`: The public key that must be stored in ClearBlade IoT Core and used to verify the authentication JWT's signature.

### Generating an ES256 key with a self-signed X.509 certificate

If you're validating keys against registry-level certificates, the certificate must meet [specific requirements](https://docs.clearblade.com/iotcore/verifying-device-credentials.md). One of these requirements is that the certificate uses the X.509 standard.

Run this command to generate an ES256 key with a self-signed X.509 certificate:

    openssl req -x509 -new -key ec_private.pem -out ec_cert.pem -subj "/CN=unused"

You can replace the `-subj` argument with an actual certificate subject and use that certificate. Alternatively, you can omit `-subj` and supply the certificate information when prompted (ClearBlade IoT Core does not verify the subject).

By default, X.509 certificates expire 30 days after creation. Add the `-days <n>` flag at creation time to set the number of days until the certificate expires. If you try to create or update a device with an expired certificate or try to connect a device to a registry and the certificate has expired, ClearBlade IoT Core returns an error.

## Converting keys to PKCS #8 for Java

In Java, you must convert private keys to the PKCS #8 format. To convert RSA and elliptic curve keys from PEM format to PKCS #8 format, run these commands:

### RSA

    openssl pkcs8 -topk8 -inform PEM -outform DER -in rsa_private.pem -nocrypt > rsa_private_pkcs8

### Elliptic curve

    openssl pkcs8 -topk8 -inform PEM -outform DER -in ec_private.pem -nocrypt > ec_private_pkcs8

## Managing keys

Review the [device security recommendations](https://docs.clearblade.com/iotcore/device-security.md#Devicesecurity-Devicesecurityrecommendations) and consider implementing [key rotation](https://docs.clearblade.com/iotcore/device-security.md#Devicesecurity-Keyrotation).

You can also use registry-level certificates to [verify key credentials](https://docs.clearblade.com/iotcore/verifying-device-credentials.md).

## Generate a signed RS256_X509 device certificate and private key

1. Generate the private key and certificate request. Change the number of days the certificate should be valid as per your requirements:

`openssl req -newkey rsa:2048 -nodes -days 365000 -keyout client-key.pem -out client-rsa-req.pem`

You will be shown this prompt to enter a common name:

Common Name (e.g., server FQDN or YOUR name) \[\]:

Ensure the common name is different from the CA certificate one.

2. Generate the X509 device certificate:

`openssl x509 -req -days 365000 -set_serial 01 -in client-rsa-req.pem -out client-rsa-cert.pem -CA ca-cert.pem -CAkey ca-key.pem`

3. Verify the signed X509 device certificate:

`openssl verify -CAfile ca-cert.pem ca-cert.pem client-rsa-cert.pem`

## Generate a signed ES256_X509 device certificate and private key

1. Generate a private key:

`openssl ecparam -genkey -name prime256v1 -out client-ec-key.pem`

2. Generate the certificate request:

`openssl req -new -key client-ec-key.pem -out client-ec-cert-req.pem`

You will be shown this prompt to enter a common name:

Common Name (e.g., server FQDN or YOUR name) \[\]:

Ensure the common name is different from the CA certificate one.

3. Sign the certificate request with the CA and generate the X509 device certificate:

`openssl x509 -req -days 365 -in client-ec-cert-req.pem -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-ec-cert.pem`

4. Verify the signed X509 device certificate:

`openssl verify -CAfile ca-cert.pem ca-cert.pem client-ec-cert.pem`

---
language: "en"
---
# Creating registries and devices

This page explains how to create, edit, and delete device registries and devices within them.

A device is a Thing in The Internet of Things. It is a processing unit capable of connecting to the internet (directly or indirectly) and exchanging data with the cloud. A device registry is a device container with shared properties. See [Devices](https://docs.clearblade.com/iotcore/devices-configuration-and-state.md) for more device and registry details.

If you still need to, complete the [Getting started](https://docs.clearblade.com/iotcore/getting-started.md) steps before proceeding.

## Creating a device registry

To use ClearBlade IoT Core, you must create at least one device registry.

### Console

1. Go to the ClearBlade IoT Core console's [Registries](https://iot.clearblade.com/iot-core/app/registries) page.

2. At the top of the page, click **ADD REGISTRY** , then select **Create registry**.

   ![image-20250827-182537.png](https://docs.clearblade.com/__attachments/a_af88868e7cc3fd874b79b212be12e4269d5a48c95637997e607c2fc0aaa1561e/image-20250827-182537.png?cb=67166d6e86f48116bd32180e1f07b0e4)

   ![image-20250829-133704.png](https://docs.clearblade.com/__attachments/a_8ec6e9ef9cb34468dda4e1332f28ed316afee44a37b3dab7dd38946b493edbb9/image-20250829-133704.png?cb=695f99401d867ac090ad4c77aade577f)

3. Enter a registry ID and select a [cloud region](https://docs.clearblade.com/iotcore/requirements.md#Cloudregions). For registry naming and size requirements, see [Permitted characters and size requirements](https://docs.clearblade.com/iotcore/requirements.md#Permittedcharactersandsizerequirements).

4. Select the [protocols](https://docs.clearblade.com/iotcore/protocols-mqtt-and-http.md) that devices in this registry will use to connect to ClearBlade IoT Core: MQTT, HTTP, or both.

5. Use the [Pub/Sub service](https://console.cloud.google.com/cloudpubsub) to create new Pub/Sub topics.

6. Click **CREATE** to continue.

### API

#### Creating a registry code samples

Use the DeviceRegistry [create](https://docs.clearblade.com/iotcore/create.md) method to create a registry.

##### Node.js

    // Client retrieved in callback
    // const cloudRegion = 'us-central1';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    import { DeviceManagerClient } from '@clearblade/iot';

    // Lookup the pubsub topic
    const topicPath = `projects/${projectId}/topics/${pubsubTopicId}`;

    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function createDeviceRegistry() {
      // Construct request
      const newParent = iotClient.locationPath(projectId, cloudRegion);
      const deviceRegistry = {
        eventNotificationConfigs: [
          {
            pubsubTopicName: topicPath
          }
        ],
        id: registryId
      };
      const request = {
        parent: newParent,
        deviceRegistry: deviceRegistry
      };

      const [response] = await iotClient.createDeviceRegistry(request);

      console.log('Successfully created registry');
      console.log(response);
    }

    createDeviceRegistry();

##### C#

    {
        logger.LogInformation("Create a registry");

        string parent = "projects/developmentenv/locations/us-central1";
        string name = "Sample-New-Registry-2";
        string pubsubTopic = "projects/developmentenv/topics/pubsubTopic";

        RegistryConfigModel registryConfigModel = new RegistryConfigModel()
        {
            Id = name,
        };

        registryConfigModel.EventNotificationConfigs = new List<EventNotificationConfig>();
        var toAdd = new EventNotificationConfig()
        {
            PubsubTopicName = pubsubTopic
        };
        registryConfigModel.EventNotificationConfigs.Add(toAdd);

        var result = await mClient.CreateRegistry(4, parent, registryConfigModel);
        if (!result.Item1 || (result.Item2 == null))
            logger.LogError("Failed to get a device states");
        else
        {
            logger.LogInformation("Successfully obtained the list of device configuration versions");

            // Use the obtained information
        }
    }

##### Python

    import os
    from clearblade.cloud import iot_v1

    def create_registry():
        project_id = 'YOUR_PROJECT_ID'
        cloud_region = 'us-central1'
        pubsub_topic = 'your-pubsub-topic'
        registry_id = 'your-registry-id'
        client = iot_v1.DeviceManagerClient()
        parent = f"projects/{project_id}/locations/{cloud_region}"
        
        if not pubsub_topic.startswith("projects/"):
            pubsub_topic = "projects/{}/topics/{}".format(project_id, pubsub_topic)

        registry = iot_v1.DeviceRegistry(
            eventNotificationConfigs = [{ "pubsubTopicName": pubsub_topic }],
            id = registry_id
        )

        request = iot_v1.CreateDeviceRegistryRequest(parent=parent, device_registry=registry)

        try:
            response = client.create_device_registry(
                request=request
            )
            print("Created registry")
            return response
        except Exception as e:
            print(e)
            raise

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    create_registry()

##### Go

    package samples

    import (
        "context"
        "fmt"
        "io"

        iot "github.com/clearblade/go-iot"
    )

    // createRegistry creates a IoT Core device registry associated with a PubSub topic
    func createRegistry(w io.Writer, projectID string, region string, registryID string, topicName string) (*iot.DeviceRegistry, error) {
        ctx := context.Background()
        service, err := iot.NewService(ctx)

        if err != nil {
            return nil, err
        }

        registry := iot.DeviceRegistry{
            Id: registryID,
            EventNotificationConfigs: []*iot.EventNotificationConfig{
                {
                    PubsubTopicName: topicName,
                },
            },
        }

        parent := fmt.Sprintf("projects/%s/locations/%s", projectID, region)
        response, err := service.Projects.Locations.Registries.Create(parent, &registry).Do()

        if err != nil {
            return nil, err
        }

        fmt.Fprintln(w, "Created registry:")
        fmt.Fprintf(w, "\tID: %s\n", response.Id)
        fmt.Fprintf(w, "\tHTTP: %s\n", response.HttpConfig.HttpEnabledState)
        fmt.Fprintf(w, "\tMQTT: %s\n", response.MqttConfig.MqttEnabledState)
        fmt.Fprintf(w, "\tName: %s\n", response.Name)

        return response, nil
    }

## Creating device key pairs

Before creating a device, [create a public/private key pair](https://docs.clearblade.com/iotcore/creating-key-pairs.md) for it. When connecting to ClearBlade IoT Core, each device creates a [JSON Web Token (JWT)](https://docs.clearblade.com/iotcore/using-json-web-tokens.md) signed with its private key, which ClearBlade IoT Core authenticates using the device's public key.

## Creating or editing a device

### Console

1. Go to the ClearBlade IoT Core console's [Registries](https://iot.clearblade.com/iot-core/app/registries) page.

2. Click the device registry's ID.

3. Click Devices in the left registry menu.

   ![image-20250827-183019.png](https://docs.clearblade.com/__attachments/a_dfaf7ad7e2931056184327d0eae46cbc934137a8f415f1ab4f4fd579b222e6ef/image-20250827-183019.png?cb=a22c54038757130e666417285f02c134)

4. Click the '**+**' icon (top-right) to Create a device.

5. Enter a device ID that describes or identifies the device. **This field cannot be edited later**.

6. To edit an existing device, click its ID on the Devices page and click Edit device at the top of the page.

   ![image-20250827-183148.png](https://docs.clearblade.com/__attachments/a_d3a43e95a4b6e4ebe07d21fb06ae6d4269db1dcf3826d101a2ec85c669a3f17a/image-20250827-183148.png?cb=6eb0c34e7aea60e2b0ca804d36906d48)

7. For Device communication, select Allow or Block. This option allows you to block communication when needed, such as when a device is not functioning properly. You'll most likely want to enable communication when creating the device.

   ![image-20250829-133959.png](https://docs.clearblade.com/__attachments/a_c3b72876c534f41619f69892909a4e6c7e64b6e67f0ec5f4b0eb2b0df8148acc/image-20250829-133959.png?cb=fe2f8a996fcf9b2c341d08a43335d1b9)

8. If you're creating a new device, select the Input method you wish to use to enter the public key:

   * Manual: Copy and paste the public key into the Public key value field.

   * Upload: In the Public key value field, click Browse to select a file on your device.

   ![image-20250829-134103.png](https://docs.clearblade.com/__attachments/a_126dfff5f556eb3c38de9b44956c26797203c0d0630cc3521e98e79dc64222ff/image-20250829-134103.png?cb=255eac90b5935b65dda3367b7254b4f9)

9. Select the public key format that matches this device's key pair. Paste the certificate or key in the Public key value field. You can also set the key's expiration date. To add a key to an existing device, click Add public key on the Device details page.

10. Use the Key and Value fields to add optional [device metadata](https://docs.clearblade.com/iotcore/devices-configuration-and-state.md#Devicemetadata), such as a serial number.

11. Select a [Cloud Logging level](https://docs.clearblade.com/iotcore/viewing-device-logs.md#Loggingdeviceactivity) to determine which device events are sent to Cloud Logging.

12. Click Submit to create the device or Update to save changes to an existing device.

### API

Use these methods to create or edit devices:

* Device [create](https://docs.clearblade.com/iotcore/create-projects-locations-registries-devices.md) method to add devices to registries

* Device [patch](https://docs.clearblade.com/iotcore/patch-projects-locations-registries-devices.md) method to edit existing devices

Public keys are specified in the `Device` resource's `credentials` field in the ClearBlade IoT Core API when creating a device. You can add or modify this field when updating the device resource. If one or more registry-level certificates are present when adding a new device credential (via device creation or modifications), the public key credential must be signed by one of the registry-level certificates. See the device resource's `DeviceCredential` for more information.

For RSA, the`Device.credentials[i].public_key.key` field must be set to the `rsa_cert.pem` contents (including the header and the footer). The `Device.credentials[i].public_key.format` field must be set to `RSA_PEM` or `RSA_X509_PEM`.

For ES256, the `Device.credentials[i].public_key.key` field must be set to the `ec_public.pem` contents (including the header and the footer). The `Device.credentials[i].public_key.format` field must be set to `ES256_PEM` or `ES256_X509_PEM`.

#### Creating a device with [RSA credentials](https://docs.clearblade.com/iotcore/device-security.md#Securitystandards) code samples

##### Node.js

    // const cloudRegion = 'us-central1';
    // const deviceId = 'my-rsa-device';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    import { DeviceManagerClient } from '@clearblade/iot';

    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function createDevice() {
      // Construct request
      const regPath = iotClient.registryPath(projectId, cloudRegion, registryId);
      const device = {
        id: deviceId,
        credentials: [
          {
            publicKey: {
              format: 'RSA_X509_PEM',
              key: readFileSync(rsaCertificateFile).toString()
            }
          }
        ]
      };

      const request = {
        parent: regPath,
        device
      };

      const [response] = await iotClient.createDevice(request);
      console.log('Created device', response);
    }

    createDevice();

##### C#

    {
        logger.LogInformation("Create a new device with RSA credentials");

        string id = "Sample-New-Device";
        string name = "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry/Devices/Sample-New-Device";

        String keyText = File.ReadAllText("path/to/key");

        var credentials = new List<DeviceCredential>
        {
            new DeviceCredential()
            {
                PublicKey = new PublicKeyCredential()
                {
                    Key = keyText,
                    Format = "RSA_X509_PEM"
                },
            }
        };

        var result = await mClient.CreateDevice(4, id, name, credentials);
        if (!result.Item1 || (result.Item2 == null))
            logger.LogError("Failed to create new device");
        else
        {
            logger.LogInformation("Successfully created new device");

            // The result.Item2 object can be used to refer to newly created device
        }
    }

##### Python

    import os
    import io
    import json
    from clearblade.cloud import iot_v1

    def create_device_with_rsa():
        project_id = 'YOUR_PROJECT_ID'
        cloud_region = 'us-central1'
        registry_id = 'your-registry-id'
        device_id = 'your-device-id'
        certificate_file = 'path/to/certificate.pem'

        client = iot_v1.DeviceManagerClient()

        parent = client.registry_path(project_id, cloud_region, registry_id)

        with io.open(certificate_file) as f:
            certificate = f.read()

        # You can have multiple credentials associated with a device.
        device = iot_v1.Device(
            id = device_id,
            credentials = [
                {
                    "publicKey": {
                        "format": iot_v1.PublicKeyFormat.RSA_X509_PEM,
                        "key": certificate,
                    }
                }
            ]
        )

        request = iot_v1.CreateDeviceRequest(parent=parent, device=device)

        return client.create_device(request=request)

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    create_device_with_rsa()

##### Go

    // createRSA creates a device in a registry given RSA X.509 credentials.
    func createRSA(w io.Writer, projectID string, region string, registryID string, deviceID string, keyPath string) (*iot.Device, error) {
        ctx := context.Background()
        service, err := iot.NewService(ctx)
        if err != nil {
            return nil, err
        }

        keyBytes, err := ioutil.ReadFile(keyPath)
        if err != nil {
            return nil, err
        }

        device := iot.Device{
            Id: deviceID,
            Credentials: []*iot.DeviceCredential{
                {
                    PublicKey: &iot.PublicKeyCredential{
                        Format: "RSA_X509_PEM",
                        Key:    string(keyBytes),
                    },
                },
            },
        }

        parent := fmt.Sprintf("projects/%s/locations/%s/registries/%s", projectID, region, registryID)
        response, err := service.Projects.Locations.Registries.Devices.Create(parent, &device).Do()
        if err != nil {
            return nil, err
        }

        fmt.Fprintf(w, "Successfully created RSA256 X.509 device: %s", deviceID)

        return response, nil
    }

#### Creating a device with [Elliptic Curve (EC) credentials](https://docs.clearblade.com/iotcore/device-security.md#Securitystandards) code samples

##### Node.js

    // const cloudRegion = 'us-central1';
    // const deviceId = 'my-es-device';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    import { DeviceManagerClient } from '@clearblade/iot';

    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function createDevice() {
      // Construct request
      const regPath = iotClient.registryPath(projectId, cloudRegion, registryId);
      const device = {
        id: deviceId,
        credentials: [
          {
            publicKey: {
              format: 'ES256_PEM',
              key: readFileSync(esCertificateFile).toString()
            }
          }
        ]
      };
      const request = {
        parent: regPath,
        device
      };

      const [response] = await iotClient.createDevice(request);
      console.log('Created device', response);
    }

    createDevice();

##### C#

    {
        logger.LogInformation("Create a new device with EC credentials");

        string id = "Sample-New-Device";
        string name = "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry/Devices/Sample-New-Device";

        String keyText = File.ReadAllText("path/to/key");

        var credentials = new List<DeviceCredential>
        {
            new DeviceCredential()
            {
                PublicKey = new PublicKeyCredential()
                {
                    Key = keyText,
                    Format = "ES256_PEM"
                },
            }
        };

        var result = await mClient.CreateDevice(4, id, name, credentials);
        if (!result.Item1 || (result.Item2 == null))
            logger.LogError("Failed to create new device");
        else
        {
            logger.LogInformation("Successfully created new device");

            // The result.Item2 object can be used to refer to newly created device
        }
    }

##### Python

    import os
    import io
    import json
    from clearblade.cloud import iot_v1

    def create_device_with_ec():
        project_id = 'YOUR_PROJECT_ID'
        cloud_region = 'us-central1'
        registry_id = 'your-registry-id'
        device_id = 'your-device-id'
        public_key_file = 'path/to/ec_public.pem'

        client = iot_v1.DeviceManagerClient()

        parent = client.registry_path(project_id, cloud_region, registry_id)

        with io.open(public_key_file) as f:
            public_key = f.read()

        # You can have multiple credentials associated with a device.
        device = iot_v1.Device(
            name = device_id,
            credentials = [
                {
                    "publicKey": {
                        "format": iot_v1.PublicKeyFormat.ES256_PEM,
                        "key": public_key,
                    }
                }
            ],
        )

        request = iot_v1.CreateDeviceRequest(parent=parent, device=device)

        return client.create_device(request=request)

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    create_device_with_ec()

##### Go

    // createES creates a device in a registry with ES256 credentials.
    func createES(w io.Writer, projectID string, region string, registryID string, deviceID string, keyPath string) (*iot.Device, error) {
        ctx := context.Background()
        service, err := iot.NewService(ctx)
        if err != nil {
            return nil, err
        }

        keyBytes, err := ioutil.ReadFile(keyPath)
        if err != nil {
            return nil, err
        }

        device := iot.Device{
            Id: deviceID,
            Credentials: []*iot.DeviceCredential{
                {
                    PublicKey: &iot.PublicKeyCredential{
                        Format: "ES256_PEM",
                        Key:    string(keyBytes),
                    },
                },
            },
        }

        parent := fmt.Sprintf("projects/%s/locations/%s/registries/%s", projectID, region, registryID)
        response, err := service.Projects.Locations.Registries.Devices.Create(parent, &device).Do()
        if err != nil {
            return nil, err
        }

        fmt.Fprintf(w, "Successfully created ES256 device: %s\n", deviceID)

        return response, nil
    }

#### Patching a device with RSA credentials code samples

##### Node.js

    // const cloudRegion = 'us-central1';
    // const deviceId = 'my-rsa-device';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    import { DeviceManagerClient } from '@clearblade/iot';
    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function updateDevice() {
      // Construct request
      const devPath = iotClient.devicePath(projectId, cloudRegion, registryId, deviceId);

      const device = {
        name: devPath,
        credentials: [
          {
            publicKey: {
              format: 'RSA_X509_PEM',
              key: readFileSync(rsaPublicKeyFile).toString()
            }
          }
        ]
      };

      const [response] = await iotClient.updateDevice({
        device: device,
        updateMask: { paths: ['credentials'] }
      });

      console.log('Patched device:', deviceId);
      console.log('Response', response);
    }

    updateDevice();

##### C#

    {
        logger.LogInformation("Update configuration of a device");

        // While running this sample, it is assumed that, device with name
        // "Sample-New-Device" exists

        string name = "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry/devices/Sample-New-Device";

        var result = await mClient.GetDevice(4, name);
        if (!result.Item1 || (result.Item2 == null))
            logger.LogError("Failed to get a device configuration");
        else
        {
            logger.LogInformation("Successfully obtained the device configuration");

            // Use the obtained information
            string updateMask = "metadata";
            string pubKey = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5P0Z4OUD5PSjri8xexGo\n6eQ39NGyQbXamIgWAwvnAs/oDRVqEejE2nwDhnpykaCGLkuDEN0LPd2wF+vC2Cq3\nY3YvkJh71IkjuAjMZQ+00CXdezfCjmTtEpMCNA3cV+G1g6uIcdEpHKs0YHfC9CFQ\nrjkc7tl3idmcQLngIov/gsFY7D1pbOgkCVVcZCRLgsdFfhCUYwYCvdEVJP3w+5mG\nybvmhNRbbFG7eG3+hmZoOg0h3f6r2fqgSx6l0+Z3D77SRT6lBEHvGDlxb08ASeuE\n0SJAc6PdAKd3FDqdZok4z1qJsgMqtU/ZGJJG54pNECWmhoOar+aQmmqnZ6kGQ5cn\nEwIDAQAB\n-----END PUBLIC KEY-----\n";
            result.Item2.Credentials.Add(new DeviceCredential
            {
                ExpirationTime = "",
                PublicKey = new PublicKeyCredential
                {
                    Format = "RSA_PEM",
                    Key = pubKey
                }
            });

            result = await mClient.PatchDevice(4, name, updateMask, result.Item2);

            if (!result.Item1 || (result.Item2 == null))
                logger.LogError("Failed to update a device configuration");
        }
    }

##### Python

    import os
    import io
    import json
    from clearblade.cloud import iot_v1

    def patch_device_with_rsa():
        project_id = 'YOUR_PROJECT_ID'
        cloud_region = 'us-central1'
        registry_id = 'your-registry-id'
        device_id = 'your-device-id'
        certificate_file = 'path/to/certificate.pem'
        print("Patch device with RSA_X509 certificate")

        client = iot_v1.DeviceManagerClient()
        device_path = client.device_path(project_id, cloud_region, registry_id, device_id)
        parent = client.registry_path(project_id, cloud_region, registry_id)

        with io.open(certificate_file) as f:
            certificate = f.read()

        cred = {
            "publicKey": {
                "format": iot_v1.PublicKeyFormat.RSA_X509_PEM,
                "key": certificate,
            }
        }

        getDeviceRequest = iot_v1.GetDeviceRequest(
            name=device_path
        )

        device = client.get_device(request=getDeviceRequest)
        
        device.credentials.append(cred)
        mask = "credentials"

        updateDeviceRequest = iot_v1.UpdateDeviceRequest(
            parent=parent,
            device=device,
            updateMask=mask
        )

        return client.update_device(request=updateDeviceRequest)

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    patch_device_with_rsa()

##### Go

    // patchDeviceRSA patches a device to use RSA256 X.509 credentials.
    func patchDeviceRSA(w io.Writer, projectID string, region string, registryID string, deviceID string, keyPath string) (*iot.Device, error) {
        // Authorize the client using Application Default Credentials.
        // See https://g.co/dv/identity/protocols/application-default-credentials
        ctx := context.Background()
        service, err := iot.NewService(ctx)

        if err != nil {
            return nil, err
        }

        keyBytes, err := ioutil.ReadFile(keyPath)
        if err != nil {
            return nil, err
        }

        device := iot.Device{
            Id: deviceID,
            Credentials: []*iot.DeviceCredential{
                {
                    PublicKey: &iot.PublicKeyCredential{
                        Format: "RSA_X509_PEM",
                        Key:    string(keyBytes),
                    },
                },
            },
        }

        parent := fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", projectID, region, registryID, deviceID)
        response, err := service.Projects.Locations.Registries.Devices.
            Patch(parent, &device).UpdateMask("credentials").Do()
        if err != nil {
            return nil, err
        }

        fmt.Fprintln(w, "Successfully patched device with RSA256 X.509 credentials")

        return response, nil
    }

### Credential and certificate expiration dates

When you create a device and add a public key, you can set the key's expiration date. If the key was generated with a self-signed X.509 certificate, then the certificate has an expiration date. However, these two expiration dates are separate.

If the key or the self-signed X.509 certificate on the key expires, the device cannot connect to ClearBlade IoT Core. Additionally, if you try to create or update a device with an expired X.509 certificate, ClearBlade IoT Core returns an error.

## Getting device details

### Console

1. Go to the ClearBlade IoT Core console's [Registries](https://iot.clearblade.com/iot-core/app/registries) page.

2. Click the device registry's ID.

3. Click Devices in the left menu.

4. Click the device ID to go to the Device details page. This page summarizes recent device activity, including the last time a message was published and the most recent error time. This page also shows the [device numeric ID](https://docs.clearblade.com/iotcore/devices-configuration-and-state.md#Deviceidentifiers).

5. Click the **CONFIGURATION \& STATE** tab to see the device's recent configuration versions and update times.

   ![image-20250828-210122.png](https://docs.clearblade.com/__attachments/a_efe24c7c1e1ad191929dd80538704b0d7d41ad266e492b7ff46613d025c27616/image-20250828-210122.png?cb=345b2c7ef6399cb7770b91c1504e4a1d)

The fields for the last heartbeat time and the last time a configuration was ACKed are for the MQTT bridge only. The HTTP bridge does not support heartbeat or explicit ACKs.

### API

Use these methods to get device details:

* Device [list](https://docs.clearblade.com/iotcore/list-projects-locations-registries-devices.md) method to list a registry's devices

* Device [get](https://docs.clearblade.com/iotcore/get-projects-locations-registries-devices.md) method to get a device's details

* Device [states.list](https://docs.clearblade.com/iotcore/list-projects-locations-registies-devices-states.md) method to list the device state's last few versions in descending order

#### Listing the devices in a registry code samples

##### Node.js

    // const cloudRegion = 'us-central1';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    import { DeviceManagerClient } from "@clearblade/iot";
    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function listDevices() {
      // Construct request
      const parentName = iotClient.registryPath(projectId, cloudRegion, registryId);

      // See the full list of device fields: https://clearblade.atlassian.net/wiki/spaces/IC/pages/2207809724/projects.locations.registries.devices#Resource:-Device
      const fieldMask = {
        paths: [
          "id",
          "name",
          "numId",
          "credentials",
          "lastHeartbeatTime",
          "lastEventTime",
          "lastStateTime",
          "lastConfigAckTime",
          "lastConfigSendTime",
          "blocked",
          "lastErrorTime",
          "lastErrorStatus",
          "config",
          "state",
          "logLevel",
          "metadata",
          "gatewayConfig",
        ],
      };

      const [response] = await iotClient.listDevices({
        parent: parentName,
        fieldMask,
      });
      const devices = response;

      if (devices.length > 0) {
        console.log("Current devices in registry:");
      } else {
        console.log("No devices in registry.");
      }

      for (let i = 0; i < devices.length; i++) {
        const device = devices[i];
        console.log(`Device ${i}: `, device);
      }
    }

    listDevices();

##### C#

    if (bGetDevicesList)
    {
        logger.LogInformation("Obtain list of devices for a particular registry");
        var result = await mClient.GetDevicesList(4, "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry");
        if (!result.Item1)
            logger.LogError("Failed to get list of devices");
        else
        {
            logger.LogInformation("Succeeded in getting the list of Devices");

            // Use the list
        }
    }

##### Python

    import os
    from clearblade.cloud import iot_v1

    def list_devices():
      project_id = 'YOUR_PROJECT_ID'
      cloud_region = 'us-central1'
      registry_id = 'your-registry-id'
      print("Listing devices")

      client = iot_v1.DeviceManagerClient()
      registry_path = client.registry_path(project_id, cloud_region, registry_id)

      # See the full list of device fields: https://cloud.google.com/iot/docs/reference/cloudiot/rest/v1/projects.locations.registries.devices
      # Warning! Use snake_case field names.
      maskItems = [
        "id",
        "name",
        "numId",
        "credentials",
        "lastHeartbeatTime",
        "lastEventTime",
        "lastStateTime",
        "lastConfigAckTime",
        "lastConfigSendTime",
        "blocked",
        "lastErrorTime",
        "lastErrorStatus",
        "config",
        "state",
        "logLevel",
        "metadata",
        "gatewayConfig",
      ]
      field_mask = ','.join(maskItems)

      request = iot_v1.ListDevicesRequest(
        parent=registry_path,
        fieldMask=field_mask
      )

      devices = list(
          client.list_devices(request=request)
      )
      for device in devices:
          print(device.id)

      return devices

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    list_devices()

##### Go

    // listDevices gets the identifiers of devices for a specific registry.
    func listDevices(w io.Writer, projectID string, region string, registryID string) ([]*iot.Device, error) {
        ctx := context.Background()
        service, err := iot.NewService(ctx)

        if err != nil {
            return nil, err
        }

        parent := fmt.Sprintf("projects/%s/locations/%s/registries/%s", projectID, region, registryID)
        response, err := service.Projects.Locations.Registries.Devices.List(parent).Do()
        if err != nil {
            return nil, err
        }

        fmt.Fprintln(w, "Devices:")
        for _, device := range response.Devices {
            fmt.Fprintf(w, "\t%s\n", device.Id)
        }

        return response.Devices, nil
    }

#### Retrieving a device and its metadata from a device registry code samples

##### Node.js

    // const cloudRegion = 'us-central1';
    // const deviceId = 'my-device';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    import { DeviceManagerClient } from "@clearblade/iot";
    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function getDevice() {
      // Construct request
      const devicePath = iotClient.devicePath(
        projectId,
        cloudRegion,
        registryId,
        deviceId
      );

      // See the full list of device fields: https://clearblade.atlassian.net/wiki/spaces/IC/pages/2207809724/projects.locations.registries.devices#Resource:-Device
      const fieldMask = {
        paths: [
          "id",
          "name",
          "numId",
          "credentials",
          "lastHeartbeatTime",
          "lastEventTime",
          "lastStateTime",
          "lastConfigAckTime",
          "lastConfigSendTime",
          "blocked",
          "lastErrorTime",
          "lastErrorStatus",
          "config",
          "state",
          "logLevel",
          "metadata",
          "gatewayConfig",
        ],
      };

      const [response] = await iotClient.getDevice({
        name: devicePath,
        fieldMask,
      });
      const data = response;

      console.log("Found device:", deviceId, data);
    }

    getDevice();

##### C#

    {
        logger.LogInformation("Get configuration of a device");

        // While running this sample, it is assumed that, device with name
        // "Sample-New-Device" exists and version is updated to "2"

        string name = "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry/Devices/Sample-New-Device";
        string localVersion = "2";

        var result = await mClient.GetDeviceConfig(4, name, localVersion);
        if (!result.Item1 || (result.Item2 == null))
            logger.LogError("Failed to get a device configuration");
        else
        {
            logger.LogInformation("Successfully obtained the device configuration");

            // Use the obtained information
        }
    }

##### Python

    import os
    from clearblade.cloud import iot_v1

    def get_device():
      project_id = 'YOUR_PROJECT_ID'
      cloud_region = 'us-central1'
      registry_id = 'your-registry-id'
      device_id = 'your-device-id'
      print("Getting device")

      client = iot_v1.DeviceManagerClient()
      device_path = client.device_path(project_id, cloud_region, registry_id, device_id)

      # See the full list of device fields: https://clearblade.atlassian.net/wiki/spaces/IC/pages/2207809724/projects.locations.registries.devices
      maskItems = [
        "id",
        "name",
        "numId",
        "credentials",
        "lastHeartbeatTime",
        "lastEventTime",
        "lastStateTime",
        "lastConfigAckTime",
        "lastConfigSendTime",
        "blocked",
        "lastErrorTime",
        "lastErrorStatus",
        "config",
        "state",
        "logLevel",
        "metadata",
        "gatewayConfig",
      ]
      field_mask = ','.join(maskItems)

      request = iot_v1.GetDeviceRequest(
        name=device_path
      )

      device = client.get_device(request=request)

      print("Id : {}".format(device.id))
      print("Name : {}".format(device.name))
      print("Credentials:")

      if device.credentials is not None:
        for credential in device.credentials:
            keyinfo = credential['publicKey']
            print("\tcertificate: \n{}".format(keyinfo['key']))
            print("\tformat : {}".format(keyinfo['format']))
            print("\texpiration: {}".format(credential['expirationTime']))

      print("Config:")
      print("\tdata: {}".format(device.config.get('binaryData')))
      print("\tversion: {}".format(device.config.get('version')))
      print("\tcloudUpdateTime: {}".format(device.config.get('cloudUpdateTime')))

      return device

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    get_device()

##### Go

    // getDevice retrieves a specific device and prints its details.
    func getDevice(w io.Writer, projectID string, region string, registryID string, device string) (*iot.Device, error) {
        ctx := context.Background()
        service, err := iot.NewService(ctx)
        if err != nil {
            return nil, err
        }

        path := fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", projectID, region, registryID, device)
        response, err := service.Projects.Locations.Registries.Devices.Get(path).Do()
        if err != nil {
            return nil, err
        }

        fmt.Fprintf(w, "\tId: %s\n", response.Id)
        for _, credential := range response.Credentials {
            fmt.Fprintf(w, "\t\tCredential Expire: %s\n", credential.ExpirationTime)
            fmt.Fprintf(w, "\t\tCredential Type: %s\n", credential.PublicKey.Format)
            fmt.Fprintln(w, "\t\t--------")
        }
        fmt.Fprintf(w, "\tLast Config Ack: %s\n", response.LastConfigAckTime)
        fmt.Fprintf(w, "\tLast Config Send: %s\n", response.LastConfigSendTime)
        fmt.Fprintf(w, "\tLast Event Time: %s\n", response.LastEventTime)
        fmt.Fprintf(w, "\tLast Heartbeat Time: %s\n", response.LastHeartbeatTime)
        fmt.Fprintf(w, "\tLast State Time: %s\n", response.LastStateTime)
        fmt.Fprintf(w, "\tNumId: %d\n", response.NumId)

        return response, nil
    }

#### Retrieving a device's state from a device registry code samples

##### Node.js

    // const cloudRegion = 'us-central1';
    // const deviceId = 'my-device';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    import { DeviceManagerClient } from '@clearblade/iot';
    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function listDeviceStates() {
      const devicePath = iotClient.devicePath(projectId, cloudRegion, registryId, deviceId);

      const [response] = await iotClient.listDeviceStates({ name: devicePath });
      const states = response.deviceStates;
      if (states.length === 0) {
        console.log(`No States for device: ${deviceId}`);
      } else {
        console.log(`States for device: ${deviceId}`);
      }

      for (let i = 0; i < states.length; i++) {
        const state = states[i];
        console.log('State:', state, '\nData:\n', state.binaryData.toString('utf8'));
      }
    }

    listDeviceStates();

##### C#

    {
        logger.LogInformation("Get a device");

        string name = "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry/Devices/Sample-New-Device";

        var result = await mClient.GetDevice(4, name);
        if (!result.Item1 || (result.Item2 == null))
            logger.LogError("Failed to get a device");
        else
        {
            logger.LogInformation("Successfully obtained the device");
        }
    }

##### Python

    import os
    from clearblade.cloud import iot_v1

    def list_device_states():
      project_id = 'YOUR_PROJECT_ID'
      cloud_region = 'us-central1'
      registry_id = 'your-registry-id'
      device_id = 'your-device-id'
      
      client = iot_v1.DeviceManagerClient()
      device_path = client.device_path(project_id, cloud_region, registry_id, device_id)

      getDeviceRequest = iot_v1.GetDeviceRequest(name=device_path)

      device = client.get_device(request=getDeviceRequest)
      print("Last state: {}".format(device.state))

      print("State history")
      listDeviceStatesRequest = iot_v1.ListDeviceStatesRequest(name=device_path)
      states = client.list_device_states(request=listDeviceStatesRequest).device_states
      for state in states:
          print("State: {}".format(state.binary_data))

      return states

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    list_device_states()

##### Go

    // getDeviceStates retrieves and lists device states.
    func getDeviceStates(w io.Writer, projectID string, region string, registryID string, device string) ([]*iot.DeviceState, error) {
        // Authorize the client using Application Default Credentials.
        // See https://g.co/dv/identity/protocols/application-default-credentials
        ctx := context.Background()
        service, err := iot.NewService(ctx)

        if err != nil {
            return nil, err
        }

        path := fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", projectID, region, registryID, device)
        response, err := service.Projects.Locations.Registries.Devices.States.List(path).Do()
        if err != nil {
            return nil, err
        }

        fmt.Fprintln(w, "Successfully retrieved device states!")

        for _, state := range response.DeviceStates {
            fmt.Fprintf(w, "%s : %s\n", state.UpdateTime, state.BinaryData)
        }

        return response.DeviceStates, nil
    }

## Deleting devices and registries

### Console

#### Delete devices

1. Go to the ClearBlade IoT Core console's [Registries](https://iot.clearblade.com/iot-core/app/registries) page.

2. Click the device registry's ID.

3. Click Devices in the left menu.

4. Select each device you want to delete, then click Delete.

5. Confirm you want to delete the selected devices, then click Delete.

### API

Use these methods to delete devices and registries:

* Device [delete](https://docs.clearblade.com/iotcore/delete-projects-locations-registries-devices.md) method to delete a device

* Registries [delete](https://docs.clearblade.com/iotcore/delete.md) method to delete a registry

#### Deleting a device from a registry code samples

##### Node.js

    // const cloudRegion = 'us-central1';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    import { DeviceManagerClient } from '@clearblade/iot';

    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function deleteDevice() {
      // Construct request
      const devPath = iotClient.devicePath(projectId, cloudRegion, registryId, deviceId);

      const [responses] = await iotClient.deleteDevice({ name: devPath });
      console.log('Successfully deleted device', responses);
    }

    deleteDevice();

##### C#

    if (bDeleteDevice)
    {
        logger.LogInformation("Delete a device");

        string id = "Sample-New-Device";
        string name = "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry/Devices/Sample-New-Device";

        var result = await mClient.DeleteDevice(4, id, name);
        if (!result.Item1 || (result.Item2 == null))
            logger.LogError("Failed to delete device");
        else
        {
            logger.LogInformation("Successfully deleted the device");
        }
    }

##### Python

    import os
    from clearblade.cloud import iot_v1

    def delete_device():
      project_id = 'YOUR_PROJECT_ID'
      cloud_region = 'us-central1'
      registry_id = 'your-registry-id'
      device_id = 'your-device-id'

      print("Delete device")
      
      client = iot_v1.DeviceManagerClient()

      device_path = client.device_path(project_id, cloud_region, registry_id, device_id)

      request = iot_v1.DeleteDeviceRequest(name=device_path)

      return client.delete_device(request=request)

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    delete_device()

##### Go

    // deleteDevice deletes a device from a registry.
    func deleteDevice(w io.Writer, projectID string, region string, registryID string, deviceID string) (*iot.Empty, error) {
        ctx := context.Background()
        service, err := iot.NewService(ctx)
        if err != nil {
            return nil, err
        }

        path := fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", projectID, region, registryID, deviceID)
        response, err := service.Projects.Locations.Registries.Devices.Delete(path).Do()
        if err != nil {
            return nil, err
        }

        fmt.Fprintf(w, "Deleted device: %s\n", deviceID)

        return response, nil
    }

#### Deleting a registry code samples

##### Node.js

    // Client retrieved in callback
    // const cloudRegion = 'us-central1';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';

    import { DeviceManagerClient } from '@clearblade/iot';

    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function deleteDeviceRegistry() {
      // Construct request
      const registryName = iotClient.registryPath(projectId, cloudRegion, registryId);

      const [response] = await iotClient.deleteDeviceRegistry({
        name: registryName
      });
      console.log(response);
      console.log('Successfully deleted registry');
    }

    deleteDeviceRegistry();

##### C#

    {
        logger.LogInformation("Delete a registry");
        // While running this sample, it is assumed that, registry with name
        // "Sample-New-Registry-2" exists
        string name = "Sample-New-Registry-2";
        var result = await mClient.DeleteRegistry(4, name);
        if (!result)
            logger.LogError("Failed to delete a registry");
        else
        {
            logger.LogInformation("Successfully deleted a registry");
        }
    }

##### Python

    import os
    from clearblade.cloud import iot_v1

    def delete_registry():
      project_id = 'YOUR_PROJECT_ID'
      cloud_region = 'us-central1'
      registry_id = 'your-registry-id'
      print("Delete registry")

      client = iot_v1.DeviceManagerClient()
      registry_path = client.registry_path(project_id, cloud_region, registry_id)

      request = iot_v1.DeleteDeviceRegistryRequest(name=registry_path)
      try:
          client.delete_device_registry(request=request)
          print("Deleted registry")
          return "Registry deleted"
      except Exception as e:
          print(e)
          raise

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    delete_registry()

##### Go

    // deleteDevice deletes a device from a registry.
    func deleteRegistry(w io.Writer, projectID string, region string, registryID string) (*iot.Empty, error) {
        ctx := context.Background()
        service, err := iot.NewService(ctx)
        if err != nil {
            return nil, err
        }

        name := fmt.Sprintf("projects/%s/locations/%s/registries/%s", projectID, region, registryID)
        response, err := service.Projects.Locations.Registries.Delete(name).Do()
        if err != nil {
            return nil, err
        }

        fmt.Fprintf(w, "Deleted registry: %s\n", registryID)

        return response, nil
    }

## What's next

* Connect a device over [MQTT](https://docs.clearblade.com/iotcore/publishing-over-mqtt.md) or [HTTP](https://docs.clearblade.com/iotcore/publishing-over-http.md)

---
language: "en"
---
# Data Processing Summary

This page contains details on the underlying ClearBlade IoT Core's data storage processing configuration:

1. Device state and configuration data:

   1. For each device in a given registry, up to ten of the most recent states are stored. State messages are those received FROM the device.

   2. For each device in a given registry, up to ten of the most recent configuration changes made are stored. Configuration changes are made in the registry (i.e. cloud-side) and may or may not have been sent TO the device.

   3. For a given registry, state and configuration data will be stored for the life of the registry. The data is immediately deleted when the registry is deleted.

2. Backups and Logs:

   1. ClearBlade does perform regular backups on application data. Backups are retained 14 days in storage before being deleted permanently.

   2. Logs are stored for 30 days.

3. Mitigation for Google PubSub outages:

   1. In the event of a PubSub outage the ClearBlade MQTT brokers contained within IoT Core will queue up up to 10,000 messages per registry for delivery upon the recovery of PubSub.

   2. ClearBlade uses Google's Golang PubSub library. That library retries delivery to PubSub until PubSub recovers.

---
language: "en"
---
# delete

Deletes a device registry configuration.  
Note: This is an [admin API](https://docs.clearblade.com/iotcore/admin-and-regional-api-differences.md#Admin-API).

The URL, systemKey, and token this endpoint requires are obtained differently than others. To get those, do the following:

1. Click the Select project drop-down at the top of the IoT Core UI.

2. Click the edit icon ( ![image-20250820-160436.png](https://docs.clearblade.com/__attachments/a_89673ccb152845265cb70609ea75bfdfc6bef3545a17f5fc18dcecc45efd062c/97d2813b-e223-4c01-9e8f-747a3b32fa53?cb=3fa3c2b962369c28ecd287dd3a331f4c) ) next to the desired project.

3. Go to the SERVICE ACCOUNTS tab.

4. If a service account already exists, select it and choose DOWNLOAD CREDENTIALS. If a service account does not exist, create it and select DOWNLOAD CREDENTIALS.

5. A JSON file will be downloaded to your local machine. Open the file with an editor. Use the file's systemKey, token, and URL as needed below.

## HTTP request

`DELETE {url}/api/v/4/webhook/execute/{systemKey}/cloudiot`

### Query parameters

|                                                             Parameters                                                             ||
|--------|----------------------------------------------------------------------------------------------------------------------------|
| `name` | `string` The device registry's name. For example, `projects/example-project/locations/us-central1/registries/my-registry`. |

### Header parameters

|                                           Parameters                                           ||
|------------------------|------------------------------------------------------------------------|
| `ClearBlade-UserToken` | See the note at the start of this document on where to find the token. |

### Request body

The request body must be empty.

### Response status codes

| Code | Meaning |
|------|---------|
| 204  | Success |

### Response body

If successful, the response body will be empty.

#### Example curl

`curl 'https://iot.clearblade.com/api/v/4/webhook/execute/aae9b9b30c8aa4e49081c7eeb9bb07/cloudiot?name=projects/iot-core-test-363819/locations/us-central1/registries/two' -X DELETE -H 'ClearBlade-UserToken: {token}'`

Using the instructions at the start of this document, replace the following: `https://iot.clearblade.com` with your URL. `aae9b9b30c8aa4e49081c7eeb9bb07` with your systemKey. {token} with your token.

This command deletes a registry with registryId "two." Replace the name with your registry's name.

---
language: "en"
---
# delete: projects.locations.registries.devices

Deletes a device.  
Note: This is a [regional API](https://docs.clearblade.com/iotcore/admin-and-regional-api-differences.md#RegionalAPI).

You can find the URL, SystemKey, and token required in the call by clicking API Keys (key icon) at the top-right of the Registry Details page. Use the Registry Keys section.

## HTTP request

`DELETE {URL}/api/v/4/webhook/execute/{SystemKey}/cloudiot_devices`

### Query parameters

|                                                                                                                                                            Parameters                                                                                                                                                             ||
|--------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `name` | `string` The device's name. For example, `projects/p0/locations/us-central1/registries/registry0/devices/device0` or `projects/p0/locations/us-central1/registries/registry0/devices/{numId}`. The device's name can be set to the deviceId or numId (i.e., without the project, location, and registry info. prepended). |

### Header parameters

|                                           Parameters                                           ||
|------------------------|------------------------------------------------------------------------|
| `ClearBlade-UserToken` | See the note at the start of this document on where to find the token. |

### Request body

The request body must be empty.

### Response status codes

| Code | Meaning |
|------|---------|
| 200  | Success |

### Response body

If successful, the response body will be empty.

---
language: "en"
---
# Deploying a GCP function that uses the Node.js SDK

To use the Node.js SDK, you must supply service account credentials via an environment variable or constructor. Do the following to use an environment variable for the service account JSON file:

1. Save your credentials JSON file in your function's directory (i.e., in the same folder with the entry point index.js file). In this example, it will be saved in a file named `dev-credentials.json` in a `lib` folder.

2. When deploying your function with the `gcloud functions deploy` command, use the `--set-env-vars` flag to set the path. It must be prefixed with `/workspace` to work correctly. Example: `--set-env-vars CLEARBLADE_CONFIGURATION=/workspace/lib/dev-credentials.json`.

---
language: "en"
---
# Device security

Security is a critical concern when deploying and managing IoT devices. ClearBlade IoT Core offers these security features:

* Per-device public/private key authentication using JSON Web Tokens (JWTs, [RFC 7519](https://tools.ietf.org/html/rfc7519)).

  * This limits an attack's surface area because a compromised key would affect only a single device and not the whole fleet.

  * JWTs are valid for a limited duration, so any compromised keys will expire.

* Support for RSA or elliptic curve algorithms to verify signatures, with enforcement for strong key sizes.

* Support to rotate keys per device by allowing concurrent keys to be registered and support for expiration time per credential.

* [TLS 1.2](https://www.ietf.org/rfc/rfc5246.txt) connection, using root certificate authorities (required for MQTT).

* User accounts with limited roles and permissions control ClearBlade IoT Core API access.

## Provisioning credentials

The following diagram summarizes the process for provisioning device credentials. The authenticated provisioner, often the user configuring the device, is assumed to have created a project and registry and has permission to create devices. The provisioner uses the ClearBlade IoT Core API or Console to create a logical device in the cloud.  
![image-20231002-200021.png](https://docs.clearblade.com/__attachments/a_b3c733c09ec317ff767d9bed1dd9ba38ffd702fe3955e3c0eecece4e5f1efd37/image-20231002-200021.png?cb=2709e6bc491cf16b42ead89d3d5fe256)

1. The provisioner generates the public-private key pair.

2. The provisioner creates the device using the ClearBlade IoT Core API or Console, specifying the public key just created. This will be used to verify the device's identity.

3. The ClearBlade IoT Core device manager stores the device resource and public key.

4. The device manager responds to the provisioner, indicating the device was created.

5. The private key is stored on the device to use later for authentication. The hardware Trusted Platform Module (TPM) can be used for this step.

The order of steps is not prescriptive. For example, the key can be stored on the device before the device has been registered in ClearBlade IoT Core.

For information on creating keys, see [Creating key pairs](https://docs.clearblade.com/iotcore/creating-key-pairs.md).

## Authentication

This diagram summarizes authentication in ClearBlade IoT Core using MQTT:  
![image-20231002-200153.png](https://docs.clearblade.com/__attachments/a_0e859f58883c18c17fd0ffefa932560ae59c94d38a55b54292b8ce347dcf2cf3/image-20231002-200153.png?cb=e1e9f74589bfa4023bd8a5b814c7ecef)

1. The device prepares a JSON Web Token (JWT), as described in [Using JSON Web Tokens](https://docs.clearblade.com/iotcore/using-json-web-tokens.md). The JWT is signed with the private key from the authentication flow.

2. When connecting to the MQTT bridge, the device presents the JWT as the password in the MQTT `CONNECT` message. The username content is ignored; however, some MQTT client libraries will not send the password unless the username is specified. For best results, set the username to an arbitrary value like `unused` or `ignored`.

3. The MQTT bridge verifies the JWT against the device's public key.

4. The MQTT bridge accepts the connection.

5. The connection is closed when the JWT expires (after accounting for the allowed clock drift).

## Security standards

ClearBlade IoT Core uses digital signature--based authentication for RSA and elliptic curve signed tokens. These algorithms are supported:

* JWT `RS256` (RSASSA-PKCS1-v1_5 using SHA-256 [RFC 7518 sec 3.3](https://tools.ietf.org/html/rfc7518#section-3.3))

* JWT `ES256` (ECDSA using P-256 and SHA-256 [RFC 7518 sec 3.4](https://tools.ietf.org/html/rfc7518#section-3.4)), defined in OpenSSL as the prime256v1 curve

The RSA algorithm is commonly used and is widely supported by client libraries. However, the generated keys and signatures can be large (one to two kilobytes). Additionally, RSA can use a significant amount of resources (regarding key length and CPU), affecting devices with limited resources.

The elliptic curve algorithm is well supported but is less widely used than RSA. You may have to install additional dependencies in your client library to use the elliptic curve. However, the generated keys and signatures are significantly smaller than those generated by RSA, which can be useful for devices with limited resources.

## Key strength

A 112-security bit minimum is required by ClearBlade IoT Core, following [NIST recommendations](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r4.pdf) (Section 5.6.2, pages 55-56). This translates to a minimum 2048-bit key size for RS256 (see Table 2 in the NIST recommendations, page 53).

ES256 has a 128-security bit preset level (fixed key size).

## Public key format

When registering a device's public key, it must be in one of these formats:  

|     Format     |                                                                                                                                                      Description                                                                                                                                                       |
|----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| RSA_PEM        | An RSA public key encoded in base64. It can verify RS256 signatures in JWT tokens ([RFC 7518](https://www.ietf.org/rfc/rfc7518.txt)).                                                                                                                                                                                  |
| RSA_X509_PEM   | An RSA_PEM key encoded in base64, wrapped in an X.509v3 certificate ([RFC 5280](https://www.ietf.org/rfc/rfc5280.txt)). The certificate can be self-signed. Otherwise, ClearBlade IoT Core can compare the device certificate signature against the registry-level certificates to verify the certificate's origin.    |
| ES256_PEM      | The ECDSA algorithm's public key (using P-256 and SHA-256) encoded in base64. It can verify JWT tokens with the ES256 algorithm ([RFC 7518](https://www.ietf.org/rfc/rfc7518.txt)). This public key is not wrapped in a certificate; this keeps the key size small, which is one of ES256's main advantages.           |
| ES256_X509_PEM | An ES256_PEM key, encoded in base64, wrapped in an X.509v3 certificate ([RFC 5280](https://www.ietf.org/rfc/rfc5280.txt)). The certificate can be self-signed. Otherwise, ClearBlade IoT Core can compare the device certificate signature against the registry-level certificates to verify the certificate's origin. |

The RSA_PEM and ES256_PEM keys begin with `-----BEGIN PUBLIC KEY-----` and end with `-----END PUBLIC KEY-----`. The RSA_X509_PEM and ES256_X509_PEM keys begin with `-----BEGIN CERTIFICATE-----` and end with `-----END CERTIFICATE-----`.

For information on creating keys, see [Creating public/private key pairs](https://docs.clearblade.com/iotcore/creating-key-pairs.md).

## Key rotation

ClearBlade IoT Core supports multiple active keys (up to 3 per device) to allow uninterrupted rotation. The service will try to verify JWTs with each active key and will accept a connection if any active key matches.

The API allows you to define an `expirationTime` for each [device credential](https://docs.clearblade.com/iotcore/projects-locations-registries-devices.md) (public key). After it expires, the key will be ignored, but it will not be automatically deleted. A 10-minute clock-skew allowance applies, and a key will never expire if no expiration time is specified.

## Device security recommendations

ClearBlade IoT Core does not enforce these security recommendations but will help you secure your devices and connections:

* Keep the private key secret.

* Use TLS 1.2 when communicating with `mqtt.googleapis.com` or `mqtt.2030.ltsapis.goog` on ports 8883 and 443. To maintain TLS connections:

  * Verify that the server certificate is valid using a [root CA certificate](https://docs.clearblade.com/iotcore/retargeting-devices.md#Root-CA).

  * Perform regular security-related firmware updates to keep server certificates up-to-date.

* Each device should have a unique [public/private key pair](https://docs.clearblade.com/iotcore/creating-key-pairs.md). If multiple devices share a single key and one is compromised, an attacker could impersonate the devices configured with that one key.

* Keep the public key secure when registering it with ClearBlade IoT Core. If an attacker can tamper with the public key and trick the provisioner into swapping it and registering the wrong one, the attacker can authenticate on the device's behalf.

* The key pair to authenticate the device to ClearBlade IoT Core should not be used for other purposes or protocols.

* Depending on the device's ability to store keys securely, key pairs should be rotated periodically. When practical, all keys should be discarded when the device is reset.

* If your device runs an operating system, update it securely. For devices that don't have an operating system, ensure that you can securely update the device's software if security vulnerabilities are discovered after deployment.

* Ensure that you have a way to update root certificates.

* Ensure that the device clock is not tampered with. If it is compromised, an attacker can trick the device into issuing tokens that will be valid in the future, circumventing the token's expiration time. For best results, use the [Google Public NTP server](https://developers.google.com/time/).

---
language: "en"
---
# Devices, configuration, and state

## Device registration

For a device to connect, it must first be registered in the device manager. The device manager lets you create and configure device registries and the devices within them. The device manager can be used through the ClearBlade IoT Core or REST-style API.

### Device registries

A device registry is a device container.  
![image-20250827-180305.png](https://docs.clearblade.com/__attachments/a_0ff8141f4aa77ae5a1ce96eeed060b993ef45e2774a4a52f2684c05a4e44bc23/image-20250827-180305.png?cb=31cb32d4719e56ebc40aea6aa9143d4d)
Example **Registry Details** page

* Each device registry is created in a specific cloud region and belongs to a cloud project.

* A registry is identified in the ClearBlade IoT Core service by its full name as `projects/{project-id}/locations/{cloud-region}/registries/{registry-id}`.

* The device registry is configured with one or more [Cloud Pub/Sub](https://cloud.google.com/pubsub) topics to which telemetry events are published for that registry's devices. A single topic can be used to collect data across all regions.

* Integrated monitoring, logging, and trace managed services are automatically enabled for each registry.

* [Identity and Access Management (IAM)](https://cloud.google.com/iam) manages access to Google Cloud Pub/Sub, Google Cloud Logging, and Google Cloud Monitoring.

* For device registry ID naming and size requirements, see [Permitted characters and size requirements](https://docs.clearblade.com/iotcore/requirements.md#Permittedcharactersandsizerequirements).

For details, see the [DeviceRegistry resource reference](https://docs.clearblade.com/iotcore/projects-locations-registries.md).

### Devices

When you create a device within a registry, you define it as a ClearBlade IoT Core resource. You can then view device details and control some properties.  
![image-20250827-180551.png](https://docs.clearblade.com/__attachments/a_84286cbc19926e0564e8b073c13c06871b878fc067741535d98dbcb5b191c23b/image-20250827-180551.png?cb=7b7079fbf132bc89e86aa721eed724b0)
Example **Device Details** page

* A device can be blocked from communicating with ClearBlade IoT Core. This can be useful when a sensor fails or a device is misconfigured.

* Device timestamps show the most recent heartbeat and telemetry event received.

* Each device can be identified by its full resource name: `projects/{project-id}/locations/{cloud-region}/registries/{registry-id}/devices/{device-id}` or `projects/{project-id}/locations/{cloud-region}/registries/{registry-id}/devices/{device-numeric-id}`. See the next section for more information on the device ID and numeric ID.

For details, see the [Device resource reference](https://docs.clearblade.com/iotcore/projects-locations-registries-devices.md).

Observe the ClearBlade IoT Core device [quotas and limits](https://docs.clearblade.com/iotcore/quotas-and-limits.md).

## Device identifiers

Each device has the following identifiers:

* A user-defined device ID. For device ID naming and size requirements, see [Permitted characters and size requirements](https://docs.clearblade.com/iotcore/requirements.md#Permittedcharactersandsizerequirements).

* A server-generated device numeric ID. ClearBlade IoT Core automatically creates the device numeric ID; it's globally unique and not editable. To view a device numeric ID, go to the [Device details](https://docs.clearblade.com/iotcore/creating-registries-and-devices.md#Gettingdevicedetails) page.

* The device's full path is described in the preceding section.

## Device metadata

You can define device metadata, such as hardware thumbprint, serial number, manufacturer information, or any other attribute. ClearBlade IoT Core does not interpret or index device metadata. In theory, device metadata is more secure than device state or device configuration because it is never sent to or from a device. This means the metadata cannot be read if a device is compromised.

Device metadata shouldn't change often; update it no more often than once daily for the best results.

When you [add or edit a device](https://docs.clearblade.com/iotcore/creating-registries-and-devices.md), you can define up to 500 key-value pairs, and each key must be unique.

For device metadata key-value naming and size requirements, see [Permitted characters and size requirements](https://docs.clearblade.com/iotcore/requirements.md#Permittedcharactersandsizerequirements).

## Device configuration

With ClearBlade IoT Core, you can control a device by sending it a device [configuration](https://docs.clearblade.com/iotcore/configuring-devices.md). A device configuration is an arbitrary user-defined data blob sent from ClearBlade IoT Core to a device. The data can be structured or unstructured. It can also be of any format, such as arbitrary binary data, text, JSON, or serialized protocol buffers.

Device configuration is persisted in storage by ClearBlade IoT Core. The maximum configuration data size is 64 KB. For additional limits, see [Quotas and limits](https://docs.clearblade.com/iotcore/quotas-and-limits.md).

A device configuration should focus on desired values or results rather than a command sequence. If you specify commands, intermediate configuration versions may create conflicts, and restoring the device's state won't be possible (without executing every command sequence since the device was first initialized). You can easily restore the device state if your configurations emphasize values and results.

### Configuration versions

#### MQTT bridge

For a given MQTT connection, a device receives configurations only in increasing order of version numbers; it will never be sent a configuration older than its current version. However, if the device reconnects to the MQTT bridge, it may receive an older configuration than it did during the earlier connection (but this should be rare, and the device will eventually receive the latest version).

A device is not guaranteed to receive every configuration update; rather, it will always receive the latest update. Devices may not receive intermediate versions if a configuration is being updated rapidly.

When modifying a device configuration, you can specify the version number to be modified. This protects against overwriting a configuration with concurrent changes.

#### HTTP bridge

Devices connecting over HTTP can specify the local version (the configuration version on the device). ClearBlade IoT Core will return only a more recent version, as described in the [HTTP bridge](https://docs.clearblade.com/iotcore/publishing-over-http.md#Updatingdeviceconfiguration) section.

## Device state

Device state information captures the device's status, not the environment. Devices can describe their state with an arbitrary user-defined data blob sent from the device to the cloud. The data can be structured or unstructured. It can also be of any format, such as binary data, text, JSON, or serialized protocol buffers.

Some device state examples include the device's health and firmware version. Typically, device state information is not updated frequently.  
![image-20250828-210122.png](https://docs.clearblade.com/__attachments/a_3e9e7b6bfd2c73cf5422ed02d74f2d9a1a44f8b7cd28e6efc527670b0e5f5d55/image-20250828-210122.png?cb=345b2c7ef6399cb7770b91c1504e4a1d)
**CONFIGURATION \& STATE** - the 10 most recent configurations sent and states received per device

## Differences between device metadata, configuration, and state

Using configuration and state together, you can answer questions like: What does the device think it should be doing? How does that compare to the most recent device configuration? In contrast, metadata serves primarily as a device label or identifier.

Configuration data is sent to the device from ClearBlade IoT Core. The device sends state data to ClearBlade IoT Core. Configuration is an external instruction sent to a device, and state is a device's internal representation. Configuration and state data can have the same schema and encoding or be different.

Information that needs to be sent to or from a device should not be stored as device metadata because device metadata stays in the cloud. That information should be in a device configuration if you send it to a device or in device state data if you report it back to ClearBlade IoT Core.

The following example explains the different uses of metadata, configuration, and state using the scenario of devices in a building:

* Suppose that you have several devices on each floor in a building. To identify devices on the seventh floor, you could add a `'floor': '7'` metadata key-value pair to the devices on the seventh floor. Applying this metadata information provides a way of identifying the devices. Still, because metadata is not interpreted or indexed, the metadata can only be used for identification purposes.

* You could send a configuration to each device to change the building's device state. This would comprise an arbitrary data blob containing the device's desired temperature and whether the device's lights are turned on or off:

      {
        temperature: 50
        lights: off
      }

  The configuration alone does not change the device's temperature or turn its lights on or off; it is up to the device to interpret the configuration and use its logic to carry out the command. Over the next several hours, the device configuration will not change (unless you update and send a new configuration). Still, the device's state should change as the temperature increases or decreases and the device turns its lights off.
* To verify the configuration was correctly applied, and the devices are in the correct state, each device can report its state (whether it's on or off, what its temperature is, and that its temperature is less than or equal to 50 degrees) to ClearBlade IoT Core.

The following table shows the differences between device metadata, configuration, and state:  

|                       |                                                                                                                                                  Device metadata                                                                                                                                                  |                                                               Device configuration                                                               |                       Device state                       |
|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------|
| Description           | Defines and classifies devices                                                                                                                                                                                                                                                                                    | * Updates a device's state by sending the expected state as a configuration * Controls a device by providing commands in a configuration         | Captures the device's state                              |
| Content               | Key-value string pairs                                                                                                                                                                                                                                                                                            | An arbitrary user-defined data blob                                                                                                              | An arbitrary user-defined data blob                      |
| Limitations           | Keys: * Permitted characters: `[a-zA-Z][-a-zA-Z0-9._+~%]+` * The first character must be a letter (`[a-zA-Z]`) * Minimum length: 1 character * Maximum length: 128 characters Values: * Minimum size: 0 KB * Maximum size: 32 KB The maximum combined total size of all device metadata key-value pairs is 256 KB | * Maximum size: 64 KB * Limited to 1 QPS per device                                                                                              | * Maximum size: 64 KB * Limited to 1 QPS per device      |
| Use cases             | Store a device's serial number and manufacturer information as a key-value pair                                                                                                                                                                                                                                   | * Send a configuration containing a firmware version to tell a device which firmware version it should be on * Send a reboot command to a device | Retrieve a device's health (such as the crash frequency) |
| Message direction     | None                                                                                                                                                                                                                                                                                                              | ClearBlade IoT Core-to-device only                                                                                                               | Device-to-ClearBlade IoT Core only                       |
| Recommended frequency | No more often than once daily per device                                                                                                                                                                                                                                                                          | Less than 0.1 QPS                                                                                                                                | Less than 0.1 QPS                                        |

## Changing device behavior or state using configuration data

### Sending the desired state as configuration data

Device configuration data stored in ClearBlade IoT Core can be used to change the device's state. For example, suppose the device's configuration is represented as follows:

#### DeviceConfig

    {
        firmwareVersionRequest: 1.11
    }

Your MQTT or HTTP client could interpret this configuration data as instructions for changing the device's state --- in this case, check that the device is on firmware version 1.11. The device can then send its state to ClearBlade IoT Core to show which firmware version it has:

#### DeviceState

    {
        firmwareVersion: 1.11
    }

### Modeling commands using configuration and state data

Device configuration data stored in ClearBlade IoT Core can be used to model device commands. For example, suppose the device's configuration is represented as follows:

#### DeviceConfig

    {
      rebootRequested: true
    }

Your MQTT or HTTP client could interpret this configuration data as instructions to execute actions --- in this case, send a reboot command. The device can then show the results by reporting its state and showing that one second has elapsed since its last reboot:

#### DeviceState

    {
      last_reboot: 1
    }

### Structuring configuration data

Configuration data can also be more structured and include command expiration details:

#### DeviceConfig

    {
      commands: {
        id1: {
          type: REBOOT
          requestedTimestamp: xxxx
          expirationTimestamp: yyyy
        }
        id2: ...
      }
    }

Your client could read these commands and update the device state accordingly, supplying a reboot timestamp and potentially an error message.

#### DeviceState

    {
      commandResults: {
        id1: {
          type: REBOOT
          completedTimestamp: zzzz
          errorMessage: >empty<
        }
        id2: ...
      }
    }

This model can be a command-and-response relationship between the client and devices. If the expiration time is used, synchronize the device's clock.

---
language: "en"
---
# DigiCert G1 Root CA Distrust

**UPDATE:** February 16, 2026

ClearBlade has obtained a special extension for the IoT Core G1 server certificates. The deadline for migrating all devices to the G5 root certificate has been extended to **March 29, 2027 at 10am CT**.

As part of standard internet best practices, DigiCert has announced that the distrust date for the G1 Root CA will be April 15, 2026. ClearBlade will provide customers a path to migrate from the G1 to the G5 root file from now until end of year 2025.

*ClearBlade understands this is a complex issue and has enabled its sales, support, and services teams to provide additional assistance. If you have any questions, please do not hesitate to open a* [*Service Desk Ticket*](https://clearblade.atlassian.net/servicedesk/customer/portal/1/group/1/create/20)*or email your dedicated customer success agent.*

To ensure your devices experience no period of disconnection, the following schedule will be used:

**Schedule:**

* **September 15, 2024:** New URLs are available for IoT Core users to begin migrating ECC or RSA-based cryptography users. [++Click here++](https://docs.clearblade.com/iotcore/retargeting-devices.md) to find those URLs.

* **December 31, 2025:** Technical Support no longer available for devices connecting using the legacy URLs and the DigiCert G1 Root CA.

* **March 29, 2027 - 10am CT:** The legacy URLs will be updated to use the TLS Certificate signed by the DigiCert G5 Root CA. Any devices still reliant on DigiCert G1 Root CA will no longer be able to connect via MQTT or HTTP to any IoT Core Region.

**More Information:**

* Why is the G1 being retired? - [++Link++](https://clearblade.us7.list-manage.com/track/click?u=8417db78764425c24c9826bfb&id=2f7d8f31e5&e=4574acf756)

* What are the new URLs? - [++Link++](https://docs.clearblade.com/iotcore/retargeting-devices.md)

* Where can I find the G5 RSA Root CA File or the G5 ECC Root CA File? - [++Link++](https://docs.clearblade.com/iotcore/retargeting-devices.md)

* What about my IoT Enterprise offering? - ClearBlade will support IoT Enterprise users individually for a smooth transition.

---
language: "en"
---
# Embedded C

The ClearBlade IoT Device Embedded C SDK is available [here](https://github.com/ClearBlade/iot-device-sdk-embedded-c).

---
language: "en"
---
# GatewayInfo

Used for PublishEventRequest, SetDeviceStateRequest, and GetDeviceConfigRequest if sent through a gateway. Specify `delegatedDeviceId` or `gatewayId`. The resource path and authorization token can correspond to the device or gateway.

These cases illustrate the field's use:

1. The request is for a device and is not sent through a gateway. The resource path and authorization token belong to the device. `gatewayInfo` should NOT be set.

2. The request is for the gateway, not for a delegated device. The resource path and authorization token belong to the gateway. `gatewayInfo` should NOT be set.

3. The request has the gateway's resource path and authorization token, but the gateway requests on a device's behalf. `gatewayInfo.delegated_device_id` MUST be set to the delegated device's ID.

4. The request has the device's resource path and authorization token and is sent through a gateway. `gatewayInfo.gateway_id` MUST be set to the gateway's ID.

|                                                                                     JSON representation                                                                                     |
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| { // Union field gateway_or_device can be only one of the following: "delegatedDeviceId": string, "gatewayId": string // End of list of possible types for union field gateway_or_device. } |

|                                                            Fields                                                            ||
|---------------------|---------------------------------------------------------------------------------------------------------|
| Union field `gateway_or_device`. Delegated_device_id or gateway_id is set. `gateway_or_device` can be only one of the following: ||
| `delegatedDeviceId` | `string` The delegated device's ID. Set only if the request's resource name corresponds to the gateway. |
| `gatewayId`         | `string` The gateway's ID. Set only if the request's resource name corresponds to the delegated device. |

---
language: "en"
---
# GatewayListOptions

Options for limiting the list based on gateway type and associations.  

|                                                                                                    JSON representation                                                                                                     |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| { // Union field filter can be only one of the following: "gatewayType": enum(GatewayType), "associationsGatewayId": string, "associationsDeviceId": string // End of list of possible types for the union field filter. } |

|                                                                                                                                              Fields                                                                                                                                              ||
|-------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Union field `filter`. If not set, all devices and gateways are returned. If set, the list is filtered based on gateway type and associations. `filter` can be only one of the following:                                                                                                         ||
| `gatewayType`           | `enum(GatewayType)` If `GATEWAY` is specified, only gateways are returned. If `NON_GATEWAY` is specified, only non-gateway devices are returned. If `GATEWAY_TYPE_UNSPECIFIED` is specified, all devices are returned.                                                  |
| `associationsGatewayId` | `string` If set, only devices associated with the specified gateway are returned. The gateway ID can be numeric (`numId`) or the user-defined string (`id`). For example, if `123` is specified, only devices bound to the gateway with `numId` 123 are returned.       |
| `associationsDeviceId`  | `string` If set, returns only the gateways associated with the specified device. The device ID can be numeric (`numId`) or the user-defined string (`id`). For example, if `456` is specified, returns only the gateways to which the device with `numId` 456 is bound. |

---
language: "en"
---
# get

Gets a device registry configuration.  
Note: This is a [regional API](https://docs.clearblade.com/iotcore/admin-and-regional-api-differences.md#RegionalAPI).

You can find the URL, SystemKey, and token required in the call by clicking API Keys (key icon) at the top-right of the Registry Details page. Use the Registry Keys section.

## HTTP request

`GET {URL}/api/v/4/webhook/execute/{SystemKey}/cloudiot`

### Query parameters

|                                                                     Parameters                                                                     ||
|--------|--------------------------------------------------------------------------------------------------------------------------------------------|
| `name` | `string` The device registry's name. For example, `projects/example-project/locations/us-central1/registries/my-registry` or `my-registry` |

### Header parameters

|                                           Parameters                                           ||
|------------------------|------------------------------------------------------------------------|
| `ClearBlade-UserToken` | See the note at the start of this document on where to find the token. |

### Request body

The request body must be empty.

### Response status codes

| Code | Meaning |
|------|---------|
| 200  | Success |

### Response body

If successful, the response body contains a [DeviceRegistry](https://docs.clearblade.com/iotcore/projects-locations-registries.md#Resource:DeviceRegistry) instance.

#### Example curl

`curl 'https://us-central1.clearblade.com/api/v/4/webhook/execute/aae9b9b30c8aa4e49081c7eeb9bb07/cloudiot?name=test-reg' -H 'ClearBlade-UserToken: {Token}'`

OR

`curl 'https://us-central1.clearblade.com/api/v/4/webhook/execute/aae9b9b30c8aa4e49081c7eeb9bb07/cloudiot?name=test-reg' -X GET -H 'ClearBlade-UserToken: {Token}'`

Using the instructions at the start of this document, replace the following: `https://us-central1.clearblade.com` with your URL. `aae9b9b30c8aa4e49081c7eeb9bb07` with your SystemKey. {Token} with your token.

---
language: "en"
---
# get: projects.locations.registries.devices

Gets a device's details.  
Note: This is a [regional API](https://docs.clearblade.com/iotcore/admin-and-regional-api-differences.md#RegionalAPI).

You can find the URL, SystemKey, and token required in the call by clicking API Keys (key icon) at the top-right of the Registry Details page. Use the Registry Keys section.

## HTTP request

`GET {URL}/api/v/4/webhook/execute/{SystemKey}/cloudiot_devices`

### Query parameters

|                                                                                                                                                                                 Parameters                                                                                                                                                                                  ||
|----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `name`         | `string` The device's name. For example, `projects/p0/locations/us-central1/registries/registry0/devices/device0` or `projects/p0/locations/us-central1/registries/registry0/devices/{numId}`. The device's name can be set to the deviceId or numId (i.e., without the project, location, and registry info. prepended).                                   |
| `fieldMask`    | `string (FieldMask format)` The `Device` resource's fields to be returned in the response. If the field mask is unset or empty, all fields are returned. A comma-separated list of field names.                                                                                                                                                             |
| `base64Encode` | `string` Optional parameter that designates whether state binaryData is to be returned as base64-encoded strings. If the parameter is present, its value must be true or false (case is ignored). If the parameter is missing, the result is the same as if it was present and its value was false. I.e., state binaryData is returned, NOT base64-encoded. |

### Header parameters

|                                           Parameters                                           ||
|------------------------|------------------------------------------------------------------------|
| `ClearBlade-UserToken` | See the note at the start of this document on where to find the token. |

### Request body

The request body must be empty.

### Response status codes

| Code | Meaning |
|------|---------|
| 200  | Success |

### Response body

If successful, the response body contains a [device](https://docs.clearblade.com/iotcore/projects-locations-registries-devices.md#Resource:Device) instance.

---
language: "en"
---
# getConfig: project.locations.registries.devices

Gets the device's configuration.  
Note: This is a [regional API](https://docs.clearblade.com/iotcore/admin-and-regional-api-differences.md#RegionalAPI).

You can find the URL and SystemKey required in the call by clicking API Keys (key icon) at the top-right of the Registry Details page.

A **ClearBlade-UserToken** header is required to call this API. Its value is set as follows:

* If using IoT Core **Standard** the value can be either...

  * The **Token** found under API Keys OR

  * A [JWT](https://docs.clearblade.com/iotcore/using-json-web-tokens.md) generated as specified [here](https://docs.clearblade.com/iotcore/admin-and-regional-api-differences.md#Credentials-for-APIs-called-by-devices) and signed by the private key of the device specified in the **name**Query parameter (see below). A JWT for any other user or device will be rejected.

* If using IoT Core **Enterprise** the value MUST be a [JWT](https://docs.clearblade.com/iotcore/using-json-web-tokens.md) generated as specified [here](https://docs.clearblade.com/iotcore/admin-and-regional-api-differences.md#Credentials-for-APIs-called-by-devices) and signed by the private key of the device specified in the **name**Query parameter (see below). A JWT for any other user or device will be rejected.

## HTTP request

`GET {URL}/api/v/4/webhook/execute/{SystemKey}/cloudiotdevice_devices`

### Query parameters

|                                                                                                                                                                                          Parameters                                                                                                                                                                                           ||
|----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `name`         | `string` The device's name. For example, `projects/p0/locations/us-central1/registries/registry0/devices/device0` or `projects/p0/locations/us-central1/registries/registry0/devices/{numId}`. The device's name can be set to the deviceId or numId (i.e., without project, location, and registry info. prepended).                                                         |
| `localVersion` | `string (int64 format)` If zero, returns the current device configuration from ClearBlade IoT Core. If nonzero, specifies the device configuration's local version. The server returns config data only if a newer version from ClearBlade IoT Core is available. If this value exceeds the latest version available in ClearBlade IoT Core, returns an `OUT_OF_RANGE` error. |
| `gatewayInfo`  | `object(GatewayInfo)` Set if the message is sent through a gateway or a gateway is making the request on a device's behalf.                                                                                                                                                                                                                                                   |

### Header parameters

|                                           Parameters                                           ||
|------------------------|------------------------------------------------------------------------|
| `ClearBlade-UserToken` | See the note at the start of this document on where to find the token. |

### Request body

The request body must be empty.

### Response status codes

| Code | Meaning |
|------|---------|
| 200  | Success |

### Response body

If successful, the response body contains data with this structure:  

|             JSON representation             |
|---------------------------------------------|
| { "version": string, "binaryData": string } |

|                                        Fields                                         ||
|--------------|-------------------------------------------------------------------------|
| `version`    | `string (int64 format)` ClearBlade IoT Core's configuration version.    |
| `binaryData` | `string (bytes format)` Data in binary format. A base64-encoded string. |

---
language: "en"
---
# getIamPolicy

Get a specified resource's IAM policy.  
Note: This is an [admin API](https://docs.clearblade.com/iotcore/admin-and-regional-api-differences.md#Admin-API).

## Required permission

To call this endpoint, you must have the following permission:

`cloudiot.registries.getIamPolicy`

### HTTP request

`GET /api/v/4/webhook/execute/{adminSysKey}/policy?method=getIamPolicy`

### Query parameters

|                                   Parameters                                    ||
|----------------|-----------------------------------------------------------------|
| `project_area` | `string` The project's ID for which you want to get the policy. |
| `registry_id`  | (optional) The registry's ID for which you want the policy.     |
| `region`       | (optional) The registry's region for which you want the policy. |

If registry_id and region are included, the request will return the roles assigned at that registry's level. If they are omitted, the request will return the roles assigned at the project's level.

### Response body

If successful, the response body contains a [CbPolicy](https://docs.clearblade.com/iotcore/policy.md#CbPolicyCbPolicy).

#### Example

`https://iot.clearblade.com/api/v/4/webhook/execute/aae9b9b30c8aa4e49081c7eeb9bb07/policy?method=getIamPolicy&project_area=myProject123&region=us-central1&registry_id=myRegistry123`

---
language: "en"
---
# getProjectCredentials (Enterprise)

Gets a service account's credentials.

To obtain this endpoint's required URL, systemKey, and token, do the following:

1. Click the Select project drop-down at the top of the IoT Core UI.

2. Click the Edit icon (pencil) next to the desired project.

3. Go to the SERVICE ACCOUNTS tab.

4. If a service account already exists, select it and choose DOWNLOAD CREDENTIALS. If a service account does not exist, create it and select DOWNLOAD CREDENTIALS.

5. A JSON file will be downloaded to your local machine. Open the file with an editor. Use the systemKey, token, and URL from the file as needed below.

## HTTP request

`POST {URL}/api/v/1/code/{SystemKey}/getProjectCredentials`

### Header parameters

|                                           Parameters                                           ||
|------------------------|------------------------------------------------------------------------|
| `ClearBlade-UserToken` | See the note at the start of this document on where to find the token. |

### Request body

|         JSON representation          |
|--------------------------------------|
| JSON { "projectId": "<project_id>" } |

### Response status codes

| Code | Meaning |
|------|---------|
| 200  | Success |

### Response body

|                            JSON representation                             |
|----------------------------------------------------------------------------|
| JSON { "type": "<type>", "projectId": "<project_id>", "email": "<email>" } |

#### Example curl

`curl -X POST 'https://iot.clearblade.com/api/v/1/code/aae9b9b30c8aa4e49081c7eeb9bb07/getProjectCredentials' -H 'ClearBlade-UserToken: {token}' -d '{"projectId": "abc"}'`

Using the instructions at the start of this document, replace the following: `https://iot.clearblade.com` with your URL. `aae9b9b30c8aa4e49081c7eeb9bb07` with your systemKey. {token} with your token.

---
language: "en"
---
# getRegistryCredentials

Gets a registry's credentials to be used for [admin APIs](https://docs.clearblade.com/iotcore/admin-and-regional-api-differences.md#Admin-API).

To obtain this endpoint's required URL, systemKey, and token, do the following:

1. Click the Select project drop-down at the top of the IoT Core UI.

2. Click the Edit icon (pencil) next to the desired project.

3. Go to the SERVICE ACCOUNTS tab.

4. If a service account already exists, select it and choose DOWNLOAD CREDENTIALS. If a service account does not exist, create it and select DOWNLOAD CREDENTIALS.

5. A JSON file will be downloaded to your local machine. Open the file with an editor. Use the systemKey, token, and URL from the file as needed below.

## HTTP request

`POST {URL}/api/v/1/code/{SystemKey}/getRegistryCredentials`

### Header parameters

|                                           Parameters                                           ||
|------------------------|------------------------------------------------------------------------|
| `ClearBlade-UserToken` | See the note at the start of this document on where to find the token. |

### Request body

|                                                JSON representation                                                |
|-------------------------------------------------------------------------------------------------------------------|
| { "project": "<project_id>", "region": "<us-central1 | europe-west1 | asia-east1>", "registry": "<registry_id>" } |

### Response status codes

| Code | Meaning |
|------|---------|
| 200  | Success |

### Response body

|                                 JSON representation                                  |
|--------------------------------------------------------------------------------------|
| { "systemKey": "system_key...", "serviceAccountToken": "token...", "url": "url..." } |

#### Example curl

`curl -X POST 'https://iot.clearblade.com/api/v/1/code/aae9b9b30c8aa4e49081c7eeb9bb07/getRegistryCredentials' -H 'ClearBlade-UserToken: {token}' -d '{"project": "{project}", "region": "{region}", "registry": "{registry}"}'`

Using the instructions at the start of this document, replace the following: `https://iot.clearblade.com` with your URL. `aae9b9b30c8aa4e49081c7eeb9bb07` with your systemKey. {token} with your token.

---
language: "en"
---
# Getting device state

With ClearBlade IoT Core, you can monitor each connected device's state. The device reports it as binary data. Device state updates are typically triggered by a device change --- a configuration update from ClearBlade IoT Core or a similar change from another external source, such as a firmware update.

Device state differs from device configuration. Configuration data is sent to the device from ClearBlade IoT Core. The device sends state data to ClearBlade IoT Core. Configuration is an external instruction, and state is an internal representation.

ClearBlade IoT Core can help you answer configuration and state questions: What does the device think it should be doing? How does that compare to the most recent device configuration?

## Limits

State updates are [limited](https://docs.clearblade.com/iotcore/quotas-and-limits.md) to 1 update per second per device. However, for best results, the device state should be updated much less often --- at most, once every 10 seconds.

## Reporting device state

### MQTT bridge

To report the state to ClearBlade IoT Core through the MQTT bridge, publish messages to the `/devices/DEVICE_ID/state` MQTT topic. You can select a Cloud Pub/Sub topic to store state events when you [create or update a registry](https://docs.clearblade.com/iotcore/creating-registries-and-devices.md).

For more details, see [Publishing over the MQTT bridge](https://docs.clearblade.com/iotcore/publishing-over-mqtt.md).

### HTTP bridge

To report the state to ClearBlade IoT Core through the HTTP bridge, devices should use a `setState` request. The binary state data is passed in the request's body as a base64-encoded string.

For more details, see [Publishing over the HTTP bridge](https://docs.clearblade.com/iotcore/publishing-over-http.md).

## Getting device state data

This section explains how to get the state data reported to ClearBlade IoT Core by devices (devices cannot read state data from the cloud).

State data is returned in binary format. State data may have a different structure than the configuration data that triggers the state change.

For example, suppose you have a device with several fans. Your configuration data might be a JSON object containing a Boolean that enables or disables cooling:

    {
      'cooling': true}

But the device's state data might include diagnostic information, as well as the fan data that you'd expect to see in response to a `'cooling'` change:

    {
      'fan1_target_rpm': 1000,
      'fan2_target_rpm': 1200,
      'firmware_version': '1.2.3b'}

The device's `firmware_version` is unrelated to the configuration data but returns its state's full internal representation. This example illustrates how the device state can help debug and confirm that devices have acknowledged specific configurations.

### Retrieving the device state from a device registry code examples

Use the [Device states.list method](https://docs.clearblade.com/iotcore/list-projects-locations-registies-devices-states.md#HTTP-request) to get the most recent device states (up to 10). Each `Device` resource has a `DeviceState` field that contains the state most recently received from the device. The `DeviceRegistry` resource has a [StateNotificationConfig](https://docs.clearblade.com/iotcore/projects-locations-registries.md#StateNotificationConfig) field that can specify a state notification Cloud Pub/Sub topic when creating or updating a registry.

#### Node.js

    // const cloudRegion = 'us-central1';
    // const deviceId = 'my-device';
    // const projectId = 'adjective-noun-123';
    // const registryId = 'my-registry';
    import { DeviceManagerClient } from '@clearblade/iot';
    const iotClient = new DeviceManagerClient({
      // optional auth parameters.
    });

    async function listDeviceStates() {
      const devicePath = iotClient.devicePath(projectId, cloudRegion, registryId, deviceId);

      const [response] = await iotClient.listDeviceStates({ name: devicePath });
      const states = response.deviceStates;
      if (states.length === 0) {
        console.log(`No States for device: ${deviceId}`);
      } else {
        console.log(`States for device: ${deviceId}`);
      }

      for (let i = 0; i < states.length; i++) {
        const state = states[i];
        console.log('State:', state, '\nData:\n', state.binaryData.toString('utf8'));
      }
    }

    listDeviceStates();

##### C#

    {
        logger.LogInformation("Get a device");

        string name = "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry/Devices/Sample-New-Device";

        var result = await mClient.GetDevice(4, name);
        if (!result.Item1 || (result.Item2 == null))
            logger.LogError("Failed to get a device");
        else
        {
            logger.LogInformation("Successfully obtained the device");
        }
    }

##### Python

    import os
    from clearblade.cloud import iot_v1

    def list_device_states():
      project_id = 'YOUR_PROJECT_ID'
      cloud_region = 'us-central1'
      registry_id = 'your-registry-id'
      device_id = 'your-device-id'
      
      client = iot_v1.DeviceManagerClient()

      device_path = client.device_path(project_id, cloud_region, registry_id, device_id)

      request = iot_v1.ListDeviceStatesRequest(
        name=device_path,
        numStates=0
      )

      response = client.list_device_states(request=request)
      states = response.device_states

      if (len(states) == 0):
        print(f"No states for device: {device_id}")
      else:
        print("States:")
      
      for state in states:
        if state.binary_data is not None:
          print(f"updateTime: {state.update_time}; binaryData: {state.binary_data}")

    os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json"
    list_device_states()

##### Go

    // getDeviceStates retrieves and lists device states.
    func getDeviceStates(w io.Writer, projectID string, region string, registryID string, device string) ([]*iot.DeviceState, error) {
        // Authorize the client using Application Default Credentials.
        // See https://g.co/dv/identity/protocols/application-default-credentials
        ctx := context.Background()
        service, err := iot.NewService(ctx)

        if err != nil {
            return nil, err
        }

        path := fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", projectID, region, registryID, device)
        response, err := service.Projects.Locations.Registries.Devices.States.List(path).Do()
        if err != nil {
            return nil, err
        }

        fmt.Fprintln(w, "Successfully retrieved device states!")

        for _, state := range response.DeviceStates {
            fmt.Fprintf(w, "%s : %s\n", state.UpdateTime, state.BinaryData)
        }

        return response.DeviceStates, nil
    }

---
language: "en"
---
# Getting started

This page walks you through the steps required to use ClearBlade IoT Core and introduces some key concepts.

If you've completed the [Quick start](https://docs.clearblade.com/iotcore/quick-start.md), you've already done some of these steps. Review this page to ensure you're ready to use ClearBlade IoT Core.

## Before you begin

1. In the Google Cloud console, on the project selector page, select or [create a Google Cloud project](https://cloud.google.com/resource-manager/docs/creating-managing-projects). If you don't plan to keep the resources you create in this procedure, create a project instead of selecting an existing one. After you finish these steps, you can delete the [project](https://console.cloud.google.com/projectselector2/home/dashboard).

2. Ensure that [billing is enabled for your Cloud project](https://cloud.google.com/billing/docs/how-to/verify-billing-enabled).

## Activate ClearBlade IoT from the Google Cloud Marketplace

1. Navigate to the ClearBlade IoT Core offering in the [Google Cloud Platform Marketplace](https://console.cloud.google.com/marketplace).

2. Click Activate.

3. Complete the forms to register your IoT Core Developer account.

4. Click Complete.

## ClearBlade IoT Core introduction

This section summarizes ClearBlade IoT Core's key features. For more information, see the [ClearBlade IoT Core overview](https://docs.clearblade.com/iotcore/clearblade-iot-core-overview.md) and the other pages in the [Concepts section](https://docs.clearblade.com/iotcore/all-concepts.md).

### Device registration

For a device to connect, it must first be registered with ClearBlade IoT Core. Registration involves adding a device to a collection (the registry) and defining some essential properties. You can register a device with the ClearBlade Platform Console or REST-style API. For details, see [Creating registries and devices](https://docs.clearblade.com/iotcore/creating-registries-and-devices.md).

Collectively, the features that allow you to register, monitor, and configure devices are called the device manager.

### MQTT and HTTP protocols

ClearBlade IoT Core supports the MQTT and HTTP device connection and communication protocols. Devices communicate with ClearBlade IoT Core across an MQTT or HTTP bridge. When you create a device registry, you select protocols to enable MQTT, HTTP, or both.

MQTT is a standard publish/subscribe protocol frequently used and supported by embedded devices and is also common in machine-to-machine interactions.

HTTP is a connectionless protocol: devices do not maintain a connection to ClearBlade IoT Core with the HTTP bridge. Instead, they send requests and receive responses.

For details, see [Using the MQTT bridge](https://docs.clearblade.com/iotcore/publishing-over-mqtt.md) and [Using the HTTP bridge](https://docs.clearblade.com/iotcore/publishing-over-http.md).

### Device authentication

ClearBlade IoT Core uses public key (or asymmetric) authentication:

* The device uses a private key to sign a [JSON Web Token (JWT)](https://docs.clearblade.com/iotcore/using-json-web-tokens.md). The token is passed to ClearBlade IoT Core to prove the device's identity.

* The service uses the device's public key (uploaded before the JWT is sent) to verify the device's identity.

For details, see the [Creating key pairs](https://docs.clearblade.com/iotcore/creating-key-pairs.md), [Using JWTs](https://docs.clearblade.com/iotcore/using-json-web-tokens.md), and [Device security](https://docs.clearblade.com/iotcore/device-security.md) sections.

### Device control from the cloud

With ClearBlade IoT Core, you can control a device by modifying its configuration. A device configuration is an arbitrary, user-defined data blob that may or may not be structured. If your devices use MQTT, configurations are automatically propagated to them. If your devices connect over HTTP, they must explicitly request configurations.

For details, see the [Configuring devices](https://docs.clearblade.com/iotcore/configuring-devices.md) section.

## What's next

* [Learn more about ClearBlade IoT Core concepts and components](https://docs.clearblade.com/iotcore/clearblade-iot-core-overview.md)

* [Create a device registry and devices](https://docs.clearblade.com/iotcore/creating-registries-and-devices.md)

* [Review the ClearBlade IoT Core quotas and limits](https://docs.clearblade.com/iotcore/quotas-and-limits.md)

---
language: "en"
---
# Getting support

ClearBlade provides support through an [online ticketing system](https://clearblade.atlassian.net/servicedesk/customer/portal/1/group/1/create/20).

In addition to describing the issue, please include this information:

* Project ID

* Region

* Registry ID

* Device IDs

* Registry configuration changes in the last 24 hours

---
language: "en"
---
# Golang

ClearBlade IoT Core's Golang SDK is available [here](https://github.com/ClearBlade/go-iot).

---
language: "en"
---
# Google Cloud Marketplace activation

ClearBlade IoT Core must first be activated from the [Google Cloud Marketplace](https://console.cloud.google.com/marketplace/product/clearbladegcp-public/clearblade-iot-core).  
Activating products from the Google Cloud Marketplace requires certain [IAM authorities](https://cloud.google.com/marketplace/docs/access-control). Reach out to your Google Cloud Administrator regarding any issues with starting the activation.

After activation, you will be asked to register as a developer in ClearBlade IoT Core. This step must be completed to enable billing and registry migration.  
![Screen Shot 2022-10-27 at 9.21.18 AM.png](https://docs.clearblade.com/__attachments/a_f5f839dfc5ddea9e4cd4a7640eceb44b54728756265d27b434d3ae5f9267a27a/Screen%20Shot%202022-10-27%20at%209.21.18%20AM.png?cb=5970ce4f1ed2cf159f540f1c8601ed43)

Upon registration completion, all connected project areas will use the associated billing account of the developer who activated the marketplace offering.  
Need to add additional developers to your registry? See [here](https://clearblade.atlassian.net/wiki/spaces/IC/pages/2233171969).

---
language: "en"
---
# How-to guides

* [Getting started](https://docs.clearblade.com/iotcore/getting-started.md)
* [Google Cloud Marketplace activation](https://docs.clearblade.com/iotcore/google-cloud-marketplace-activation.md)
* [Creating a Google Cloud service account key](https://docs.clearblade.com/iotcore/creating-google-cloud-service-account-key.md)
* [Manage Users in a project (Standard)](https://docs.clearblade.com/iotcore/manage-users-in-a-project-standard.md)
* [Manage Users in a project (Enterprise)](https://docs.clearblade.com/iotcore/manage-users-in-a-project-enterprise.md)
* [Manage Service Accounts in a project (Standard)](https://docs.clearblade.com/iotcore/manage-service-accounts-in-a-project-standard.md)
* [Manage Service Accounts in a project (Enterprise)](https://docs.clearblade.com/iotcore/manage-service-accounts-in-a-project-enterprise.md)
* [Creating registries and devices](https://docs.clearblade.com/iotcore/creating-registries-and-devices.md)
* [Sending commands to devices](https://docs.clearblade.com/iotcore/sending-commands-to-devices.md)
[Targeting devices](https://docs.clearblade.com/iotcore/retargeting-devices.md) [Using gateways](https://docs.clearblade.com/iotcore/using-gateways.md)
* [Publishing over MQTT](https://docs.clearblade.com/iotcore/publishing-over-mqtt.md)
* [Publishing over HTTP](https://docs.clearblade.com/iotcore/publishing-over-http.md)
[Configuring devices and getting state](https://docs.clearblade.com/iotcore/configuring-devices-and-getting-state.md) [Managing credentials](https://docs.clearblade.com/iotcore/managing-credentials.md) [Logging and Monitoring](https://docs.clearblade.com/iotcore/logging-and-monitoring.md)
* [Implementing exponential backoff](https://docs.clearblade.com/iotcore/implementing-exponential-backoff.md)
* [Load balancer configuration](https://docs.clearblade.com/iotcore/configuring-a-load-balancer.md)
* [Deploying a GCP function that uses the Node.js SDK](https://docs.clearblade.com/iotcore/deploying-a-gcp-function-that-uses-the-node-js-sdk.md)
* [Migration from Standard to Enterprise](https://docs.clearblade.com/iotcore/migration-from-standard-to-enterprise.md)
* [Making billing changes within GCP](https://docs.clearblade.com/iotcore/making-billing-changes-within-gcp.md)
[Manage Components in a project](https://docs.clearblade.com/iotcore/manage-components-in-a-project.md)

---
language: "en"
---
# Identity and Access Management (IAM)

## Identity

In IAM, you grant access to principals. Principals can be of the following types:

* Users

* Service accounts

## Resource

If a principal needs access to a specific resource, you can grant the principal a role for that resource. Some examples of resources are projects and registries.

When an authenticated principal attempts to access a resource, IAM checks the resource's allow policy to determine whether the action is allowed.

## Permissions

Permissions determine what operations are allowed on a resource. In the IAM world, permissions are represented as `service.resource.verb` (e.g.,`cloudiot.registries.create)`.

Permissions often correspond one-to-one with REST API methods. Most IoT Core services have an associated set of permissions for each REST API method they expose. The method's caller needs those permissions to call it. For example, if you need to call the`getIamPolicy`method, you must have the`cloudiot.registries.getIamPolicy`permission.

You don't grant permissions to users directly. Instead, you identify roles with the appropriate permissions and grant them to the user.

## Roles

A role is a collection of permissions. You cannot grant permissions to users directly. Instead, you grant them a role, which grants them all its permissions.

These are each role's permissions:  

|          Role name          |               ID                |                                                                                                                                                                             Permissions                                                                                                                                                                              |
|-----------------------------|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Cloud IoT Viewer            | roles/cloudiot.viewer           | * cloudiot.registries.get * cloudiot.registries.list * cloudiot.devices.get * cloudiot.devices.list                                                                                                                                                                                                                                                                  |
| Cloud IoT Device Controller | roles/cloudiot.deviceController | * All permissions from Cloud IoT Viewer * cloudiot.devices.updateConfig * cloudiot.devices.sendCommand                                                                                                                                                                                                                                                               |
| Cloud IoT Provisioner       | roles/cloudiot.provisioner      | * All permissions from Cloud IoT Device Controller * cloudiot.devices.create * cloudiot.devices.delete * cloudiot.devices.update                                                                                                                                                                                                                                     |
| Cloud IoT Editor            | roles/cloudiot.editor           | * All permissions from Cloud IoT Provisioner * cloudiot.registries.create * cloudiot.registries.delete * cloudiot.registries.update * cloudiot.registries.migrate                                                                                                                                                                                                    |
| Cloud IoT Admin             | roles/cloudiot.admin            | * All permissions from Cloud IoT Editor * cloudiot.registries.getIamPolicy * cloudiot.registries.setIamPolicy * cloudiot.projects.update * cloudiot.projects.delete * cloudiot.projects.updateUsers * cloudiot.projects.updateServiceAccounts * cloudiot.projects.listPrincipals * cloudiot.projects.deleteServiceAccounts * cloudiot.projects.createServiceAccounts |
| Cloud IoT Project Admin     | roles/project.admin             | * All permissions from Cloud IoT Admin                                                                                                                                                                                                                                                                                                                               |

You can grant roles to users by creating an allow policy, which is a collection of statements that define who has what type of access. An allow policy is attached to a resource and is used to enforce access control whenever that resource is accessed. An allow policy consists of a list of role bindings. A role binding binds a list of principals to a role.

The following code snippet shows an allow policy's structure.

    [
        {
          "role": "roles/cloudiot.viewer",
          "members": [
            "user@example.com",
            "serviceAccount-12345@example.com",
          ]
        },
        {
          "role": "roles/cloudiot.editor",
          "members": [
            "anotherUser@example.com"
          ]
        }
    ]

---
language: "en"
---
# Implementing exponential backoff

This page explains how to use [truncated exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff) to ensure your devices do not generate excessive load.

When devices retry calls without waiting, they can produce a heavy load on the ClearBlade IoT Core servers. ClearBlade IoT Core automatically limits projects that generate excessive load. Even a small fraction of overactive devices can trigger limits that affect all devices in the same Google Cloud project.

You are strongly encouraged to implement truncated exponential backoff with introduced jitter to avoid triggering these limits. If you have questions or would like to discuss your algorithm's specifics, email [iotcore@clearblade.com](mailto:iotcore@clearblade.com) with this information:

1. IoT Core registry name

2. Number of devices connected

3. Industry

Truncated exponential backoff is a standard error-handling strategy for network applications. Clients will periodically retry a failed request with increasing delays between requests. Clients should use truncated exponential backoff for all requests to ClearBlade IoT Core that return HTTP `5xx` and `429` response codes and disconnections from the MQTT server.

## Example algorithm

An exponential backoff algorithm retries requests exponentially, increasing the waiting time between retries up to a maximum backoff time. For example:

1. Make a request to ClearBlade IoT Core.

2. If the request fails, wait 1 + `random_number_milliseconds` seconds and retry the request.

3. If the request fails, wait 2 + `random_number_milliseconds` seconds and retry the request.

4. If the request fails, wait 4 + `random_number_milliseconds` seconds and retry the request.

5. And so on, up to a `maximum_backoff` time.

6. Continue waiting and retrying up to some maximum number of retries, but do not increase the waiting period between retries.

where:

* The wait time is `min(((2^n)+random_number_milliseconds), maximum_backoff)`, with `n` incremented by 1 for each iteration (request).

* `random_number_milliseconds` is a random number of milliseconds less than or equal to 1000. This helps to avoid cases in which some situation synchronizes many clients, and all retry at once, sending requests in synchronized waves. The `random_number_milliseconds` value is recalculated after each retry request.

* `maximum_backoff` is typically 32 or 64 seconds. The appropriate value depends on the use case.

The client can continue retrying after it has reached the `maximum_backoff` time. Retries after this point do not need to continue increasing backoff time. For example, suppose a client uses a `maximum_backoff` time of 64 seconds. After reaching this value, the client can retry every 64 seconds. At some point, clients should be prevented from retrying indefinitely.

The wait time between retries and the number of retries depends on your use case and network conditions.

---
language: "en"
---
# IoT Core Service Level Agreement (SLA)

During the Term of the agreement under which ClearBlade has agreed to provide ClearBlade IoT Core to Customer (as applicable, the "Agreement"), the Covered Service will provide a Monthly Uptime Percentage to Customer as follows (the "Service Level Objective" or "SLO"):

| **Covered Service** | **Monthly Uptime Percentage** |
|---------------------|-------------------------------|
| IoT Core Service    | \>= 99.9%                     |

If ClearBlade does not meet the SLO, and if Customer meets its obligations under this SLA, Customer will be eligible to receive the Financial Credits described below. This SLA states Customer's sole and exclusive remedy for any failure by ClearBlade to meet the SLO. Capitalized terms used in this SLA, but not defined in this SLA, have the meaning stated in the Agreement. If the Agreement authorizes the resale or supply of ClearBlade Platform under a ClearBlade partner or reseller program, then all references to Customer in this SLA mean Partner or Reseller (as applicable), and any Financial Credit(s) will only apply for impacted Partner or Reseller order(s) under the Agreement.

## Definitions

The following definitions apply to the SLA:

* **"Back-off Requirements"** means, when an error occurs, the devices are responsible for waiting for a period of time before issuing another request. This means that after the first error, there is a minimum back-off interval of 1 second and for each consecutive error, the back-off interval increases exponentially up to 32 seconds.

* **"Covered Service"** means the IoT Core Service.

* **"Downtime"** means more than a 10% Error Rate for the IoT Core device manager or protocol bridge component. Downtime is measured based on server-side Error Rate.

* **"Downtime Period"** means a period of five or more consecutive minutes of Downtime. Partial minutes will not be counted towards any Downtime Periods.

* **"Error Rate"** means:

  * for the IoT Core device manager component and IoT Core protocol bridge (HTTP) component, the number of Valid Requests that result in a response with HTTP Status 50x and Code "Internal Error" divided by the total number of Valid Requests during that period; and

  * for the IoT Core protocol bridge (MQTT) component, the number of Valid Requests that result in device disconnections as reported in Google Stackdriver metrics (or other similar metrics made available to Customer), divided by the total number of Valid Requests during that period.

  Repeated identical requests do not count toward the Error Rate unless they conform to the Back-off Requirements.
* **"Financial Credit"** means the credit amount based on the percentage of the monthly bill for the Covered Service in the table below.

| **Monthly Uptime Percentage** | **Percentage of the monthly bill for the Covered Service that will be credited to future monthly Customer bills** |
|-------------------------------|-------------------------------------------------------------------------------------------------------------------|
| 99% to \< 99.9%               | 10%                                                                                                               |
| 95% to \< 99%                 | 25%                                                                                                               |
| \< 95%                        | 50%                                                                                                               |

* **"Monthly Uptime Percentage"** means total number of minutes in a month, minus the number of minutes of Downtime suffered from all Downtime Periods for the Covered Service in a month, divided by the total number of minutes in a month.

* **"Valid Requests"** are requests that conform to the Documentation, and that would normally result in a non-error response.

### Customer Must Request Financial Credit

To receive any of the Financial Credits described above, Customer must contact ClearBlade Support at ++support@clearblade.com++ within 30 days from the time Customer becomes eligible to receive a Financial Credit. Customer must also provide ClearBlade with identifying information (e.g., region, developer id and and registry/system IDs) and the date and time those errors occurred. If Customer does not comply with these requirements, Customer will forfeit its right to receive a Financial Credit. If a dispute arises with respect to this SLA, ClearBlade will make a determination in good faith based on its system logs, monitoring reports, configuration records, and other available information, which ClearBlade will make available to Customer at Customer's request.

#### Maximum Financial Credit

The total maximum number of Financial Credits to be issued by ClearBlade to Customer for any and all Downtime Periods that occur in a single billing month will not exceed 50% of the amount due by Customer for the Covered Service for the applicable month. Financial Credits will be made in the form of a monetary credit applied to future use of the Service and will be applied within 60 days after the Financial Credit was requested.

#### SLA Exclusions

The SLA does not apply to any: (a) features or services designated Alpha or Beta (unless otherwise stated in the associated Documentation), (b) features or services excluded from the SLA (in the associated Documentation), or (c) errors: (i) caused by factors outside of ClearBlade's reasonable control; (ii) that resulted from Customer's software or hardware or third party software or hardware, or both; (iii) that resulted from abuses or other behaviors that violate the Agreement; (iv) that resulted from quotas applied by the system or listed in the Admin Console; or (v) that resulted from Customer use of the Covered Service in a way which is inconsistent with the Documentation, including invalid request fields, unauthorized users, or inaccessible data.

---
language: "en"
---
# Java

ClearBlade IoT Core's Java SDK is available [here](https://github.com/ClearBlade/java-iot).

---
language: "en"
---
# list

Lists device registries.  
Note: This is an [admin API](https://docs.clearblade.com/iotcore/admin-and-regional-api-differences.md#Admin-API).

The URL, systemKey, and token this endpoint requires are obtained differently than others. To get those, do the following:

1. Click the Select project drop-down at the top of the IoT Core UI.

2. Click the Edit icon (pencil) next to the desired project.

3. Go to the SERVICE ACCOUNTS tab.

4. If a service account already exists, select it and choose DOWNLOAD CREDENTIALS. If a service account does not exist, create it and select DOWNLOAD CREDENTIALS.

5. A JSON file will be downloaded to your local machine. Open the file with an editor. Use the systemKey, token, and URL from the file as needed below.

## HTTP request

`GET {url}/api/v/4/webhook/execute/{systemKey}/cloudiot`

### Query parameters

|                                                                                                                                     Parameters                                                                                                                                      ||
|-------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `parent`    | `string` The project and cloud region path. For example, `projects/example-project/locations/us-central1`.                                                                                                                                                             |
| `pageSize`  | `number` The maximum number of registries to return in the response. If this value is zero, the service will select a default size. A call may return fewer objects than requested. A non-empty `nextPageToken` in the response indicates that more data is available. |
| `pageToken` | `string` The value returned by the last `ListDeviceRegistriesResponse`; indicates that this is a prior `registries.list` call's continuation, and the system should return the next data page.                                                                         |

### Header parameters

|                                           Parameters                                           ||
|------------------------|------------------------------------------------------------------------|
| `ClearBlade-UserToken` | See the note at the start of this document on where to find the token. |

### Request body

The request body must be empty.

### Response status codes

| Code | Meaning |
|------|---------|
| 200  | Success |

### Response body

If successful, the response body contains data with this structure:

Response for `registries.list`.  

|                               JSON representation                               |
|---------------------------------------------------------------------------------|
| { "deviceRegistries": [ { object(DeviceRegistry) } ], "nextPageToken": string } |

|                                                                            Fields                                                                            ||
|----------------------|----------------------------------------------------------------------------------------------------------------------------------------|
| `deviceRegistries[]` | `object(`[DeviceRegistry](https://docs.clearblade.com/iotcore/projects-locations-registries.md#Resource:DeviceRegistry)`)` The registries that matched the query. |
| `nextPageToken`      | `string` If not empty, more registries may match the request; this value should be passed into a new `ListDeviceRegistriesRequest`.    |

#### Example curl

`curl 'https://iot.clearblade.com/api/v/4/webhook/execute/aae9b9b30c8aa4e49081c7eeb9bb07/cloudiot?parent=projects/iot-core-test-363819/locations/us-central1' -H 'ClearBlade-UserToken: {token}'`

OR

`curl 'https://iot.clearblade.com/api/v/4/webhook/execute/aae9b9b30c8aa4e49081c7eeb9bb07/cloudiot?parent=projects/iot-core-test-363819/locations/us-central1' -X GET -H 'ClearBlade-UserToken: {token}'`

Using the instructions at the start of this document, replace the following: `https://iot.clearblade.com` with your URL. `aae9b9b30c8aa4e49081c7eeb9bb07` with your systemKey. {token} with your token.

---
language: "en"
---
# list: project.locations.registies.devices.configVersions

Lists the device configuration's last few versions in descending order (i.e., newest first).  
Note: This is a [regional API](https://docs.clearblade.com/iotcore/admin-and-regional-api-differences.md#RegionalAPI).

You can find the URL, SystemKey, and token required in the call by clicking API Keys (key icon) at the top-right of the Registry Details page. Use the Registry Keys section.

## HTTP request

`GET {URL}/api/v/4/webhook/execute/{SystemKey}/cloudiot_devices_configVersions`

### Query parameters

|                                                                                                                                                                Parameters                                                                                                                                                                ||
|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `name`        | `string` The device's name. For example, `projects/p0/locations/us-central1/registries/registry0/devices/device0` or `projects/p0/locations/us-central1/registries/registry0/devices/{numId}`. The device's name can be set to the deviceId or numId (i.e., without the project, location, and registry info. prepended). |
| `numVersions` | `number` The number of versions to list. Versions are listed in decreasing order of the version number. The maximum number of versions retained is 10. If this value is zero, it will return all the versions available.                                                                                                  |

### Header parameters

|                                           Parameters                                           ||
|------------------------|------------------------------------------------------------------------|
| `ClearBlade-UserToken` | See the note at the start of this document on where to find the token. |

### Request body

The request body must be empty.

### Response status codes

| Code | Meaning |
|------|---------|
| 200  | Success |

### Response body

If successful, the response body contains a [ListDeviceConfigVersionsResponse](https://docs.clearblade.com/iotcore/listdeviceconfigversionsresponse.md) instance.

---
language: "en"
---
# list: projects.locations.registies.devices.states

Lists the device state's last few versions in descending order (i.e., newest first).  
Note: This is a [regional API](https://docs.clearblade.com/iotcore/admin-and-regional-api-differences.md#RegionalAPI).

You can find the URL, SystemKey, and token required in the call by clicking API Keys (key icon) at the top-right of the Registry Details page. Use the Registry Keys section.

## HTTP request

`GET {URL}/api/v/4/webhook/execute/{SystemKey}/cloudiot_devices_states`

### Query parameters

|                                                                                                                                                                                 Parameters                                                                                                                                                                                  ||
|----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `name`         | `string` The device's name. For example, `projects/p0/locations/us-central1/registries/registry0/devices/device0` or `projects/p0/locations/us-central1/registries/registry0/devices/{numId}`. The device's name can be set to the deviceId or numId (i.e., without the project, location, and registry info. prepended).                                   |
| `numStates`    | `number` The number of states to list. States are listed in descending order of update time. The maximum number of states retained is 10. If this value is zero, it will return all the states available.                                                                                                                                                   |
| `base64Encode` | `string` Optional parameter that designates whether state binaryData is to be returned as base64-encoded strings. If the parameter is present, its value must be true or false (case is ignored). If the parameter is missing, the result is the same as if it was present and its value was false. I.e., state binaryData is returned, NOT base64-encoded. |

### Header parameters

|                                           Parameters                                           ||
|------------------------|------------------------------------------------------------------------|
| `ClearBlade-UserToken` | See the note at the start of this document on where to find the token. |

### Request body

The request body must be empty.

### Response status codes

| Code | Meaning |
|------|---------|
| 200  | Success |

### Response body

If successful, the response body contains a [ListDeviceStatesResponse](https://docs.clearblade.com/iotcore/listdevicestatesresponse.md) instance.

[Next Page](https://docs.clearblade.com/llms-full.txt/1)
