ExonaExona API
Core Concepts

Scans

A scan is the core object in the Exona API. It represents a single risk analysis for one company.

What is a scan?

A scan is a complete risk analysis run for a single company. You create one with POST /v1/scans and retrieve it with GET /v1/scans/{id}. When a scan is complete, it contains:

  • Enrichment: structured business intelligence extracted from public sources (sector, revenue, operations, AI product description)
  • Risk assessment: AI-generated scores across nine risk dimensions with evidence-backed rationale
  • Matched incidents: historical AI incidents from the Exona incident database that are relevant to this company's profile

Scan lifecycle

A scan moves through three possible states:

processing → completed
           → failed
StatusMeaning
processingThe scan is running. Check back in 10–30 seconds.
completedThe scan finished successfully. The result field is populated.
failedAn unrecoverable error occurred. The error field explains what went wrong.

Scan ID format

Every scan has an opaque, unique identifier prefixed with scn_:

EnvironmentExample
Livescn_01jrq7m2d3e4f5g6h7j8k9l0mn
Testscn_test_01jrq7m2d3e4f5g6h7j8k9l0mn

The prefix makes it immediately clear in logs which environment a scan belongs to.


What Exona does during a scan

When you create a scan, Exona runs a three-stage pipeline in the background:

  1. Web research & enrichment: A research agent searches public sources (company website, news, regulatory filings) and extracts structured business intelligence.
  2. Incident matching: The enriched company profile is compared against a curated database of AI-related incidents using vector similarity search and LLM validation. Incidents with high relevance are included in the result.
  3. AI risk assessment: A risk model scores the company across nine dimensions using the enriched data and matched incidents as evidence. Each score is accompanied by a rationale citing the specific evidence used.

This pipeline typically completes in 30–120 seconds. The exact time depends on how much public information is available about the company.


One company per scan

Each scan covers exactly one company. If you need to analyse multiple companies, create multiple scans in parallel. There is no batch endpoint: this is intentional to keep the response contract simple and predictable.

import requests
import concurrent.futures
 
API_KEY = "exo_live_..."
BASE_URL = "https://platform.exonalab.com/api/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
 
companies = [
    {"company_name": "Acme AI", "company_website": "https://acme.ai"},
    {"company_name": "Zenith ML", "company_website": "https://zenith.ml"},
    {"company_name": "Cortex Risk", "company_website": "https://cortexrisk.com"},
]
 
def create_scan(company):
    r = requests.post(f"{BASE_URL}/scans", headers=HEADERS, json=company)
    r.raise_for_status()
    return r.json()["id"]
 
with concurrent.futures.ThreadPoolExecutor() as executor:
    scan_ids = list(executor.map(create_scan, companies))
 
print(scan_ids)
# ['scn_...', 'scn_...', 'scn_...']

Retrieving past scans

Any scan you have created can be retrieved by its ID indefinitely. Completed results are persisted and do not expire. This means you can store scan IDs in your own system and retrieve the result at any time without re-running the analysis.

If you want to re-run a scan for a company to get fresher data, see Scan caching.

On this page