> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kodelabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Organize devices and points

> Link devices to each other and to spaces, copy points, group points on virtual devices, update or delete devices and points in batches, and see what a delete removes.

Once devices and points exist in a building, you can organize them. You link a device to the devices it feeds or is fed by, link it to the spaces it serves or measures, copy a point onto another device, and group points on a virtual device. You can also change or delete devices and points one at a time or in batches.

Each linked endpoint can switch the sample between cURL, JavaScript, Python, and PowerShell, or send the request for you.

> [!WARNING]
>
> Deletes are permanent and cascade to points, copies, and links. There is no undo. Read [What a delete removes](#what-a-delete-removes) first, and test on a device you created for the purpose.

## Before you begin

You need:

* An access token. See the [quickstart](https://docs.kodelabs.com/products/kode-api/quickstart.md).
* The `buildingId` of the building, from [List buildings](https://docs.kodelabs.com/products/kode-api/api-reference/buildings/list-buildings.md).
* The ids of the devices, points, and spaces you want to work with. [List building devices](https://docs.kodelabs.com/products/kode-api/api-reference/devices/list-building-devices.md) and [List building points](https://docs.kodelabs.com/products/kode-api/api-reference/points/list-building-points.md) return them.
* A service account whose role allows creating, updating, and deleting devices and points in the building.

## Link devices to each other

A device reference links one device to another, for example an air handler to the VAV boxes it feeds. You add the link from one device, and KODE OS stores the reverse link on the other device.

**1. Find the connection to use**

Call [List connections for a canonical type](https://docs.kodelabs.com/products/kode-api/api-reference/ontology/list-connections-for-a-canonical-type.md) with the canonical type of the device you link from. Each row has the `key`, `multi`, and `type` you send as `relationship`, and `canonicalTypes` lists the types of devices it can link to.

Both devices need an ontology applied. A device without one is refused with `400`.

**2. Add the link**

The device in the path is the one you link from. Send the ids of the devices to link to.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST \
  "https://api.kodelabs.com/kodeos/api/v1/buildings/${BUILDING_ID}/devices/${DEVICE_ID}/references" \
  --header "Authorization: Bearer ${KODE_ACCESS_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{
    "relationship": { "key": "feeds", "multi": true, "type": "OUTPUT" },
    "referencedDeviceIds": ["67c977317437671625264e03"]
  }'
```

[Add device references](https://docs.kodelabs.com/products/kode-api/api-reference/devices/add-device-references.md) returns `204` with an empty body. It refuses, with `400`, a link where a device references itself, a device is already linked, or the link would create a loop or reverse an existing link.

**3. Read the links back**

Call [List device references](https://docs.kodelabs.com/products/kode-api/api-reference/devices/list-device-references.md) on either device. Each item has the linked `device`, the `key`, the `type`, and the `ontology` of the linked device. The two devices show opposite `type` values, `OUTPUT` on the device that feeds and `INPUT` on the device that is fed.

Check the list after you add links. The response of the add request does not list what was stored.

**4. Remove a link**

Send the linked device ids to [Remove device references](https://docs.kodelabs.com/products/kode-api/api-reference/devices/remove-device-references.md).

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{ "referencedDeviceIds": ["67c977317437671625264e03"] }
```

The link is removed from both devices. Neither device is deleted.

## Link a device to spaces

A space reference links a device to a space it serves or measures. You send the space ids. KODE OS decides whether each link is `serves` or `measures`.

**1. Add the links**

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST \
  "https://api.kodelabs.com/kodeos/api/v1/buildings/${BUILDING_ID}/devices/${DEVICE_ID}/space-references" \
  --header "Authorization: Bearer ${KODE_ACCESS_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{ "referencedSpaceIds": ["67c977317437671625264e10"] }'
```

[Add device space references](https://docs.kodelabs.com/products/kode-api/api-reference/devices/add-device-space-references.md) returns `204` with an empty body. The device needs an ontology applied. Repeating an id does not add a second link.

**2. List the links**

[List device space references](https://docs.kodelabs.com/products/kode-api/api-reference/devices/list-device-space-references.md) returns the `space` and the `key` of each link. Use `category` to narrow the list to `Level`, `SpaceUnit`, or `Zone` spaces.

**3. Remove links**

Send the space ids to [Remove device space references](https://docs.kodelabs.com/products/kode-api/api-reference/devices/remove-device-space-references.md). The device and the spaces are not deleted.

## Copy points to other devices

A point copy puts a point on another device without a second ingest. The copy mirrors its source: it has its own `id` and sits on the device you chose, and [Get a point](https://docs.kodelabs.com/products/kode-api/api-reference/points/get-a-point.md) shows the live value of the source.

**1. Send the copy request**

Send the points and the devices. KODE OS creates one copy for each pair, up to 50 pairs in a request.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST \
  "https://api.kodelabs.com/kodeos/api/v1/buildings/${BUILDING_ID}/points/copies" \
  --header "Authorization: Bearer ${KODE_ACCESS_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{
    "pointIds": ["67c977317437671625264e21"],
    "deviceIds": ["67c977317437671625264e05"]
  }'
```

These rules apply to the request. If one is broken, the request is refused with `400` and nothing is written:

* The points must be origin points on one device. A copy cannot be copied.
* The target devices must be origin or virtual devices, and not the device or base device of a source point.

**2. Check each pair**

[Copy points to devices](https://docs.kodelabs.com/products/kode-api/api-reference/points/copy-points-to-devices.md) returns one item per pair, in request order. `status` is `CREATED`, `COPY_EXISTS` when the copy was already there, or `LIMIT_REACHED` when the source has 200 copies. You can repeat a request safely: existing copies are not created again.

**3. Keep the copy ids**

Each `CREATED` item in the response carries the `_id` of the new copy. To find copies later, call [List point copies](https://docs.kodelabs.com/products/kode-api/api-reference/points/list-point-copies.md) with `sourcePointId` and `deviceId`. Each item has the copy `_id`, its `device`, and its `source`.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl "https://api.kodelabs.com/kodeos/api/v1/buildings/${BUILDING_ID}/points/copies?sourcePointId=${POINT_ID}&deviceId=${DEVICE_ID}" \
  --header "Authorization: Bearer ${KODE_ACCESS_TOKEN}"
```

Copies are written device by device. If a request fails part way, the copies already written stay. List the copies, then send the request again.

Deleting a copy with [Delete a point](https://docs.kodelabs.com/products/kode-api/api-reference/points/delete-a-point.md) removes only the copy. Deleting the source point removes all of its copies.

## Group points on a virtual device

A virtual device holds points that come from other devices, for example the supply and return temperatures of one air handler shown together. You have two ways to put points on it.

**1. Create the virtual device**

Send a `name`. `typeId` and `locatedInSpaceId` are optional.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST \
  "https://api.kodelabs.com/kodeos/api/v1/buildings/${BUILDING_ID}/virtual-devices" \
  --header "Authorization: Bearer ${KODE_ACCESS_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{ "name": "Rooftop summary" }'
```

[Create a virtual device](https://docs.kodelabs.com/products/kode-api/api-reference/virtual-devices/create-a-virtual-device.md) returns `201` with the new device. The device id is `id`, and `pointsCount` is `0`. Sending the same name again creates a second device.

**2. Add points**

To show points of a real device without moving them, use the copy request above with the virtual device in `deviceIds`.

To move points that sit on a pseudo device, call [Attach points to a virtual device](https://docs.kodelabs.com/products/kode-api/api-reference/virtual-devices/attach-points-to-a-virtual-device.md) with up to 200 `pointIds`. The points keep their `id` and trend data, and their modeling is reset, so apply modeling after you attach.

**3. Take points off**

[Detach points from a virtual device](https://docs.kodelabs.com/products/kode-api/api-reference/virtual-devices/detach-points-from-a-virtual-device.md) returns origin points to their base device and lists them in `detached`. Copies cannot go back, so they are deleted and listed in `deletedCopies`. The request is all or nothing: every point must be on the device.

Deleting a virtual device with [Delete a device](https://docs.kodelabs.com/products/kode-api/api-reference/devices/delete-a-device.md) deletes the copies on it.

## Update many devices or points

Use a batch update when many devices or points need different changes. Both endpoints take up to 1,000 `items`. Each item has the `id` and the fields to change, and fields you leave out keep their value.

**1. Send the batch**

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request POST \
  "https://api.kodelabs.com/kodeos/api/v1/buildings/${BUILDING_ID}/points/batch-update" \
  --header "Authorization: Bearer ${KODE_ACCESS_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{
    "items": [
      { "id": "67c977317437671625264e21", "name": "Supply Air Temp" },
      { "id": "67c977317437671625264e22", "precision": 1 }
    ]
  }'
```

Use [Update points in a batch](https://docs.kodelabs.com/products/kode-api/api-reference/points/update-points-in-a-batch.md) for points and [Update devices in a batch](https://docs.kodelabs.com/products/kode-api/api-reference/devices/update-devices-in-a-batch.md) for devices. Send each `id` once. The response is a job with the status `PROCESSING`.

**2. Poll the job**

Call [Get a job](https://docs.kodelabs.com/products/kode-api/api-reference/buildings/get-a-job.md) with the job `_id` every few seconds until `status` is `COMPLETED`, `FAILED`, or `CANCELED`.

**3. Read the result**

The job checks that every id exists in the building. If any id is unknown or belongs to another building, the job ends with `FAILED` and nothing is changed. On `COMPLETED`, read the devices or points to confirm the new values.

To change one device or point, use [Update a device](https://docs.kodelabs.com/products/kode-api/api-reference/devices/update-a-device.md) or [Update a point](https://docs.kodelabs.com/products/kode-api/api-reference/points/update-a-point.md).

## Delete devices and points

| To delete | Use |
| - | - |
| One device | [Delete a device](https://docs.kodelabs.com/products/kode-api/api-reference/devices/delete-a-device.md) |
| Up to 1,000 devices | [Delete devices in a batch](https://docs.kodelabs.com/products/kode-api/api-reference/devices/delete-devices-in-a-batch.md) |
| One point or one copy | [Delete a point](https://docs.kodelabs.com/products/kode-api/api-reference/points/delete-a-point.md) |
| Up to 1,000 points | [Delete points in a batch](https://docs.kodelabs.com/products/kode-api/api-reference/points/delete-points-in-a-batch.md) |

The single deletes return `204` with an empty body. The batch deletes return a job. Poll it as described in the previous section.

> [!WARNING]
>
> A batch delete skips ids that do not match an object in the building, and the job still ends with `COMPLETED`. The job carries no per-item result. Read each object afterwards. Get a device or Get a point answers `404` when the object is gone.

## What a delete removes

KODE OS removes the dependents with the object, so nothing points at an object that no longer exists.

| Deleting | Also removes |
| - | - |
| A device | Every point of the device. Every copy of those points on other devices, and every copy that sits on the device. Every device reference and space reference that other devices hold to it. |
| A device, effect on counts | The point count of each device that held a removed copy, and the device count of the building and of the space the device was located in. |
| A point | Every copy of the point on other devices. The device that holds the point is not deleted. |
| A copy | Only the copy. The source point and the other copies stay. |
| A virtual device | The copies on it. To keep points that you attached from pseudo devices, detach them first. |

If a device came from a connector discovery, a later discovery offers the device and its deleted points again as new.

Other KODE OS features can use a device or point, for example schedules or graphics. This guide lists what the API exposes. Check those features after a delete.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.