Skip to content

VAARHAFT API (v2.5.0)

API for image and document verification.

Send us your files in a ZIP archive through a request like below, and we verify them for you. You can give us images (like JPEG, PNG, ...) or PDF documents - we extract relevant items like embedded images or document scans automatically.

You will get back a response where we detail exactly what the results of our different analyses are - and if your file is suspicious.

The results are packaged in a clean, structured JSON response like below, that is easy to understand, read and integrate. Additionally, depending on the results, we may send you one or multiple ZIP attachments containing additional results or indicators, like heatmaps that show you where your files have been edited.

We can even generate an evaluation report for you, which shows you everything we found in an intuitive way, that everyone, even without technical knowledge, can understand.



One more thing:

If you're using Python (v3.9 or higher), the easiest way to integrate our API is through our SDK - just run pip install vaarhaft-fraudscanner and you're good to go! (more info here)

Download OpenAPI description
Languages
Servers
https://api.vaarhaft.com
Operations

Upload a ZIP file for fraud analysis

Request

Analyze image and document files for fraud indicators.

There are two ways to send your ZIP file, depending on its size:

ZIP sizeMethodHow
< 10 MBDirect uploadSend the ZIP as file in the request body (multipart/form-data)
10–50 MBPresigned S3 uploadFirst call POST /v2/getUploadUrl, upload to S3, then call this endpoint with s3_key as query parameter

For files under 10 MB, nothing changes — use the direct upload as before. For larger files, the presigned flow bypasses the 10 MB gateway limit.

Python example (both flows):

import requests, os

API_URL = "https://api.vaarhaft.com"
HEADERS = {"x-api-key": "YOUR_KEY", "caseNumber": "Case-123"}
THRESHOLD = 9 * 1024 * 1024  # 9 MB safety margin

zip_path = "images.zip"
zip_size = os.path.getsize(zip_path)

if zip_size < THRESHOLD:
    # --- Direct upload (small files) ---
    with open(zip_path, "rb") as f:
        resp = requests.post(
            f"{API_URL}/v2/fraudscanner",
            files={"file": (zip_path, f, "application/zip")},
            headers=HEADERS,
        )
else:
    # --- Presigned S3 upload (large files) ---
    # Step 1: Get presigned URL
    url_resp = requests.post(
        f"{API_URL}/v2/getUploadUrl", headers=HEADERS
    )
    upload_url = url_resp.json()["upload_url"]
    s3_key = url_resp.json()["s3_key"]

    # Step 2: Upload ZIP to S3
    with open(zip_path, "rb") as f:
        requests.put(
            upload_url,
            data=f,
            headers={"Content-Type": "application/zip"},
        )

    # Step 3: Trigger analysis
    resp = requests.post(
        f"{API_URL}/v2/fraudscanner",
        params={"s3_key": s3_key},
        headers=HEADERS,
    )

result = resp.json()

Note: requests with many or large files can take longer due to compute-heavy analysis. The request timeout is 120s.

Security
apiKeyAuth
Query
s3_keystring

The S3 key returned by POST /v2/getUploadUrl. Use this instead of file for ZIPs larger than 10 MB. Either file (body) or s3_key (query) must be provided — not both, not neither.

Headers
x-api-keystringrequired

The API key for authentication.

caseNumberstringrequired

A case number to assign to the request. Typically matches the one that you use internally to track the files you're sending us.

issueDatestring(date)

The issue date of the case, if available.

languagestring

The language setting for the request; currently only used for the language of the generated analysis report. Defaults to 'de' (German).

Enum"de""en""pl"
Acceptstring

Optionally set the desired response media type. Use application/json for a JSON response with Base64-encoded attachments grouped by category (actual files: PDFs, PNGs, etc.; no ZIP bundles). If the header is not set, or if multipart/mixed or */* is set, the server will respond with JSON plus one or more ZIP attachments (e.g., heatmaps, reports), combined in a multipart response. This is the standard way to consume the FraudScanner API.

Enum"application/json""multipart/mixed""*/*"
Example: application/json
Bodymultipart/form-data

Required for direct upload (files < 10 MB). Omit when using the presigned S3 upload flow with s3_key.

filestring(binary)

The ZIP file to be uploaded for analysis. Required for direct upload (< 10 MB). Omit when using the presigned S3 upload flow.

curl -i -X POST \
  'https://api.vaarhaft.com/v2/fraudscanner?s3_key=string' \
  -H 'Accept: application/json' \
  -H 'Content-Type: multipart/form-data' \
  -H 'caseNumber: string' \
  -H 'issueDate: 2019-08-24' \
  -H 'language: de' \
  -H 'x-api-key: YOUR_API_KEY_HERE' \
  -F file=string

Responses

Success. The file was successfully uploaded and processed.

Body
suspicion_levelstring

An indicator as to how suspicious the contents of the request were. Is calculated from the suspicion levels of the contained files.

Enum"Green""Yellow""Red"
Filesobject

A mapping of filename to file analysis results.

caseNumberstring

The case number assigned to the request.

Example: "Case 123A"
sessionIdstring(UUID)

A unique identifier generated for the request.

Example: "5a8d8fd2-3317-4964-8298-caa96cd5cfa3"
modelVersionsobject

Overview of the internal VAARHAFT AI models used for classification.

tokensConsumedinteger

The amount of API tokens that were consumed by this request, depending for example on the number and types of processed files.

Example: 12
attachmentsobject

Map of 'categories-to-lists' for attachment objects (only relevant for pure JSON responses; see 'Accept'-header). Attachments are base64 encoded strings of the raw files. Categories:

  • analysis_report (PDF files)
  • heatmaps (PNG files)
  • thumbnails (PNG files)
  • reverse_search_downloads (different formats)
  • pdf_versions (PDF files)
Response
{ "suspicion_level": "Green", "Files": { "<FileID>1": { … }, "<FileID>2": { … } }, "caseNumber": "Case 123A", "sessionId": "5a8d8fd2-3317-4964-8298-caa96cd5cfa3", "modelVersions": { "generatedModelVersion": "vh-gen-uranus", "tamperedModelVersion": "vh-tp-venus", "semanticModelVersion": "vh-sem-mars" }, "tokensConsumed": 12, "attachments": { "heatmaps": [ … ], "analysis_report": [ … ] } }

Get a presigned S3 upload URL for large files

Request

Returns a presigned S3 PUT URL for uploading ZIP files that exceed the 10 MB direct upload limit. The URL is valid for 10 minutes. After uploading to S3, pass the returned s3_key to POST /v2/fraudscanner.

Flow:

  1. POST /v2/getUploadUrl → receive upload_url + s3_key
  2. PUT your ZIP to upload_url (with Content-Type: application/zip)
  3. POST /v2/fraudscanner?s3_key=<s3_key> → receive analysis results

The uploaded file is automatically deleted after processing (or after 24h if not consumed).

Security
apiKeyAuth
Headers
x-api-keystringrequired

The API key for authentication.

curl -i -X POST \
  https://api.vaarhaft.com/v2/getUploadUrl \
  -H 'x-api-key: YOUR_API_KEY_HERE'

Responses

Presigned URL generated successfully.

Bodyapplication/json
upload_urlstring(uri)required

Presigned S3 PUT URL. Upload your ZIP file here using an HTTP PUT request with Content-Type application/zip. Expires after 10 minutes.

Example: "https://s3.eu-central-1.amazonaws.com/vh-fs-large-uploads-prod/uploads/company123/a1b2c3d4.zip?..."
s3_keystringrequired

The S3 key to pass as query parameter to POST /v2/fraudscanner after uploading.

Example: "uploads/company123/a1b2c3d4.zip"
Response
application/json
{ "upload_url": "https://s3.eu-central-1.amazonaws.com/vh-fs-large-uploads-prod/uploads/company123/a1b2c3d4.zip?...", "s3_key": "uploads/company123/a1b2c3d4.zip" }