Skip to main content

pjdev-armis-sdk

PyPI - Version PyPI - Python Version


Async Python SDK for the Armis API, built on httpx and pydantic.

Table of Contents

Installation

pip install pjdev-armis-sdk

Usage

Configure once at startup (reads from environment variables prefixed with ARMIS_):

from pjdev_armis_sdk import config_service

config_service.init(
    instance_url="https://your-tenant.armis.com",
    secret_key="your-secret-key",
)

Then call any of the resource modules:

from pjdev_armis_sdk import devices, search

# AQL search
result = await search.aql_search("in:devices type:MOBILE_PHONE")

# Lookup a single device by id
device = await devices.get_device(id=12345)

Auth (Authorization header with a temporary access token) is handled automatically by the underlying httpx.AsyncClient. Tokens are refreshed on the fly when they expire or when the API returns 401.

Retries and backoff

Every endpoint call retries transient failures with capped, jittered exponential backoff. Retry N waits http_retry_delay_seconds * 2 ** (N - 1) seconds, clamped to http_retry_max_delay_seconds and then scaled by a random factor in [0.5, 1.0]. A Retry-After header on a retried response is honored instead — both the delay-seconds and HTTP-date forms — clamped to the same ceiling.

Config knobs (all readable as ARMIS_-prefixed environment variables):

Setting Default Meaning
http_retry_max_count 5 Maximum attempts per call.
http_retry_delay_seconds 2 Base delay; doubles each retry.
http_retry_max_delay_seconds 60.0 Ceiling for any single wait.
http_retry_jitter True Spread out callers that failed together.

What is retried: any status not listed in a call's status_codes_to_ignore, plus transport failures (httpx.TransportError — connect errors, read/write and pool timeouts, protocol errors). 400, 403 and 404 are treated as deterministic and fail immediately.

401 is retried, with one deliberate exception. For ordinary endpoints a 401 means a stale access token, and it is worth retrying — note that ArmisAccessTokenAuth has already re-authenticated and replayed the request once, with no delay, before the retry layer ever sees it, so what retrying adds is elapsed time for a transient condition to clear. Against the token endpoint itself a 401 means the secret key is wrong, which no retry can fix, so access_token.get_access_token() and failed token fetches inside the auth flow fail fast on any 4xx and retry only on 429 or 5xx.

Consumers that need different behavior can override per call site without changing the shared defaults:

from pjdev_armis_sdk.api_utilities import async_retry_http

# Retry a status that this call site would otherwise treat as fatal.
@async_retry_http(status_codes_to_ignore=[400, 403], retry_status_codes=[409])
async def my_call() -> None: ...

retry_status_codes takes precedence over status_codes_to_ignore; passing only the latter behaves exactly as it always has. It is an override layered on the base rule, never an allowlist — it widens what is retried, never narrows it.

Writes that are not safe to repeat

Creates, and actions like _run_now/ that trigger work, are marked idempotent=False. On those calls the SDK retries only failures that prove the request never landed:

Never landed — safe to retry ConnectError, ConnectTimeout, PoolTimeout (no connection was ever established, so nothing was transmitted) and 401 (rejected at the authentication boundary before the handler runs)
May have landed — not retried ReadTimeout, WriteTimeout, ReadError, WriteError, RemoteProtocolError (the request was on the wire and the response was lost) and every 4xx/5xx other than 401

The question for a write is not "is this failure transient?" but "could the server have applied the write and still returned this?" A 504 or a ReadTimeout means the request arrived and the response was lost — the write may well have landed, so repeating it creates a duplicate. Armis offers no idempotency key, so nothing about the request lets the SDK work this out for itself; it has to be declared at the call site.

Note this is not a read/write split. A connection refused mid-deploy is the commonest transient failure there is, and it stays retryable on every endpoint including creates, because a refused connection cannot have written anything.

Affected: create_user, create_site, create_boundary, create_integration, create_integration_v2, run_silk_integration, run_va_integration, add_site_integration_id, add_site_network_equipment, bulk_add_site_network_equipment.

The last three are a deliberate conservative guess, not a known fact: they POST an id into a collection, and if Armis stores that collection as a set they are harmless to repeat and the flag costs retry resilience for nothing. The guess is made on cost asymmetry — a wrong False costs availability, a wrong True costs duplicate data — and confirmation from Armis that POSTing an already-present id is a no-op would settle it.

Not affected, because repeating them is harmless: every read, the update_* / patch_* calls (they set fields to given values), the delete_* calls, add_device_tags / remove_device_tags (set semantics), and bulk_upsert_devices (upsert keyed by macAddress).

Upgrading

Which statuses retry is unchanged for callers that pass only status_codes_to_ignore. Two timing changes are visible without any code change on your side:

  • Transport failures other than ConnectError — read/write and pool timeouts, protocol errors — are now retried instead of propagating after one attempt. A call that used to fail fast on a ReadTimeout now consumes its retry budget and the wall-clock time that goes with it.

  • Jitter is on by default, so a delay is 0.5x–1.0x of the computed value. At the default http_retry_delay_seconds=2 the schedule was 2, 4, 8, 16 and is now 1–2, 2–4, 4–8, 8–16. Set http_retry_jitter=False for the exact old schedule.

  • Creates no longer survive a transient 5xx or 429. This is the change most likely to affect you, and it is a reduction in write resilience, not only a bug fix. The ten non-idempotent calls listed above previously retried those statuses up to http_retry_max_count times; they now fail on the first one. If you have code relying on create_user riding out a brief 503, it will now raise where it used to succeed, and the caller has to decide whether to retry.

    The trade is deliberate: a duplicate user is worse than a failed create the caller can retry on purpose. Note this closes a pre-existing hole as well as a recent one — a 504 on a create could already produce duplicate rows before this release, because any status outside status_codes_to_ignore was retried. Connection failures are unaffected and still retry, since they cannot duplicate anything.

License

pjdev-armis-sdk is distributed under the terms of the MIT license.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pjdev_armis_sdk-5.2.1.tar.gz (22.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pjdev_armis_sdk-5.2.1-py3-none-any.whl (28.8 kB view details)

Uploaded Python 3

File details

Details for the file pjdev_armis_sdk-5.2.1.tar.gz.

File metadata

  • Download URL: pjdev_armis_sdk-5.2.1.tar.gz
  • Upload date:
  • Size: 22.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: Hatch/1.18.0 {"ci":true,"cpu":"aarch64","distro":{"id":"noble","libc":{"lib":"glibc","version":"2.39"},"name":"Ubuntu","version":"24.04"},"implementation":{"name":"CPython","version":"3.12.3"},"installer":{"name":"hatch","version":"1.18.0"},"openssl_version":"OpenSSL 3.0.13 30 Jan 2024","python":"3.12.3","system":{"name":"Linux","release":"7.0.12-linuxkit"}} HTTPX2/2.12.0

File hashes

Hashes for pjdev_armis_sdk-5.2.1.tar.gz
Algorithm Hash digest
SHA256 c44c33dd4358387bfb04833b9ba959f583a0ca0e40f43d41848d84794fddd2bc
MD5 a39e090fdc98cd634220ca5fc971b35c
BLAKE2b-256 f05c7b33a4bd9530f03510a6841caf046d49c796704f0fbc8d81802b3bcf54a6

See more details on using hashes here.

File details

Details for the file pjdev_armis_sdk-5.2.1-py3-none-any.whl.

File metadata

  • Download URL: pjdev_armis_sdk-5.2.1-py3-none-any.whl
  • Upload date:
  • Size: 28.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: Hatch/1.18.0 {"ci":true,"cpu":"aarch64","distro":{"id":"noble","libc":{"lib":"glibc","version":"2.39"},"name":"Ubuntu","version":"24.04"},"implementation":{"name":"CPython","version":"3.12.3"},"installer":{"name":"hatch","version":"1.18.0"},"openssl_version":"OpenSSL 3.0.13 30 Jan 2024","python":"3.12.3","system":{"name":"Linux","release":"7.0.12-linuxkit"}} HTTPX2/2.12.0

File hashes

Hashes for pjdev_armis_sdk-5.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d05c0d3a6f74515d8b222809f985f655edf4178c5fa46515068d03496892a03c
MD5 75ebb155f2ac0267e08d3a7ecea80b74
BLAKE2b-256 7b133c1328e877de948b4cafb42dbb8aa9c867d662d05477a93eddea160ab3a7

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

5.2.1 This release

2 files

5.2.0

2 files

5.1.14

2 files

5.1.13

2 files

5.1.12

2 files

5.1.10

2 files

5.1.9

2 files

5.1.7

2 files

5.1.6

2 files

5.1.5

2 files

5.1.4

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page