Dokumentation

DATEV CSV-Export

Exportiert gespeicherte Rechnungen für einen Datumsbereich als DATEV-kompatible CSV-Datei.


Status: Beta — externe DATEV-Importvalidierung steht aus.

Der Export ist durch automatisierte Tests abgedeckt und erzeugt CSV im DATEV-Format, wurde aber noch nicht durch einen Import in eine echte DATEV-Rechnungswesen-Umgebung validiert. Verlassen Sie sich für die produktive Buchhaltung nicht darauf, ohne die erzeugte Datei mit einer qualifizierten Steuerberatung oder Ihrer eigenen DATEV-Umgebung zu prüfen.

Bekannte Einschränkungen:

  • Nur CSV; DATEV XML wird nicht unterstützt.
  • Belegnummern, die das 12-Zeichen-Limit des älteren Formats überschreiten, blockieren den Export, statt gekürzt zu werden — eine Referenz wird nie stillschweigend mehrdeutig.
  • Rechnungen, die dieselbe DATEV-Belegnummer ergeben, blockieren den Export, bis eine von ihnen eine abweichende Export-Belegnummer erhält.
  • Mögliche Doppelrechnungen müssen vor dem Export geprüft werden.
  • Ein echter DATEV-Importtest steht noch aus.
POST/v1/exports/datevPro

DATEV-Export ist für Pro und Business verfügbar. Der Endpunkt erzeugt eine Windows-1252-kodierte CSV aus gespeicherten Rechnungen Ihres Workspaces, soweit sie im Retention-Fenster Ihres Tarifs sichtbar sind.

Anfrage

Verwenden Sie POST /v1/exports/datev mit den Query-Parametern from und to.

Query-ParameterTypPflichtBeschreibung
fromdateJaStartdatum, YYYY-MM-DD
todateJaEnddatum, YYYY-MM-DD
curl -X POST "https://api.parsurai.com/v1/exports/datev?from=2026-06-01&to=2026-06-30" \
  -H "X-API-Key: $PARSURAI_API_KEY" \
  -o datev_export.csv
import httpx

response = httpx.post(
    "https://api.parsurai.com/v1/exports/datev",
    headers={"X-API-Key": api_key},
    params={"from": "2026-06-01", "to": "2026-06-30"},
)

with open("datev_export.csv", "wb") as file_obj:
    file_obj.write(response.content)

Antwort

Bei Erfolg gibt der Endpunkt einen CSV-Bytestream zurück:

HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-Disposition: attachment; filename=datev_export.csv

Die CSV-Bytes sind als windows-1252 kodiert.

Exportierte Felder

Der Exporter schreibt eine DATEV-Metadatenzeile, den DATEV-Spaltenkopf und danach eine Zeile pro Rechnung. Aktuell gemappte Felder:

DATEV-SpalteQuelle
Umsatz (ohne Soll/Haben-Kz)invoice.total_amount.amount
Soll/Haben-KennzeichenImmer S
WKZ Umsatzinvoice.total_amount.currency
Konto1600
Gegenkonto (ohne BU-Schlüssel)70000
Belegdatuminvoice.issue_date als DDMM
Leistungsdatuminvoice.issue_date als DDMMYYYY
Belegfeld 1invoice.invoice_number
Buchungstextinvoice.vendor.name

Berater- und Mandantennummer werden serverseitig konfiguriert, nicht über die öffentliche API-Anfrage übergeben.

Fehlerbehandlung

Der DATEV-Export ist nur für Pro und Business verfügbar. Unterhalb von Pro gibt POST /v1/exports/datev den Code feature_not_in_plan zurück.

StatusCodeUmgang
401invalid_api_keySchlüssel prüfen oder einen aktiven sk_live_-Schlüssel verwenden
402feature_not_in_planExport-Button ausblenden oder Upgrade anbieten
409datev_export_blockedMindestens eine Rechnung im Zeitraum ist eine ungeprüfte mögliche Doppelrechnung
409datev_reference_too_longMindestens eine Belegnummer ist länger, als Belegfeld 1 zulässt
409datev_reference_collisionMehrere Rechnungen im Zeitraum ergeben dieselbe DATEV-Belegnummer
422validation_errorfrom und to als YYYY-MM-DD senden

Ungeprüfte mögliche Doppelrechnungen

Eine Rechnung, die von der Duplikaterkennung mit 0.85 oder höher bewertet wird, stoppt den gesamten Export, bis eine Person darüber entscheidet. Es entsteht keine Teil-CSV — eine ins DATEV gebuchte Doppelrechnung wird doppelt verbucht, deshalb scheitert der Export lieber ganz, als stillschweigend eine Zeile wegzulassen.

Die Antwort nennt die blockierenden Rechnungen und sonst nichts:

FeldBedeutung
blocking_invoice_countWie viele Rechnungen den Export blockieren
blocking_invoice_idsDeren IDs, ausschließlich aus Ihrem Workspace

Lieferantennamen, Beträge und Belegnummern werden bewusst nie zurückgegeben.

Zur Lösung halten Sie für jede genannte Rechnung mit PATCH /v1/invoices/{invoice_id}/duplicate-review eine Entscheidung fest und starten den Export erneut. Die möglichen Status und ihre Wirkung auf den Exportstapel beschreibt Duplikatprüfung. Die zugehörige Gegenüberstellung der Kandidaten liegt im Dashboard, nicht in der öffentlichen API.

Belegnummer zu lang

Belegfeld 1 fasst 12 Zeichen in der DATEV-Formatversion, die dieser Exporter schreibt. Ist eine Belegnummer länger, wird der gesamte Export mit 409 datev_reference_too_long abgelehnt. Belegnummern werden nie gekürzt: zwei Belegnummern mit denselben ersten 12 Zeichen würden zu einem einzigen exportierten Wert zusammenfallen und die Verbindung zwischen Buchungszeile und Beleg stillschweigend zerstören. Stattdessen scheitert der Export.

Die Länge wird gemessen, nachdem die von DATEV in Belegfeld 1 abgelehnten Zeichen entfernt wurden. Eine Belegnummer kann in der App also länger als 12 Zeichen sein und trotzdem exportieren.

Die Antwort enthält nur das, was zur Eingrenzung nötig ist:

FeldBedeutung
max_lengthMaximale Belegnummernlänge, die der Exporter akzeptiert (12)
invoice_countAnzahl der Rechnungen, die sie überschreiten
invoice_idsIDs dieser Rechnungen, ausschließlich aus Ihrem Workspace

Die Belegnummern selbst werden bewusst nie zurückgegeben.

{
  "error": {
    "code": "datev_reference_too_long",
    "message": "Der DATEV-Export ist blockiert, weil mindestens eine Belegnummer das 12-Zeichen-Limit des gewählten DATEV-Formats überschreitet. Korrigieren Sie die Belegnummer oder exportieren Sie mit einer bewusst aktualisierten DATEV-Formatversion.",
    "max_length": 12,
    "invoice_count": 2,
    "invoice_ids": [
      "6f1c2b8e-0f2a-4a1d-9c47-7b4e1f2a3d55",
      "b3d9a1c4-52e7-4f08-8c3b-1a9d6e5f0c22"
    ]
  }
}

So lösen Sie das Problem:

  • Die App öffnet einen Korrekturdialog, der jede betroffene Rechnung mit ihrer extrahierten Belegnummer, dem heute exportierten Wert und der maximal zulässigen Länge auflistet. Längere Arbeitslisten werden seitenweise angezeigt; die Seitennavigation nennt, wie viele Rechnungen noch eine Belegnummer benötigen.
  • Sie können eine separate DATEV-Belegnummer festlegen, ohne die ursprünglich extrahierte Belegnummer der Rechnung zu ändern. Die extrahierte Belegnummer bleibt exakt so erhalten, wie sie auf dem Beleg gefunden wurde, und wird weiterhin nie gekürzt.
  • Lesen Sie den Kontext zu den zurückgegebenen invoice_ids mit GET /v1/invoices/datev-export-reference-remediation, setzen Sie einen Wert mit PUT /v1/invoices/{invoice_id}/datev-export-reference-override und starten Sie den Export erneut.
  • Ein Export über einen Datumsbereich, der die betroffenen Rechnungen ausschließt, funktioniert ebenfalls und bleibt der schnellste Weg, wenn diese Rechnungen ohnehin in eine andere Periode gehören.

Die Meldung erwähnt eine neuere DATEV-Formatversion; der Exporter schreibt derzeit jedoch nur eine einzige Formatversion, ein Formatwechsel ist also aktuell keine Option.

Doppelte DATEV-Belegnummer

Zwei Rechnungen desselben Exports können ein und denselben Wert in Belegfeld 1 ergeben — weil ihre Belegnummern identisch werden, sobald die von DATEV abgelehnten Zeichen entfernt sind, oder weil eine abweichende DATEV-Belegnummer auf einen Wert gesetzt wurde, den eine andere Rechnung im Zeitraum bereits ergibt.

Der gesamte Export wird dann mit 409 datev_reference_collision abgelehnt. Es wird keine CSV erzeugt, auch keine teilweise mit den nicht betroffenen Rechnungen: zwei Buchungszeilen mit derselben Belegnummer würden die Verbindung zwischen Zeile und Beleg genauso zerstören wie eine gekürzte Belegnummer.

Die Antwort enthält nur das, was zur Eingrenzung nötig ist:

FeldBedeutung
invoice_countAnzahl der betroffenen Rechnungen
invoice_idsIDs dieser Rechnungen, flach und dedupliziert, ausschließlich aus Ihrem Workspace
collision_groupsJe ein Array von Rechnungs-IDs pro Gruppe mit gemeinsamer Belegnummer

Der kollidierende Wert selbst wird bewusst nie zurückgegeben.

{
  "error": {
    "code": "datev_reference_collision",
    "message": "Der DATEV-Export ist blockiert, weil mehrere Rechnungen dieselbe DATEV-Belegnummer ergeben. Vergeben Sie für die betroffenen Rechnungen eine abweichende DATEV-Belegnummer und exportieren Sie erneut.",
    "invoice_count": 4,
    "invoice_ids": [
      "6f1c2b8e-0f2a-4a1d-9c47-7b4e1f2a3d55",
      "b3d9a1c4-52e7-4f08-8c3b-1a9d6e5f0c22",
      "1d7f4a90-8c31-4b6e-a0f5-2c8b9e4d7a10",
      "9a5e0c73-4d18-4f2b-b7c6-3e1a8d0f5b44"
    ],
    "collision_groups": [
      [
        "6f1c2b8e-0f2a-4a1d-9c47-7b4e1f2a3d55",
        "b3d9a1c4-52e7-4f08-8c3b-1a9d6e5f0c22"
      ],
      [
        "1d7f4a90-8c31-4b6e-a0f5-2c8b9e4d7a10",
        "9a5e0c73-4d18-4f2b-b7c6-3e1a8d0f5b44"
      ]
    ]
  }
}

Zur Lösung geben Sie allen Rechnungen einer Gruppe bis auf eine eine abweichende DATEV-Belegnummer und starten den Export erneut. collision_groups zeigt, welche Rechnungen miteinander kollidieren.

Abweichende DATEV-Belegnummer

Eine abweichende DATEV-Belegnummer ist ein separater Wert, der ausschließlich beim Erzeugen der DATEV-Ausgabe verwendet wird. Sie ändert invoice.invoice_number nie: die extrahierte Belegnummer bleibt exakt erhalten, und jeder andere Export und jede andere API-Antwort geben sie unverändert zurück.

Diese Endpunkte sind nicht tarifgebunden. Der DATEV-Export selbst ist eine Pro- und Business-Funktion, aber jeder authentifizierte Eigentümer kann einen blockierten Export auflösen.

Jede Änderung wird in einem Audit-Trail festgehalten, inklusive des handelnden Benutzers und der Information, ob die Änderung über einen API-Schlüssel oder die gehostete App kam. Der Audit-Trail ist unveränderlich und vollständig geordnet: Die Datenbank selbst weist jeden Versuch ab, ein erfasstes Ereignis zu ändern oder zu löschen. Ereignisse verschwinden nur, wenn die zugehörige Rechnung gelöscht wird.

PUT/v1/invoices/{invoice_id}/datev-export-reference-override

Senden Sie die Belegnummer, die exportiert werden soll. Der Server normalisiert sie — die von DATEV in Belegfeld 1 abgelehnten Zeichen werden entfernt — und speichert das Ergebnis, das nach der Normalisierung zwischen 1 und 12 Zeichen lang sein muss.

curl -X PUT "https://api.parsurai.com/v1/invoices/6f1c2b8e-0f2a-4a1d-9c47-7b4e1f2a3d55/datev-export-reference-override" \
  -H "X-API-Key: $PARSURAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reference": "RE 2026/0042"}'
{
  "invoice_id": "6f1c2b8e-0f2a-4a1d-9c47-7b4e1f2a3d55",
  "reference_override": "RE2026/0042"
}

reference_override ist der normalisierte Wert, der tatsächlich exportiert wird, und kann daher von dem abweichen, was Sie gesendet haben. Maßgeblich ist die Antwort, nicht Ihr Request-Body.

Der Aufruf ist idempotent: ein Wert, der sich zur bereits gespeicherten Belegnummer normalisiert, liefert 200 und erzeugt kein Audit-Ereignis.

Ein unbrauchbarer Wert — nach der Normalisierung leer oder länger als 12 Zeichen — liefert 422:

{
  "error": {
    "code": "validation_error",
    "field": "reference",
    "message": "reference is not a usable DATEV export reference."
  }
}

Der gesendete Wert wird bewusst nie zurückgespiegelt.

DELETE/v1/invoices/{invoice_id}/datev-export-reference-override

Entfernt die abweichende Belegnummer, sodass die Rechnung auf ihre extrahierte Belegnummer zurückfällt. Der Endpunkt liefert 204, unabhängig davon, ob zuvor eine gesetzt war.

curl -X DELETE "https://api.parsurai.com/v1/invoices/6f1c2b8e-0f2a-4a1d-9c47-7b4e1f2a3d55/datev-export-reference-override" \
  -H "X-API-Key: $PARSURAI_API_KEY"
GET/v1/invoices/datev-export-reference-remediation

Liest den Belegnummern-Kontext zu den invoice_ids, die ein blockierter Export zurückgegeben hat, damit Sie entscheiden können, was Sie überschreiben.

Query-ParameterTypPflichtBeschreibung
idsstringJaKommagetrennte Rechnungs-IDs, dedupliziert, höchstens 50, Reihenfolge bleibt erhalten
curl "https://api.parsurai.com/v1/invoices/datev-export-reference-remediation?ids=6f1c2b8e-0f2a-4a1d-9c47-7b4e1f2a3d55,b3d9a1c4-52e7-4f08-8c3b-1a9d6e5f0c22" \
  -H "X-API-Key: $PARSURAI_API_KEY"
{
  "items": [
    {
      "invoice_id": "6f1c2b8e-0f2a-4a1d-9c47-7b4e1f2a3d55",
      "invoice_number": "RE 2026/ACCOUNTING 0042",
      "reference_override": "RE2026/0042",
      "normalized_invoice_number": "RE2026/ACCOUNTING0042",
      "max_length": 12
    },
    {
      "invoice_id": "b3d9a1c4-52e7-4f08-8c3b-1a9d6e5f0c22",
      "invoice_number": "RE 2026/0043",
      "reference_override": null,
      "normalized_invoice_number": "RE2026/0043",
      "max_length": 12
    }
  ]
}
FeldBedeutung
invoice_idDie Rechnung, die die Zeile beschreibt
invoice_numberDie ursprünglich extrahierte Belegnummer, unverändert
reference_overrideDie aktuell gesetzte abweichende Belegnummer, sonst null
normalized_invoice_numberWozu sich die ursprüngliche Belegnummer für Belegfeld 1 normalisiert
max_lengthMaximale Belegnummernlänge, die der Exporter akzeptiert (12)

Die Einträge werden in der Reihenfolge der angefragten IDs zurückgegeben. IDs, die Ihnen nicht gehören, fehlen einfach in items, statt abgelehnt zu werden — die Antwort bestätigt also nie, ob die Rechnung eines anderen Workspaces existiert.

Fehlerbehandlung der abweichenden Belegnummer

StatusCodeUmgang
404not_foundDie Rechnung liegt nicht in Ihrem Workspace
422validation_errorreference ist nach der Normalisierung leer oder zu lang
422invalid_invoice_idsids ist leer, enthält keine UUID oder mehr als 50 IDs

404 behandelt eine fehlende Rechnung und eine Rechnung aus einem anderen Workspace identisch. Die beiden Fälle sind nie unterscheidbar, die API lässt sich also nicht nutzen, um die Existenz einer fremden Rechnungs-ID zu bestätigen.

Erstellen Sie DATEV-Exporte erst, wenn die Extraktions- und Prüf-Workflows abgeschlossen sind. Der Exporter liest gespeicherte Rechnungen; nicht gespeicherte oder fehlgeschlagene Extraktionen werden nicht berücksichtigt.