ExonaExona API
Core Concepts

Questionnaire Data

Provide insurer questionnaire answers to improve scan accuracy and personalise the risk assessment.

What is questionnaire data?

When underwriters assess a risk, they often have additional information from the insured company that is not available in public sources: answers to application questions, self-reported technical details, or specific coverage disclosures. This information can significantly improve the accuracy of the AI risk assessment.

The Exona API accepts an optional questionnaire field in POST /v1/scans: a list of question-and-answer pairs that are fed into the enrichment and risk assessment pipeline alongside publicly gathered data.


Adding questionnaire data

response = requests.post(
    f"{BASE_URL}/scans",
    headers=HEADERS,
    json={
        "company_name": "Acme AI Ltd",
        "company_website": "https://acme.ai",
        "questionnaire": [
            {
                "question": "Does your product use AI or machine learning to make autonomous decisions?",
                "answer": "Yes. Our claims processing system automatically approves or denies claims under $10,000 without human review."
            },
            {
                "question": "How many end users interact with your AI system?",
                "answer": "Approximately 40,000 claimants per month across our insurer clients."
            },
            {
                "question": "Is your system subject to any regulatory oversight or pending investigations?",
                "answer": "We are currently in dialogue with the FCA regarding our automated decision-making disclosure obligations under Consumer Duty."
            },
            {
                "question": "What personal data does your product process?",
                "answer": "Medical records, photographic evidence, and financial transaction data."
            },
        ],
    },
)

How questionnaire data is used

Questionnaire answers are treated as first-party evidence. They are:

  1. Fed into enrichment: answers can confirm, correct, or extend what public research finds. For example, if public sources are ambiguous about the level of AI autonomy, a direct answer resolves that ambiguity.
  2. Cited in risk assessment rationale: when the AI generates risk score motivations, it can cite questionnaire answers as evidence alongside web sources. This makes the rationale fully auditable.
  3. Not used to override risk scores: questionnaire answers influence the assessment but do not mechanically override scores. The AI model weighs all evidence together.

Format

The questionnaire field is an array of objects, each with a question (string) and an answer (string). Both fields are required if the object is included.

FieldTypeRequiredDescription
questionstringYesThe question text, as asked to the insured.
answerstringYesThe insured's answer. Can be free-form text of any length.

There is no fixed list of questions: you can pass any questions from your application form. Exona handles the interpretation.


Limits

LimitValue
Maximum questions per scan50
Maximum answer length5,000 characters
Maximum total questionnaire size20,000 characters

Requests exceeding these limits return a 400 error with code QUESTIONNAIRE_TOO_LARGE.


Questionnaire data and caching

When questionnaire data is present, the scan cache (max_age_days) is bypassed. A cached scan may have been generated with different questionnaire answers: or none at all: so it is not considered a valid match.

If you want to avoid re-running scans for the same company across multiple sessions, store the scan ID on your side and retrieve it with GET /v1/scans/{id} directly.


Example: application intake workflow

import requests
import time
 
def assess_application(company_name, company_website, application_answers):
    """
    Run a scan for an incoming insurance application with questionnaire data.
    Returns the completed scan result.
    """
    response = requests.post(
        f"{BASE_URL}/scans",
        headers=HEADERS,
        json={
            "company_name": company_name,
            "company_website": company_website,
            "questionnaire": application_answers,
        },
    )
    response.raise_for_status()
    scan_id = response.json()["id"]
 
    while True:
        r = requests.get(f"{BASE_URL}/scans/{scan_id}", headers=HEADERS)
        data = r.json()
 
        if data["status"] == "completed":
            return data["result"]
        elif data["status"] == "failed":
            raise RuntimeError(f"Scan failed: {data['error']['message']}")
 
        time.sleep(10)
 
 
# Example usage
result = assess_application(
    company_name="Acme AI Ltd",
    company_website="https://acme.ai",
    application_answers=[
        {
            "question": "Describe how AI is used in your core product.",
            "answer": "We use a transformer-based model to assess vehicle damage from photos and automatically approve or deny claims."
        },
        {
            "question": "What safeguards exist for AI-generated decisions?",
            "answer": "Claims above £25,000 are always reviewed by a human adjuster. All decisions are logged and explainable."
        },
    ],
)
 
print(result["risk_assessment"]["overall_risk_level"])

On this page