この記事は現在英語版のみです。翻訳は近日公開予定です。
The Programmablaufplan (PAP) Lohnsteuer 2026 is the official algorithm published by Germany's Federal Ministry of Finance (Bundesministerium der Finanzen, BMF) that every payroll system must follow to calculate wage tax (Lohnsteuer), solidarity surcharge (Solidaritätszuschlag), and the church-tax assessment base.
コンプライアンスと規制シリーズの一部
完全ガイドを読むThe Programmablaufplan (PAP) Lohnsteuer 2026 is the official algorithm published by Germany's Federal Ministry of Finance (Bundesministerium der Finanzen, BMF) that every payroll system must follow to calculate wage tax (Lohnsteuer), solidarity surcharge (Solidaritätszuschlag), and the church-tax assessment base. It is published both as a human-readable flowchart/pseudocode PDF and as a machine-readable XML file, and the BMF operates an official online calculation service developers can use as a reference oracle for testing. If you are implementing German payroll — in Odoo or any other system — the PAP is not a guideline; it is the binding specification, and your output must match it to the cent.
This guide explains what the PAP actually is, how the XML pseudocode format works, what changes between tax years, how to validate your implementation against the BMF's own service and test data, and how the pieces map onto Odoo's German payroll setup. We implement and customize Odoo for German businesses, so the pitfalls listed here are ones we have hit or audited in real payroll projects.
Key Takeaways
- The PAP is the legally binding calculation specification for German wage tax — published annually by the BMF as a flowchart/pseudocode PDF plus a machine-readable XML version on bmf-steuerrechner.de
- The XML encodes the entire algorithm as typed variables (inputs like STKL, RE4, LZZ; outputs like LSTLZZ, SOLZLZZ, BK) and execution nodes — it is designed for code generation, not hand-porting
- All monetary arithmetic is defined in cents with exact, prescribed rounding at specific steps — using floating-point math is the classic way implementations drift by one cent and fail certification
- 2026 carries updated parameters versus 2025 (basic allowance, child allowance, and related thresholds rise under already-legislated tax relief) — always take the exact constants from the published 2026 PAP, never from news articles
- The BMF provides an official online wage-tax calculator with a developer-accessible interface plus published test-case tables — your implementation should reproduce every test row exactly
- The PAP covers tax only: Lohnsteuer, Solidaritätszuschlag, and the church-tax base (BK). Social-insurance contributions follow separate annually-updated Rechengrößen and are out of scope
- Mid-year revised PAPs happen — a compliant payroll engine needs versioned calculators selectable by payment date, not a single hardcoded algorithm
- In Odoo, the PAP belongs in a dedicated, versioned calculation module called from salary rules — with employee tax attributes (Steuerklasse, Kinderfreibeträge, church tax) sourced from ELStAM data on the employee/contract record
What the Programmablaufplan actually is
Germany does not let payroll vendors interpret tax law individually. Under § 39b of the income tax act (Einkommensteuergesetz, EStG), the BMF publishes a Programmablaufplan für die maschinelle Berechnung der Lohnsteuer — literally a "program flow chart for the machine calculation of wage tax" — for each tax year. Every employer or payroll product calculating Lohnsteuer by machine must produce results consistent with it.
Three properties matter to a developer:
- It is an algorithm, not a table. The PAP defines named input variables, internal variables, constants, and a step-by-step computation — including the income-tax tariff formula, the Vorsorgepauschale (a notional social-insurance allowance deducted within the tax calculation), allowances by tax class, and the solidarity-surcharge thresholds.
- It is exact. Amounts flow through the algorithm in euro cents as integer/decimal values, with rounding prescribed at specific steps (where to truncate, where to round, and to which unit). Two implementations that follow the PAP must agree to the cent.
- It is versioned by year — and sometimes within a year. When tax parameters change retroactively or mid-year (which has happened repeatedly in recent years, for example when allowances are raised by late-passing legislation), the BMF publishes a geänderter Programmablaufplan (revised PAP) with its own validity window. A payroll engine must select the correct PAP version based on the wage-payment date.
The PAP family typically includes the main annual PAP for regular payroll runs and a manual-calculation variant; the machine PAP is the one you implement.
What the PAP covers — and what it does not
| In scope (PAP outputs) | Out of scope (separate rules) |
|---|---|
| Lohnsteuer for the payment period (LSTLZZ) | Social-insurance contributions (pension, health, care, unemployment) |
| Solidaritätszuschlag (SOLZLZZ) | Contribution ceilings (Beitragsbemessungsgrenzen) and Rechengrößen |
| Church-tax assessment base (BK) | The church-tax rate itself (8% or 9% depending on the federal state — applied by your system, not the PAP) |
| Tax on other/one-off payments (sonstige Bezüge) and multi-year compensation (Fünftelregelung inputs) | ELStAM data retrieval (the procedure that tells you an employee's tax attributes) |
| Faktorverfahren for tax-class IV couples (factor input f) | Wage-tax filing/remittance (Lohnsteuer-Anmeldung via ELSTER) |
This boundary is the first compliance pitfall: a "German payroll implementation" needs the PAP plus the social-insurance calculation plus the reporting procedures. The PAP is the tax brain only.
The XML pseudocode format, explained for implementers
Alongside the PDF, the BMF publishes the PAP as an XML file on its developer pages (the Lohnsteuerrechner service at bmf-steuerrechner.de hosts the machine-readable artifacts). The XML is not a data file — it is a serialized program, structured roughly like this (illustrative, simplified):
<PAP name="Lohnsteuer2026" version="1.0">
<VARIABLES>
<INPUTS>
<INPUT name="STKL" type="int"/> <!-- Steuerklasse 1-6 -->
<INPUT name="RE4" type="BigDecimal"/> <!-- wage for the period, in CENTS -->
<INPUT name="LZZ" type="int"/> <!-- period: 1=year 2=month 3=week 4=day -->
<INPUT name="ZKF" type="BigDecimal"/> <!-- child allowance count, halves allowed -->
<INPUT name="R" type="int"/> <!-- church-tax liability flag -->
<INPUT name="KVZ" type="BigDecimal"/> <!-- health-insurance add-on rate -->
<!-- ... roughly two dozen inputs in total ... -->
</INPUTS>
<OUTPUTS>
<OUTPUT name="LSTLZZ" type="BigDecimal"/> <!-- wage tax, cents -->
<OUTPUT name="SOLZLZZ" type="BigDecimal"/> <!-- solidarity surcharge, cents -->
<OUTPUT name="BK" type="BigDecimal"/> <!-- church-tax base, cents -->
</OUTPUTS>
<INTERNALS> ... </INTERNALS>
</VARIABLES>
<CONSTANTS> ... tariff constants, allowance amounts ... </CONSTANTS>
<METHODS>
<MAIN>
<EVAL exec="MPARA()"/>
<EVAL exec="MRE4JL()"/>
<IF expr="STKL < 5">
<THEN> ... </THEN>
<ELSE> ... </ELSE>
</IF>
</MAIN>
<METHOD name="MPARA"> ... </METHOD>
</METHODS>
</PAP>
Key implications:
- It is built for code generation. The element set (variables, constants, methods, EVAL/IF/THEN/ELSE execution nodes with expressions) maps mechanically to any imperative language. The established pattern in the German payroll ecosystem is a generator that emits a calculator class per PAP year — there are mature open-source generators and pre-generated libraries for Java, C#, PHP, Python, and JavaScript. We strongly recommend generating rather than hand-porting: hand-ported PAPs are where one-cent bugs live.
- Variable names are the documentation. STKL is the tax class, RE4 the period wage in cents, JFREIB/JHINZU annual allowance/add-back amounts from the employee's ELStAM record, PKV/KRV/PVS flags describing the employee's insurance situation, AF/F the Faktorverfahren flag and factor. Keep the cryptic names in your code — renaming them breaks the audit trail back to the official document.
- Decimal semantics are part of the spec. The pseudocode assumes exact decimal arithmetic (BigDecimal in the original Java idiom) with explicit scale and rounding-mode operations. In Python use
decimal.Decimal; in JavaScript use an arbitrary-precision decimal library. IEEE-754 floats will pass most test cases and then fail a handful — the worst kind of bug.
What changes from 2025 to 2026
Each annual PAP carries the year's updated parameters. For 2026, the headline movements were already legislated in the tax-relief packages passed in late 2024: the basic allowance (Grundfreibetrag) rises again (from EUR 12,096 in 2025 to EUR 12,348 in 2026 under that legislation), the child allowance (Kinderfreibetrag) increases correspondingly, and dependent values — the tariff zone boundaries and the solidarity-surcharge exemption threshold (Freigrenze) — shift with them. Contribution-related inputs that feed the Vorsorgepauschale (such as the average health-insurance add-on rate and the contribution ceilings used inside the tax calculation) are also updated annually.
Two practitioner warnings:
- Take constants only from the published PAP itself. Press summaries round numbers and omit interactions; late amendments happen. The XML's constants block is the single source of truth for the year, and a revised mid-year PAP supersedes it from its stated effective date.
- Version your calculator by validity window, not by calendar year. Recent years have repeatedly required two PAPs per year (an initial one and a revised one effective from a mid-year month, with retroactive correction permitted via the payroll). Your engine should resolve "payment date → PAP version" through configuration.
Testing against the BMF's official service and test data
You never have to guess whether your implementation is correct. Two official instruments exist:
1. The BMF online calculator and its developer interface. The BMF operates its wage- and income-tax calculator at bmf-steuerrechner.de. Beyond the browser UI, the service exposes a parameterized interface that accepts the PAP input variables (STKL, LZZ, RE4 in cents, and so on) for a given PAP version and returns the computed outputs (LSTLZZ, SOLZLZZ, BK) as XML. Access conditions have changed over time — check the current terms on the site — but the pattern for implementers is stable: treat the BMF service as a reference oracle, fire your own test matrix at both your engine and the service, and diff the results. Do this at integration-test time, not per payroll run; production payroll must not depend on an external service being up.
2. The published test-case tables. Each PAP release comes with official test data: tables of input combinations (across tax classes, periods, wage levels, child allowances, and insurance situations) with the expected outputs. A compliant implementation reproduces every row exactly — to the cent. Wire these tables into your CI suite as golden tests. When the 2026 PAP (or a revision) lands, regenerate the calculator, swap in the new test tables, and your pipeline tells you within minutes whether you are compliant.
A minimal sanity check we run on every engagement, in pseudocode:
for each row in official_test_table_2026:
result = pap2026.calculate(row.inputs)
assert result.LSTLZZ == row.expected.LSTLZZ # exact, in cents
assert result.SOLZLZZ == row.expected.SOLZLZZ
assert result.BK == row.expected.BK
If even one assertion is off by a cent, do not patch the output — find the rounding step you got wrong. One-cent diffs are almost always a misplaced truncation or a float that leaked into the pipeline.
Mapping the PAP to Odoo payroll (l10n_de)
Odoo's payroll framework computes payslips through salary rules organized in a salary structure, reading from the contract, the employee record, and input lines. Germany's localization layers German specifics on top. Whether you use Odoo's own German payroll localization, a partner localization, or a custom build, the architecture that works is the same:
| PAP concept | Where it lives in Odoo |
|---|---|
| Input STKL (tax class) | Employee record — German payroll setups add a Steuerklasse field, sourced from ELStAM |
| ZKF (child allowance count) | Employee record (note: halves like 0.5 and 1.5 are valid — use a decimal field, not an integer) |
| R / church-tax attribute | Employee record (denomination from ELStAM); the 8%/9% state rate applied on BK in a separate rule |
| RE4 (period wage, cents) | Computed from the contract wage plus taxable input lines on the payslip — converted to cents before entering the PAP |
| LZZ (payment period) | Derived from the payslip period (monthly payroll → LZZ 2) |
| KVZ, PKV, KRV, PVS, PVZ (insurance flags/rates) | Contract-level insurance configuration |
| Outputs LSTLZZ / SOLZLZZ / BK | Three salary rules that call the PAP calculator and post the results (converted back from cents) |
The design rules we hold to in Odoo customization projects for German clients:
- Isolate the PAP in its own module/class, one per version, with a resolver that picks the version from the payslip's payment date. Salary rules call
compute_lohnsteuer(payslip)— they never contain tariff math inline. Inline Python in salary-rule definitions is untestable and unauditable for something this sensitive. - Generate the calculator from the official XML and commit both the generated code and the source XML. Your auditor — and the next developer — can then verify provenance.
- Keep cents end-to-end inside the calculator. Convert Odoo's float currency values to
Decimalcents at the boundary, never inside. - Golden-test in CI with the official test tables, as above, plus a handful of your client's real anonymized payslips cross-checked against the BMF reference service.
And a scope warning we give every client: passing the PAP makes your tax calculation correct. Full German payroll operation additionally involves ELStAM retrieval for employee tax attributes, social-insurance calculation and electronic reporting (DEÜV), and wage-tax filing via ELSTER — procedures with their own certification and communication requirements that no PAP implementation covers. Treat "we implemented the PAP" as one milestone of roughly three, and validate the overall setup with a German tax advisor (Steuerberater) before the first live payroll run. For the broader context of running a German entity on Odoo — GoBD, e-invoicing, DATEV export — see our Odoo ERP guide for German businesses.
Frequently Asked Questions
What is the BMF Programmablaufplan Lohnsteuer?
It is the official, legally binding algorithm published annually by Germany's Federal Ministry of Finance for the machine calculation of wage tax, solidarity surcharge, and the church-tax assessment base under § 39b EStG. It is released as a flowchart/pseudocode PDF and as a machine-readable XML file, and every payroll system in Germany must produce results consistent with it to the cent.
Where do I get the PAP 2026 XML file?
The BMF publishes the machine-readable PAP alongside its official wage-tax calculator on the bmf-steuerrechner.de developer pages, with the announcement of each year's PAP appearing on bundesfinanzministerium.de. Download the XML for the exact version and validity window you need — and watch for revised mid-year PAPs (geänderte Programmablaufpläne), which supersede the initial release from their stated effective date.
Is there an official API to calculate German wage tax?
The BMF's online calculator at bmf-steuerrechner.de exposes a parameterized developer interface that accepts the PAP input variables and returns the computed outputs as XML. It is intended as a reference and test oracle, not as a production dependency — use it to validate your own implementation in integration tests, and check the current access terms on the site, since they have changed over time.
What inputs does the PAP wage-tax calculation need?
The core inputs are STKL (tax class 1–6), LZZ (payment period: year, month, week, or day), RE4 (the period's taxable wage in euro cents), ZKF (number of child allowances, halves allowed), church-tax liability, allowance amounts from the employee's ELStAM record, and a set of insurance flags and rates (statutory vs private health insurance, care-insurance specifics, the health-insurance add-on rate) that feed the Vorsorgepauschale. The main outputs are LSTLZZ (wage tax), SOLZLZZ (solidarity surcharge), and BK (church-tax base), all in cents.
Does Odoo support the German Programmablaufplan out of the box?
Odoo provides a payroll framework and German localization content, but in our project experience any production German payroll on Odoo needs careful localization work: a versioned PAP calculator module called from salary rules, employee fields for ELStAM attributes (Steuerklasse, child allowances, denomination), correct cent-based decimal arithmetic, and golden tests against the official BMF test tables. Social-insurance calculation and electronic reporting (DEÜV, ELSTER) are separate workstreams on top of the PAP.
Why does my implementation differ from the official calculator by one cent?
Almost always rounding: the PAP prescribes exact decimal arithmetic in cents with truncation or rounding at specific algorithm steps, and an implementation that uses binary floating-point or rounds at the wrong step will match most inputs but drift by a cent on edge cases. Use a decimal type end-to-end, follow the prescribed scale operations literally, and locate the divergence by comparing intermediate variables against the pseudocode rather than patching the final output.
執筆者
ECOSIRE Teamテクニカルライティング
ECOSIRE のテクニカルライティングチームは、Odoo ERP、Shopify による EC、AI エージェント、Power BI による分析、GoHighLevel による自動化、そしてエンタープライズソフトウェアのベストプラクティスを扱っています。私たちのガイドは、企業が十分な情報に基づいてテクノロジーを判断できるよう支援します。
関連記事
AI を活用した顧客セグメンテーション: RFM から予測クラスタリングまで
AI が顧客セグメンテーションを静的な RFM 分析から動的な予測クラスタリングにどのように変換するかを学びます。 Python、Odoo、および実際の ROI データを使用した実装ガイド。
サプライチェーン最適化のための AI: 可視性、予測、自動化
AI を使用してサプライ チェーンの運用を変革します。需要の検知、サプライヤーのリスク スコアリング、ルートの最適化、倉庫の自動化、混乱の予測などです。 2026年のガイド。
B2B卸売Eコマースガイド:バイヤーポータル・掛け払い・顧客別価格
バイヤーが実際に使うB2B卸売ポータルの作り方:顧客別価格、掛け払いと与信限度、発注書と承認付きチェックアウト、注文履歴からの再注文。
コンプライアンスと規制のその他の記事
電子商取引のサイバーセキュリティ: 2026 年のビジネスを守る
2026 年の完全な e コマース サイバーセキュリティ ガイド。PCI DSS 4.0、WAF セットアップ、ボット保護、支払い詐欺防止、セキュリティ ヘッダー、およびインシデント対応。
化学産業向け ERP: 安全性、コンプライアンス、バッチ処理
ERP システムが化学会社の SDS 文書、REACH および GHS 準拠、バッチ処理、品質管理、危険物輸送、配合管理をどのように管理するか。
輸出入取引用ERP: 多通貨、物流、コンプライアンス
ERP システムが商社の信用状、税関書類、インコタームズ、多通貨損益計算書、コンテナ追跡、関税計算をどのように処理するか。
ERP を使用した持続可能性と ESG レポート: コンプライアンス ガイド 2026
ERP システムを使用して、2026 年の ESG 報告コンプライアンスをナビゲートします。 CSRD、GRI、SASB、スコープ 1/2/3 排出量、炭素追跡、Odoo の持続可能性をカバーします。
監査準備チェックリスト: 書籍の準備をする
財務諸表の準備状況、裏付け文書、内部統制文書、監査人の PBC リスト、一般的な監査結果を網羅した完全な監査準備チェックリスト。
電子商取引ビジネスのためのオーストラリア GST ガイド
ATO 登録、75,000 ドルの基準値、少額輸入、BAS 申請、デジタル サービスの GST を網羅した、e コマース ビジネス向けのオーストラリア GST 完全ガイド。