ml-connector
DATEVCin7

DATEV and Cin7 integration

Cin7 Core runs inventory, procurement, and order management. DATEV is the German accounting and tax backend that the company's tax advisor works in. Connecting the two sends the invoices and payments recorded in Cin7 Core into DATEV as bookings, with the supporting PDF documents filed alongside them, so the finance team and the Steuerberater stop re-keying transactions by hand. ml-connector reads from Cin7 Core, uploads documents to DATEV Unternehmen Online, and submits booking jobs to DATEV Rechnungswesen. It manages the very different auth and the asynchronous file processing on the DATEV side so the data lands without manual steps.

How DATEV works

DATEV is not a conventional REST API. It uses OAuth 2.0 Authorization Code with PKCE against login.datev.de, and there is no machine-to-machine flow, so a tax advisor or client must authorise the connection interactively and access tokens last only 15 minutes. A small REST surface lists clients and uploads documents to DATEV Unternehmen Online, but the actual bookings go in as asynchronous file jobs: EXTF CSV files for finalized postings to the on-premise Rechnungswesen engine, or DXSO XML for booking suggestions. There are no webhooks, finalized bookings cannot be read back, and the full chart of accounts is not retrievable through the API, so account numbers must be configured up front.

How Cin7 works

Cin7 Core, formerly DEAR Systems, is a cloud inventory and accounting ERP with a real REST API at inventory.dearsystems.com. Every call carries two static secret headers, api-auth-accountid and api-auth-applicationkey, rather than OAuth. It reads and writes suppliers, purchases that cover the procure-to-pay cycle through an Approach field, sales invoices, payments, products, and a read-only chart of accounts. Cin7 Core can push outbound webhooks from its Automation module for purchase, supplier, sale, and payment events, though those payloads are not signed, and list endpoints use page and limit paging with a Retry-After header on rate limits.

What moves between them

The flow runs from Cin7 Core into DATEV. ml-connector reads authorised supplier invoices, sales invoices, and their payments from Cin7 Core, uploads the source PDFs to DATEV Unternehmen Online as the correct document type, and submits the matching bookings to DATEV as EXTF CSV jobs for finalized postings or DXSO XML jobs for booking suggestions, mapped to DATEV GL accounts, cost centers, and tax keys. Cin7 Core webhooks for new and updated purchases, sales, and payments trigger the work, and a scheduled poll backfills anything a webhook missed. DATEV is treated as a write-only accounting target, so ml-connector never writes posted journals back into Cin7 Core.

How ml-connector handles it

ml-connector stores both credential sets encrypted and sends the two Cin7 Core key headers on every read, while holding the DATEV OAuth2 user session and refreshing the access token before its 15-minute expiry, sending only the client_id on refresh as DATEV requires. Each Cin7 Core invoice becomes a DATEV booking: the line accounts, the debit and credit (Soll/Haben) sides, the tax key, and the cost center are mapped from Cin7 codes to DATEV account numbers, which matters because DATEV will not return its own chart of accounts over the API. The PDF goes up first with an idempotent PUT keyed on a GUID, then the booking file is submitted and polled, since DATEV processes jobs asynchronously and never calls back; ml-connector polls with exponential backoff and surfaces the final status. EXTF files are written as UTF-8 with precomposed characters and stable filenames so a retry is detected as a duplicate rather than double-posted. Cin7 webhooks are unsigned, so each one is treated as a trigger and verified against the API before a booking is created, and Cin7 rate limits return HTTP 429 with Retry-After, which ml-connector honours. Every record carries a full audit trail and can be replayed if a DATEV job fails.

A real-world example

A mid-sized German wholesale distributor with around 80 staff runs Cin7 Core for purchasing, stock, and order fulfilment across two warehouses, and its external tax advisory firm keeps the books in DATEV. Before the integration, the finance team exported supplier and sales invoices from Cin7 Core each week, emailed PDFs to the Steuerberater, and the advisor re-entered every booking into DATEV by hand, which delayed the monthly VAT return and caused mismatches between the warehouse system and the ledger. With Cin7 Core and DATEV connected, each authorised invoice and payment posts to DATEV automatically with the PDF filed in Unternehmen Online and the booking allocated to the right account and cost center. The advisor reviews instead of re-typing, and the VAT period closes on time.

What you can do

  • Post Cin7 Core supplier and sales invoices into DATEV as EXTF CSV or DXSO XML booking jobs.
  • Upload the supporting invoice PDFs to DATEV Unternehmen Online as the correct client-specific document type.
  • Map Cin7 Core account codes, tax rules, and cost centers to DATEV GL account numbers, tax keys, and Kostenstellen.
  • Bridge Cin7 Core static key headers and the DATEV OAuth2 user session, refreshing the 15-minute token automatically.
  • React to Cin7 Core webhooks, poll each async DATEV job to completion, and keep a full audit trail with replay.

Questions

Which direction does data move between Cin7 Core and DATEV?
The flow is Cin7 Core into DATEV. Supplier invoices, sales invoices, and payments recorded in Cin7 Core move into DATEV as bookings, with the source PDFs filed in DATEV Unternehmen Online. DATEV finalized bookings cannot be read back through the API, so ml-connector treats DATEV as a write-only accounting target and does not post journals back into Cin7 Core.
How does the integration handle DATEV's lack of webhooks and asynchronous processing?
DATEV never calls your endpoint, and every booking and document import is an asynchronous job. ml-connector submits the EXTF or DXSO file, receives a job ID, then polls the job status with exponential backoff until DATEV reports complete or failed. On the other side, Cin7 Core webhooks for purchases, sales, and payments act as triggers, and a scheduled poll backfills anything a webhook missed.
Why does ml-connector need GL account and cost center mapping for this pair?
DATEV does not return its full chart of accounts through the API, so the target account numbers must be known and configured in advance. Cin7 Core does expose a readable chart of accounts, but its codes are not the same as DATEV's SKR03 or SKR04 numbers. ml-connector maps Cin7 account codes, tax rules, and cost centers to the matching DATEV accounts, tax keys, and Kostenstellen so each booking line lands on a valid account.

Related integrations

Connect DATEV and Cin7

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

Get started