ml-connector
DATEVPaylocity

DATEV and Paylocity integration

DATEV runs accounting and tax for German businesses. Paylocity runs HR and payroll for US mid-market employers. Connecting the two turns each completed Paylocity payroll into a booking batch inside DATEV without re-keying the totals. After a pay run finishes, ml-connector reads each pay statement's gross earnings, employer and employee taxes, and deductions, then submits them to DATEV as an EXTF CSV file job posted to the correct SKR accounts and Kostenstelle cost centers. It also reconciles the very different mechanics on each side, since Paylocity is a modern REST API and DATEV is an asynchronous file-import system that exposes no accounting objects to read back.

How DATEV works

DATEV is not a conventional REST API. The accounting:clients REST product lists the clients (companies) the logged-in tax advisor can reach and supplies the client-id used as a path parameter everywhere else. Finalized bookings are written by submitting EXTF-format CSV files to DATEV Rechnungswesen through the accounting:extf-files product, or as DXSO XML to DATEV Unternehmen Online, both as asynchronous jobs you poll until complete. Authentication is OAuth 2.0 Authorization Code with PKCE against login.datev.de, with a 15-minute access token and a real interactive user session required. EXTF posting is write-only, posted journal entries cannot be read back, and the standard chart of accounts is not retrievable through the API.

How Paylocity works

Paylocity is a cloud HCM and payroll platform exposing employees, pay statements, deductions and earnings, positions, work locations, and time punches through the Paylocity Web Services REST API, scoped by a company_id path parameter on every data endpoint. The Pay Statement API is read-only and returns per-employee checkDate, processId, grossEarnings, netPay, totalTaxes, totalDeductions, and earnings, deductions, and taxes line items. Authentication is OAuth 2.0 client credentials, machine-to-machine with no user login and no refresh flow: a one-hour bearer token is re-requested on expiry, and the client secret must be rotated annually. Paylocity pushes a lightweight Payroll Processed webhook carrying only identifiers on the process date, with no HMAC signature scheme documented.

What moves between them

The flow runs from Paylocity into DATEV. After a pay run completes in Paylocity, ml-connector reads each pay statement and builds a DATEV EXTF booking batch: gross wages, employer taxes, employee withholdings, and deductions become debit and credit lines mapped to your SKR accounts and Kostenstelle cost centers. The batch is submitted as an asynchronous EXTF file job to the matching DATEV client and the job is polled until DATEV reports complete or failed. Supporting payroll registers can also be uploaded to DATEV Unternehmen Online as documents against a client-specific document type. Because EXTF posting is one-way write-only and Paylocity exposes no GL chart of accounts, ml-connector never writes booking results back into Paylocity.

How ml-connector handles it

ml-connector stores both credential sets encrypted and keeps each side's auth on its own clock, which is the main bridge here: DATEV uses an interactive Authorization Code plus PKCE session with a 15-minute access token refreshed using the client_id only, while Paylocity uses pure client-credentials with a one-hour token that is simply re-requested since there is no refresh flow. It tracks the Paylocity client secret expiry, because that secret must be rotated annually and a missed rotation would otherwise silently break the link. A Payroll Processed webhook fires on the process date but carries only companyId, processId, runId, and checkDate, so ml-connector treats it purely as a trigger and calls the Pay Statement API with those IDs to pull the real grossEarnings, taxes, and deduction totals; a scheduled poll backfills any run a webhook missed, since DATEV itself sends no events. Paylocity offers no payload HMAC signature, so the callback endpoint is protected with the Basic auth credentials Paylocity sends over TLS 1.2, and webhooks are deduplicated by processId because the same event can arrive more than once. Earning, deduction, and tax codes are mapped first to SKR accounts and cost centers, so every EXTF line lands on an account that exists. The EXTF file is written as UTF-8 with precomposed (NFC) characters and a deterministic filename, since DATEV silently rejects non-precomposed text and flags duplicate filename plus document-type combinations with error DCO01253, which keeps re-submission retry-safe. Multi-entity employers have a separate company_id per subsidiary, so each is mapped to its own DATEV client-id, and DATEV jobs are polled with exponential backoff and jitter. Every record carries a full audit trail and can be replayed if a DATEV job fails.

A real-world example

A US subsidiary of a German manufacturing group, with around 250 employees across two plants, runs payroll in Paylocity while the parent keeps the consolidated books in DATEV through its Steuerberater. Before the integration, the finance team exported a payroll register from Paylocity each pay period, hand-keyed the wage, tax, and deduction totals into a DATEV booking batch, and figured out which Kostenstelle each plant's labor belonged to, every cycle. With DATEV and Paylocity connected, each completed pay run posts into DATEV automatically as an EXTF batch allocated to the right SKR accounts and cost centers, so the labor accounts are booked the same day payroll processes. The manual export and re-keying step is gone, and month-end close starts from numbers the tax advisor can review directly in DATEV.

What you can do

  • Post each completed Paylocity payroll into DATEV as an EXTF booking batch, debited and credited to the correct accounts.
  • Map Paylocity gross earnings, employer and employee taxes, and deduction codes to your SKR accounts and Kostenstelle cost centers.
  • Trigger on the Paylocity Payroll Processed webhook, then call the read-only Pay Statement API to pull the real totals.
  • Bridge Paylocity's machine-to-machine client-credentials token and DATEV's interactive PKCE user login on separate token clocks.
  • Submit DATEV file jobs with deterministic NFC filenames and poll them with retries and a full audit trail on every record.

Questions

Which direction does data move between DATEV and Paylocity?
The flow is Paylocity into DATEV. Completed payroll totals such as gross earnings, taxes, and deductions move from Paylocity into DATEV as EXTF booking batches mapped to your accounts and cost centers. DATEV EXTF posting is one-way write-only and exposes no API to read journal entries back, and Paylocity has no GL chart of accounts, so ml-connector does not write booking results into Paylocity.
How does the integration handle the very different auth on each side?
Paylocity uses OAuth 2.0 client credentials, a machine-to-machine grant with a one-hour token and no refresh flow, so ml-connector simply re-requests the token before it expires and tracks the secret because Paylocity requires it to be rotated annually. DATEV instead needs an interactive Authorization Code plus PKCE session whose 15-minute access token is refreshed with the client_id only. ml-connector keeps both sets of credentials encrypted and renews each on its own clock.
Paylocity webhooks have no signature, so how are they secured and used?
Paylocity does not document an HMAC payload signature, so the callback endpoint is protected with the Basic auth credentials Paylocity sends over TLS 1.2. The Payroll Processed webhook carries only identifiers like companyId and processId, so ml-connector uses it purely as a trigger, then calls the read-only Pay Statement API to fetch the actual grossEarnings, taxes, and deductions, and deduplicates by processId since the same event can arrive more than once.

Related integrations

Connect DATEV and Paylocity

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

Get started