# Connect an IoT Device

> Register, provision, and verify a device through the API-led Infuse-IoT Cloud path.

Use this guide when device onboarding is managed by a trusted backend, manufacturing system, gateway, or commissioning tool.

The Infuse console can create boards and networks, generate MQTT tokens, inspect devices, edit metadata, queue KV updates, and dispatch commands. Production device creation and key derivation still usually belong in an API-led workflow because credentials and provisioning material must stay server-side.

Run these calls from a trusted backend. Requests go to the Infuse-IoT Cloud API at `https://api.infuse-iot.com`.

## 1. Get An Infuse IoT Token

Create a [service account](/docs/iam-and-access/service-accounts) for the onboarding system in the organisation that will own the devices. Give it the IoT access this guide needs: creating boards, networks, and devices, deriving device keys, generating MQTT tokens, and sending RPCs. The **IoT Admin** template covers all of these; clone it into a narrower organisation role if your workflow does not need everything. Grant these permissions organisation-wide, because the Infuse-IoT Cloud API does not yet support resource-limited IoT grants.

Issue an API key for the service account, then exchange it for an Infuse IoT token:

```http
POST https://api.infuse-cloud.io/iam/auth/token
Content-Type: application/json

{
  "apiKey": "ik_<keyId>.<keySecret>",
  "audience": "infuse-iot"
}
```

Use the returned `accessToken` as `{infuse_iot_token}` in the requests below, and exchange the key again before `expiresAt`. See [Token Exchange](/docs/iam-and-access/token-exchange) for token lifetime and retry guidance.

## 2. Confirm The Organisation

Devices, boards, networks, and MQTT tokens belong to the organisation that owns the API key. Copy its organisation ID from **Organisation settings** > **Developer tools** in the Infuse Portal. The ID is the same in Infuse Platform and Infuse-IoT Cloud.

Creating an organisation in the Infuse Portal also creates its linked Infuse-IoT Cloud organisation, so you do not need to create one with the API. To confirm the organisation from your backend:

```http
GET /organisation/id/{organisationId}
Authorization: Bearer {infuse_iot_token}
```

Store the organisation ID. You will use it when creating boards, devices, and MQTT tokens.

## 3. Create Or Select A Board

Boards represent hardware or product profiles.

You can create boards from **Infuse IoT** > **Boards** when setting up manually. Use the API when your onboarding system needs to create or reconcile boards automatically.

```http
GET /board?organisationId={organisationId}
Authorization: Bearer {infuse_iot_token}
```

Create a board if the target hardware profile is not registered:

```http
POST /board
Authorization: Bearer {infuse_iot_token}
Content-Type: application/json

{
  "organisationId": "{organisationId}",
  "name": "Example Sensor Board",
  "description": "Low-power field sensor board",
  "soc": "nRF9151"
}
```

Store the returned `boardId`. Use board metadata fields if your integration needs consistent serial, site, customer, or hardware-variant values.

## 4. Create Or Select A Network

If your deployment model uses networks, resolve or create the network before registering devices.

You can create networks from **Infuse IoT** > **Networks** when setting up manually. Use the API when deployment automation owns network setup.

```http
GET /network?organisationId={organisationId}&includePublic=false
Authorization: Bearer {infuse_iot_token}
```

```http
POST /network
Authorization: Bearer {infuse_iot_token}
Content-Type: application/json

{
  "organisationId": "{organisationId}",
  "name": "Field Network",
  "description": "Primary field deployment network",
  "key": "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=",
  "public": false,
  "networkId": 1001
}
```

If your integration does not separate devices by network, keep this step as an internal no-op and continue with the organisation and board identifiers.

## 5. Create The Device

Create the device with the MCU identifier, board, organisation, and any metadata your backend needs for reconciliation.

```http
POST /device
Authorization: Bearer {infuse_iot_token}
Content-Type: application/json

{
  "mcuId": "0011223344556677",
  "boardId": "{boardId}",
  "organisationId": "{organisationId}",
  "metadata": {
    "serialNumber": "SN-10001",
    "deploymentSite": "Brisbane"
  }
}
```

Store the returned `deviceId`. This is the identifier downstream systems should use for device-specific workflows such as Infuse-Marketplace checkout, RPC commands, and data ingestion.

## 6. Provision Keys

Fetch the current cloud public key:

```http
GET /key/publicKey
Authorization: Bearer {infuse_iot_token}
```

Use the device public key to generate shared secret material:

```http
POST /key/sharedSecret
Authorization: Bearer {infuse_iot_token}
Content-Type: application/json

{
  "key": "{device_public_key_base64}"
}
```

Derive device encryption key material as required by your provisioning flow:

```http
POST /key/derived/device
Authorization: Bearer {infuse_iot_token}
Content-Type: application/json

{
  "deviceId": "{deviceId}",
  "interface": "udp"
}
```

Keep provisioning secrets in your trusted backend, manufacturing system, or device secure storage. Rotate device-specific credentials when devices are replaced, reassigned, or exposed.

## 7. Generate An MQTT Token

Issue a short-lived MQTT token for the organisation when your device, gateway, or broker integration needs MQTT connectivity.

For development or operational use, you can generate an MQTT token from **Infuse IoT** > **API Access**. Backend integrations should generate tokens server-side.

```http
POST /mqtt/token
Authorization: Bearer {infuse_iot_token}
Content-Type: application/json

{
  "organisationId": "{organisationId}",
  "ttlSeconds": 3600
}
```

Use the returned `expiresAt` value to refresh the token before it expires.

## 8. Confirm Communication

After the device or gateway starts communicating, confirm Infuse-IoT Cloud can see its operational state.

```http
GET /device/deviceId/{deviceId}/state
Authorization: Bearer {infuse_iot_token}
```

Check the last route when you need to confirm downlink reachability:

```http
GET /device/deviceId/{deviceId}/lastRoute
Authorization: Bearer {infuse_iot_token}
```

## 9. Send A Test RPC

Send a small RPC supported by the device firmware.

```http
POST /rpc
Authorization: Bearer {infuse_iot_token}
Content-Type: application/json

{
  "deviceId": "{deviceId}",
  "sendWaitTimeoutMs": 60000,
  "rpc": {
    "commandName": "ping",
    "params": {}
  }
}
```

Store the returned RPC message ID and read it until the command reaches a terminal state:

```http
GET /rpc/{id}
Authorization: Bearer {infuse_iot_token}
```

## Next Steps

- Use [Devices](/docs/infuse-iot-cloud/devices) to understand identifiers and lookup paths.
- Use [Console](/docs/infuse-iot-cloud/console) to understand the UI workflow.
- Use [Boards](/docs/infuse-iot-cloud/boards) and [Networks](/docs/infuse-iot-cloud/networks) to understand setup resources.
- Use [Telemetry and State](/docs/infuse-iot-cloud/telemetry) to track state, routes, logger progress, and KV entries.
- Use [Device Configuration](/docs/infuse-iot-cloud/device-configuration) for metadata, KV updates, and logger sync.
- Use [Commands and RPC](/docs/infuse-iot-cloud/commands) for production command flows.
- Use [Definitions](/docs/infuse-iot-cloud/definitions) to align backend payloads with firmware schemas.
