Germany is the largest economy in the EU and the most common source of B2B customers for European SaaS and e-commerce platforms. Correctly validating German VAT numbers — the Umsatzsteuer-Identifikationsnummer, commonly abbreviated USt-IdNr — is a routine requirement for any developer handling EU compliance. This guide covers the exact format, the VIES validation flow specific to Germany, the common errors that cause silent failures, and complete code examples for Node.js, Python, and PHP.
Note
German VAT numbers (Umsatzsteuer-Identifikationsnummer, USt-IdNr.) are issued by the Bundeszentralamt für Steuern (BZSt). Validation via VIES queries the BZSt database in real time.
The German VAT Number Format (USt-IdNr)
A German VAT number follows a strict format: the prefix DE followed by exactly 9 digits. There are no letters, no separators, and no variable length — it is always DE + 9 digits. A valid example is DE123456789. The German national tax authority that maintains VAT registrations is the Bundeszentralamt für Steuern (BZST), headquartered in Bonn. VIES routes all German validation requests to the BZST system, which is generally well-maintained but has scheduled maintenance windows on Sunday mornings (typically 01:00-07:00 CET).
The 9-digit number after the DE prefix is not entirely random — it has a check digit structure, but implementing check digit validation is generally not worth the effort unless you are building a form that provides immediate feedback before making an API call. The TaxID API performs both format validation (DE + exactly 9 digits) and check digit validation locally before making the VIES call, so format errors return immediately with format_invalid status without consuming your monthly quota.
| Property | Value |
|---|---|
| Prefix | DE |
| Length | 11 characters total (DE + 9 digits) |
| Format | DE followed by 9 numeric digits |
| Example | DE123456789 |
| Regex | ^DE[0-9]{9}$ |
| VIES country code | DE |
| National authority | Bundeszentralamt für Steuern (BZST) |
| Local name | Umsatzsteuer-Identifikationsnummer (USt-IdNr) |
One important distinction: the USt-IdNr is different from the Steuernummer (tax number). The Steuernummer is a national tax identification number used for domestic German tax purposes. It is not a VAT number and cannot be used for VIES validation or reverse charge purposes. German businesses often have both — the Steuernummer for domestic tax filings and the USt-IdNr for international trade. If a customer provides a Steuernummer instead of a USt-IdNr, format validation will catch it (Steuernummern have a different format and do not start with DE in the VIES sense).
Common German VAT Format Errors
The most frequent input error with German VAT numbers is customers omitting the DE prefix and submitting just the 9-digit number. The correct response is to ask for the full number including prefix — do not silently prepend DE, because a 9-digit number without a country prefix could theoretically be from another country that uses the same digit count (though Germany is the most likely in practice).
- →Missing prefix: '123456789' instead of 'DE123456789' — the most common error. Reject and ask for the full number.
- →Wrong digit count: German numbers are always 9 digits after DE. '12345678' (8 digits) or '1234567890' (10 digits) are invalid.
- →Spaces or dots: users copy-paste from invoices that may format the number as 'DE 123 456 789' or 'DE.123.456.789'. Strip all non-alphanumeric characters before validation.
- →Lowercase prefix: 'de123456789' — normalise to uppercase before validation. The TaxID API accepts lowercase and normalises internally.
- →Steuernummer submitted: German Steuernummern follow formats like '123/456/78901' — completely different from USt-IdNr. If a customer provides one, explain they need the USt-IdNr specifically.
- →DE prefix repeated: 'DEDE123456789' — rare but happens when a system concatenates country code + number that already includes the prefix.
German Company Types and VAT Registration
Not all German businesses are VAT-registered. Kleinunternehmer (small business owners) operating under §19 UStG are exempt from VAT registration and charge no VAT — they do not have a USt-IdNr. If a German B2B customer claims they are VAT-exempt, they cannot receive reverse charge treatment and you must charge the applicable VAT rate. This is a legitimate scenario, particularly for freelancers and small service businesses.
German companies that are VAT-registered include GmbH (Gesellschaft mit beschränkter Haftung), AG (Aktiengesellschaft), UG (Unternehmergesellschaft, a low-capital GmbH variant), GbR (Gesellschaft bürgerlichen Rechts) when above the threshold, and sole traders (Einzelunternehmer) above the Kleinunternehmer threshold. VIES will return the company name in the format registered with BZST, which is typically the legal trading name. For holding companies or subsidiaries, the company name returned may be the parent group name rather than the subsidiary's trading name.
Some German companies have multiple VAT numbers — for example, large companies with separate legal entities for different business units. Each entity has its own USt-IdNr. Validate the specific entity's number, not the group's. If a customer provides a parent company's VAT number for a subsidiary, VIES will return the parent company name, which will not match the entity named on the invoice. This discrepancy can cause audit issues for the customer.
VIES and Germany's BZST: What to Expect
Germany's BZST system is one of the more reliable VIES member state endpoints, with uptime typically above 99% during business hours. The most predictable downtime window is Sunday morning maintenance, approximately 01:00-07:00 CET. During this window, all German VAT number validations will return service_unavailable regardless of whether the number is valid.
For German VAT numbers, VIES returns the company name and registered address in the majority of cases. Germany does not restrict sharing of company name and address data through VIES, unlike some member states (the Netherlands and Sweden occasionally return null for address). The company name is the name as registered with the BZST — for most GmbH and AG companies this is the full legal name including the legal form designation (e.g., 'Acme Software GmbH' rather than just 'Acme Software').
Response times for German VAT validation via TaxID are under 10ms for cached results (numbers validated in the last 24 hours) and typically 200-600ms for uncached live VIES lookups. The TaxID API caches active German VAT numbers for 24 hours in Redis — the same number validated twice within 24 hours returns the cached result from the first call. Invalid and inactive numbers are cached for 1 hour.
German VAT Rates
Germany applies a standard VAT rate of 19% (Umsatzsteuer) to most goods and services. A reduced rate of 7% applies to food, books, newspapers, cultural services, local public transport, and certain agricultural products. A temporary reduced rate of 7% was applied to restaurant meals following COVID policy changes and has been extended — check the Germany VAT rates page for the current rates via API.
For SaaS and digital services sold to German consumers (B2C), you must charge 19% German VAT if you are above the EU-wide €10,000 OSS threshold. For German B2B customers with a valid USt-IdNr, zero-rate reverse charge applies. Germany participates fully in the EU One Stop Shop (OSS) scheme, so you can register for OSS in any EU member state and use it to account for German consumer VAT without a German VAT registration.
Code Examples
cURL
# Validate a German VAT number
curl https://taxid.dev/api/v1/validate/DE/DE123456789 \
-H "Authorization: Bearer YOUR_API_KEY"
# Expected response:
# {
# "valid": true,
# "status": "active",
# "vat": "DE123456789",
# "country_code": "DE",
# "company_name": "Example GmbH",
# "address": "Musterstraße 1, 10115 Berlin",
# "cached": false,
# "request_id": "req_01j..."
# }Node.js / TypeScript
export async function validateGermanVat(vatNumber: string): Promise<{
valid: boolean;
companyName: string | null;
address: string | null;
status: string;
}> {
// Normalise: strip spaces, ensure uppercase
const normalised = vatNumber.replace(/\s/g, '').toUpperCase();
// Quick format check before API call
if (!/^DE[0-9]{9}$/.test(normalised)) {
return { valid: false, companyName: null, address: null, status: 'format_invalid' };
}
const res = await fetch(
`https://taxid.dev/api/v1/validate/DE/${normalised}`,
{
headers: { Authorization: `Bearer ${process.env.TAXID_API_KEY}` },
signal: AbortSignal.timeout(5000),
}
);
const data = await res.json();
return {
valid: data.valid,
companyName: data.company_name,
address: data.address,
status: data.status,
};
}Python
import re, os, requests
from dataclasses import dataclass
from typing import Optional
DE_PATTERN = re.compile(r'^DE[0-9]{9}$')
@dataclass
class GermanVatResult:
valid: bool
company_name: Optional[str]
address: Optional[str]
status: str
def validate_german_vat(vat: str) -> GermanVatResult:
normalised = vat.replace(' ', '').upper()
if not DE_PATTERN.match(normalised):
return GermanVatResult(False, None, None, 'format_invalid')
r = requests.get(
f'https://taxid.dev/api/v1/validate/DE/{normalised}',
headers={'Authorization': f'Bearer {os.environ["TAXID_API_KEY"]}'},
timeout=5,
)
r.raise_for_status()
d = r.json()
return GermanVatResult(
valid=d['valid'],
company_name=d.get('company_name'),
address=d.get('address'),
status=d['status'],
)Frequently Asked Questions
- →Is DE always the VIES country code for Germany? Yes. Germany uses DE in VIES, matching its ISO 3166-1 alpha-2 code. Unlike Greece (which uses EL instead of GR), Germany's VIES code matches ISO.
- →What is the difference between USt-IdNr and Steuernummer? The USt-IdNr (DE + 9 digits) is for international VAT identification and VIES validation. The Steuernummer is for domestic German tax filings and has a different format. Only the USt-IdNr is relevant for EU reverse charge.
- →Does VIES return the company name for all German businesses? In most cases yes — Germany does not restrict sharing company name via VIES. Some holding companies or recently registered businesses may temporarily return null for company_name.
- →How long does VIES take for German validations? Cached German VAT numbers respond in under 10ms. Uncached live VIES lookups to BZST typically complete in 200-600ms outside maintenance windows.
- →When does BZST take VIES offline? Typically Sunday mornings 01:00-07:00 CET. During this window, German validations return service_unavailable. Implement the allow-and-re-validate pattern for checkout flows.
Validating German VAT Numbers at Scale
For applications that process large numbers of German B2B customers — ERP systems importing supplier data, marketplace platforms onboarding German sellers, or accounting software syncing customer records — batch or high-frequency validation requires some additional considerations. The TaxID API handles German VAT validation at up to 1,000,000 requests per month on published pricing tiers. For bulk imports, implement a rate limiter on your side to stay within your plan's monthly quota and avoid hitting per-minute rate limits.
For validating a large list of German VAT numbers (for example, migrating a database of 10,000 supplier records), process them in batches of 50-100 with a short delay between batches. Cache the results locally — if the same VAT number appears multiple times in your dataset, validate it once and reuse the result. Store the validation timestamp alongside the result: you need to know not just whether the number was valid, but when it was checked, for audit purposes.
For German numbers specifically, the BZST system has a lower tolerance for rapid sequential requests than some other member states' VIES endpoints. If you are sending many German validation requests in quick succession, you may see occasional slow responses or timeouts that are not typical of normal operation. TaxID handles this transparently — our caching layer means that repeated lookups for the same number do not create additional load on BZST, and our timeout handling returns service_unavailable rather than hanging.
Using German VAT Data for Invoice Compliance
When VIES returns company_name and address for a German customer, use those values on your invoice rather than whatever the customer self-reported. The VIES-registered name and address are what German tax authorities check during B2B invoice audits. A mismatch between the invoice recipient's details and their VIES registration data can cause the customer to have their input VAT claim rejected — which is their problem, not yours, but it creates support issues and damages the customer relationship.
German GmbH and AG companies often have formal legal names that differ from their trading names. For example, a company trading as 'Acme Software' might be legally registered as 'Acme Software Solutions GmbH'. Use the legal name from VIES on the invoice, and optionally display the trading name in the subject line or invoice notes. If the VIES response returns null for company_name (rare for German companies but possible for very recently registered businesses), fall back to the name the customer provided and add a note in your records that VIES did not return a name at validation time.
Integration Testing with German VAT Numbers
When writing integration tests for German VAT validation, you need a stable set of test numbers to validate against. The VIES system does not provide official test numbers, but you can use well-known German public institutions and organisations whose USt-IdNr are publicly registered. Alternatively, use the TaxID API's format_invalid response as your test case for malformed inputs — you do not need a real invalid number, you can just send a structurally incorrect string like 'DE12345' (too short) or 'DEXYZ123456' (non-numeric).
For CI/CD pipelines, mock the TaxID API response rather than making real API calls in automated tests. Real API calls in tests consume your monthly quota, are non-deterministic (VIES can be slow or unavailable during a test run), and add latency to your test suite. The Vitest mock pattern from the Node.js VAT validation tutorial works well for German-specific tests — just include DE as the country_code in your mock responses.
For manual testing against the live API during development, use the official BZST-registered test number DE115235681 (Bundeszentralamt für Steuern itself) — it is a real, stable, active German VAT number that will always return a valid active response from VIES. This is documented in the TaxID API docs. For testing the inactive path, you need to find a deregistered number — the VIES web interface at ec.europa.eu/taxation_customs/vies can be used manually to identify numbers that return inactive status for specific countries.
German VAT validation is straightforward once you have the format right and BZST maintenance windows accounted for. The TaxID validate-vat/de page has the complete format reference, code examples in four languages, and the full FAQ specific to German validation. Use it as a reference alongside this guide when building your integration.
Germany is the EU's largest economy and often the first country a developer needs to support when building EU VAT compliance. The format is simple, the VIES endpoint is reliable, and the data quality (company name and address returned) is among the best in the EU. Once you have German validation working correctly, extending to the other 26 member states is mostly a matter of handling the format variations — all of which are documented on the individual validate-vat country pages.
Related pages on taxid.dev
Format reference, code examples, and FAQ specific to Germany
Current standard (19%) and reduced (7%) rates via API
All 27 EU member states, VIES architecture, and compliance guide
Handling BZST maintenance windows without blocking checkouts
End-to-end B2B vs B2C billing implementation
Start validating EU VAT numbers
Free plan — 100 validations/month. No credit card required.