Client Types

The Saner Python SDK ships three client classes: SanerClient, PlatformClient, and CvemClient. All three share the exact same underlying configuration: authentication, environment variable fallbacks, retry policy, and logging behave identically regardless of which one you use. The choice between them is not a difference in behavior; it's a difference in which resources are exposed, how they're exposed (nested under two product namespaces vs. flat), and a small but real difference in how many pooled HTTP connections get opened. This guide covers all three, the resource split behind them, and how to pick the right one for your integration.


The Three Client Classes

SanerClient

SanerClient is the universal client. It nests every resource under two namespaces, .platform and .cvem, matching Saner's two product areas.

from saner import SanerClient

client = SanerClient(
    api_key="YOUR_API_KEY",
    accountid="YOUR_ACCOUNT_ID",
)

organizations = client.platform.Organization.get()
job_status = client.cvem.Patch.getRemediationJobStatus(accountid="Default", name="job1")

Use SanerClient when a single script or service needs both platform resources (organizations, users, accounts) and CVEM resources (vulnerability, patch, compliance), or when you're not yet sure which resources you'll need and want the option to reach either without changing your import.


PlatformClient

PlatformClient exposes only the 7 platform resources, flat on the client, with no .platform prefix needed.

from saner.platform import PlatformClient

client = PlatformClient(
    api_key="YOUR_API_KEY",
    accountid="YOUR_ACCOUNT_ID",
)

organizations = client.Organization.get()

Use PlatformClient when your integration only ever manages organizations, users, accounts, groups, service provisioning, reports, or MFA policy, and never calls a CVEM resource.


CvemClient

CvemClient exposes only the 13 CVEM resources, also flat.

from saner.cvem import CvemClient

client = CvemClient(
    api_key="YOUR_API_KEY",
    accountid="YOUR_ACCOUNT_ID",
)

job_status = client.Patch.getRemediationJobStatus(accountid="Default", name="job1")

Use CvemClient when your integration is scoped to vulnerability management, patching, compliance, endpoint, agent, or network-scanner operations and never touches organization/user administration.


Resource-to-Product Mapping

ProductResources
platform (7)Organization, Account, User, Group, ServiceProvision, Report, MFA
cvem (13)Agent, Device, CyberHygiene, PostureAnomaly, AssetExposure, Vulnerability, Compliance, RiskPrioritization, Patch, Endpoint, AD, NetworkScanner, Configuration

On SanerClient, every resource above is reached through its product namespace: client.platform.Organization, client.cvem.Patch. On PlatformClient/CvemClient, drop the namespace: client.Organization, client.Patch.

Note: The name you call a cvem resource by is sometimes shorter than the class backing it: client.Vulnerability is a VulnerabilityManagement instance, client.Compliance is ComplianceManagement, client.Patch is PatchManagement, and client.Endpoint is EndpointManagement. This only matters if you're inspecting type(client.Patch) directly or writing type hints against the class name; normal usage (client.Patch.getRemediationJobStatus(...)) is unaffected.


Decision Guide: Which Client Should You Use?

Use SanerClient when

  • your integration touches both products (for example, onboarding a new organization and checking its vulnerability posture in the same workflow)
  • you're building a general-purpose tool or internal library that shouldn't assume which product its caller needs
  • you're following the Quick Start guide and haven't yet settled on a narrower scope

Use PlatformClient when

  • your integration is scoped to organization/account/user administration and never calls a CVEM resource
  • you want the shortest possible call sites (client.Organization.get() instead of client.platform.Organization.get())
  • you're writing a small, single-purpose script or microservice dedicated to platform administration

Use CvemClient when

  • your integration is scoped to vulnerability management, patching, compliance, endpoints, or agents, and never calls a platform resource
  • the same flat-access and single-purpose reasoning as PlatformClient applies, mirrored for the 13 CVEM resources

The Connection-Pooling Cost of Mixing Clients

Every client, regardless of class, opens its own pair of pooled requests.Session objects (one for RPC calls, one for REST calls) the moment it's constructed. SanerClient opens exactly one pair and covers both products through it. If you instead instantiate a PlatformClient and a CvemClient side by side to get the same coverage, you pay for two pairs: twice the open connections, and two independent retry/logging contexts to keep in sync.

SetupSession pairs openedProducts covered
One SanerClient1platform + cvem
One PlatformClient1platform only
One CvemClient1cvem only
One PlatformClient + one CvemClient2platform + cvem

Note: Prefer a single SanerClient over instantiating both scoped clients side by side, unless you have a specific reason to isolate their connection pools, for example wanting an independent log_dir per product (see the Logging guide) or different timeout/retry_backoff settings for platform vs. CVEM calls.


Code Examples

SanerClient: onboarding a new organization, then checking its patch status

from saner import SanerClient

with SanerClient(api_key="YOUR_API_KEY", accountid="YOUR_ACCOUNT_ID") as client:
    org = client.platform.Organization.add(
        name="Demo Org",
        email="[email protected]",
        numberofsubscriptions="100",
    )
    print(org)

    job_status = client.cvem.Patch.getRemediationJobStatus(
        accountid="Demo Org",
        name="job1",
    )
    print(job_status)

PlatformClient: looking up a user

from saner.platform import PlatformClient

with PlatformClient(api_key="YOUR_API_KEY", accountid="YOUR_ACCOUNT_ID") as client:
    users = client.User.get(id=["[email protected]"])
    print(users)

CvemClient: reading an account's cyber hygiene score

from saner.cvem import CvemClient

with CvemClient(api_key="YOUR_API_KEY", accountid="YOUR_ACCOUNT_ID") as client:
    score = client.CyberHygiene.getAccountScore(account_name="Demo Account")
    print(score)

Switching Between Client Types

Because all three classes share the same constructor signature and environment-variable fallbacks (SANER_API_KEY, SANER_ACCOUNT_ID, SANER_BASE_URL, SANER_VERIFY_SSL), switching from one to another is just an import change plus un-nesting or nesting resource access, with no authentication, retry, or logging configuration changes needed.

Before (universal client):

from saner import SanerClient

client = SanerClient(api_key="YOUR_API_KEY", accountid="YOUR_ACCOUNT_ID")
client.platform.Organization.get()

After (scoped to platform once you know that's all you need):

from saner.platform import PlatformClient

client = PlatformClient(api_key="YOUR_API_KEY", accountid="YOUR_ACCOUNT_ID")
client.Organization.get()

Everything else about the client (configuration, retries, logging, close()) stays exactly the same.


Relationship to Other Guides

  • Client Configuration: the constructor parameters described there (api_key, timeout, retry_backoff, enable_logging, and the rest) apply identically to PlatformClient and CvemClient; this page only covers which resources you get, not how to configure the client.
  • Multi-Account Usage: that guide covers running multiple instances of one client class (for multiple accounts or regions), which is a different axis from the client type covered here. You can combine both: multiple CvemClient instances, one per account, for example.
  • Logging: the log filename is derived from accountid/base_url/log_dir, not from the client class; see the note there on exactly what happens to log files when a script uses both a PlatformClient and a CvemClient.
  • IDE Docstring Support: autocomplete differs by class, nested (client.platform., client.cvem.) on SanerClient, flat on PlatformClient/CvemClient.

Did this page help you?