Skip to main content

Findings API

The Findings API provides programmatic access to finding details from the QuilrAI platform. Use it to automate finding retrieval, integrate with SIEMs, build reporting pipelines, or perform scheduled security posture queries — without manual UI interaction.

The API is language-agnostic and works with any scripting or programming language that supports HTTP requests. This guide includes ready-to-use examples in PowerShell and Python.

Prerequisites

RequirementDetails
QuilrAI tenant accessActive user account with valid credentials
Scripting environmentPowerShell 5.1+ or Python 3.6+ (or any HTTP-capable tool)
Python libraryrequests — install via pip install requests
Network accessHTTPS connectivity to your QuilrAI platform URL
Subscriber IDYour organization's subscriber identifier (UUID)
Tenant IDYour assigned tenant identifier (UUID)
User roleRole with permission to access findings
API credentialsDedicated service account email and password
info

API credentials (email and password) are created exclusively by the QuilrAI team. To obtain your API credentials, Subscriber ID, and Tenant ID, contact the QuilrAI support team.

Platform URLs

Use the base URL that matches your region and deployment environment:

RegionEnvironmentBase URL
IndiaPOChttps://platform.quilr.ai
IndiaProductionhttps://platform.quilrai.com
USPOChttps://app.quilr.ai
USProductionhttps://app.quilrai.com

Replace <base-url> in all examples below with the appropriate domain for your environment.

API Workflow

The integration follows a two-step workflow:

┌─────────────────────┐     ┌────────────────────────┐     ┌──────────────────┐
│ 1. Authenticate │────▶│ 2. Extract JWT Token │────▶│ 3. Query │
│ POST /auth/login │ │ from response/cookie │ │ Findings API │
└─────────────────────┘ └────────────────────────┘ └──────────────────┘
StepEndpointMethodPurpose
Authenticate/bff/auth/auth/loginPOSTObtain JWT session token
Get Findings/bff/quilr-query-builder/findings/table/dataPOSTRetrieve finding records

Step 1 — Authenticate

Send your credentials to the login endpoint to receive a JWT token stored in the quilr_web_auth session cookie.

Endpoint

POST https://<base-url>/bff/auth/auth/login
Content-Type: application/json

Request body

{
"email": "<your-email>",
"password": "<your-password>"
}
info

The JWT token has a limited lifespan (typically 4 hours). Generate a new token before it expires to maintain uninterrupted API access.

PowerShell

# Create a web session
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$session.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"

# Send login request
$loginResponse = Invoke-WebRequest -UseBasicParsing `
-Uri "https://<base-url>/bff/auth/auth/login" `
-Method "POST" `
-WebSession $session `
-Headers @{
"Accept" = "application/json, text/plain, */*"
"Origin" = "https://<base-url>"
"Referer" = "https://<base-url>/en/internal-login"
"Sec-Fetch-Dest" = "empty"
"Sec-Fetch-Mode" = "cors"
"Sec-Fetch-Site" = "same-origin"
} `
-ContentType "application/json" `
-Body '{"email":"<your-email>","password":"<your-password>"}'

# Extract JWT token from quilr_web_auth cookie
$authCookie = $session.Cookies.GetCookies("https://<base-url>") |
Where-Object { $_.Name -eq "quilr_web_auth" }
$decoded = [System.Web.HttpUtility]::UrlDecode($authCookie.Value)
$authData = $decoded | ConvertFrom-Json
$token = $authData.token

Write-Host "Token acquired successfully"

Python

import requests
import json
import urllib.parse

# Create a session
session = requests.Session()
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
"Accept": "application/json, text/plain, */*",
"Origin": "https://<base-url>",
"Referer": "https://<base-url>/en/internal-login",
})

# Send login request
login_url = "https://<base-url>/bff/auth/auth/login"
credentials = {"email": "<your-email>", "password": "<your-password>"}
login_response = session.post(login_url, json=credentials)
login_response.raise_for_status()

# Extract JWT token from quilr_web_auth cookie
auth_cookie = session.cookies.get("quilr_web_auth", domain="<base-url>")
decoded = urllib.parse.unquote(auth_cookie)
auth_data = json.loads(decoded)
token = auth_data["token"]

print("Token acquired successfully")

Step 2 — Retrieve Findings

Use the JWT token from Step 1 to query the findings endpoint.

Endpoint

POST https://<base-url>/bff/quilr-query-builder/findings/table/data
Content-Type: application/json

Required headers

HeaderDescriptionExample
AuthorizationBearer token from loginBearer eyJhbG...
subscriberidOrganization subscriber UUIDa1b2c3d4-e5f6-7890-abcd-ef1234567890
tenantTenant UUIDf9e8d7c6-b5a4-3210-fedc-ba0987654321
Content-TypeRequest content typeapplication/json

Request body parameters

ParameterTypeDescription
filtersObjectFilter criteria for narrowing results. Empty {} returns all findings.
limitIntegerMaximum records to return per request (default: 10)
offsetIntegerNumber of records to skip for pagination (default: 0)

PowerShell

$headers = @{
"Accept" = "application/json, text/plain, */*"
"Authorization" = "Bearer $token"
"Origin" = "https://<base-url>"
"Referer" = "https://<base-url>/en/findings"
"Sec-Fetch-Dest" = "empty"
"Sec-Fetch-Mode" = "cors"
"Sec-Fetch-Site" = "same-origin"
"subscriberid" = "<your-subscriber-id>"
"tenant" = "<your-tenant-id>"
}

$body = '{"filters":{},"limit":10,"offset":0}'

$findingsResponse = Invoke-WebRequest -UseBasicParsing `
-Uri "https://<base-url>/bff/quilr-query-builder/findings/table/data" `
-Method "POST" `
-WebSession $session `
-Headers $headers `
-ContentType "application/json" `
-Body $body

$findings = ($findingsResponse.Content | ConvertFrom-Json)
$findings.data | Format-Table
Write-Host "Total findings returned: $($findings.data.Count)"

Python

headers = {
"Accept": "application/json, text/plain, */*",
"Authorization": f"Bearer {token}",
"Origin": "https://<base-url>",
"Referer": "https://<base-url>/en/findings",
"subscriberid": "<your-subscriber-id>",
"tenant": "<your-tenant-id>",
}
body = {"filters": {}, "limit": 10, "offset": 0}

findings_url = "https://<base-url>/bff/quilr-query-builder/findings/table/data"
findings_response = session.post(findings_url, json=body, headers=headers)
findings_response.raise_for_status()

findings = findings_response.json()
for finding in findings.get("data", []):
print(finding)

print(f"Total findings returned: {len(findings.get('data', []))}")

Pagination

Adjust limit and offset to page through large result sets. For example, set offset to 10 on the second request to fetch records 11–20.

Python — paginate all findings

all_findings = []
offset = 0
limit = 50

while True:
body = {"filters": {}, "limit": limit, "offset": offset}
resp = session.post(findings_url, json=body, headers=headers)
data = resp.json().get("data", [])
if not data:
break
all_findings.extend(data)
offset += limit

print(f"Total findings collected: {len(all_findings)}")

PowerShell — paginate all findings

$allFindings = @()
$offset = 0
$limit = 50

do {
$body = '{"filters":{},"limit":' + $limit + ',"offset":' + $offset + '}'
$resp = Invoke-WebRequest -UseBasicParsing `
-Uri "https://<base-url>/bff/quilr-query-builder/findings/table/data" `
-Method "POST" -WebSession $session -Headers $headers `
-ContentType "application/json" -Body $body
$data = ($resp.Content | ConvertFrom-Json).data
$allFindings += $data
$offset += $limit
} while ($data.Count -eq $limit)

Write-Host "Total findings collected: $($allFindings.Count)"

Validation and Testing

After setting up the integration, verify it is working correctly:

  1. Run the authentication script and confirm an HTTP 200 response.
  2. Check that the JWT token is present in the quilr_web_auth cookie after login.
  3. Execute the findings request and confirm a 200 OK status.
  4. Inspect the response body to confirm finding records appear in the expected JSON structure.
  5. Test pagination by adjusting limit and offset to confirm all records are accessible.

Quick validation — PowerShell

Write-Host "Login Status:        $($loginResponse.StatusCode)"
Write-Host "Findings Status: $($findingsResponse.StatusCode)"
Write-Host "Records returned: $($findings.data.Count)"

Quick validation — Python

print(f"Login Status:     {login_response.status_code}")
print(f"Findings Status: {findings_response.status_code}")
print(f"Records returned: {len(findings.get('data', []))}")

Troubleshooting

IssueResolution
HTTP 401 on loginVerify email and password are correct. Check that the account is active in QuilrAI.
HTTP 401 on findings requestToken may have expired. Re-run the authentication script to obtain a fresh JWT.
HTTP 403 ForbiddenUser role does not have permission to access findings. Contact your QuilrAI administrator.
Empty response / no findingsConfirm the Subscriber ID and Tenant ID are correct. Remove or adjust filters.
Connection timeoutVerify network / firewall allows HTTPS traffic to your QuilrAI platform URL.
PowerShell TLS errorRun [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 before requests.
Python SSL errorUpgrade the requests library: pip install --upgrade requests certifi
JSON parse errorEnsure response Content-Type is application/json. Check for HTML error pages in the response body.

Summary

StepActionEndpoint / Detail
1Create HTTP sessionLanguage-specific session or client object
2Authenticate with credentialsPOST /bff/auth/auth/login
3Extract JWT from response cookieParse quilr_web_auth cookie value
4Configure findings request headersSet Authorization, subscriberid, tenant
5Send findings POST requestPOST /bff/quilr-query-builder/findings/table/data
6Parse and process JSON responseLanguage-specific JSON parsing
tip

The QuilrAI Findings API is language-agnostic. While this guide provides PowerShell and Python examples, the same calls can be made from any tool that supports HTTP requests — cURL, Node.js, Java, Go, C#, and others.