Jahresabschluss.io
DESign inRegister →

UStVA API

German VAT return API: UStVA figures, check and approval

GET /v1/vat-returns?period=2026-09 — or the MCP tool get_vat_return — returns one company's German VAT return (Umsatzsteuer-Voranmeldung, UStVA) for a calendar month or quarter: the box figures, the amount payable and the postings behind each box, computed from the books exactly as the app computes them. From there the same API settles the form's conditional questions, runs the official ELSTER check, freezes the figures and gives the user an approval link; filing happens in the app. EC sales list and Dauerfristverlängerung drafts are built from the books as well.

Last reviewed: 2026-10-19

The UStVA in brief

A German business that charges VAT files advance VAT returns by the tenth day after each period, electronically in the official format (§ 18(1) UStG). The period is the calendar quarter; it becomes the month if last year's VAT exceeded €9,000, and the tax office can waive returns if it was no more than €2,000 (§ 18(2) UStG), which also has its own rules for newly founded businesses. The Dauerfristverlängerung moves every deadline by one month (§ 46 UStDV); monthly filers pay a special prepayment of one eleventh of last year's prepayments (§ 47 UStDV).

Once filed, a VAT return counts as a tax assessment subject to review (§ 168 AO); changing it later means a corrected return, which the API leaves to the app. Which period and which taxation method apply to your company is set in the app; the agent reads both with get_entity_settings.

Reading a period with get_vat_return

One parameter, the calendar month or quarter:

# MCP
{ "name": "get_vat_return", "arguments": { "period": "2026-Q3" } }

# REST
curl -s "https://api.jahresabschluss.io/functions/v1/bookkeeping-api/v1/vat-returns?period=2026-Q3" \
  -H "Authorization: Bearer $JAB_API_KEY"
  • kennzahlen — the official box numbers with their values, for example 81 for net sales taxed at 19 % and 83 for the remaining advance payment or refund.
  • figures with the amount payable (Zahllast) as it would be filed, and booked_zahllast as the sum of the VAT accounts; a small difference comes from the tax bases being cut to whole euros, as ELSTER calculates.
  • belege — for each box the postings with amount and journal ID, for payments also invoice number, customer and date; belege_gekappt says whether the list was cut short.
  • dauerfristverlaengerung — whether the extension is active and the state of the special prepayment.
  • quelle, hinweise and transmission_blocked — whether the values come from the books or were entered by hand, notes, and whether filing this period is blocked at the moment, for example because of a VAT group.
  • A period that does not fall into exactly one fiscal year returns 409 fiscal_year_ambiguous instead of estimated figures; a deviating fiscal year is mapped automatically.

The form's conditional questions

The official form contains questions that only matter in special cases — triangular transactions, VAT shown on an invoice without being owed (§ 14c UStG), input-tax adjustments (§ 15a UStG) and others. get_vat_supplementary (GET /v1/vat-returns/supplementary) returns them for a period with their official wording and says whether they have been confirmed. Until they are, every check and preparation lists the blocker zusatzangaben_offen.

The agent may confirm exactly one answer: that none of them applies. confirm_vat_supplementary takes keine_sonderfaelle=true and confirm=true, and its description tells the agent to call it only after you have said so. If a special case does apply, you record it in the app; recorded entries are never overwritten, and the API answers 409 zusatzangaben_in_app.

Check, prepare, approve

The filing itself, as an agent or a script runs it:

BASE="https://api.jahresabschluss.io/functions/v1/bookkeeping-api/v1"

# Official ELSTER check with the test flag — nothing is sent
curl -s -X POST "$BASE/tax/check" -H "Authorization: Bearer $JAB_API_KEY" \
  -H "Content-Type: application/json" -d '{"art":"ustva","period":"2026-09"}'

# Freeze box figures and fingerprint for 30 minutes
curl -s -X POST "$BASE/tax/operations" -H "Authorization: Bearer $JAB_API_KEY" \
  -H "Content-Type: application/json" -d '{"art":"ustva","period":"2026-09"}'

# Link for the user, valid 7 days
curl -s -X POST "$BASE/tax/operations/<vorgang_id>/approval-link" \
  -H "Authorization: Bearer $JAB_API_KEY" -H "Content-Type: application/json" -d '{}'

For a VAT return the frozen manifest holds the box figures and the amount payable, and the fingerprint is computed over the box figures. When the user opens the link, the app recomputes it from the books: unchanged figures are confirmed as such, changed figures are shown on the filing page before anything is sent. The user files there with the second factor and the ELSTER PIN; get_tax_operation then reports the transfer ticket.

EC sales list and Dauerfristverlängerung from the books

create_tax_draft (POST /v1/tax/drafts) builds both — only for the regular case, and nothing is sent.

  • art=zm with a period builds the EC sales list (ZM, § 18a UStG) from the bookings. You first confirm that there are no triangular transactions and no reporting lines outside the bookkeeping; only then does the agent set keine_sonderfaelle and confirm.
  • A booking without the customer's VAT ID stops the draft with 422 zm_ust_idnr_fehlt and the open bookings; no reportable lines, a single zero line, an unclear legal status or a correction go to the app.
  • art=dauerfrist with the current year creates the extension application. Quarterly filers get it without special prepayment; for monthly filers the special prepayment is computed from last year's acknowledged returns, all of which must exist, and the application is sent as art=sovz.
  • Other years, an unclear filing rhythm, an application already filed and corrections are handled in the app.
  • An existing draft is never overwritten: the same values answer 200, different ones 409 entwurf_vorhanden. The answer names the next step, POST /v1/tax/operations with art and source_id.

Deadlines from the tax calendar

list_tax_deadlines (GET /v1/tax/deadlines) returns the same deadlines as the app's tax calendar: VAT returns, special prepayment, EC sales lists, payroll tax, OSS, annual returns — including earlier years' returns due this year — prepayments set by the tax office and deadlines the office has moved. Each entry has its due date, whether it is done — by a transmission with transfer ticket or marked by hand — and whether it is overdue. Without year it uses the current year; status=offen shows only what is open. If a source cannot be read, the route answers 503 instead of a shorter calendar.

Limits and prices

  • No transmission by the agent: the right file is not granted at present; the user files through the approval link.
  • No corrected returns (422 api_berichtigung_nur_in_app) and no special cases in the conditional questions.
  • The annual VAT return's draft is created in the app (422 api_ustje_entwurf_in_app); afterwards the API checks and prepares it as art=ustje.
  • Settings such as the VAT period, taxation on invoiced or received amounts and the extension flag change only in the app.
  • Keys: read for figures, questions and deadlines; write for confirmations, drafts, checks, preparations and the link. 30 checks, preparations and drafts per hour per key.
  • Transmission prices depend on your plan; see the pricing page.

Frequently asked questions

Is there an API for the German VAT return?

Yes. GET /v1/vat-returns reads a period's figures, POST /v1/tax/check runs the official ELSTER check, POST /v1/tax/operations prepares the filing and an approval link lets the user file in the app.

Can the API submit the UStVA to ELSTER by itself?

No. The right that would allow a direct transmission through the API is not granted at present. The user files in the app, via the approval link, with the second factor and ELSTER PIN.

Which period format does the API expect?

A calendar month as YYYY-MM or a calendar quarter as YYYY-Qn. The API maps it to the right fiscal year, also for a deviating fiscal year, and answers 409 if that is not unambiguous.

Are these the same figures as in the app?

Yes. The preview uses the same building blocks as the app, without sending anything. After a booking changes, the next call shows the new figures.

What does the blocker zusatzangaben_offen mean?

The form's conditional questions are not confirmed for the period. If none applies, the agent confirms that after asking you; if one applies, you record it in the app.

Can I create an EC sales list through the API?

Yes, for the regular case: create_tax_draft with art=zm and a period builds it from the bookings. Then check, prepare and file it like a VAT return.