Skip to content

Cisco Secure Network Analytics API Client Code Examples

This guide shows how to use the CiscoSNA client to interact with Cisco Secure Network Analytics APIs.

Environment Variables

You can set environment variables in your shell to avoid hardcoding sensitive information in your code. Check Environment Variables for details.

Connect using username and password
from wingpy import CiscoSNA

sna = CiscoSNA(
    base_url="https://sna.example.com", # (1)!
    username="...", # (2)!
    password="...", # (3)!
    tenant_name="...", # (4)!
    verify=False,
)
  1. Environment variable:

    WINGPY_SNA_BASE_URL
    
  2. Environment variable:

    WINGPY_SNA_USERNAME
    
  3. Environment variable:

    WINGPY_SNA_PASSWORD
    
  4. Environment variable:

    WINGPY_SNA_TENANT_NAME
    

If you have multiple tenants, you can specify the tenant name to use. If no tenant name is provided, the client will use the first/only available tenant for the user.

A simple GET request
response = sna.get("/smc-users/rest/v1/user-context")
print(f"Username: {response['data']['userName']}")

Even though Secure Network Analytics does not use pagination you can still benefit from using the get_all method to retrieve all results from a list-based API call. Response data is usually placed in a data list element by the API. But for some API endpoints some cases list-data is nested further and in those cases get_all will extract and return the actual list so you can iterate over it directly.

Use get_all to locate and return just a list of result items so you can iterate over them
host_group_tags = sna.get_all("/sw-reporting/v1/tenants/{tenantId}/customHosts/tags")
for tag in host_group_tags:
    print(tag["displayName"])

Some Secure Network Analytics API calls are query-based, meaning they return an ID and you need to poll for the status of the result.

When the query status indicates that the job is complete, you can retrieve the results using the provided result ID and the path documented in the API.

Secure Network Analytics API has two different reporting APIs that work in this way, but their implementation details differ.

Handling version 1 queries manually

Tip

Use the wait_for method in the client to handle queries for you automatically.

Version 1 queries is created using a POST request to /sw-reporting/v1/tenants/{tenantId}/{query_path} which creates the job and returns a query ID.

{
  "data": {
    "queryId": "6a7af913782f23084d65cfbb",
    "status": "IN_PROGRESS"
  }
}

We must then periodically poll /sw-reporting/v1/tenants/{tenantId}{query_path}/{queryId} to check the status of the job.

Once the status field changes to "COMPLETED", the results are available at /sw-reporting/v1/tenants/{tenantId}{result_path}/{queryId}/results.

Handling version 2 queries manually

Tip

Use the wait_for method in the client to handle queries for you automatically.

Version 2 queries is created using a POST request to /sw-reporting/v2/tenants/{tenantId}{query_path} which creates the job and returns a query ID.

{
  "data": {
    "query": {
      "id": "6a7af7a8782f23084d65cfb2",
      "domainId": "301",
      "percentComplete": 8.33,
      "status": "IN_PROGRESS"
    }
  }
}

We must then periodically poll /sw-reporting/v2/tenants/{tenantId}{query_path}/{queryId} to check the status of the job.

Once the status field changes to "COMPLETED", the results are available at /sw-reporting/v2/tenants/{tenantId}{query_path}/{queryId}/results.

Automatic v1/v2 query handling with wait_for

The wait_for method in the client handles queries for you, and simply returns the result path when the job is complete. You can then use get_all to retrieve the results.

Job based API calls like flow searches are easily handled with wait_for
query = {
    "startDateTime": "2026-08-11T08:00:00Z",
    "endDateTime": "2026-08-11T08:00:00Z",
}
flows_path = sna.wait_for(
    sna.post,
    "/sw-reporting/v2/tenants/{tenantId}/flows/queries",
    data=query,
)
flows = sna.get_all(flows_path)

for flow in flows:
    print(flow["peer"]["ipAddress"])
Simplify the process even further by using the `on_complete` hook to automatically retrieve the results when the job is complete.
query = {
    "startTime": "2026-08-11T08:00:00.000",
    "endTime": "2026-08-11T09:00:00.000",
}
top_hosts = sna.wait_for(
    sna.post,
    "/sw-reporting/v1/tenants/{tenantId}/flow-reports/top-hosts/queries",
    data=query,
    on_complete=sna.get_all,
)

for host in top_hosts:
    print(host["bytes"])