irusdk
A Python SDK and thin CLI for querying and acting on an Iru (formerly Kandji) fleet — devices, their state, the actions you take against them, and the blueprints, users, and tags that organise them.
[!NOTE] Kandji is now Iru. The API still serves from
*.api.kandji.io, and this SDK follows suit.
[!IMPORTANT]
irusdkdoes not author library content. To version-control Custom Profiles, Scripts, and Apps, useiructl— Iru's own tool, which does that job well. The two compose:iructlmanages what you deploy,irusdktells you what your fleet is doing. See Scope below.
Features
- Sync and async clients —
IruClientandAsyncIruClient, same surface, same models. - Pydantic models for API responses, so you get real attributes and IDE autocomplete.
- Transparent pagination — list methods iterate every page for you, with concurrent prefetch where the API exposes a total.
- Rate-limit aware — honors Iru's 50 req/sec and 10,000 req/hour tenant limits, with
Retry-Afterbackoff on 429. - Optional CLI for ad-hoc terminal use.
Installation
pip install irusdk # library only
pip install irusdk[cli] # library plus the `irusdk` command
Quickstart
from irusdk import IruClient
client = IruClient(subdomain="mycompany", token="...")
for device in client.devices.list(platform="Mac"):
print(device.device_name, device.serial_number, device.os_version)
No with block is required — construct the client and use it, the way you would httpx.Client.
Call client.close() when you are finished to release the connection pool promptly, or use the
client as a context manager and let it close itself:
with IruClient(subdomain="mycompany", token="...") as client:
device = client.devices.get("2cfeb3ac-3b5d-423e-bcff-e2676a3a32da")
The async client is the same code plus async:
import asyncio
from irusdk import AsyncIruClient
async def main():
client = AsyncIruClient(subdomain="mycompany", token="...")
async for device in client.devices.list(platform="Mac"):
print(device.device_name, device.serial_number)
await client.aclose()
asyncio.run(main())
What's covered
| Attribute | Endpoints |
|---|---|
client.devices |
list, pages, get, update, delete, details |
client.blueprints |
list, pages, get, create, update, delete, library items, templates |
client.users |
list, get, delete |
client.tags |
list, create, update, delete |
Pagination
List methods paginate for you — client.devices.list() walks every page and yields Device
models. When you want page boundaries, the reported total, or control over how many pages are in
flight, use pages() instead:
for page in client.devices.pages(platform="Mac", prefetch=8):
print(f"page {page.index}: {len(page)} devices of {page.total}")
CLI
export IRU_SUBDOMAIN=mycompany
export IRU_API_TOKEN=...
irusdk devices list --platform Mac
irusdk devices get <device-id>
irusdk blueprints list
irusdk users list --limit 50
irusdk tags create "lab-machines"
Every read command takes --json.
Scope
irusdk covers the fleet surface of the Iru API. It deliberately leaves library-content
authoring to iructl.
The two problems are different, and the vendor already solves one of them well. Authoring library
content is a content-lifecycle problem — payloads in git, reviewed in PRs, synced to your tenant,
packages uploaded through presigned S3 URLs. That is what iructl is built for. Managing a fleet is
a query-and-act problem — which Macs are on an old OS, which are missing, what is installed where,
lock the one that just walked out the door. That is what this is built for.
There is also a durability argument: iructl is maintained by Iru, so when the API changes for
Custom Apps, the people who changed it ship the fix. Anywhere the vendor ships a supported tool,
that tool should win.
| Task | Tool |
|---|---|
| Version-control Custom Profiles, Scripts, Apps | iructl |
| Upload a Custom App package | iructl |
| Declaratively assign library items to blueprints | iructl |
| Find every Mac on an outdated OS | irusdk |
| Report FileVault or compliance state across the fleet | irusdk |
| Lock, erase, or restart a device | irusdk |
| Build a dashboard, Slack bot, or scheduled report | irusdk |
Blueprints appear in both, for different reasons: iructl assigns content to them, while
irusdk reads them as fleet context, since every device carries a blueprint_id.
Documentation
Full documentation lives at irusdk.readthedocs.io.
License
Apache-2.0. See LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file irusdk-0.1.0.tar.gz.
File metadata
- Download URL: irusdk-0.1.0.tar.gz
- Upload date:
- Size: 139.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc01b57f017ffed5b51ef40073139bb8351e5630dc3642329b15c28d509af4fa
|
|
| MD5 |
93a290e7f56ab784c1ff835d530c13d8
|
|
| BLAKE2b-256 |
45c6c156ed5bb7dcc4d50c6a17d154f7a86855772c5e90397df5d53330e31f3b
|
Provenance
The following attestation bundles were made for irusdk-0.1.0.tar.gz:
Publisher:
build-release-publish.yml on liquidz00/irusdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
irusdk-0.1.0.tar.gz -
Subject digest:
bc01b57f017ffed5b51ef40073139bb8351e5630dc3642329b15c28d509af4fa - Sigstore transparency entry: 2581292391
- Sigstore integration time:
-
Permalink:
liquidz00/irusdk@650cdf56abfcd70932d2d78133fc46051068d9c0 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/liquidz00
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-release-publish.yml@650cdf56abfcd70932d2d78133fc46051068d9c0 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file irusdk-0.1.0-py3-none-any.whl.
File metadata
- Download URL: irusdk-0.1.0-py3-none-any.whl
- Upload date:
- Size: 54.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6fb45ea4413c0ee4a8f77bd0209f49824be4ee350705a095d911b46c4cf19266
|
|
| MD5 |
2900d201c42a174910d27ff4e7ca1223
|
|
| BLAKE2b-256 |
4701551995978846f6f535006849f7ec0de4a856ccc5063a84c3c2989c2eefe3
|
Provenance
The following attestation bundles were made for irusdk-0.1.0-py3-none-any.whl:
Publisher:
build-release-publish.yml on liquidz00/irusdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
irusdk-0.1.0-py3-none-any.whl -
Subject digest:
6fb45ea4413c0ee4a8f77bd0209f49824be4ee350705a095d911b46c4cf19266 - Sigstore transparency entry: 2581292406
- Sigstore integration time:
-
Permalink:
liquidz00/irusdk@650cdf56abfcd70932d2d78133fc46051068d9c0 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/liquidz00
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-release-publish.yml@650cdf56abfcd70932d2d78133fc46051068d9c0 -
Trigger Event:
workflow_dispatch
-
Statement type: