DATEV and Tipalti integration
DATEV is the German accounting and tax backend that German tax advisors and their clients use to keep the books. Tipalti runs accounts payable and global supplier payments. Connecting the two means the supplier invoices Tipalti approves and the payments it sends out land in DATEV as bookings without anyone re-keying them, and the invoice documents are filed in DATEV Unternehmen Online. ml-connector handles the very different interfaces on each side, since DATEV takes booking data as asynchronous file jobs rather than live API writes. Because DATEV exposes its general ledger as write-only file import, postings move into DATEV in one direction and are never read back.
What moves between them
The flow runs from Tipalti into DATEV. After supplier invoices are approved and payments complete in Tipalti, ml-connector reads the changed invoices and payment results and builds them into EXTF CSV booking batches that post into the DATEV Rechnungswesen ledger, mapped to the right SKR account, creditor, cost center, and tax code. The invoice PDF or e-invoice file is uploaded into DATEV Unternehmen Online as an incoming-invoice document and linked to the booking. Payee records inform the creditor accounts referenced in those bookings. Because the DATEV ledger is write-only over the API, ml-connector never reads posted journal entries back into Tipalti.
How ml-connector handles it
ml-connector stores both credential sets encrypted. On the Tipalti side it computes the HMAC-SHA256 key for each SOAP call from the exact payer name, id, and timestamp, requests an OAuth2 token for the REST endpoints, and pulls changed invoices and payments incrementally in pages of 250 with the changed-since-timestamp calls. On the DATEV side it runs the PKCE Authorization Code login, holds the refresh token, and re-mints the 15-minute access token when it expires, sending the X-DATEV-Client-Id header and the per-client id on every request. It fetches each client's allowed document types before any upload, since those are client-specific, and writes EXTF files as UTF-8 with precomposed (NFC) characters because non-precomposed text is silently rejected. Booking submission is asynchronous: ml-connector submits the EXTF or DXSO job, then polls the job status with exponential backoff and jitter, because DATEV sends no completion webhook. DATEV detects duplicate EXTF files by filename plus document type and returns error DCO01253, so ml-connector generates stable, deterministic filenames and ties each submission to a BullMQ jobId, which makes a re-read of the same Tipalti payment safe to resubmit. Where Tipalti IPNs are enabled, a completed-payment callback triggers the posting run, while a scheduled poll backfills anything an IPN missed. The standard DATEV chart of accounts cannot be read over the API, so the SKR account and creditor mapping is configured up front and validated before posting.
A real-world example
A mid-sized engineering firm in Germany with around 250 staff runs its books in DATEV through its Steuerberater and pays a few hundred domestic and cross-border suppliers each month through Tipalti. Before the integration, a bookkeeper exported the Tipalti payment register every week and typed the invoice and payment lines into DATEV by hand, picking the SKR account and creditor for each one, which was slow and produced posting mistakes that surfaced at month end. With DATEV and Tipalti connected, each approved invoice and completed payment is built into an EXTF booking batch and posted into the DATEV ledger automatically, the invoice file is filed in DATEV Unternehmen Online, and the cost centers and accounts are already correct. The weekly re-keying disappears and the AP accounts reconcile against Tipalti without a manual pass.
What you can do
- Post approved Tipalti supplier invoices and completed payments into DATEV as EXTF booking batches.
- Upload Tipalti invoice files into DATEV Unternehmen Online as incoming-invoice documents.
- Map Tipalti payees and amounts to the right DATEV SKR accounts, creditors, cost centers, and tax codes.
- Bridge the Tipalti HMAC and OAuth2 credentials to the DATEV PKCE login with 15-minute token refresh.
- Submit DATEV jobs asynchronously with stable filenames, jobId dedup, status polling, and a full audit trail.
Questions
- Which direction does data move between DATEV and Tipalti?
- The flow is one-way, from Tipalti into DATEV. Approved supplier invoices and completed payments move from Tipalti into the DATEV ledger as EXTF booking batches, and the invoice files are uploaded into DATEV Unternehmen Online. The DATEV general ledger is write-only over the API, so ml-connector never reads posted journal entries back into Tipalti.
- How does the integration deal with DATEV having no webhooks and asynchronous bookings?
- DATEV processes EXTF and DXSO submissions as background jobs and sends no completion callback. ml-connector submits each booking job, then polls the DATEV job status with exponential backoff and jitter until it reports complete or failed. On the Tipalti side it can use a completed-payment IPN to trigger the posting run, with a scheduled poll backfilling anything the IPN missed.
- What stops a Tipalti payment from being posted into DATEV twice?
- DATEV rejects duplicate EXTF files by filename plus document type with error DCO01253, so ml-connector generates a stable, deterministic filename for each booking batch. Each submission is also tied to a BullMQ jobId, so re-reading the same Tipalti payment resubmits under the same id rather than creating a second booking. Together these make a retry safe.
Related integrations
More DATEV integrations
Other systems that connect to Tipalti
Connect DATEV and Tipalti
Free to use. Add your credentials, ping your real systems, and see if we fit.
Get started