

# Departments API Reference

API endpoints for managing departments.

## List Departments

`GET` `https://api.igloohome.co/works/departments`

### Query Parameters

- **`limit`** `integer`
  - Constraints: `>= 1`, `<= 300`
  - Default: `100`
- **`cursor`** `string`
- **`sort`** `string`
  - Default: `desc`
  - Allowed values: `asc`, `desc`

### Request Example

```bash
curl -X GET "https://api.igloohome.co/works/departments?limit=value&cursor=value&sort=value" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Accept: application/json"
```

```go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	url := "https://api.igloohome.co/works/departments?limit=value&cursor=value&sort=value"
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("Authorization", "Bearer YOUR_ACCESS_TOKEN")
	req.Header.Set("Accept", "application/json")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()

	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
```

```javascript
const res = await fetch("https://api.igloohome.co/works/departments?limit=value&cursor=value&sort=value", {
  method: "GET",
  headers: {
    "Authorization": "Bearer YOUR_ACCESS_TOKEN",
    "Accept": "application/json"
  }
});

const data = await res.json();
console.log(data);
```

```python
import requests

url = "https://api.igloohome.co/works/departments"
headers = {
    "Authorization": "Bearer YOUR_ACCESS_TOKEN",
    "Accept": "application/json"
}
params = {
    "limit": "value",
    "cursor": "value",
    "sort": "value"
}
response = requests.get(url, headers=headers, params=params)
print(response.json())
```

```php
<?php
$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => "https://api.igloohome.co/works/departments?limit=value&cursor=value&sort=value",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer YOUR_ACCESS_TOKEN",
        "Accept: application/json"
    ]
]);

$response = curl_exec($curl);
curl_close($curl);

echo $response;
```

```kotlin
val client = OkHttpClient()

val request = Request.Builder()
    .url("https://api.igloohome.co/works/departments?limit=value&cursor=value&sort=value")
    .method("GET", null)
    .addHeader("Authorization", "Bearer YOUR_ACCESS_TOKEN")
    .addHeader("Accept", "application/json")
    .build()

val response = client.newCall(request).execute()
println(response.body?.string())
```

```swift
import Foundation

var request = URLRequest(url: URL(string: "https://api.igloohome.co/works/departments?limit=value&cursor=value&sort=value")!)
request.httpMethod = "GET"
request.setValue("Bearer YOUR_ACCESS_TOKEN", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Accept")

let task = URLSession.shared.dataTask(with: request) { data, response, error in
    if let data = data {
        print(String(data: data, encoding: .utf8) ?? "")
    }
}
task.resume()
```

### Responses

`200 OK.`
`401 Unauthorized, invalid or expired authorization token`
`402-account-suspended Payment Required. Account is billing-suspended or past its trial grace period.`
`402-trial-ended Payment Required. iglooworks API trial has ended.`
`403 Forbidden. One of: (1) the token is valid but lacks the required scope for this endpoint (no body); (2) the user revoked the OAuth client's access ('{error: "The user has revoked access for this application..."}').`

**Response body — `200`:**

- **`nextCursor`** `string`\
  Present only if another page exists.
- **`payload`** `array of object`
  - **`id`** `string`
  - **`departmentName`** `string`
  - **`propertyRef`** `array of object`

**Response body — `402-account-suspended`:**

- **`error`** `string`

**Response body — `402-trial-ended`:**

- **`error`** `string`

**Response body — `403`:**

- **`error`** `string`

**Example response — `200`:**

```json
{
  "nextCursor": "string",
  "payload": [
    {
      "departmentName": "string",
      "id": "string",
      "propertyRef": [
        {}
      ]
    }
  ]
}
```

**Example response — `402-account-suspended`:**

```json
{
  "error": "account.payment.is.suspended"
}
```

**Example response — `402-trial-ended`:**

```json
{
  "error": "30 days iglooworks API trial has ended"
}
```

**Example response — `403`:**

```json
{
  "error": "string"
}
```

## List Department Properties

`GET` `https://api.igloohome.co/works/departments/{departmentId}/properties`

### Path Parameters

| Parameter | Type | Required |
| --- | --- | --- |
| departmentId | string | Yes |

### Query Parameters

- **`limit`** `integer`
  - Constraints: `>= 1`, `<= 300`
  - Default: `100`
- **`cursor`** `string`
- **`sort`** `string`
  - Default: `desc`
  - Allowed values: `asc`, `desc`

### Request Example

```bash
curl -X GET "https://api.igloohome.co/works/departments/{departmentId}/properties?limit=value&cursor=value&sort=value" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Accept: application/json"
```

```go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	url := "https://api.igloohome.co/works/departments/{departmentId}/properties?limit=value&cursor=value&sort=value"
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("Authorization", "Bearer YOUR_ACCESS_TOKEN")
	req.Header.Set("Accept", "application/json")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()

	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
```

```javascript
const res = await fetch("https://api.igloohome.co/works/departments/{departmentId}/properties?limit=value&cursor=value&sort=value", {
  method: "GET",
  headers: {
    "Authorization": "Bearer YOUR_ACCESS_TOKEN",
    "Accept": "application/json"
  }
});

const data = await res.json();
console.log(data);
```

```python
import requests

url = "https://api.igloohome.co/works/departments/{departmentId}/properties"
headers = {
    "Authorization": "Bearer YOUR_ACCESS_TOKEN",
    "Accept": "application/json"
}
params = {
    "limit": "value",
    "cursor": "value",
    "sort": "value"
}
response = requests.get(url, headers=headers, params=params)
print(response.json())
```

```php
<?php
$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => "https://api.igloohome.co/works/departments/{departmentId}/properties?limit=value&cursor=value&sort=value",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer YOUR_ACCESS_TOKEN",
        "Accept: application/json"
    ]
]);

$response = curl_exec($curl);
curl_close($curl);

echo $response;
```

```kotlin
val client = OkHttpClient()

val request = Request.Builder()
    .url("https://api.igloohome.co/works/departments/{departmentId}/properties?limit=value&cursor=value&sort=value")
    .method("GET", null)
    .addHeader("Authorization", "Bearer YOUR_ACCESS_TOKEN")
    .addHeader("Accept", "application/json")
    .build()

val response = client.newCall(request).execute()
println(response.body?.string())
```

```swift
import Foundation

var request = URLRequest(url: URL(string: "https://api.igloohome.co/works/departments/{departmentId}/properties?limit=value&cursor=value&sort=value")!)
request.httpMethod = "GET"
request.setValue("Bearer YOUR_ACCESS_TOKEN", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Accept")

let task = URLSession.shared.dataTask(with: request) { data, response, error in
    if let data = data {
        print(String(data: data, encoding: .utf8) ?? "")
    }
}
task.resume()
```

### Responses

`200 OK. Empty 'payload' (not a 404) if the department has zero properties.`
`401 Unauthorized, invalid or expired authorization token`
`402-account-suspended Payment Required. Account is billing-suspended or past its trial grace period.`
`402-trial-ended Payment Required. iglooworks API trial has ended.`
`403 Forbidden. One of: (1) the token is valid but lacks the required scope for this endpoint (no body); (2) the user revoked the OAuth client's access ('{error: "The user has revoked access for this application..."}').`
`409 Department not found.`

**Response body — `200`:**

- **`nextCursor`** `string`\
  Present only if another page exists.
- **`payload`** `array of object`
  - **`id`** `string`
  - **`name`** `string`
  - **`timezone`** `string`
  - **`totalLock`** `integer`

**Response body — `402-account-suspended`:**

- **`error`** `string`

**Response body — `402-trial-ended`:**

- **`error`** `string`

**Response body — `403`:**

- **`error`** `string`

**Response body — `409`:**

- **`error`** `string`

**Example response — `200`:**

```json
{
  "nextCursor": "string",
  "payload": [
    {
      "id": "556e2b1a7c4d9e5f6a2b8c3d",
      "name": "Riverside Apartments - Block A",
      "timezone": "Asia/Singapore",
      "totalLock": 12
    }
  ]
}
```

**Example response — `402-account-suspended`:**

```json
{
  "error": "account.payment.is.suspended"
}
```

**Example response — `402-trial-ended`:**

```json
{
  "error": "30 days iglooworks API trial has ended"
}
```

**Example response — `403`:**

```json
{
  "error": "string"
}
```

**Example response — `409`:**

```json
{
  "error": "string"
}
```

## List Department Access

`GET` `https://api.igloohome.co/works/departments/{id}/access`

Same response shape as GET /devices/{id}/access, scoped to the department.

### Path Parameters

| Parameter | Type | Required |
| --- | --- | --- |
| id | string | Yes |

### Query Parameters

- **`limit`** `integer`
  - Constraints: `>= 1`, `<= 300`
  - Default: `100`
- **`cursor`** `string`
- **`sort`** `string`
  - Default: `desc`
  - Allowed values: `asc`, `desc`

### Request Example

```bash
curl -X GET "https://api.igloohome.co/works/departments/{id}/access?limit=value&cursor=value&sort=value" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Accept: application/json"
```

```go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	url := "https://api.igloohome.co/works/departments/{id}/access?limit=value&cursor=value&sort=value"
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("Authorization", "Bearer YOUR_ACCESS_TOKEN")
	req.Header.Set("Accept", "application/json")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()

	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
```

```javascript
const res = await fetch("https://api.igloohome.co/works/departments/{id}/access?limit=value&cursor=value&sort=value", {
  method: "GET",
  headers: {
    "Authorization": "Bearer YOUR_ACCESS_TOKEN",
    "Accept": "application/json"
  }
});

const data = await res.json();
console.log(data);
```

```python
import requests

url = "https://api.igloohome.co/works/departments/{id}/access"
headers = {
    "Authorization": "Bearer YOUR_ACCESS_TOKEN",
    "Accept": "application/json"
}
params = {
    "limit": "value",
    "cursor": "value",
    "sort": "value"
}
response = requests.get(url, headers=headers, params=params)
print(response.json())
```

```php
<?php
$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => "https://api.igloohome.co/works/departments/{id}/access?limit=value&cursor=value&sort=value",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer YOUR_ACCESS_TOKEN",
        "Accept: application/json"
    ]
]);

$response = curl_exec($curl);
curl_close($curl);

echo $response;
```

```kotlin
val client = OkHttpClient()

val request = Request.Builder()
    .url("https://api.igloohome.co/works/departments/{id}/access?limit=value&cursor=value&sort=value")
    .method("GET", null)
    .addHeader("Authorization", "Bearer YOUR_ACCESS_TOKEN")
    .addHeader("Accept", "application/json")
    .build()

val response = client.newCall(request).execute()
println(response.body?.string())
```

```swift
import Foundation

var request = URLRequest(url: URL(string: "https://api.igloohome.co/works/departments/{id}/access?limit=value&cursor=value&sort=value")!)
request.httpMethod = "GET"
request.setValue("Bearer YOUR_ACCESS_TOKEN", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Accept")

let task = URLSession.shared.dataTask(with: request) { data, response, error in
    if let data = data {
        print(String(data: data, encoding: .utf8) ?? "")
    }
}
task.resume()
```

### Responses

`200 OK.`
`401 Unauthorized, invalid or expired authorization token`
`402-account-suspended Payment Required. Account is billing-suspended or past its trial grace period.`
`402-trial-ended Payment Required. iglooworks API trial has ended.`
`403 Forbidden. One of: (1) the token is valid but lacks the required scope for this endpoint (no body); (2) the user revoked the OAuth client's access ('{error: "The user has revoked access for this application..."}').`
`404 Department not found.`

**Response body — `200`:**

- **`nextCursor`** `string`\
  Present only if another page exists.
- **`payload`** `array of object`
  - **`id`** `string`
  - **`name`** `string`
  - **`accessType`** `string`
    - Allowed values: `pin`, `ekey`, `nfc`, `fingerprint`
  - **`bluetoothDeviceName`** `string`
  - **`isCustomPin`** `boolean`\
    Present only if accessType===pin.
  - **`pin`** `string`\
    Present only if accessType===pin.
  - **`pinType`** `string`\
    Present only if accessType===pin. The API stores and reports AlgoPIN daily/hourly variants as `duration`.
    - Allowed values: `otp`, `duration`, `permanent`
  - **`startDateTime`** `string<date-time>`
  - **`endDateTime`** `string<date-time>`
  - **`recipient`** `object`\
    Present only if `accessType` is `ekey`.
    - **`name`** `string`
    - **`email`** `string`
  - **`createdAt`** `string<date-time>`

**Response body — `402-account-suspended`:**

- **`error`** `string`

**Response body — `402-trial-ended`:**

- **`error`** `string`

**Response body — `403`:**

- **`error`** `string`

**Example response — `200`:**

```json
{
  "nextCursor": "string",
  "payload": [
    {
      "accessType": "pin",
      "bluetoothDeviceName": "IGH-LK-3F9A21",
      "createdAt": "2026-09-13T09:30:00+08:00",
      "endDateTime": "2026-09-14T18:00:00+08:00",
      "id": "556e1b3a8c2d4e5f6a7b8c8e",
      "isCustomPin": true,
      "name": "Temp PIN - Maintenance",
      "pin": "2847",
      "pinType": "duration",
      "startDateTime": "2026-09-13T10:00:00+08:00"
    }
  ]
}
```

**Example response — `402-account-suspended`:**

```json
{
  "error": "account.payment.is.suspended"
}
```

**Example response — `402-trial-ended`:**

```json
{
  "error": "30 days iglooworks API trial has ended"
}
```

**Example response — `403`:**

```json
{
  "error": "string"
}
```

## List Department Devices

`GET` `https://api.igloohome.co/works/departments/{id}/devices`

Same response shape as GET /devices, scoped to the department.

### Path Parameters

| Parameter | Type | Required |
| --- | --- | --- |
| id | string | Yes |

### Query Parameters

- **`limit`** `integer`
  - Constraints: `>= 1`, `<= 300`
  - Default: `100`
- **`cursor`** `string`
- **`sort`** `string`
  - Default: `desc`
  - Allowed values: `asc`, `desc`

### Request Example

```bash
curl -X GET "https://api.igloohome.co/works/departments/{id}/devices?limit=value&cursor=value&sort=value" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Accept: application/json"
```

```go
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	url := "https://api.igloohome.co/works/departments/{id}/devices?limit=value&cursor=value&sort=value"
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("Authorization", "Bearer YOUR_ACCESS_TOKEN")
	req.Header.Set("Accept", "application/json")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()

	body, _ := io.ReadAll(res.Body)
	fmt.Println(string(body))
}
```

```javascript
const res = await fetch("https://api.igloohome.co/works/departments/{id}/devices?limit=value&cursor=value&sort=value", {
  method: "GET",
  headers: {
    "Authorization": "Bearer YOUR_ACCESS_TOKEN",
    "Accept": "application/json"
  }
});

const data = await res.json();
console.log(data);
```

```python
import requests

url = "https://api.igloohome.co/works/departments/{id}/devices"
headers = {
    "Authorization": "Bearer YOUR_ACCESS_TOKEN",
    "Accept": "application/json"
}
params = {
    "limit": "value",
    "cursor": "value",
    "sort": "value"
}
response = requests.get(url, headers=headers, params=params)
print(response.json())
```

```php
<?php
$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => "https://api.igloohome.co/works/departments/{id}/devices?limit=value&cursor=value&sort=value",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer YOUR_ACCESS_TOKEN",
        "Accept: application/json"
    ]
]);

$response = curl_exec($curl);
curl_close($curl);

echo $response;
```

```kotlin
val client = OkHttpClient()

val request = Request.Builder()
    .url("https://api.igloohome.co/works/departments/{id}/devices?limit=value&cursor=value&sort=value")
    .method("GET", null)
    .addHeader("Authorization", "Bearer YOUR_ACCESS_TOKEN")
    .addHeader("Accept", "application/json")
    .build()

val response = client.newCall(request).execute()
println(response.body?.string())
```

```swift
import Foundation

var request = URLRequest(url: URL(string: "https://api.igloohome.co/works/departments/{id}/devices?limit=value&cursor=value&sort=value")!)
request.httpMethod = "GET"
request.setValue("Bearer YOUR_ACCESS_TOKEN", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Accept")

let task = URLSession.shared.dataTask(with: request) { data, response, error in
    if let data = data {
        print(String(data: data, encoding: .utf8) ?? "")
    }
}
task.resume()
```

### Responses

`200 OK.`
`401 Unauthorized, invalid or expired authorization token`
`402-account-suspended Payment Required. Account is billing-suspended or past its trial grace period.`
`402-trial-ended Payment Required. iglooworks API trial has ended.`
`403 Forbidden. One of: (1) the token is valid but lacks the required scope for this endpoint (no body); (2) the user revoked the OAuth client's access ('{error: "The user has revoked access for this application..."}').`
`404 Department not found.`

**Response body — `200`:**

- **`nextCursor`** `string`\
  Present only if another page exists.
- **`payload`** `array of object`
  - **`id`** `string`
  - **`type`** `string`
    - Allowed values: `Lock`, `Bridge`, `Keypad`, `Fob`
  - **`deviceId`** `string`
  - **`deviceName`** `string`
  - **`batteryLevel`** `number`
  - **`pairedAt`** `string<date-time>`
  - **`lockStatus`** `string`\
    Present only on `GET /devices/{id}`, and only for a Lock linked to a Bridge. No list endpoint that returns this schema populates it.
  - **`properties`** `array of object`
    - **`id`** `string`
    - **`name`** `string`
    - **`timezone`** `string`
  - **`linkedDevices`** `array of object`
    - **`id`** `string`
    - **`type`** `string`
    - **`deviceId`** `string`
    - **`name`** `string`
  - **`linkedAccessories`** `array of object`
    - **`id`** `string`
    - **`type`** `string`
    - **`deviceId`** `string`
    - **`name`** `string`
  - **`lastSync`** `string<date-time>`

**Response body — `402-account-suspended`:**

- **`error`** `string`

**Response body — `402-trial-ended`:**

- **`error`** `string`

**Response body — `403`:**

- **`error`** `string`

**Example response — `200`:**

```json
{
  "nextCursor": "string",
  "payload": [
    {
      "batteryLevel": 82.5,
      "deviceId": "IGH-LK-3F9A21",
      "deviceName": "Front Door Lock",
      "id": "665f1c2a9b3e4d5f6a7b8c9d",
      "lastSync": "2026-09-13T09:45:00Z",
      "linkedAccessories": [
        {
          "deviceId": "IGH-BR-7C2E19",
          "id": "445d1a0b6c5e8d4f7a1b9c2e",
          "name": "Main Bridge",
          "type": "Bridge"
        }
      ],
      "linkedDevices": [],
      "lockStatus": "locked",
      "pairedAt": "2026-09-08T14:32:00Z",
      "properties": [
        {
          "id": "556e2b1a7c4d9e5f6a2b8c3d",
          "name": "Riverside Apartments - Block A",
          "timezone": "Asia/Singapore"
        }
      ],
      "type": "Lock"
    }
  ]
}
```

**Example response — `402-account-suspended`:**

```json
{
  "error": "account.payment.is.suspended"
}
```

**Example response — `402-trial-ended`:**

```json
{
  "error": "30 days iglooworks API trial has ended"
}
```

**Example response — `403`:**

```json
{
  "error": "string"
}
```

