model_scanner, community_scanner, evaluation_sessions) do not cover what you need, for example listing past scans or exporting a report.
If you are new to the SDK, read Core concepts first.
Before you run the examples
Every example creates a client withHiddenLayer() and no arguments. The client reads your credentials from environment variables, so no secrets appear in code. Set them before running a script:
- macOS/Linux
- Windows
YOUR_SCAN_ID or YOUR_MODEL_ID with real IDs from your account. You can find scan IDs with the first recipe below, or in the scan_id field of a ScanReport returned by the model scanner.
List recent scans
client.scans.jobs.list() returns scan results that match your filters. Use it to build dashboards, audit recent activity, or find a scan ID.
This method is not auto-paginated. It returns a JobListResponse with four fields: items (the current page), limit, offset, and total (the number of matching scans). To read every matching scan, increase offset until you reach total.
The API describes
status only as a list of “Statuses”. Using the response status values (such as done) as filter values is an assumption that needs confirmation. The format of the sort parameter is not documented in the SDK, so it is not shown here.Get a full scan report
client.scans.jobs.retrieve(scan_id) returns a ScanReport for one scan, including per-file results in file_results. Pass has_detections=True to include only files with detections (and their parent files), which keeps large reports small.
Get a scan summary
client.scans.results.retrieve_summary(scan_id) returns a ScanReportSummary: the scan’s status, inventory, and summary counts, without per-file results. It is a lighter request than a full report, so use it to check progress or show a headline result.
Iterate over file results
A scan of a large model folder can contain many files.client.scans.results.list_files(scan_id) returns the file results one page at a time using cursor pagination: each page includes a pointer (cursor) to the next page.
Automatic pagination
Loop over the returned object and the SDK requests the next page whenever it needs more items.Manual page control
Use manual control when you want to process one page at a time, for example to stop early or to show progress per page. The current page’s items are in.items.
AsyncHiddenLayer, use async for for automatic pagination and await page.get_next_page() for manual control.
Export a SARIF report
SARIF (Static Analysis Results Interchange Format) is a standard JSON format for security findings. Tools such as GitHub code scanning can import SARIF files.client.scans.results.sarif(scan_id) returns the SARIF document as a str, so you can write it straight to a file.
Retrieve a model
client.models.retrieve(model_id) returns a ModelRetrieveResponse with the model’s name, source, model_id, tenant_id, and versions. A scan result’s inventory.model_id gives you the model ID.
Delete a model
client.models.delete(model_id) deletes a model and returns None. Your API credentials need appropriate permissions for this operation.
What else is removed along with the model (for example, its versions and scan results) is not documented in the SDK and needs confirmation.
Analyze a prompt with Prompt Analyzer
client.prompt_analyzer.create() sends a prompt (and optionally a model output) to Prompt Analyzer. The response includes a verdict and per-category results.
The SDK types
verdict as an optional boolean. Its exact meaning (for example, whether True means a detection) is not described in the SDK and needs confirmation. See the Prompt Analyzer documentation.Read response headers with with_raw_response
Add .with_raw_response before the method name to get the HTTP response object. Call .parse() to get the same object the normal method returns. This is how you read the hl-runtime-action header from the agentic evaluation endpoints (see Runtime security).
Stream a response body
.with_streaming_response does not read the body until you ask for it. It must be used in a with block so that the connection is always closed. This example streams a SARIF report to disk in chunks instead of holding it in memory.
.read(), .text(), .json(), .iter_text(), .iter_lines(), and .parse().
Set per-request options
Timeouts and retries with with_options
client.with_options() returns a copy of the client with some settings changed. The copy shares the original client’s connection pool. Use it to give one slow operation a longer timeout or to disable retries for one call.
timeout= argument directly, for example client.scans.jobs.list(limit=10, timeout=10.0).
Extra headers, query parameters, and body fields
Every method acceptsextra_headers, extra_query, and extra_body. Use them to send values that the SDK does not model yet, for example a field recently added to the REST API. Values passed this way take precedence over values set on the client or by the method.
extra_body works the same way for methods that send a JSON body, such as interactions.analyze.
Call an endpoint the SDK does not wrap (advanced)
This is an advanced technique. Prefer the typed resource methods whenever they exist. Responses from custom requests are not validated or typed.
client.get(), client.post(), and the other HTTP verb methods send a request to any path relative to the base URL. They use the client’s authentication, retries, and timeouts. Pass cast_to=httpx.Response to get the raw httpx response. Error responses still raise the usual hiddenlayer exceptions.
client.post(path, cast_to=httpx.Response, body={...}).
Run requests concurrently with the async client
When you need to analyze many interactions at once, the async client lets you send requests in parallel instead of one after another.asyncio.gather starts all calls and waits for them to finish. Passing return_exceptions=True keeps one failure from cancelling the others.
Use the aiohttp backend
By default the async client useshttpx to send requests. You can switch to aiohttp, which the SDK README recommends for improved concurrency performance. Install the extra first:
DefaultAioHttpClient() as the HTTP client:
Deprecated resources
client.models.cards.list()is deprecated in favor of the asset inventory API (GET /asset-inventory/v2/assets). That endpoint is not available in this SDK version. Avoid building new code onmodels.cards.list().client.sensorsis deprecated. The SDK docstring states the endpoint “will be removed after April 13, 2026”. Do not use it in new code.

