Skip to content

API Client

kandji-trent edited this page Jun 23, 2026 · 1 revision

API Client

iructl ships the same Python client module it uses internally at iructl.api.

This page covers the setup shared by every resource: installation, authentication, sessions, and error handling. Each endpoint has its own resource class with a dedicated page of worked examples.

from iructl.api import (
    # Configuration
    ApiConfig,

    # Custom profiles
    CustomProfilesResource, CustomProfilePayload,

    # Custom scripts
    CustomScriptsResource, CustomScriptPayload, ExecutionFrequency,

    # Custom apps
    CustomAppsResource, CustomAppPayload, InstallType, InstallEnforcement,

    # Blueprints
    BlueprintsResource, BlueprintPayload, is_duplicate_assignment,

    # Self Service categories
    SelfServiceCategoriesResource, SelfServiceCategoryPayload,

    # Installer transfer
    S3Client,

    # List results
    PayloadList,
)

Table of contents

Installation and import

The API client is installed as part of the iructl package. Add a dependency based on whichever method best fits your project's workflow:

# uv
uv add iructl
# poetry
poetry add iructl
# pip
echo "iructl" >> requirements.txt
pip install -r requirements.txt

Authentication

Client resources are configured with an ApiConfig, which holds your tenant URL and API token:

from iructl.api import ApiConfig

config = ApiConfig(
    tenant_url="https://mycompany.api.iru.com",
    api_token="12345678-1234-4234-8234-123456789012",
)

Warning

Your API token is a private secret and should never be hardcoded in source code. Best practice is to read it from the environment or inject it from a secret store such as the macOS Keychain.

ApiConfig validates its inputs up front and raises a pydantic.ValidationError if either value is malformed:

  • Tenant URL — normalized to https:// and must be a supported API host. Valid forms:
    • https://<subdomain>.api.kandji.io
    • https://<subdomain>.api.eu.kandji.io
    • https://<subdomain>.api.iru.com
  • API token — must be a UUID4 string, e.g. 12345678-1234-4234-8234-123456789012.

Resource classes

A resource class is a thin wrapper around a single API endpoint. It exposes that endpoint's operations (such as list() and get()) as methods, manages its own authenticated HTTP session, and returns parsed pydantic models rather than raw JSON.

The client ships one resource class per endpoint:

Opening a session

A resource manages its own session. The recommended pattern is a with block, which opens the session on entry and closes it on exit:

from iructl.api import ApiConfig, CustomProfilesResource

config = ApiConfig(
    tenant_url="https://mycompany.api.kandji.io",
    api_token="12345678-1234-4234-8234-123456789012",
)

with CustomProfilesResource(config) as profiles:
    for profile in profiles.list().results:
        print(profile.name)

If a with block doesn't fit your control flow, open and close the session manually:

profiles = CustomProfilesResource(config)
profiles.open()
try:
    profiles.list()
finally:
    profiles.close()

Important

Calling a resource method before the session is open (or after close) raises ApiClientError. Always use a with block or call open() first.

Working with results

Methods return parsed pydantic models rather than raw JSON, so you get typed attribute access and validation for free. Each resource page documents the model it returns. In most cases, list methods return a PayloadList containing the returned results.

PayloadList

Attribute Type Description
count int Total number of items reported by the API
results list[PayloadType] Every item, combined across all pages
next str | None Internal pagination cursor, consumed by list()
previous str | None Internal pagination cursor, consumed by list()
with CustomProfilesResource(config) as profiles:
    page = profiles.list()
    print(page.count)            # total reported by the API
    print(len(page.results))     # every profile, across all pages

Note

List endpoints are paginated on the server, but list() handles that for you: it follows every page and returns a single PayloadList with the combined results. You rarely need to deal with pagination yourself.

Error handling

The client raises a small set of exceptions. The iructl-specific ones live in iructl.exceptions:

Exception Raised when
ApiClientError A resource method is called before its session is open.
PayloadTransferError An installer binary fails to upload to or download from S3.
PayloadIntegrityError A downloaded installer fails its sha256 check (subclass of PayloadTransferError).

Errors from the underlying libraries pass through unchanged:

Exception Raised when
requests.HTTPError The API returns a non-2xx status code.
requests.ConnectionError The connection to the API fails.
pydantic.ValidationError A response (or an ApiConfig) doesn't match the expected schema.
ValueError / FileNotFoundError Invalid arguments are passed (e.g. a missing file, or a mutually exclusive option combination).

Clone this wiki locally