Python client for Securonix Spotter search via the shared snypr-service-gateway: authenticate, submit async queries, poll status, and fetch results as JSON.
Official Spotter API documentation: Securonix Documentation — Spotter API.
Source code: github.com/williamgomez71/SecuronixAPI
End-to-end flow implemented by this library:
GET /ws/token/generatefor the WS session token.POST /api/v2/oauth/tokenwithwstokenfor the OAuth Bearer (JWT in practice).POST /spotter-api/spotter/api/v1/search/queries.- Poll
GET .../statusuntilCOMPLETED. GET .../resultsand return structured JSON.
The sequence matches the working examples in the SecuronixAPI repository (examples/).
From PyPI (distribution name securonix-spotter-client):
pip install securonix-spotter-clientFrom a clone of the GitHub repository:
git clone https://github.com/williamgomez71/SecuronixAPI.git
cd SecuronixAPI
pip install .Import the securonix_spotter package in Python:
from securonix_spotter import SpotterClientTENANT_BASE_URL(e.g.https://<tenant>.securonix.net/Snypr)TENANT_USERNAMETENANT_PASSWORD
A .env file is loaded automatically via python-dotenv (without overwriting variables already set in the shell).
If you used older names (SPOTTER_BASE_URL, SPOTTER_USERNAME, SPOTTER_PASSWORD), rename those keys in .env to the TENANT_* names above.
The URL most tenants use:
https://us-east1-prod01.securonix.net/shared/snypr-service-gateway
If you omit gateway_url when constructing SpotterClient, that base URL is used by default.
The Spotter gateway rejects fromTime=0 and toTime=0 (error 1005: invalid time range). The client therefore always sends a valid window.
| What you pass | Effective window |
|---|---|
Both omitted or both 0 (default) |
Last 24 hours in UTC: from (now UTC − 24h) to now UTC, as epoch milliseconds. |
from_time only (> 0, to_time ≤ 0) |
From your from_time to now (UTC, ms). |
to_time only (from_time ≤ 0, to_time > 0) |
24 hours before to_time up to to_time (UTC, ms). |
| Both set | Your exact range (must satisfy from_time < to_time). |
So if you call execute(query) with no time arguments, you are querying the past 24 hours, not “all time”.
from_time and to_time are always Unix epoch in milliseconds in UTC.
from securonix_spotter import SpotterClient
client = SpotterClient()
query = "index = violation | stats count by tenantname policyname criticality"
results = client.execute(query)
print(results)from datetime import datetime, timedelta, timezone
from securonix_spotter import SpotterClient
client = SpotterClient()
query = "index = violation | stats count by tenantname policyname criticality"
# Last 2 hours
end = datetime.now(timezone.utc)
start = end - timedelta(hours=2)
from_time = int(start.timestamp() * 1000)
to_time = int(end.timestamp() * 1000)
results = client.execute(query, from_time=from_time, to_time=to_time)
print(results)from datetime import datetime, timezone
from securonix_spotter import SpotterClient
client = SpotterClient()
query = "index = violation | stats count by tenantname policyname criticality"
from_time = int(datetime(2026, 4, 28, 0, 0, 0, tzinfo=timezone.utc).timestamp() * 1000)
to_time = int(datetime(2026, 4, 28, 10, 0, 0, tzinfo=timezone.utc).timestamp() * 1000)
results = client.execute(
query,
from_time=from_time,
to_time=to_time,
poll_interval=3,
timeout=420,
)
print(results)from securonix_spotter import SpotterAuthError, SpotterClient, SpotterTimeoutError
gateway = "https://us-east1-prod01.securonix.net/shared/snypr-service-gateway"
client = SpotterClient(gateway_url=gateway)
try:
data = client.execute(
"index = violation | stats count by tenantname policyname criticality",
poll_interval=3,
timeout=420,
)
print(data)
except SpotterAuthError as exc:
print(f"Authentication error: {exc}")
except SpotterTimeoutError as exc:
print(f"Polling timeout: {exc}")from securonix_spotter import SpotterClient
client = SpotterClient()
query = (
'index = violation and policyname = "possible brute force attack detected - csso" '
"| STATS sourceaddress destinationaddress accountname destinationport"
)
query_id = client.run_query(
query,
limit=5000,
sort_by="sourceaddress",
sort_order="desc",
timeout=600,
)
client.wait_for_results(query_id, poll_interval=2, timeout=600)
results = client.get_results(query_id, offset=0, limit=500)
print(results)examples/basic_query.pyexamples/advanced_query.py