Auskunft, Liste und Belege
Webhooks melden jeden Zustandswechsel. Geht ein Ereignis verloren, holen Sie den Stand über die Schnittstelle nach. Liste, Auskunft und Belegabruf hängen am Vorgang, nicht an der Vorgangsart: Sie antworten unter allen fünf Präfixen gleich — vehicleDeregistrations, vehicleHolderChanges, vehicleTransfers, vehicleReRegistrations und vehicleRegistrations.
Auftragsliste
GET /{präfix}/orders listet Ihre Aufträge, neueste zuerst.
| Parameter | Bedeutung |
|---|---|
externalId | genau Ihre Referenz aus dem Antrag — nicht unscharf |
state | ein Zustand oder mehrere mit Komma: beschieden,abgelehnt,fehlgeschlagen |
businessTransaction | ein Geschäftsvorfall oder mehrere mit Komma, in Großschreibung: NZ,TZ |
createdSince | nur Aufträge ab diesem Zeitpunkt (ISO 8601) |
changedSince | nur Aufträge, deren Stand sich seitdem geändert hat — der Parameter für den täglichen Abgleich |
limit | Seitengröße, Vorgabe 50, höchstens 200; 0 gilt als 1 |
offset | Versatz, Vorgabe 0 |
Die Liste ist streng, damit ein Tippfehler nicht still den ganzen Bestand liefert. 400 gibt es für:
- einen unbekannten Parameter — auch
derivedStatus, das kein Filter ist, - einen mehrfach angegebenen Parameter (
state=a&state=b; verbinden Sie die Werte mit Komma), state=,businessTransaction=,externalId=,createdSince=oderchangedSince=ohne Wert (bei den letzten drei auch nur aus Leerzeichen),- einen unbekannten Zustand oder Geschäftsvorfall (etwa
nz), - einen unlesbaren Zeitpunkt oder ein
limit/offset, das keine ganze Zahl ab 0 ist.
curl -u "$API_LOGIN:$API_PASSWORT" \
"https://api.kfz-api.de/dropshipping-api/$CLIENT_ID/2.3.0/vehicleRegistrations/orders?businessTransaction=NZ,TZ&changedSince=2026-09-14T00:00:00Z&limit=200"{
"orders": [
{
"order": { "id": 17, "externalId": "neuzulassung-4711" },
"attemptOf": 17,
"businessTransaction": "NZ",
"state": "beschieden",
"derivedStatus": "SUCCESS",
"applicationId": "88888020260915000002",
"vehicleIdentificationNumber": "WVWZZZ7HZ8H654321",
"licensePlate": "SL-AB 123",
"createdAt": "2026-09-15T09:02:11.412Z",
"changedAt": "2026-09-15T11:02:10.087Z"
}
],
"limit": 200,
"offset": 0,
"total": 1,
"hasMore": false
}limit, offset und total nennen die Werte, die wirklich gegolten haben. Blättern Sie, solange hasMore true ist, und erhöhen Sie offset um die Zahl der gelieferten Einträge.
Die Liste führt nur Auftragsköpfe und bewusst keine Belege, Zulassungsdaten oder Gebühren — die holt die Einzelauskunft.
Vorgangsauskunft
GET /{präfix}/orders/{orderId} liefert den vollständigen Stand eines Vorgangs. Ein unbekannter oder fremder Vorgang ergibt 404.
{
"order": { "id": 17, "externalId": "neuzulassung-4711" },
"attempt": 1,
"attemptOf": 17,
"businessTransaction": "NZ",
"state": "beschieden",
"derivedStatus": "SUCCESS",
"applicationId": "88888020260915000002",
"vehicleIdentificationNumber": "WVWZZZ7HZ8H654321",
"licensePlate": "SL-AB 123",
"files": [
{
"purposeType": "CERTIFICATE",
"mediaType": "application/pdf",
"fileAccessKey": "k-7a2e91d0",
"expirationTime": "2026-09-18T09:02:10.000Z",
"filename": "Vorgang-17_SL-AB-123_Zulassungsbescheid.pdf"
}
],
"registrationData": { "Kennzeichen": "SL AB 123" },
"registrationDocumentsReady": true,
"costBreakdown": {
"kbaCost": 30,
"registrationOfficeCosts": {
"items": [{ "number": 1, "amount": 1110 }],
"total": { "number": 2, "name": "Summe", "amount": 1110 }
}
},
"attempts": [
{
"id": 17,
"attempt": 1,
"state": "beschieden",
"derivedStatus": "SUCCESS",
"applicationId": "88888020260915000002",
"vehicleIdentificationNumber": "WVWZZZ7HZ8H654321"
}
],
"messages": [
{ "type": "QUITTUNG", "kind": "Warnung", "code": "07085", "text": "Für den Antrag wird eine Gebühr nach Geb. Nr. 129 GebOSt erhoben." }
],
"createdAt": "2026-09-15T09:02:11.412Z",
"updatedAt": "2026-09-15T11:02:10.087Z"
}Die Beträge im Beispiel sind erfunden; die echten stehen im Bescheid der Zulassungsbehörde.
| Feld | Inhalt |
|---|---|
state | Zustand des Versuchs, siehe unten |
derivedStatus | dieselbe Einordnung wie im Webhook-Ereignis |
applicationId | Antragsnummer des KBA — erst nach der Quittung gesetzt |
licensePlate | Kennzeichen in Anzeigeform, bei Zulassungen nach dem Bescheid das zugeteilte. Solange der Vorgang auf angelegt steht, also noch nicht gesendet ist, ist es null |
files | Belege aus dem Rückkanal mit fileAccessKey, expirationTime und filename; am Auftragskopf die aller Versuche, siehe Versuche und Korrektur |
registrationData | Daten der Zulassungsbescheinigung, wenn angefordert und geliefert |
registrationDocumentsReady | Erweiterung — kennzeichen.dev führt das Feld nicht. true, wenn die Zulassungsunterlagen (ZB I, ZB II, Plaketten) versandt sind oder zur Abholung bereitliegen. Nur bei Zulassungen und nur in der automatisierten Bearbeitung; fehlt das Feld, ist nichts gesagt — nicht „nicht versandt" |
parties | Beteiligte laut Rückmeldung, vor allem der Halter — dieselben Felder wie im Webhook-Ereignis: role, roleName, kind, name und bei einer Vereinigung representative |
messages | Meldungen des KBA mit code, text und additional — bei einer Ablehnung steht der Grund oft erst in additional. code ist nicht immer fünfstellig, siehe Quittungscodes |
retryable | nur gesetzt, wenn der Vorgang vorübergehend gescheitert ist |
attempt, attemptOf, attempts | Versuche des Auftrags, siehe unten |
paymentReference, feeAmountCents, costBreakdown | Gebühren, siehe unten |
holderDataProvenance | Herkunftsnachweis der Halterdaten, nur bei Anträgen mit powerOfAttorney.processId |
Zustände
state | Bedeutung | Ereignis status | derivedStatus |
|---|---|---|---|
angelegt | angenommen, noch nicht an das KBA gesendet | — | PENDING |
eingereicht | vom KBA angenommen, Entscheidung steht aus | ACCEPTED | PENDING |
inBearbeitung | beim i-Kfz-Portal in Bearbeitung | ACCEPTED | PENDING |
weitergeleitet | an die Zulassungsbehörde ausgesteuert | FORWARDED | PENDING |
beschieden | positiv beschieden | APPROVED_WITH_DOCUMENTS oder APPROVED | SUCCESS |
abgelehnt | abgelehnt | REJECTED_WITH_DOCUMENTS oder REJECTED | FAILURE oder genauer |
fehlgeschlagen | abgewiesen, korrigieren und neu stellen | FAILED | FAILURE oder genauer |
_WITH_DOCUMENTS heißt: Es liegen Belege bei. Ist ein Antrag an die Zulassungsbehörde weitergeleitet, kennt das KBA den Arbeitsstand nicht mehr; die Entscheidung kommt trotzdem über den Rückkanal.
Eine Rückmeldung ohne Entscheidung schließt den Vorgang nicht. Meldet das KBA den Antrag als „abgeschlossen", ohne einen Entscheidungsblock und ohne einen Bescheid mitzuschicken, bleibt der Vorgang auf inBearbeitung mit derivedStatus: PENDING, und es geht kein Ereignis an Sie hinaus — aus einer Meldung, die nichts entscheidet, eine Ablehnung zu machen, wäre die gefährlichere Fehlrichtung. Das KBA schickt danach keine weitere Rückmeldung zu diesem Antrag. Ein solcher Vorgang fällt deshalb nur über die Überfälligkeit auf (nach 24 Stunden ohne Entscheidung); im Dashboard wird er dann über der Vorgangsliste eigens als überfällig ausgewiesen, und der Betrieb klärt ihn mit der Zulassungsbehörde. Beobachtet im Probelauf vom 16.09.2026; die einzige Kombination, nach der ein Vorgang ohne Kundenmeldung stehenbleibt.
Versuche und Korrektur
Ein abgewiesener Antrag lässt sich im Dashboard korrigieren und erneut senden. Beim KBA ist das ein neuer Antrag mit eigener Antragsnummer, bei der Schnittstelle ein weiterer Versuch desselben Auftrags:
- Der neue Versuch trägt dieselbe
externalIdund eine eigene Id;attemptOfnennt die Id des Auftrags,attemptdie laufende Nummer. - Der Auftragskopf folgt dem jüngsten Versuch — sein
statekann vonfehlgeschlagenwieder auf einen offenen Zustand wechseln. Ein Endzustand ist der Endzustand des Versuchs, nicht des Auftrags. - Die Liste führt nur Köpfe.
attemptsin der Auskunft nennt alle Versuche; jeder ist über seine Id einzeln abrufbar. filesam Auftragskopf führt die Belege aller Versuche (Kopf undattempts[].id), ohne Dubletten und in der Reihenfolge ihres Eingangs. Jeder davon ist über seinenfileAccessKeyabrufbar. Die Auskunft zu einer Versuchs-Id führt nur die Belege dieses Versuchs. Dasselbe gilt für Webhook-Ereignisse: Trägtorder.iddie Id des Auftragskopfs, stehen infilesdie Belege aller Versuche.- Nach einer Korrektur trägt der Auftragskopf kein
attempt; er ist selbst kein Versuch mehr. - Ordnen Sie Webhook-Ereignisse über
attemptOfzu, nicht überorder.id. - Abgerechnet wird der Auftrag einmal, dazu 0,12 € je abgewiesener Übermittlung. Das gilt nur für die Korrektur im Dashboard: Ein erneuter
POSTüber die Schnittstelle legt einen neuen Auftrag an, und der wird wie jeder Auftrag berechnet.
Belege abrufen
GET /{präfix}/files/content/{fileAccessKey} liefert die Datei mit ihrem Content-Type und dem Dateinamen in Content-Disposition — derselbe wie filename in Ereignis und Auskunft.
curl -u "$API_LOGIN:$API_PASSWORT" -OJ \
"https://api.kfz-api.de/dropshipping-api/$CLIENT_ID/2.3.0/vehicleRegistrations/files/content/$FILE_ACCESS_KEY"- Ein Schlüssel gilt bis
expirationTime— wie lange, hängt davon ab, woher er stammt. Belege eines Vorgangs (aus Vorgangsauskunft und Webhook-Ereignis) gelten 72 Stunden ab dem Ablegen; im Dashboard unter „Belege" lässt sich ein solcher Beleg erneut freigeben. Die Dateien eines Sammelgebührenbescheids (gb_…) und einer Nachricht ohne Vorgang (ek_…) gelten 90 Tage; ihre Einzelauskunft —GET /vehicleDeregistrations/feeNotices/{id}undGET /vehicleDeregistrations/unmatchedMessages/{id}— setzt die Frist neu an. Danach antwortet der Abruf mit404. expirationTimeträgt in Auskunft und Ereignis verschiedene Formate, und beide sind so gewollt: Die Auskunft liefert den vollständigen ISO-Zeitstempel mit Zone und Millisekunden (2026-09-19T14:38:22.558Z), das Webhook-Ereignis denselben Zeitpunkt alsLocalDateTime— in UTC, ohne Zone, sekundengenau (2026-09-19T14:38:22), wie es der Webhook-Vertrag für jeden Zeitstempel vorschreibt. Beim Vergleich lesen Sie den Wert des Ereignisses als UTC.- Zwei Belege mit
purposeTypeCERTIFICATE— etwa Zulassungsbescheid und vorläufiger Zulassungsnachweis — unterscheiden Sie amfilename. Der Gebührenbescheid hatRECEIPT. - Ein unbekannter, abgelaufener oder fremder Schlüssel ergibt dieselbe Antwort:
404.
Gebühren
costBreakdown stammt aus dem Bescheid (0709):
kbaCost— die Nutzungsgebühr des KBA nach Nr. 129 GebOSt, 30 Cent. Sie steht erst da, wenn der Bescheid (0709) eingegangen ist — dann, wenn das KBA sie mit Quittungscode 07085 angekündigt hat oder der Antrag beschieden bzw. abgelehnt ist. Die Quittung mit 07085 allein führt noch keincostBreakdown.registrationOfficeCosts— die Positionen der Zulassungsbehörde (items, Beträge in Cent) und ihre Summe (total). Die Position des KBA ist dort herausgenommen, damit sie nicht doppelt zählt.
paymentReference (Kassenzeichen) und feeAmountCents stammen aus dem Sammelgebührenbescheid (0103) der Zulassungsbehörde. Beide werden einzeln gesetzt — ein Betrag ohne Kassenzeichen kommt vor. Die Sammelgebührenbescheide selbst liefern GET /vehicleDeregistrations/feeNotices und das Ereignis FEE_NOTICE_XKFZ_EVENT.
Sichtbar nur mit eigener KBA-Registrierung. Die amtlichen Bescheide lauten auf den beim KBA Registrierten. Fahren Sie als Vertragspartner unter fremder Registrierung, fehlen costBreakdown, paymentReference und feeAmountCents in Auskunft, Versuchen und Webhook-Ereignis, der Gebührenbescheid fehlt in files, und sein Abruf ergibt 404 — dieselbe Antwort wie für einen unbekannten Schlüssel. GET /vehicleDeregistrations/feeNotices und GET /vehicleDeregistrations/feeNotices/{id} antworten dagegen mit 403 und nennen den Grund; eine leere Liste bekommen Sie dort nicht.
Was kfz-api.de berechnet, steht auf der Preisseite; Ihre Rechnungen liefert GET /invoices.
Nachrichten ohne Vorgang
Schickt das KBA etwas an Ihre Registrierung, zu dem kein Antrag dieser Schnittstelle passt — etwa den Bescheid zu einem Antrag aus einem früheren System —, legt die Schnittstelle es als Nachricht ohne Vorgang ab: GET /vehicleDeregistrations/unmatchedMessages, Ereignis UNMATCHED_MESSAGE_XKFZ_EVENT. Den Stand — OPEN, HANDLED oder IGNORED, auf Wunsch mit der orderId eines eigenen Vorgangs — setzen Sie mit PUT /vehicleDeregistrations/unmatchedMessages/{id}/state. Die Felder stehen in der Referenz.