@fin.cx/payroll
German payroll as a business's books meet it. This first release gives the due dates a payroll's obligations have:
svDueDatesOf(): the social insurance. For each month, the day the contribution statement (Beitragsnachweis) must be present at the collecting agency (Einzugsstelle) and the day the contributions fall due. Both are counted in bank working days of the state where the collecting agency has its seat.lstaDueDateOf(): the wage tax. The day the wage tax return (Lohnsteuer-Anmeldung) must reach the tax office and the wage tax must be paid, and the last day of the payment's grace period (Schonfrist).
The package is pure. It reads no clock, keeps no state and makes no requests. The holidays come from the holiday calendar of @fin.cx/opendata, which computes them per year.
Issue Reporting and Security
For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.
Install
pnpm install @fin.cx/payroll
Usage
import { svDueDatesOf, lstaDueDateOf } from '@fin.cx/payroll';
// A collecting agency with its seat in Hamburg
const dueDates = svDueDatesOf(2026, 'DE-HH', { regionalHolidays: 'count' });
dueDates[0]; // { month: '2026-01', contributionStatementDue: '2026-01-26', contributionsDue: '2026-01-28' }
dueDates[11]; // { month: '2026-12', contributionStatementDue: '2026-12-22', contributionsDue: '2026-12-28' }
// The seat is not known: the earliest date of all states
svDueDatesOf(2025, 'unknown', { regionalHolidays: 'count' })[9];
// { month: '2025-10', contributionStatementDue: '2025-10-24', contributionsDue: '2025-10-28' }
// A monthly return to a tax office in Bavaria
lstaDueDateOf('2026-04', 'DE-BY', { regionalHolidays: 'count' });
// { period: '2026-04', due: '2026-05-11', surchargeFreeUntil: '2026-05-15' }
// A quarterly or a yearly return
lstaDueDateOf('2026-Q1', 'DE-BY', { regionalHolidays: 'count' }); // due '2026-04-10'
lstaDueDateOf('2026', 'DE-BY', { regionalHolidays: 'count' }); // due '2027-01-11'
// The tax office's state is not known: the earliest date of all states
lstaDueDateOf('2028-05', 'unknown', { regionalHolidays: 'ignore' });
// { period: '2028-05', due: '2028-06-12', surchargeFreeUntil: '2028-06-15' }
States are given by their ISO 3166-2 codes, such as DE-BY. Dates are calendar days written YYYY-MM-DD, without a time zone. The options say whether regional holidays count, the ones that hold only in a part of a state: { regionalHolidays: 'count' } or { regionalHolidays: 'ignore' }. When you do not know whether the place you mean keeps them, choose the option that is never late. For svDueDatesOf() that is 'count': a counted holiday takes a bank working day out of the month, so the due dates can only move earlier. For lstaDueDateOf() it is 'ignore': a counted holiday moves a due date off it to a later day.
Social insurance
Contributions earned by employment fall due on the third-last bank working day of the month in which the employment was exercised. They are due in the amount they are expected to come to (§ 23 Abs. 1 Satz 2 SGB IV). The employer sends the contribution statement two working days before that (§ 28f Abs. 3 Satz 1 SGB IV). The social insurance reads this to mean that the statement must be present at the collecting agency for the whole of the fifth-last bank working day, from 0:00. So it is sent on the day before at the latest. contributionStatementDue is that fifth-last bank working day, and contributionsDue is the third-last.
A bank working day is neither a Saturday, nor a Sunday, nor a public holiday, nor 24 or 31 December, when the Deutsche Bundesbank is closed. The holidays that count are those of the state where the collecting agency has its seat, which need not be where the business is. In 2025, for example, a collecting agency in Niedersachsen took the contributions for October on 28 October because of Reformationstag, while one in Bayern took them on 29 October.
When the seat is not known, 'unknown' counts the holidays of every state and gives the earliest of their dates. A date given this way is never too late, but it can be a day or two too early.
The remaining amount of a month's contributions is due with the next month's contributions, on the third-last bank working day of the following month (§ 23 Abs. 1 Satz 2 SGB IV), so it needs no date of its own.
Wage tax
The wage tax return is due on the tenth day after the return period ends, and so is the payment of the wage tax withheld in it (§ 41a Abs. 1 Satz 1 EStG). Under § 41a Abs. 2 EStG, the period is:
- a calendar month by default;
- a quarter if the wage tax of the previous calendar year was more than 1,080 euros but not more than 5,000 euros;
- a calendar year if it was not more than 1,080 euros.
The caller decides which period applies and passes it as YYYY-MM, YYYY-Qn or YYYY.
When the tenth day is a Saturday, a Sunday or a public holiday, the deadline moves to the next working day (§ 108 Abs. 3 AO). The holidays that count are those of the state the tax office is in. Strictly, the return counts the holidays at the tax office's seat and the payment those at the place of its cash office (Finanzkasse), which is normally in the same state. When the state is not known, 'unknown' gives the earliest date of all states. With { regionalHolidays: 'ignore' } such a date is never too late, but it can be a day or two too early.
A payment by transfer counts as made on the day it is credited to the tax office's account (§ 224 Abs. 2 Nr. 2 AO). If it is credited up to three days after the due date, it draws no late-payment surcharge (§ 240 Abs. 3 Satz 1 AO). The end of this grace period moves off weekends and holidays in the same way, which the commentaries and the published tax calendars derive from § 108 Abs. 3 AO. surchargeFreeUntil is that last day. Three things to note about it:
- It does not apply to a payment in cash or by cheque (§ 240 Abs. 3 Satz 2 AO).
- A SEPA direct debit counts as paid on the due date (§ 224 Abs. 2 Nr. 3 AO).
- The return itself has no grace period. A late return can draw a late-filing surcharge (§ 152 AO).
What is refused
Each refusal throws a PayrollError with a code:
unsupported_year: a year outside 2018 to 9999, the years the holiday calendar answers for, or a period whose due date would fall after 9999;invalid_period: a wage tax return period not writtenYYYY-MM,YYYY-QnorYYYY;unknown_state: a state that is neither the ISO 3166-2 code of a German federal state nor'unknown';invalid_options: options that do not say how regional holidays are treated.
API
svDueDatesOf(year, seat, options): ISocialInsuranceDueDates[]: the twelve months of a year, each{ month, contributionStatementDue, contributionsDue }.lstaDueDateOf(period, state, options): IWageTaxDueDate:{ period, due, surchargeFreeUntil }.- Types
TCollectingAgencySeatandTTaxOfficeState(each a state code or'unknown') andTWageTaxPeriod. PayrollErrorandTPayrollErrorCode.
Not covered
- Contributions that are not earned by employment, which are due on the fifteenth of the following month (§ 23 Abs. 1 Satz 5 SGB IV), and the household cheque procedure (Haushaltsscheckverfahren).
- The employer's choice to pay the previous month's amount instead of the expected one (§ 23 Abs. 1 Satz 3 SGB IV), which changes the amount but not the date.
- Choosing the wage tax return period from the previous year's wage tax, and the rules for a business's first year.
- Computing late-payment surcharges.
Sources
- § 23 SGB IV (Fälligkeit): https://www.gesetze-im-internet.de/sgb_4/__23.html
- § 28f SGB IV (Aufzeichnungspflicht, Nachweise der Beitragsabrechnung und der Beitragszahlung): https://www.gesetze-im-internet.de/sgb_4/__28f.html
- The social insurance's reading of § 28f Abs. 3 SGB IV, that the statement must be present at 0:00 of the fifth-last bank working day, from the meeting of its umbrella organisations on questions of the joint contribution collection (Besprechung über Fragen des gemeinsamen Beitragseinzugs) of 7 and 8 May 2008, as summarised at https://www.lohn-info.de/meldewesen_faelligkeit_beitragsnachweis.html
- The due dates the collecting agencies publish, which the tests hold the package against: 2026 by the TK (https://www.tk.de/resource/blob/2205860/25a117a691ab0a9531fedcfc671ac6fd/faelligkeitstermine-2026-data.pdf), the AOK (https://www.aok.de/fk/tools/weitere-inhalte/beitraege-und-rechengroessen-der-sozialversicherung/faelligkeit-der-sozialversicherungsbeitraege/werte-2026/) and the KKH (https://www.kkh.de/firmenkunden/beitrag-sozialversicherung/faelligkeitstermine); 2025 by the AOK (https://www.aok.de/fk/fileadmin/user_upload/tools/downloads/universell/2025-faelligkeiten-sv-beitraege.pdf)
- 24 and 31 December as days that are not bank working days, by the TK: https://www.tk.de/firmenkunden/versicherung/beitraege-faq/angaben-beitragszahlung/heiligabend-und-silvester-bankarbeitstage-2034048
- § 41a EStG (Anmeldung und Abführung der Lohnsteuer): https://www.gesetze-im-internet.de/estg/__41a.html
- § 108 AO (Fristen und Termine): https://www.gesetze-im-internet.de/ao_1977/__108.html
- The holidays at the tax office's seat for the return and at its cash office for the payment: OFD Cottbus, 14 January 2004, S 0260-3-St 251, https://bravors.brandenburg.de/verwaltungsvorschriften/feiertagsrecht
- § 152 AO (Verspätungszuschlag): https://www.gesetze-im-internet.de/ao_1977/__152.html
- § 224 AO (Leistungsort, Tag der Zahlung): https://www.gesetze-im-internet.de/ao_1977/__224.html
- § 240 AO (Säumniszuschläge): https://www.gesetze-im-internet.de/ao_1977/__240.html
- The grace period moved off weekends and holidays, and the published wage tax dates the tests hold the package against: https://www.smartsteuer.de/online/lexikon/s/saeumniszuschlag/ and https://sevdesk.de/ratgeber/buchhaltung-finanzen/steuern/termine/
License and Legal Information
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the license.md file.
Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
Trademarks
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
Company Information
Task Venture Capital GmbH Registered at District Court Bremen HRB 35230 HB, Germany
For any legal inquiries or further information, please contact us via email at hello@task.vc.
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.