ml-connector
DATEVStripe

DATEV and Stripe integration

DATEV is the accounting backend German tax advisors and their clients run. Stripe processes the card and wallet payments, refunds, and payouts that sit downstream of billing. Connecting the two means each settled Stripe charge, refund, and processor fee becomes a DATEV booking instead of being re-keyed from a downloaded report. ml-connector reads Stripe payment and balance-transaction activity, then writes the gross receipts, refunds, and fees into DATEV as a finalized EXTF booking file against the accounts and cost centers you map. Because Stripe has no vendor, purchase order, or GL account objects of its own, the integration is built around what Stripe does expose: customers, invoices, payment intents, charges, refunds, payouts, and balance transactions.

How DATEV works

DATEV is not a single REST API. Core accounting runs as asynchronous batch file processing: finalized bookings are submitted as EXTF CSV jobs to the on-premise DATEV Rechnungswesen engine, and booking suggestions go as DXSO XML jobs to DATEV Unternehmen Online, with each submission returning a job id you poll until it completes. A REST surface covers client lookup and document upload only. Authentication is OAuth 2.0 Authorization Code with PKCE through Login mit DATEV, which always needs an interactive user session, with 15-minute access tokens. DATEV has no outbound webhooks, the standard chart of accounts is not readable over the API, and posted journal entries cannot be read back.

How Stripe works

Stripe exposes customers, invoices, payment intents, charges, refunds, payouts, disputes, and read-only balance transactions through a REST API where updates are POST requests and all amounts are in the smallest currency unit. Authentication is a secret API key sent over HTTP Basic auth, since Stripe offers no OAuth2 for standard server-to-server use; restricted keys allow least-privilege scoping. Stripe pushes events such as charge.succeeded, charge.refunded, and payout.paid by webhook, signed with HMAC-SHA256 over the raw request body and delivered at least once with retries for up to three days. Stripe has no vendor, purchase order, or GL account objects, so charges, refunds, and the fee lines on balance transactions are the canonical source for accounting.

What moves between them

The flow runs one direction, from Stripe into DATEV. As payments settle, ml-connector reads the Stripe charge, the refunds against it, and the processing fee from its balance transaction, then assembles the gross receipts, refunds, and fees into an EXTF CSV booking batch with debit and credit accounts, document numbers, tax keys, and cost centers. That file is submitted as an async EXTF job to the DATEV Rechnungswesen engine, then polled until it reports complete or failed. Stripe charge, refund, and payout webhooks trigger the work as money moves, and a scheduled poll on the charges and balance-transactions lists backfills anything a webhook missed. Each booking line carries the Stripe charge or payout id as its document reference. DATEV bookings are write-only, so ml-connector never reads journals back, and Stripe has no GL records to receive financial entries.

How ml-connector handles it

ml-connector stores both credential sets encrypted and sends the Stripe secret key over HTTP Basic auth on every request, while holding the DATEV OAuth session that the tax advisor or client established through the PKCE login, refreshing the 15-minute access token from the refresh token and sending only the client_id, not the secret, on refresh. Incoming Stripe webhooks are verified by recomputing the HMAC-SHA256 signature over the raw, unmodified body before anything is queued, and because Stripe delivers at least once and does not guarantee order, each event is deduplicated on its event id and the resource is re-fetched from the Stripe API rather than trusted from the payload. Charge and balance-transaction amounts are converted from Stripe minor units into decimal values, mapped to DATEV GL accounts by payment type and fee category, and the EXTF text is written as precomposed UTF-8 so DATEV does not silently reject it. Because DATEV has no webhooks and processes imports asynchronously, each EXTF job is polled with exponential backoff and jitter until it finishes. EXTF filenames are generated deterministically so DATEV's duplicate-file check, which rejects a repeat filename and document type with error DCO01253, makes a retry safe, and every record carries a full audit trail and can be replayed if a submission fails.

A real-world example

A German software vendor with roughly seventy staff bills its customers through Stripe, takes card and SEPA payments at checkout, and has its books kept in DATEV by an external Steuerberater. Before the integration, a bookkeeper logged into the Stripe Dashboard each morning, downloaded the prior day's payout and balance report, and hand-keyed the gross receipts, refunds, and Stripe processing fees into DATEV against the right SKR accounts, then spent month-end trying to tie each bank payout back to the hundreds of individual charges it covered. With DATEV and Stripe connected, each settled charge and payout becomes an EXTF booking batch automatically, split into receipts, refunds, and fees with the correct tax keys and cost centers, and the Stripe charge id on every line. Bank reconciliation turns into a match against bookings that are already posted, and the daily download-and-key step is gone.

What you can do

  • Turn Stripe settled charges, refunds, and processor fees into DATEV EXTF booking batches with debit and credit accounts, tax keys, and cost centers.
  • Post Stripe payouts into DATEV so each bank deposit reconciles against the charges it covers.
  • Carry the Stripe charge or payout id into the DATEV document reference so each booking line traces back to the originating transaction.
  • Verify the Stripe webhook HMAC-SHA256 signature over the raw body and deduplicate on event id before any booking file is built.
  • Bridge the Stripe secret key with DATEV's interactive OAuth PKCE login, convert smallest-unit amounts, then submit and poll each async EXTF job to completion.

Questions

Which direction does data move between DATEV and Stripe?
Data moves one way, from Stripe into DATEV. Settled charges, refunds, processor fees, and payouts flow from Stripe and are written into DATEV as EXTF booking batches. DATEV bookings are write-only and Stripe has no vendor or GL records, so ml-connector never reads journals back from DATEV and never pushes financial entries into Stripe.
How does the integration get accounting data out of Stripe if it has no GL accounts?
Stripe reports every fund movement, including processing fees, on its read-only balance transactions, and charges and refunds carry the gross amounts. ml-connector reads those records and maps the receipts, refunds, and fees to the DATEV GL accounts, tax keys, and cost centers you choose, since the mapping lives in the connector rather than in Stripe. The Stripe charge or payout id is carried onto each booking line as the document reference.
How are Stripe webhooks and DATEV's asynchronous, pull-only design reconciled?
Stripe pushes signed webhooks, but DATEV has no inbound webhooks and processes bookings as asynchronous file jobs. ml-connector verifies each Stripe HMAC-SHA256 signature over the raw body, deduplicates on the event id, builds an EXTF booking file, submits it as a job, and then polls the DATEV job status with exponential backoff until it reports complete or failed. Deterministic filenames make DATEV's duplicate-file check safe, so a failed submission can be retried without double-booking.

Related integrations

Connect DATEV and Stripe

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

Get started