ml-connector
DATEVProcore

DATEV and Procore integration

DATEV is the accounting backend German contractors file their bookings through. Procore is where the same contractors run project financials, commitments, and field invoicing. Connecting the two moves approved construction spend from Procore into the DATEV ledger without re-keying. Subcontractor invoices, direct costs, and committed purchase orders from Procore become EXTF booking batches in DATEV, and the matching invoice PDFs land in DATEV Unternehmen Online for the tax advisor. ml-connector handles the very different access models on each side and submits the work on the cadence you set.

How DATEV works

DATEV is not a conventional CRUD API. Core bookings are written as asynchronous file jobs: EXTF CSV batches go to the on-premise DATEV Rechnungswesen engine through a cloud relay, and DXSO XML jobs go to DATEV Unternehmen Online, while invoice and receipt PDFs upload through the accounting documents REST product. A small REST surface lists clients and document types, but posted journal entries and the standard chart of accounts cannot be read back. Authentication is OAuth2 authorization code with PKCE against login.datev.de, so a real tax advisor or client session is required, access tokens last 15 minutes, and there are no webhooks, so job status is followed by polling.

How Procore works

Procore exposes its construction financials through a JSON REST API at api.procore.com, covering vendors, purchase order commitments, subcontractor invoices called requisitions, payment applications, direct costs, change orders, budget line items, and cost codes. Most financial endpoints are scoped to a company and a project, so company_id and usually project_id are required on each call. Authentication for sync uses OAuth2 client credentials through a Developer Managed Service Account, with no user login and tokens valid for 90 minutes. Procore can push create, update, and delete events by webhook for resources such as Commitments, Requisitions, and DirectCosts, and supports paginated polling as the reconciliation backstop.

What moves between them

The flow runs from Procore into DATEV. ml-connector reads approved subcontractor invoices, direct costs, and committed purchase orders from Procore and writes them into DATEV as EXTF CSV booking batches, with each line mapped to the right DATEV debit and credit account, tax code, and cost center. The matching invoice PDFs are uploaded into DATEV Unternehmen Online under the correct client-specific document type so the source paperwork sits beside the booking. Procore vendors are carried into the DATEV creditor master rows that the booking file references. Because posted entries and the chart of accounts cannot be read from DATEV, ml-connector treats DATEV as a write-only accounting destination and never pulls bookings back into Procore.

How ml-connector handles it

ml-connector stores both credential sets encrypted and runs two separate auth paths. On the Procore side it requests a client-credentials token for the service account and refreshes it before the 90 minute expiry, paginating each project at up to 100 records per page and reading the rate-limit headers to back off on a 429. On the DATEV side it holds the PKCE-obtained refresh token from the tax advisor's one-time login and mints a fresh 15 minute access token for every batch, sending client_id only on refresh as DATEV requires. Procore cost codes and cost types are mapped first to DATEV accounts and cost centers, so every EXTF line lands on an account that already exists, since DATEV will not return its chart of accounts to validate against. EXTF files are written as UTF-8 with precomposed characters and deterministic filenames, because DATEV rejects duplicate filename and document-type pairs, which makes a re-submission safe. After upload ml-connector polls the DATEV job endpoint with backoff until the batch reports complete or failed, since there is no push notification, and a Procore Requisitions or DirectCosts webhook can trigger a run while a nightly poll reconciles anything a webhook missed. Every record carries a full audit trail and can be replayed if a downstream call fails.

A real-world example

A mid-sized German general contractor with around 200 staff runs project budgets, commitments, and subcontractor billing in Procore across several active job sites, while its tax advisor keeps the statutory books in DATEV. Before the integration, an accounts clerk exported approved subcontractor invoices and direct costs from each Procore project every week and typed the totals into DATEV by hand, then emailed the invoice PDFs separately, and month-end close stalled while the team reconciled project costs against the ledger. With DATEV and Procore connected, each approved invoice and direct cost posts into DATEV as a booking line on the right account and cost center, the PDF arrives in DATEV Unternehmen Online attached to the same client, and the manual export and re-keying step is gone.

What you can do

  • Post approved Procore subcontractor invoices and direct costs into DATEV as EXTF booking batches on the cost center for each project.
  • Upload the matching Procore invoice PDFs into DATEV Unternehmen Online under the correct client-specific document type.
  • Map Procore cost codes and cost types to DATEV accounts and tax codes so every booking line lands on a valid account.
  • Bridge Procore client-credentials tokens and the interactive DATEV PKCE login, refreshing each before expiry.
  • Trigger runs from Procore webhooks, poll DATEV job status to completion, and replay any record after a failed downstream call.

Questions

Which direction does data move between DATEV and Procore?
The flow runs from Procore into DATEV. Approved subcontractor invoices, direct costs, committed purchase orders, and their invoice PDFs move from Procore into DATEV. DATEV does not return posted journal entries or its chart of accounts through the API, so ml-connector treats DATEV as a write-only destination and never pushes bookings back into Procore.
How does the integration handle DATEV's lack of webhooks and async file jobs?
DATEV writes bookings as asynchronous EXTF or DXSO file jobs and provides no outbound webhooks. ml-connector submits each batch, receives a job ID, and polls the DATEV job status endpoint with exponential backoff until it reports complete or failed. On the Procore side, create and update webhooks can trigger a run while a nightly poll reconciles anything a webhook missed.
How are Procore cost codes mapped to DATEV accounts?
Procore organizes financial data by cost code and cost type, while DATEV bookings require explicit debit and credit account numbers and tax codes. ml-connector maps each Procore cost code and cost type to the matching DATEV account and cost center before any batch is written. This mapping is configured up front because DATEV will not return its chart of accounts for the connector to validate against.

Related integrations

Connect DATEV and Procore

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

Get started