Skip to content

About

Export Stripe transactions to DATEV — EXTF booking batches, BEDI document archive, deferred revenue. Runs locally, no third-party service.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

1 watching

Forks

Repository files navigation

npm CI License Node >= 20 TypeScript strict DATEV EXTF 700 Changelog

🃏 StripeJack

English · Deutsch

stripe-jack.jungherz.com

Export Stripe transactions to DATEV.
EXTF booking batches · BEDI document archive · deferred revenue · cron-ready · multi-account

Installation · Quick Start · Configuration · CLI · Cron · Multi-Account · Mail · Output · Booking rules · Migration · Privacy · Claude Code · Development · License


German bookkeeping expects a very specific package: an EXTF booking batch, the matching invoice PDFs in a BEDI archive, and a deferred-revenue schedule for subscriptions. StripeJack produces exactly that from a Stripe account, in one command, ready to upload to DATEV Unternehmen online.

It is verified against a real DATEV export produced by other software for the same month: in compatibility mode the output matches field for field, header timestamp aside.

Installation

npm install -g @jungherz-de/stripe-jack

Or without installing:

npx @jungherz-de/stripe-jack export --month 2026-07

Requires Node.js 20 or newer.

Quick Start

stripe-jack init         # asks for your Stripe key and account numbers, writes .env
stripe-jack accounts     # check the configuration, no API call
stripe-jack export       # export the last completed month

init defaults every account number from the chart of accounts you pick (SKR 03 or 04) and validates the result before writing, so a typo surfaces immediately rather than on the first export. Prefer to fill the file in yourself? Copy .env.example.

The archive lands in ./out, next to a manifest with counts, totals and checksums.

Configuration

stripe-jack init writes the file for you. It ends up looking like this — the full reference is in docs/configuration.md (German):

STRIPE_API_SEC_KEY=sk_live_…

# From the letter of your tax firm
DATEV_BERATER=1234567
DATEV_MANDANT=12345
DATEV_SACHKONTENLAENGE=4
EXTF_SKR=04

# Core accounts (SKR 04 shown; SKR 03 equivalents in the reference)
KONTO_DEBITOR=10004        # receivables
KONTO_GEBUEHREN=6855       # Stripe and PSP fees
KONTO_GELDTRANSIT=1461     # money in transit to the bank account
KONTO_GUTHABEN=1810        # the Stripe balance itself
KONTO_KLAERUNG=1370        # suspense account
ERLOES_REGEL=4400          # standard-rate revenue

StripeJack only ever reads, so a restricted key (rk_live_…) belongs here rather than a full secret key. The quickest route is Stripe’s permission template for read-only accounting access; only Basic Business Contact Information has to be added as Read on top — that is how the merchant’s country is read, and the country decides every revenue account. No write access is needed at all. Full list: docs/configuration.md.

CLI

stripe-jack init                                     # interactive setup, writes .env
stripe-jack export                                   # last completed month, all accounts
stripe-jack export --month 2026-07
stripe-jack export --from 2026-07-01 --to 2026-07-31
stripe-jack export --account shop --out ./exports --no-mail
stripe-jack export --month 2026-07 --dry-run         # report only, write nothing
stripe-jack export --month 2026-07 --force           # replace an existing export

stripe-jack accounts                                 # show the resolved configuration
stripe-jack verify --month 2026-07 --against old-export.zip

Exit codes: 0 success · 1 configuration · 2 Stripe/network · 3 data · 4 mail · 5 lock held. A failed mail never costs you the archive — it is on disk before the first byte goes out.

Running on a schedule

15 4 3 * * cd /srv/stripe-jack && /usr/bin/npx stripe-jack export >> /var/log/stripe-jack.log 2>&1

With no arguments StripeJack exports the last completed month. Runs are locked per account, already-exported periods are not silently overwritten, and logs are JSON lines when stdout is not a terminal. systemd and launchd units are in docs/cron.md (German).

Multiple accounts

STRIPE_ACCOUNTS=main,shop
MAIN_STRIPE_API_SEC_KEY=sk_live_…
MAIN_DATEV_MANDANT=54321
SHOP_STRIPE_API_SEC_KEY=sk_live_…
SHOP_DATEV_MANDANT=40921

Each account is exported into its own subdirectory with its own chart of accounts, lock and recipient. See docs/multi-account.md (German).

Sending the export

MAIL_ENABLED=true
MAIL_SMTP_HOST=smtp.example.com
MAIL_FROM=buchhaltung@example.com
MAIN_MAIL_TO=kanzlei@example.de

The mail carries the archive plus a summary of counts, totals and any warnings. --dry-run reports what would be sent without sending it.

What gets exported

DATEV_Stripe_<client>_<uuid>_2026-07.zip
├── Stripe_PRAP_…xlsx              deferred revenue per subscription invoice
├── Income_By_Product_…xlsx        net revenue per product, weekly/monthly/yearly
├── EXTF_Stripe_Zahlungen_…csv     one batch of payment bookings
├── EXTF_Stripe_Rechnungen_…csv    one batch of invoice bookings
└── documents.zip                  invoice PDFs + BEDI document.xml index

Field-by-field description of the format: docs/datev-format.md (German).

Booking rules

The Stripe balance is modelled as a bank-like account. Payments clear receivables, fees become an expense, payouts move through a money-in-transit account, and refunds reverse the same account pair rather than swapping accounts — so tax automation on the revenue accounts keeps working.

The revenue account is derived, not configured per customer: domestic standard and reduced rate, intra-community reverse charge, One-Stop-Shop, third country. Anything StripeJack cannot classify with confidence goes to the suspense account with a warning, never to a plausible guess.

Full decision tree, the deferral maths and the foreign-currency handling: docs/booking-rules.md (German).

Replacing an existing tool

StripeJack ships two profiles:

Profile Behaviour
strict (default) correct German bookkeeping
compat follows the conventions of older export tools
# Compare against an export produced by your current tool
stripe-jack verify --month 2026-07 --profile compat --against old-export.zip
# → No differences.

Use compat for the switch-over month so nothing changes for your tax advisor, then move to strict. The five differences are documented in docs/compatibility.md (German).

Privacy and self-hosting

StripeJack runs on your machine. There is no service behind it, no account, no sign-up, and no server of ours that ever sees anything.

That matters for GDPR. An export carries personal data — customer names, addresses, invoice amounts and the invoice PDFs. With StripeJack the parties to that data are your company, Stripe (which already holds it) and your tax firm. No additional provider is introduced, so there is no processor to contract under Art. 28 GDPR, no third-party server location to assess, and no extra entry in your record of processing activities.

If you would rather have the export run for you, StripeJack Cloud is the hosted sibling — the same core, operated by Jungherz GmbH on a server in Germany. There the paragraph above does not apply: processing happens on your behalf, and the Art. 28 agreement is part of the subscription. Which one fits depends on who should carry operation and data storage.

The tool opens exactly two kinds of outbound connection, both from your own machine: to api.stripe.com to read, and to your own SMTP server if — and only if — you switch mailing on. There is no telemetry, no usage reporting and no update check. The source is open, and every outbound call lives in src/stripe/ and src/output/mailer.ts.

Nothing is stored beyond the archive and its manifest in your output directory: no database, no cache, no temporary spool.

Details, including operating it under its own system user and what to do about access and erasure requests: docs/datenschutz.md (German).

Using it with Claude Code

The package ships a SKILL.md. Point Claude Code (or any agent that reads skill files) at this repository and it knows how to run the tool, what the exit codes mean, and how to walk you through setup by asking for the values it cannot guess.

"Set up StripeJack for my Stripe account and export last month."

Nothing about the tool requires an agent — stripe-jack init does the same guided setup on its own.

Development

npm install
npm run typecheck
npm run lint
npm test          # unit tests + an offline golden-master test
npm run build

The golden-master test replays a recorded Stripe response and compares the result with a reference export for the same month. Both sides are anonymised by scripts/anonymize-fixture.ts, which applies one replacement table to the Stripe data and to the reference CSVs — pseudonyms keep the original string length, so the 60-character truncation the format relies on is still exercised.

No customer data and no live keys are in this repository.

License

MIT © Jungherz GmbH

StripeJack is not affiliated with Stripe, Inc. or DATEV eG. It produces import files according to publicly documented formats; verifying the resulting bookings remains your and your tax advisor's responsibility.

About

Export Stripe transactions to DATEV — EXTF booking batches, BEDI document archive, deferred revenue. Runs locally, no third-party service.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages