Skip to main content
Yanked

This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Reason given by maintainers: placeholder upload to reserve package name

Saner SDK for Python

Official Python SDK for the SecPod Saner CVEM platform — continuous vulnerability and exposure management, patching, compliance, and endpoint management.

📖 Full API reference: apidocs-cvem.readme.io

This README is a quickstart. Every endpoint, parameter, and response shape is documented on the developer portal.


Installation

pip install secpod-saner-sdk

Requires Python 3.9+. The only runtime dependency is requests.

Quickstart

from saner import SanerClient

client = SanerClient(
    api_key="<YOUR_API_KEY>",
    accountid="<YOUR_ACCOUNT>",
    base_url="https://saner.secpod.com",
)

orgs = client.platform.Organization.get()
print(orgs)

client.close()

The client owns pooled HTTP connections, so close it when you're done — or let a with block do it:

with SanerClient(api_key="...", accountid="...") as client:
    devices = client.cvem.Device.get(ip="192.168.1.10")

Configuration

api_key, accountid, base_url, and verify_ssl all fall back to environment variables when omitted, so SanerClient() works unmodified across dev, CI, and containers — only the environment differs. An explicit argument always wins over the environment, which keeps the multi-client pattern (several clients, several accounts, one script) isolated even when the variables are set.

# with SANER_API_KEY / SANER_ACCOUNT_ID set in the environment
client = SanerClient()
Argument Default Description
api_key required — or SANER_API_KEY Saner API key, sent as the Authorization header.
accountid required — or SANER_ACCOUNT_ID Account the client operates against.
base_url SANER_BASE_URL, else https://saner.secpod.com Saner server URL. Use your regional or on-prem host.
verify_ssl SANER_VERIFY_SSL ("true"/"false"), else True Verify TLS certificates. Only disable against a lab server or an internal host with a self-signed cert.
timeout 30 Per-request timeout, in seconds.
max_retries 3 Retries after the first attempt. 0 disables retrying.
retry_backoff 1.0 Base for exponential backoff, in seconds.
retry_on_write False Also retry requests that may mutate server state. See below.
enable_logging False Write a JSONL request/response log.
log_dir "logs" Directory for the JSONL log.

Resources

Resources are split into two products, each with its own client if you only need one of them:

Resources Client
platform — shared across every Saner product Organization, Account, User, Group, ServicePrivision, Report, MFA from saner.platform import PlatformClient → flat: client.Organization
cvem — vulnerability management, patching, compliance, endpoints Agent, Device, Configuration, CyberHygiene, Vulnerability, Compliance, Patch, RiskPrioritization, PostureAnomaly, AssetExposure, Endpoint, NetworkScanner, AD from saner.cvem import CvemClient → flat: client.Patch

SanerClient (the universal client) nests both under client.platform.* / client.cvem.* instead. Prefer it when your process touches both products — each client instance opens its own pair of pooled sessions, so creating a PlatformClient and a CvemClient side by side doubles connection overhead for no benefit over one SanerClient. Reach for PlatformClient/CvemClient only when you exclusively work within one product and want flatter attribute access.

Methods return the parsed JSON response as a dict. Endpoints that produce a file (Report.getPdf, AD.downloadAgent) return bytes instead:

with SanerClient(api_key="...", accountid="...") as client:
    report = client.platform.Report.getPdf(accountid="MyAccount", reportname="Asset Report")
    if isinstance(report, bytes):
        open("report.zip", "wb").write(report)

Error handling

Every SDK error derives from SanerError and carries structured context, so you can branch on it without parsing message strings.

from saner import SanerClient, SanerAuthError, SanerRateLimitError, SanerError

try:
    client.cvem.Device.get(ip="192.168.1.10")
except SanerAuthError:
    ...                                  # 401 / 403 — bad or expired key
except SanerRateLimitError as e:
    print("retry after", e.retry_after)  # 429, exhausted retries
except SanerError as e:
    print(e.status_code, e.method, e.url, e.attempts, e.response_body)
Exception Raised when
SanerAuthError HTTP 401 / 403.
SanerRateLimitError HTTP 429 after retries are exhausted. Exposes retry_after.
SanerRequestError Network failure, SSL error, or a non-retryable HTTP error.
SanerResponseError Server replied successfully but the body was not valid JSON.
SanerError Base class — catch this to handle everything.

Invalid arguments raise plain ValueError / TypeError before any network call is made.

Retries

The SDK retries HTTP 429 and 500/502/503/504, plus connection failures, using exponential backoff with jitter capped at 60s. A Retry-After header always takes precedence over the computed delay.

Writes are not retried by default. Replaying a request that already reached the server can duplicate it — creating the same remediation job twice, for example. So retries apply to read-only calls only. Two exceptions are always safe and always retried: HTTP 429 (the server refused to process the request) and connect timeouts (the request never arrived).

Set retry_on_write=True if your workload is idempotent and you'd rather have the retries.

Logging

With enable_logging=True the SDK writes one JSON object per request to <log_dir>/secpod-saner-sdk__<account>__<hash>.jsonl, rotating weekly and keeping 8 backups.

Credentials (password, client_secret, token, ssl, …) are replaced with ***REDACTED*** and long values are truncated. Response bodies are not redacted, and in a CVEM product those contain asset inventories and CVE exposure data — treat the log directory as sensitive.

For application-level logging, the SDK also emits retry warnings through the standard logging module under the saner.* logger namespace.

Thread safety

None of the three client classes (SanerClient, PlatformClient, CvemClient) are thread-safe — each wraps requests.Session, which does not guarantee thread safety. Create one client per thread.

Support

License

Proprietary — see LICENSE. Use is governed by your SecPod license agreement.

Download files

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

Source Distribution

secpod_saner_sdk-0.1.0.dev0.tar.gz (85.9 kB view details)

Uploaded Source

Built Distribution

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

secpod_saner_sdk-0.1.0.dev0-py3-none-any.whl (105.3 kB view details)

Uploaded Python 3

File details

Details for the file secpod_saner_sdk-0.1.0.dev0.tar.gz.

File metadata

  • Download URL: secpod_saner_sdk-0.1.0.dev0.tar.gz
  • Upload date:
  • Size: 85.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for secpod_saner_sdk-0.1.0.dev0.tar.gz
Algorithm Hash digest
SHA256 17453a449a58b44e40a08a33508b86d2bc85c150893339d0a156f362711fe054
MD5 03a90b91415ceabffb676c9ac81f43d0
BLAKE2b-256 882399e71950aced8a0c37117f679d845195ea4596c44606f9ef2c7e2603d7d5

See more details on using hashes here.

File details

Details for the file secpod_saner_sdk-0.1.0.dev0-py3-none-any.whl.

File metadata

File hashes

Hashes for secpod_saner_sdk-0.1.0.dev0-py3-none-any.whl
Algorithm Hash digest
SHA256 3c9cb11f04e0e450e2d27bc78862aee81203fc88328232c5375d8cee0c9100b5
MD5 6d91ccb4579be100ea86298c489a367e
BLAKE2b-256 2644579af0c606ee66d4a3f76a1829eddc7f069f69d9b3ccbcf1b0f08952ea4b

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0.dev0 This release

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