Python
elastio_client.py is a single-file reference client you can drop into any Python 3.8+ project. It wraps requests, reads your token from the environment, raises a typed exception with the gateway’s error message, retries transient failures and walks paginated lists for you.
Install
Section titled “Install”-
Install
requests:Terminal window python3 -m pip install requests -
Download the client next to your script: elastio_client.py.
Terminal window curl -sSO https://developer.elastio.com/downloads/elastio_client.py -
Export a personal access token:
Terminal window export ELASTIO_TOKEN="…"
Connect
Section titled “Connect”from elastio_client import ElastioClient, ElastioAPIError
client = ElastioClient("acme") # https://acme.app.elastio.com, token from $ELASTIO_TOKEN| Argument | Default | What it does |
|---|---|---|
tenant |
None | Console subdomain. acme → https://acme.app.elastio.com. |
token |
$ELASTIO_TOKEN |
Personal access token, sent as Authorization: Bearer …. |
base_url |
https://{tenant}.app.elastio.com |
Override the host, for example to go through a proxy. |
timeout |
30 |
Per-request timeout in seconds. |
max_retries |
3 |
Retries for GET, PUT and DELETE after a 5xx response or connection error, with exponential backoff. POST and PATCH are never retried. |
get, post, put, patch and delete take a path relative to the tenant host and return the parsed JSON body (None for 204 No Content).
List open incidents
Section titled “List open incidents”The incidents list uses limit / offset paging and returns total and data. paginate_offset keeps requesting pages until it has seen total items:
for incident in client.paginate_offset( "/gateway/api/v2/incidents", params={"status": "open", "severity": "critical,high"}, limit=100,): finding = incident.get("finding") or {} print(incident["handle"], finding.get("severity"), finding.get("asset_name"))Fetch a single page with get when you only need the first few:
page = client.get("/gateway/api/v2/incidents", params={"status": "open", "limit": 10})print(f"{page['total']} open incidents")Search assets with findings
Section titled “Search assets with findings”Unified asset search paginates with page_size and a page_token query parameter, and nests its results under data.assets and data.pagination. Tell paginate_token where to look:
assets = client.paginate_token( "/gateway/api/v1/search/assets", params={"health": "infected", "platform": "aws"}, page_size=100, items_key="data.assets", token_param="page_token",)for asset in assets: print(asset["asset_name"], asset["asset_type"], asset["threat_counts"]["total"])Export every finding from a hunt result
Section titled “Export every finding from a hunt result”This operation uses the common token style: page_size plus next_page_token, with the next token in pagination.next_page_token. Those are the helper’s defaults:
import json
scan_job_id = "9b2f4c1e-6d7a-4e8b-a1c3-5f0e2d4b6a71"
with open("findings.jsonl", "w") as out: for finding in client.paginate_token( f"/gateway/api/v1/scanjobs/{scan_job_id}/threats", params={"suppressed": "false"}, page_size=100, ): out.write(json.dumps(finding) + "\n")paginate_token also accepts size_param="pageSize", token_param="pageToken" for operations that use the camelCase style. Check each operation’s parameters in the API reference and see Pagination.
Handle errors
Section titled “Handle errors”Any non-2xx response raises ElastioAPIError with the fields of the gateway’s error envelope:
try: client.get("/gateway/api/v2/incidents/00000000-0000-0000-0000-000000000000")except ElastioAPIError as err: print(err.status, err.error, err.message) # e.g. 404 Not Found … if err.status == 401: raise SystemExit("Token missing, expired or revoked")err.response holds the underlying requests.Response if you need headers or the raw body. See Errors for what each status means.
Run it from the command line
Section titled “Run it from the command line”The file doubles as a quick smoke test:
python3 elastio_client.py acme /gateway/api/v2/incidents