ml-connector
DATEVZuora

DATEV and Zuora integration

DATEV is the accounting and tax backend for German businesses. Zuora runs subscription billing and revenue. Connecting the two moves your recurring revenue into the books without re-keying. Posted invoices, payments, and credit memos from Zuora become DATEV booking batches, mapped to the right GL accounts and tax codes, so finance does not transcribe billing data by hand. ml-connector handles the very different APIs on each side and submits bookings to DATEV on the cadence you set.

How DATEV works

DATEV is not a conventional REST API for bookings. Finalized journal entries go to the on-premise DATEV Rechnungswesen engine as asynchronous EXTF CSV file imports, and booking suggestions go to DATEV Unternehmen Online as DXSO XML jobs; both return a job ID that you must poll, since DATEV sends no webhooks. A small REST surface lists clients and uploads invoice documents to DUO. Auth is OAuth 2.0 Authorization Code with PKCE through Login mit DATEV, which requires an interactive user session and a 15-minute access token, with no machine-to-machine flow. The standard chart of accounts cannot be read back through the API.

How Zuora works

Zuora exposes its billing data through the v1 REST API as JSON over HTTPS, against a region-specific tenant base URL that must be captured per customer. Accounts, subscriptions, posted invoices, payments, payment methods, and credit memos are all readable, and credit memos require the Invoice Settlement feature on the tenant. Auth is OAuth 2.0 client credentials with a one-hour token that should be cached and reused. Zuora can push Callout notifications on events such as Invoice Posted, Payment Processed, and credit memo posted, but the callout body carries only the object ID, so the receiver calls back to fetch the full record. Payment callouts fire for electronic payments only.

What moves between them

The flow runs from Zuora into DATEV. ml-connector reads posted invoices, the payments applied against them, and posted credit memos from Zuora, then assembles DATEV EXTF CSV booking batches that carry the transaction amount, debit and credit account, tax code, document number, and document date for each line. Invoice PDFs can also be uploaded to DUO as incoming or outgoing invoice documents. Reference data such as GL account and tax-code mappings is configured once and applied to every batch. DATEV bookings are write-only, so ml-connector never reads posted journal entries back from DATEV into Zuora.

How ml-connector handles it

ml-connector stores both credential sets encrypted and runs two different OAuth flows: Zuora client credentials for unattended reads, and the interactive Login mit DATEV PKCE flow whose refresh token it renews using the client_id only, never the client_secret. It captures the Zuora tenant URL per customer because Zuora has no single base address, and it caches the Zuora token rather than re-requesting it, since the auth endpoint is rate-limited per IP. Zuora callouts on Invoice Posted, Payment Processed, and credit memo posted trigger a callback that fetches the full record, and a scheduled poll backfills anything a callout missed, including external payments that never fire one. Each booking line is mapped to a DATEV GL account and tax code up front, because the DATEV chart of accounts cannot be read through the API. EXTF files use UTF-8 with precomposed characters and deterministic filenames, so DATEV duplicate detection by filename and document type makes a re-submission safe rather than a double post. After upload, ml-connector polls the DATEV import job with backoff until it reports complete or failed, because there is no synchronous confirmation, and every record carries a full audit trail and can be replayed if a call fails.

A real-world example

A German SaaS company with roughly 150 employees bills several thousand monthly and annual subscriptions in Zuora and keeps its books in DATEV through its tax advisor. Before the integration, an accountant exported Zuora invoice and payment registers each month and re-typed the revenue and VAT totals into DATEV by hand, which delayed the VAT return and left differences between collected cash in Zuora and the ledger. With DATEV and Zuora connected, each posted invoice, applied payment, and credit memo becomes a DATEV booking batch automatically, allocated to the correct revenue and tax accounts. The monthly close starts with billing already booked, and the manual re-keying step is gone.

What you can do

  • Turn posted Zuora invoices, payments, and credit memos into DATEV EXTF booking batches against the right GL accounts and tax codes.
  • Upload Zuora invoice PDFs into DATEV Unternehmen Online as incoming or outgoing invoice documents.
  • Bridge Zuora client-credentials OAuth and the interactive DATEV PKCE login, renewing each token on its own schedule.
  • React to Zuora invoice and payment callouts, fetch the full record, and backfill missed events by scheduled poll.
  • Poll each DATEV import job to a confirmed result, with deterministic filenames, retries, and a full audit trail on every record.

Questions

Which direction does data move between DATEV and Zuora?
The flow runs from Zuora into DATEV. Posted invoices, applied payments, and posted credit memos move from Zuora into DATEV as booking batches and uploaded documents. DATEV bookings are write-only, so ml-connector does not read posted journal entries back from DATEV into Zuora.
Does DATEV confirm a booking the moment it is submitted?
No. DATEV processes EXTF and DXSO imports asynchronously and never sends a webhook, so a submission returns a job ID rather than a result. ml-connector polls the DATEV import job with exponential backoff until it reports complete or failed, and surfaces that status instead of assuming success.
How are Zuora's different tenant URLs and minimal callouts handled?
ml-connector captures each customer's Zuora tenant base URL at setup, since Zuora has no single global address, and caches the one-hour token to respect the per-IP auth limit. Because a Zuora callout carries only the event object ID, the handler calls back to Zuora to fetch the full invoice or payment before building the DATEV booking.

Related integrations

Connect DATEV and Zuora

Free to use. Add your credentials, ping your real systems, and see if we fit.

Get started