ml-connector
DATEVProcurify

DATEV and Procurify integration

DATEV is the accounting backend German tax advisors and their clients use to keep the books. Procurify is where the purchasing team raises requests, issues purchase orders, and approves vendor bills. Connecting the two means approved spend in Procurify reaches the DATEV ledger without anyone re-keying it. ml-connector reads each approved AP bill and its vendor from Procurify, then submits it to DATEV as a booking job and uploads the invoice document, mapping Procurify account codes to the DATEV accounts you set. It handles the very different auth on each side and confirms every job, since DATEV has no push notifications.

How DATEV works

DATEV is not a single REST API. Client and document operations use REST against product-specific hosts like accounting-clients.api.datev.de and accounting-documents.api.datev.de, but finalized bookings go in as asynchronous file jobs: EXTF CSV files to DATEV Rechnungswesen via the extf-files product, or DXSO XML invoice suggestions to DATEV Unternehmen Online via the dxso-jobs product. Auth is OAuth 2.0 Authorization Code with PKCE through login.datev.de, and a real tax advisor or client must log in interactively because there is no machine-to-machine flow. Access tokens last 15 minutes and must be refreshed with client_id only. There are no webhooks, so submitted jobs are polled until they complete, and the standard chart of accounts cannot be read back through the API.

How Procurify works

Procurify is a cloud procurement and spend platform with a REST JSON API served from a per-customer subdomain such as acme.procurify.com. It authenticates with OAuth 2.0 client credentials, a pure server-to-server flow that returns a 24-hour bearer token, and every request also carries the X-Procurify-Client header. It exposes vendors, purchase orders, order items, AP bills and payments, vendor payment methods, account codes, locations, departments, and users, with vendors and account codes readable and writable. Procurify does not support webhooks, so the connector polls list endpoints and filters on fields like last_modified and dateModified. Pagination is page-number based with a metadata block carrying the next page link.

What moves between them

The main flow runs from Procurify into DATEV. ml-connector reads approved AP bills and their line items from Procurify, along with the linked vendor and account code, and writes each bill into DATEV: a routine finalized booking goes in as an EXTF CSV job to DATEV Rechnungswesen, while an invoice that still needs review goes in as a DXSO XML suggestion to DATEV Unternehmen Online. The invoice PDF is uploaded as a Rechnungseingang document to DATEV Unternehmen Online. Vendor master data from Procurify supplies the creditor rows on the booking. Cadence is scheduled polling against Procurify, since neither system pushes events, typically aligned to how often the AP team approves bills. DATEV bookings are write-only, so ml-connector never reads posted journals back into Procurify.

How ml-connector handles it

ml-connector stores both credential sets encrypted and bridges two unlike auth models: it requests a client-credentials token from the Procurify subdomain and reuses it for its 24-hour life, while it runs the interactive DATEV OAuth flow with PKCE, keeps the refresh token, and renews the 15-minute DATEV access token with client_id alone. Because both systems are poll-only, it runs on a schedule rather than waiting for a push. DATEV will not return its chart of accounts, so you map Procurify account codes to DATEV GL accounts and cost centers once, and every booking line references an account that already exists in DATEV. Document types in DATEV are client-specific, so the connector fetches the document-type list before uploading rather than hardcoding Rechnungseingang. EXTF files are written as UTF-8 with precomposed characters and a deterministic filename, so DATEV's filename-plus-type duplicate check makes a retry safe instead of double-posting; the DATEV duplicate error code DCO01253 is treated as already-posted. Every booking and document upload is an asynchronous DATEV job, so the connector polls the job endpoint with exponential backoff until it confirms complete or failed, and records that DATEV processes on its own schedule. Failed submissions are retried and can be replayed, and every record carries a full audit trail.

A real-world example

A 250-person engineering services firm in Germany runs all purchasing through Procurify and keeps its statutory books in DATEV through an outside Steuerberater. Before the integration, the AP clerk exported approved bills from Procurify each week, retyped the vendor, amount, tax code, and account into a DATEV booking batch by hand, and emailed the invoice PDFs to the tax office, where mismatched account assignments often bounced back for correction. With DATEV and Procurify connected, each approved bill in Procurify becomes a DATEV booking job with the invoice already uploaded to DATEV Unternehmen Online, posted against the mapped GL account and cost center. The clerk stops re-keying, the tax advisor receives clean booking batches, and month-end no longer waits on a backlog of manually entered invoices.

What you can do

  • Post approved Procurify AP bills into DATEV as EXTF CSV booking jobs or DXSO XML invoice suggestions.
  • Upload each Procurify invoice PDF to DATEV Unternehmen Online as a Rechnungseingang document, using the client-specific document type.
  • Map Procurify account codes and vendors to the DATEV GL accounts and cost centers you configure, since DATEV cannot return its own chart of accounts.
  • Bridge the Procurify 24-hour client-credentials token and the interactive DATEV OAuth login with PKCE and 15-minute token refresh.
  • Poll each asynchronous DATEV job to a confirmed result with backoff, deterministic filenames for safe retries, and a full audit trail on every record.

Questions

Which direction does data move between DATEV and Procurify?
The main flow is Procurify into DATEV. Approved AP bills, their line items, and vendor data move from Procurify into DATEV as booking jobs, and the invoice PDF is uploaded to DATEV Unternehmen Online. DATEV bookings are write-only, so ml-connector does not read posted journal entries back into Procurify.
How are accounts matched when DATEV will not share its chart of accounts?
DATEV does not expose the standard chart of accounts through its API, so the GL accounts and cost centers are configured once as a mapping. ml-connector reads the account code on each Procurify bill and translates it to the matching DATEV account, so every booking line references an account that already exists in DATEV. You set this mapping up front rather than discovering accounts at runtime.
Neither system has webhooks, so how does the sync stay current?
Both DATEV and Procurify are poll-only, so ml-connector runs on a schedule instead of waiting for push events. It queries Procurify list endpoints, filtering on fields like last_modified to pick up newly approved bills, and then polls each DATEV job until it confirms complete or failed. The cadence is usually tied to how often the AP team approves bills.

Related integrations

Connect DATEV and Procurify

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

Get started