DEVELOPERS

API documentation

This documentation shows how to send an image of a vehicle registration document and get structured fields back — with a confidence value per field, optionally with authenticity checks. Processed in Germany; images are not stored.

Create an API key Full documentation in the dashboard

Endpoint

Authenticate with an API key in the Authorization header. Create keys in the dashboard under “API keys”; every call counts against your monthly quota. The version lives in the path — /v1/ is the current one.

curl -X POST https://api.fahrzeugschein24.de/v1/extract \
  -H "Authorization: Bearer <your-api-key>" \
  -F "file=@registration.jpg" \
  -F "services=extraction"

Formats and limits

  • JPEG, PNG, TIFF, BMP, WebP, HEIC/HEIF and PDF (page 1)
  • Max. 20 MB per file
  • Instead of a form upload you can send the image as the raw request body
  • Rotated or tilted shots are corrected automatically
  • Per-plan burst limit: 10 (Free) to 150 (Enterprise) requests per minute, on top of the monthly quota
  • Requests including the authenticity check have their own, tighter per-minute limit

Versioning

The API is versioned: within a version the response shape and error codes no longer change. New, backwards-incompatible capabilities ship under a new version — your existing integration keeps running unchanged.

  • Current path: /v1/extract — the version is always in the path
  • The path without a version segment (/extract) stays pinned to v1 permanently
  • Every response names the handling version in the X-API-Version header
  • Ahead of a retirement, the Deprecation and Sunset headers announce the schedule

Per-request options

Optional form fields next to “file”. When omitted, your saved dashboard settings apply.

  • services “extraction” (default) or “extraction,fraud_detection” to add the authenticity check.
  • include_field_images true/false — include the per-field image cutout (cutout_image).
  • include_document_image true/false — include the cropped document image (noticeably enlarges the response).

Response

“fields” is an object mapping each field name to value, confidence (0–1), bbox and optionally cutout_image. Which fields are included is configured in your settings. “vin_valid” is not a field but the result of the VIN check-digit comparison — true, false or null when there was nothing to compare.

{
  "fields": {
    "registrationNumber": { "value": "K AU 8823",         "confidence": 0.98, "bbox": [502, 327, 814, 388] },
    "vin":                { "value": "WAUZZZ8W9MA004711", "confidence": 0.97, "bbox": [939, 624, 1573, 690] },
    "d1":                 { "value": "AUDI",              "confidence": 0.99, "bbox": [939, 736, 1231, 795] },
    "ez":                 { "value": "07.11.2021",        "confidence": 0.96, "bbox": [502, 736, 736, 795] }
  },
  "vin_valid": true,
  "image_width": 3024,
  "image_height": 2136,
  "services": ["extraction"]
}

Authenticity check (optional)

When fraud detection is enabled, the response also carries a fraud_detection object: an overall_risk grade (A–F), separate scores for image manipulation and AI generation, plus one entry per individual check under tests. Over the API the check is included from the Business plan onwards; on the smaller plans you can evaluate it with 10 free analyses per month in the playground.

{
  "fraud_detection": {
    "overall_risk": "B",
    "verdict": "authentic",
    "fraud_score":  { "risk": "B", "score": 0.31 },
    "ai_generated": { "risk": "A", "score": 0.04 },
    "tests": {
      "metadata":          { "risk": "A", "score": 0.22, "findings": ["EXIF lacks camera/lens fields — possibly synthesised or stripped"] },
      "ela":               { "risk": "A", "score": 0.25, "findings": ["Mild ELA non-uniformity (concentration 9.4)"] },
      "clone":             { "risk": "A", "score": 0.09, "findings": [] },
      "field_consistency": { "risk": "A", "score": 0.00, "status": "ok" }
    }
  }
}

Duplicate check (cross-document)

Every response contains a cross_document object. Independently of the authenticity check — and only within your own account — it flags when the same document number or page template is submitted again with different data. Only salted hashes are stored, never plaintext.

{
  "cross_document": {
    "verdict": "review",
    "is_duplicate": true,
    "document_id": "K-M-4-072/23-00918",
    "matches": [
      {
        "type": "document_id_reuse",
        "severity": "review",
        "message": "Same document number already seen with different document data.",
        "prior_seen_at": "2026-07-08T14:32:00+00:00",
        "distinct_count": 3
      }
    ]
  }
}

Error codes

  • 400No image in the request (“file” field missing or empty body).
  • 401API key missing, invalid or revoked.
  • 402Feature not included in your plan (e.g. the authenticity check below Business).
  • 413File larger than 20 MB.
  • 415Unsupported file format.
  • 429Per-minute limit exceeded, service momentarily at capacity, or monthly quota exhausted (the “code” field tells them apart).
  • 502Processing temporarily unavailable.
  • 504Processing timed out.

More examples

The full documentation with cURL, Node.js and Python samples — plus your own keys — is in the dashboard after signing in.

Full documentation in the dashboard