Skip to content
Fintech

fiskaly SUBMIT DE: Automating §146a Cash Register Declarations to ELSTER

Germany now requires declaring every electronic cash register to the tax office. How to automate the whole pipeline — taxpayer, establishments, clients, XML validation and ERiC transmission — with the SUBMIT DE API.

4 min read Updated Sep 2, 2026
fiskaly SUBMIT DE: Automating §146a Cash Register Declarations to ELSTER

Signing transactions with a TSE was only half of Germany's cash-register regulation. The other half arrived on January 1, 2025: under §146a(4) AO, taxpayers must declare their electronic record-keeping systems — which tills exist, where they operate, and which TSE protects them — to the tax authorities via ELSTER. Doing that manually for a fleet is misery. fiskaly SUBMIT DE wraps the whole declaration pipeline — taxpayer, establishments, clients, XML generation, ERiC validation and transmission — in a REST API. Here's how to automate it end to end.

Flow: taxpayer and establishment data become a submission XML, validated and transmitted to ELSTER via ERiC

Key takeaways

  • The declaration is mandatory: initial registrations plus a declaration on every change (new till, moved till, decommissioned TSE).
  • SUBMIT DE's model: Taxpayer → Establishments → Clients (+TSS) → Submission → Transmission.
  • Submissions ride a validation state machine ending in TRANSMISSION_SUCCEEDED; every state is queryable, so you can build real monitoring.
  • If you already use SIGN DE, client and TSS data auto-populates — external TSE fleets can be declared too, with manual data.

The domain model in five minutes

EntityWhat it representsKey fields
TaxpayerThe legal entity declaring13-digit unified federal tax number, 4-digit tax office number
EstablishmentA physical business locationAddress; one submission per establishment
ClientOne ERS — cash register, taximeter, odometerSerial, type, commissioning date, linked TSS
External TSSA non-fiskaly TSE you also need to declareCertification data entered manually
SubmissionThe declaration file for one establishmentXML + human-readable PDF preview

Wiring it up

1. Authenticate and register the taxpayer

curl -X POST https://submission.fiskaly.com/api/v1/auth \
  -d '{"api_key": "...", "api_secret": "..."}'

curl -X PUT .../api/v1/taxpayer \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "tax_number": "1234567890123",
    "tax_office_number": "9201",
    "name": "Beispiel GmbH"
  }'

2. Describe establishments and clients

curl -X PUT .../api/v1/establishment/$EST_ID -d '{
  "name": "Filiale Berlin Mitte",
  "address": { "street": "Torstraße 1", "zip": "10119", "town": "Berlin" }
}'

# SIGN DE clients: referenced — their TSS data is fetched automatically.
# External systems: registered manually with their TSE certification info.
curl -X PUT .../api/v1/external/tss/$XT_ID  -d '{ "certification_id": "BSI-K-TR-0000-0000", ... }'
curl -X PUT .../api/v1/external/client/$XC_ID -d '{ "tss_id": "'$XT_ID'", "serial_number": "TILL-07", ... }'

3. Create, validate, review, transmit

// Illustrative C# orchestration
var submissionId = Guid.NewGuid();

await api.PutAsync($"/submission/{submissionId}", new { establishment_id = estId });

// The service validates against ERiC plausibility rules:
// CREATED → VALIDATION_TRIGGERED → VALIDATION_SUCCEEDED → READY_FOR_TRANSMISSION
var state = await PollUntilAsync(
    () => api.GetStateAsync($"/submission/{submissionId}"),
    s => s is "READY_FOR_TRANSMISSION" or "VALIDATION_FAILED");

if (state == "VALIDATION_FAILED")
    throw new DeclarationException(await api.GetErrorsAsync(submissionId));

// Optional but wise: archive the artifacts before sending
await Save(await api.DownloadXmlAsync(submissionId));   // what will be transmitted
await Save(await api.DownloadPdfAsync(submissionId));   // human-readable preview

await api.PutAsync($"/submission/{submissionId}/transmission", new { });
// → TRANSMISSION_SUCCEEDED (or a queryable failure)

When do you have to (re)submit?

Think of the requirement as an event log of your till fleet. Triggers include:

  • Initial registration of existing systems (the 2025 obligation, grace period to July 31, 2025 for pre-existing devices).
  • Commissioning a new cash register — declare within a month.
  • Decommissioning, replacing a TSE, or moving a till to another establishment.

The automation win: hook your device-lifecycle events (till provisioned / retired in your fleet DB) to submission creation, and the compliance paperwork becomes a side effect of operations instead of a quarterly panic.

Operational advice

  1. Archive every XML and PDF with the transmission timestamp — that's your proof of compliance.
  2. Alert on terminal states. VALIDATION_FAILED and transmission failures should page whoever owns compliance, with the API's error detail attached.
  3. Reconcile quarterly: fleet database vs. declared clients. Drift means someone plugged in a till without telling the pipeline.
  4. Use metadata fields to tag submissions with your internal store ids — future you will grep for them.

FAQ

We use hardware TSEs from another vendor — is SUBMIT DE still useful?

Yes. The external TSS/client endpoints exist exactly for mixed fleets: you enter the certification data manually and still get the managed XML/ERiC/ELSTER pipeline.

Is this the same as the DSFinV-K export?

No — DSFinV-K is the transaction data format auditors pull during an audit (see the DSFinV-K article); SUBMIT DE is the registration of the systems themselves. You need both stories straight.

Can I preview what the tax office receives?

Yes — download the generated XML and the PDF rendering before triggering transmission. Put the PDF in front of a human for the first few runs.

Series & next steps

This is part two of the German fiscalization series — start with SIGN DE cloud TSE integration, continue with DSFinV-K exports. Building compliance into a POS product? Let's scope it together.

Keep reading

Related articles