For developers

The Fahrzeugschein API for developers

One POST, one finished record: send the photo or PDF of a German vehicle registration certificate — the Zulassungsbescheinigung Teil I, commonly called Fahrzeugschein — to the Fahrzeugschein API and get JSON back, usually within one to two seconds: up to 65 fields, each with a value, a confidence and its location in the image. Developers need four lines of curl and no sales call. Operated by Picsure GmbH in Hamburg, processed in Germany and the EU.

Start free — 15 extractions per monthFull API reference

One call to the Fahrzeugschein API, one finished record

A call handles one document. The response always carries the full field catalogue — including the boxes that are not printed on the document in front of you; those come back as `null` rather than as a missing key. Your code can index into the object instead of probing every response.

Up to 65 fields carry a read value, from the plate and the vehicle identification number through to the technical entries; how many you get is decided by the document. Every recognised field arrives with the value, a confidence between 0 and 1 and its location as a pixel rectangle, plus the cropped image on request. Your reviewer sees how confidently each value was read and where it sits on the original — for the wider picture, see reading the Zulassungsbescheinigung.

Your first request takes minutes, not days

curl -X POST https://api.fahrzeugschein24.de/v1/extract \
  -H "Authorization: Bearer $FZ24_API_KEY" \
  -F "file=@registration.jpg" \
  -F "services=extraction" \
  -F "include_field_images=true"

The response: value, confidence, location

{
  "fields": {
    "registrationNumber": { "value": "B MW 4711 E",       "confidence": 0.98, "bbox": [425, 277, 690, 328] },
    "vin":                { "value": "WBY11CF080FL04715", "confidence": 0.98, "bbox": [795, 529, 1332, 584] },
    "field_3":            { "value": "3",                 "confidence": 0.92, "bbox": [1344, 529, 1392, 584] },
    "hsn":                { "value": "0005",              "confidence": 0.99, "bbox": [415, 712, 529, 760] },
    "tsn":                { "value": "CTN",               "confidence": 0.95, "bbox": [578, 712, 690, 760] },
    "ez_string":          { "value": "09.06.2023",        "confidence": 0.98, "bbox": [425, 624, 624, 673] },
    "ez":                 { "value": "2023-06-09",        "confidence": 0.98, "bbox": [425, 624, 624, 673] },
    "field_10":           { "value": "0004",              "confidence": 0.96, "bbox": [1012, 838, 1098, 886] },
    "field_21":           null
  },
  "vin_valid": true,
  "image_width": 2560,
  "image_height": 1804,
  "services": ["extraction"]
}

Decide per call how much comes back

FieldValuesEffect
servicesextraction | extraction,fraud_detectionRuns fraud detection alongside extraction. Omitted means extraction only.
include_field_imagestrue | falseAdds a cropped image for each recognised field. Switch it on where you actually show the crops — the body grows noticeably.
include_document_imagetrue | falseReturns the deskewed, cropped document image: the frame of reference for every bbox and the basis for an overlay in your own interface.

Four details that get your integration right on the first run

First registration arrives twice

ez_string holds the date exactly as printed (DD.MM.YYYY), ez the same date in ISO form (YYYY-MM-DD). Store ez, display ez_string — you never parse German date formats yourself.

Plates come space-separated

registrationNumber returns as "B MW 4711 E"; the district prefix is checked against the German district codes. If your target system expects hyphens, that is a one-liner on write.

Key numbers raw and split

HSN sits in box 2.1, TSN in box 2.2. tsn and vsn are derived from the raw value while field_2_2 keeps it unsplit — so you hold both. More on that under HSN and TSN.

Contradictions are flagged, never overwritten

field_10 is the four-digit KBA energy-source code (0004 = electric), P.3 the fuel in plain text. When the two disagree it comes back as an advisory — you see the conflict instead of inheriting it.

Quotas that scale with you, a contract that stays put

There are two independent ceilings: requests per minute, from 10 on Free to 150 on Enterprise, and extractions per month — 15 on Free, 100 on Starter, 1,000 on Business, 5,000 on Scale, 20,000 on Enterprise. Free stops hard, so a test never turns into an invoice. On the paid plans processing continues past the quota and each additional extraction is billed, from €0.20 on Starter down to €0.11 on Enterprise (net, plus VAT). A traffic spike is therefore a question of billing rather than of changing plan; all tiers stand side by side on the pricing page.

The endpoint is versioned: /v1/extract stays /v1/extract, and breaking changes get a version of their own. Every response names the version that handled it and the state of your rate limit; every rejection carries a stable error code you branch on instead of a message string. Webhooks, signature verification and the full error list are in the API documentation; processing and retention are covered under security.

Questions developers ask about the Fahrzeugschein API

How fast can I have the first extraction running in my code?

Usually in minutes: create an account, confirm your email address, generate an API key in the dashboard and fire the curl call above at one of your own documents. The Free plan costs nothing and needs no credit card — 15 extractions a month are enough to build the integration and test it on real paperwork.

Do I have to build the call asynchronously?

Not necessarily: an extraction usually takes one to two seconds, which you can wait out on the open request. For larger volumes a queue with bounded concurrency is the calmer design, and on a 429 you wait out the Retry-After value. A whole day's intake then runs through without special handling.

How do I know how reliably a value was read?

From the confidence per field, its location in the image and — once enabled in your account settings — the cropped image of the field. Add the check-digit comparison for the vehicle identification number and the advisories raised when entries contradict each other. Fields without a value come back as null.

Can fraud detection run in the same call?

Yes, via services=extraction,fraud_detection. You then get nine individual checks with per-check findings and an overall grade from A (unremarkable) to F (highly suspicious). It is a signal for your own review, not an official authenticity ruling; over the API it is included from the Business plan up.

What happens to the uploaded image?

It is processed for the duration of the request only and not stored; only the extracted data and account-level log data are kept. Processing takes place in Germany and the EU — the details are on security and data handling and in the privacy policy, and the Art. 28 GDPR data processing agreement can be reviewed upfront.

Get a key and wire it up

The Free plan is enough to build the integration and try it on your own documents: 15 extractions per month, no credit card, a hard stop instead of a surprise invoice. When volume grows you change plan without touching a line of code.

Create a free account