Qualified Confirmation (§18e UStG)
Why you need this
Section titled “Why you need this”If your German company issues zero-rated intra-EU B2B invoices, you are required to verify the counterparty’s VAT ID at invoicing time. If a tax auditor later challenges the zero-rating and you cannot prove you checked, the consequences are concrete:
- Reversed zero-rating — you owe 19% VAT on the invoice amount.
- Interest charges — on the unpaid VAT from the original invoice date.
- Penalties — for negligent tax reporting.
A simple VIES lookup is not sufficient for German VAT IDs. §18e of the German VAT Act (Umsatzsteuergesetz) grants German businesses the right to request a qualified confirmation from the Federal Central Tax Office (BZSt) that verifies not just validity, but also company name and address data.
Giltiq automates this. One API call gives you BZSt’s field-level match results and a
receipt_id you store on your invoice. Years later during an audit, retrieve the full record with a
single API call. Giltiq retains receipts for a minimum of 10 years — covering the full German
tax audit window.
See also: Qualified Confirmations API Reference
What §18e UStG requires
Section titled “What §18e UStG requires”Under §18e of the German VAT Act, German businesses can request a qualified confirmation from BZSt before issuing a zero-rated intra-EU invoice. This confirmation verifies:
- That the counterparty’s VAT ID is valid and active.
- That the company name and address registered at BZSt match the data on your invoice.
A simple VIES lookup is insufficient because:
- VIES does not perform company data matching.
- VIES does not issue a timestamped receipt that proves you checked.
- VIES availability is not guaranteed — BZSt is the authoritative source for German VAT IDs.
How Giltiq bridges the gap
Section titled “How Giltiq bridges the gap”Giltiq calls BZSt’s eVatR REST API directly on your behalf when you supply company data in the validate request. For each field you supply, BZSt returns one of:
| Result | Meaning |
|---|---|
match | Your supplied value matches the BZSt registry |
mismatch | Your supplied value does not match |
not_queried | You did not supply this field |
not_provided | BZSt did not return a value for this field |
After a successful BZSt call, Giltiq:
- Persists the full record — your input, BZSt’s response, match results, and official name/address.
- Issues a
receipt_id(e.g.GQ-QC-20260410-A7K2M9P4R3) — a stable identifier you can store on your invoice or in your accounting system. - Returns the
receipt_idin the validate response so you can reference it immediately.
You can retrieve the full receipt at any future point via
GET /v1/qualified-confirmations/{receipt_id}.
Where this fits in your invoicing flow
Section titled “Where this fits in your invoicing flow”- Invoice created — your system generates an intra-EU B2B invoice for a German counterparty.
- Call Giltiq validate with the counterparty’s VAT ID and company data from the invoice.
- Check the result:
- All fields
match→ proceed, storereceipt_idon the invoice record. - Any field
mismatch→ flag for manual review before sending the invoice. - BZSt unavailable → fall back to a simple VIES check and queue a retry (see Error handling below).
- All fields
- Years later during audit → retrieve the full receipt by
receipt_idwith a single API call.
Store the receipt_id wherever you store invoice metadata — your database, ERP system, or
accounting software. This is your audit reference for the life of the invoice.
The receipt model
Section titled “The receipt model”The Giltiq receipt is a Giltiq-issued audit record, not an official BZSt Drucksache.
The old BZSt XML-RPC API (deactivated 2025-11-30) used to issue a printed “Drucksache” receipt number. The current BZSt REST API does not. Giltiq fills this gap by:
- Capturing all inputs and the complete BZSt response at call time.
- Generating a unique, time-stamped
receipt_idin the formatGQ-QC-YYYYMMDD-<random>. - Storing BZSt’s own internal request ID (
bzst_request_id) alongside the receipt, so you can reference it in an audit dispute.
Receipts are immutable — they record the state of the check at the moment it was made. Giltiq retains receipts for the lifetime of your account, with a minimum of 10 years to cover German tax audit windows (§§ 147 AO, 14b UStG).
Worked example: invoice-time check and later audit retrieval
Section titled “Worked example: invoice-time check and later audit retrieval”Step 1 — Request at invoicing time
Section titled “Step 1 — Request at invoicing time”When generating an invoice for counterparty DE811575812, call the validate endpoint with the
company data from the invoice:
curl "https://api.giltiq.de/v1/validate/DE811575812\?requester_vat_id=DE123456789\&company_name=Bundeszentralamt+f%C3%BCr+Steuern\&company_street=An+der+K%C3%BCppe+1\&company_zip=53225\&company_city=Bonn" \ -H "X-Api-Key: gq_live_..."Response (abbreviated):
{ "valid": true, "vat_id": "DE811575812", "source": "bzst", "qualified_confirmation": { "name_match": "match", "street_match": "match", "zip_match": "match", "city_match": "match", "receipt_id": "GQ-QC-20260410-A7K2M9P4R3", "issued_at": "2026-04-10T12:34:56.000Z", "source": "giltiq-issued" }}Step 2 — Store the receipt_id
Section titled “Step 2 — Store the receipt_id”Store receipt_id: "GQ-QC-20260410-A7K2M9P4R3" against your invoice record in your accounting
system. This is the audit reference.
Step 3 — Retrieve years later during an audit
Section titled “Step 3 — Retrieve years later during an audit”When a tax auditor asks you to prove the §18e check for invoice #2026-0042:
curl "https://api.giltiq.de/v1/qualified-confirmations/GQ-QC-20260410-A7K2M9P4R3" \ -H "X-Api-Key: gq_live_..."The full receipt — including the exact inputs you supplied, BZSt’s match results, and the official company data at the time — is returned.
How to retrieve past confirmations
Section titled “How to retrieve past confirmations”Use the receipt_id stored at invoice time to look up the full record years later:
curl "https://api.giltiq.de/v1/qualified-confirmations/GQ-QC-20260410-A7K2M9P4R3" \ -H "X-Api-Key: gq_live_..."Or list all receipts for a given counterparty:
curl "https://api.giltiq.de/v1/qualified-confirmations?target_vat_id=DE811575812" \ -H "X-Api-Key: gq_live_..."Code samples
Section titled “Code samples”# Validate with qualified confirmationcurl "https://api.giltiq.de/v1/validate/DE811575812\?requester_vat_id=DE123456789\&company_name=Acme+GmbH\&company_street=Hauptstrasse+1\&company_zip=10115\&company_city=Berlin" \ -H "X-Api-Key: gq_live_..."
# Retrieve receiptcurl "https://api.giltiq.de/v1/qualified-confirmations/GQ-QC-20260410-A7K2M9P4R3" \ -H "X-Api-Key: gq_live_..."
# List receipts for a counterpartycurl "https://api.giltiq.de/v1/qualified-confirmations?target_vat_id=DE811575812" \ -H "X-Api-Key: gq_live_..."Node.js SDK
Section titled “Node.js SDK”import Giltiq from "@giltiq/node";
const client = new Giltiq({ apiKey: "gq_live_..." });
// Validate with qualified confirmationconst result = await client.validate("DE811575812", { requesterVatId: "DE123456789", companyName: "Acme GmbH", companyStreet: "Hauptstrasse 1", companyZip: "10115", companyCity: "Berlin",});
const receiptId = result.qualifiedConfirmation?.receiptId;console.log("Receipt ID:", receiptId);Python SDK
Section titled “Python SDK”import giltiq
client = giltiq.Giltiq(api_key="gq_live_...")
# Validate with qualified confirmationresult = client.validate( "DE811575812", requester_vat_id="DE123456789", company_name="Acme GmbH", company_street="Hauptstrasse 1", company_zip="10115", company_city="Berlin",)
receipt_id = result.qualified_confirmation.receipt_idprint("Receipt ID:", receipt_id)Error handling
Section titled “Error handling”BZSt unavailable
Section titled “BZSt unavailable”When BZSt’s eVatR service is down, the API returns an error. Your code should:
- Fall back to a simple VIES validation (call without company data parameters).
- Flag the invoice for a qualified confirmation retry once BZSt is available again.
- Check BZSt availability via
GET /v1/statusbefore retrying.
Mismatch response
Section titled “Mismatch response”A mismatch means the data on your invoice doesn’t match BZSt’s registry:
{ "valid": true, "vat_id": "DE811575812", "source": "bzst", "qualified_confirmation": { "name_match": "mismatch", "street_match": "match", "zip_match": "match", "city_match": "match", "receipt_id": "GQ-QC-20260410-B3C4D5E6F7", "issued_at": "2026-04-10T12:35:00.000Z", "source": "giltiq-issued" }}The VAT ID is still valid, but the company name on your invoice doesn’t match BZSt’s records. Do not issue the zero-rated invoice until you’ve resolved the discrepancy — contact your counterparty to confirm the correct legal name, then re-validate.
Authentication required
Section titled “Authentication required”Qualified confirmation requires an API key. Anonymous (Tier 0) requests return
qualified_confirmation: null even when company data parameters are supplied.
Non-German VAT IDs
Section titled “Non-German VAT IDs”Qualified confirmation only applies to German VAT IDs (DE prefix). For all other EU VAT IDs,
the qualified_confirmation field is null — Giltiq performs a standard VIES validation instead.
Retention policy
Section titled “Retention policy”Giltiq retains qualified confirmation receipts for the lifetime of your account, with a minimum of 10 years from the date of issue. This covers:
- The standard 10-year retention requirement for tax-relevant documents (§ 147 Abs. 1 AO).
- The 10-year correction period for VAT deductions (§ 14b UStG).
If you close your account, contact support to arrange export of your receipts before deletion.