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.

Metadata

Release files for secpod-saner-sdk 0.1.0.dev0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for secpod-saner-sdk 0.1.0.dev0
File Size Uploaded Provenance
secpod_saner_sdk-0.1.0.dev0.tar.gz 85.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for secpod-saner-sdk 0.1.0.dev0
File Interpreter ABI Platform
secpod_saner_sdk-0.1.0.dev0-py3-none-any.whl Python 3 none any Details

Total release size: 191.2 kB

Release files / secpod_saner_sdk-0.1.0.dev0.tar.gz

Download URL secpod_saner_sdk-0.1.0.dev0.tar.gz
Size 85.9 kB
Tags Source
SHA-256 checksum
How to use checksums
17453a449a58b44e40a08a33508b86d2bc85c150893339d0a156f362711fe054
BLAKE2b-256 checksum
How to use checksums
882399e71950aced8a0c37117f679d845195ea4596c44606f9ef2c7e2603d7d5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.2

Release files / secpod_saner_sdk-0.1.0.dev0-py3-none-any.whl

Download URL secpod_saner_sdk-0.1.0.dev0-py3-none-any.whl
Size 105.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3c9cb11f04e0e450e2d27bc78862aee81203fc88328232c5375d8cee0c9100b5
BLAKE2b-256 checksum
How to use checksums
2644579af0c606ee66d4a3f76a1829eddc7f069f69d9b3ccbcf1b0f08952ea4b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.2

Security for secpod-saner-sdk 0.1.0.dev0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0.dev0 This release

2 release files No provenance

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