Package Exports
- evatr-api
- evatr-api/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (evatr-api) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme

evatr-api
Checks a VAT-ID using the eVatR REST-API of the German Federal Central Tax Office (Bundeszentralamt für Steuern, BZSt)
[!CAUTION] This package is in early development and is not yet ready for production use. It is currently being tested and may undergo significant changes.
[!IMPORTANT] This is an unofficial wrapper for the eVatR API. For official documentation and terms of use, please refer to the German Federal Central Tax Office (BZSt) website.
[!NOTE] This package uses the new REST-API released in July 2025. The old XML-RPC API is being discontinued and will be sunset on November 30th, 2025 (based on information from BZSt-Newsletter USTKV 01/2025 dated July 1st, 2025).
Installation
You can install the package via npm:
npm install evatr-apiQuick Start
import { EvatrClient } from 'evatr-api';
const client = new EvatrClient();
// Simple validation (only checks if VAT-ID is valid)
const result = await client.validateSimple({
vatIdOwn: 'DE123456789',
vatIdForeign: 'ATU12345678'
});
console.log(result);or
// Qualified validation with company data
const result = await client.validateQualified({
vatIdOwn: 'DE123456789',
vatIdForeign: 'ATU12345678',
company: 'Musterhaus GmbH & Co KG',
location: 'musterort'
});
console.log(result);[!TIP] You might want to take a look at some examples.
Status Codes
The API returns various status codes. You can check the status using the client methods:
const result = await client.validateSimple({ /* ... */ });
client.isSuccessStatus(result.status); // true for valid VAT-IDs
client.isErrorStatus(result.status); // true for errors
client.isWarningStatus(result.status); // true for warnings
// Get human-readable message
const message = client.getStatusMessage(result.status);
console.log(message?.message); // Message in GermanAPI Reference
Constructor
const client = new EvatrClient(config?: EvatrClientConfig);Configuration Options:
timeout?: number- Request timeout in milliseconds (default: 30000 ms; = 30 s)headers?: Record<string, string>- Custom headers to include with requests
Methods
Simple Validation
Validates only the VAT-ID without company data verification:
await client.validateSimple({
vatIdOwn: 'DE123456789', // Your German VAT-ID (required)
vatIdForeign: 'ATU12345678', // VAT-ID to validate (required)
includeRaw: true, // Include raw response (optional)
});Qualified Validation
Validates VAT-ID and verifies company data:
await client.validateQualified({
vatIdOwn: 'DE123456789', // Your German VAT-ID (required)
vatIdForeign: 'ATU12345678', // VAT-ID to validate (required)
company: 'Musterhaus GmbH & Co KG', // Company name (required)
location: 'musterort', // City (required)
street: 'Musterstrasse 22', // Street address (optional)
zip: '12345', // Postal code (optional)
includeRaw: true, // Include raw response (optional)
});[!TIP] You may set
trueas the second parameter to get anExtendedResponseobject.
Utility Methods
// Get status messages
const statusMessages = await client.getStatusMessages();
// Get availability map by EU member state (alpha-2 code -> boolean)
const availability = await client.getAvailability();
const isGermanyAvailable = availability.DE === true;
// Get content of specific status message
const message = client.getStatusMessage('evatr-0000');
// Check status types
client.isSuccessStatus('evatr-0000'); // true
client.isErrorStatus('evatr-0004'); // true
client.isWarningStatus('evatr-2002'); // trueRequest
The API uses German terms, which have been mapped to the following English parameters:
| BZSt API | evatr-api |
|---|---|
| anfragendeUstid | vatIdOwn |
| angefragteUstid | vatIdForeign |
| firmenname | company |
| ort | location |
| strasse | street |
| plz | zip |
Response
All validation methods return a Response object by default:
interface Response {
id: string; // Technical request ID returned by the API, related to the request
timestamp: string; // Query timestamp (ISO string)
status: string; // Status code (e.g., "evatr-0000")
vatIdOwn: string; // Normalized own VAT-ID used for API request
vatIdForeign: string; // Normalized foreign VAT-ID used for API request
validFrom?: string; // Valid from date (ISO string)
validTill?: string; // Valid until date (ISO string)
company?: QualifiedResultCode; // Company name validation result
street?: QualifiedResultCode; // Street validation result
zip?: QualifiedResultCode; // ZIP code validation result
location?: QualifiedResultCode; // Location validation result
raw?: string; // Raw response from API (only if includeRaw is true)
}The API uses German terms, which have been mapped to the following English parameters:
| BZSt API | evatr-api |
|---|---|
| id | id |
| anfrageZeitpunkt | timestamp |
| status | status |
| gueltigAb | validFrom |
| gueltigBis | validTill |
| ergFirmenname | company |
| ergStrasse | street |
| ergPlz | zip |
| ergOrt | location |
Extended Response
By passing true as the second parameter to function validateSimple({...}, true) or validateQualified({...}, true) an ExtendedResponse object is returned. It maps date strings to Date objects, adds convenience fields valid and message, and provides a timestamp object with both the original string and a parsed Date:
interface ExtendedResponse {
id: string; // Technical request ID returned by the API, related to the request
timestamp: Timestamp; // Timestamp object with original string and Date object
valid: boolean; // true if isSuccessStatus()
status: string;
message?: string; // German description for the status
vatIdOwn: string; // Normalized own VAT-ID used for API request
vatIdForeign: string; // Normalized foreign VAT-ID used for API request
validFrom?: Date; // Date object
validTill?: Date; // Date object
company?: QualifiedResultCode;
street?: QualifiedResultCode;
zip?: QualifiedResultCode;
location?: QualifiedResultCode;
raw?: string;
}Validation Results (Qualified Validation)
For qualified validation, the response includes validation results for each field:
- A - Data matches registered information
- B - Data does not match registered information
- C - Data was not requested
- D - Data not provided by the EU member state
Utility Functions
The library includes helpful utility functions via EvatrUtils:
import { EvatrUtils } from 'evatr-api';
// Validate VAT-ID format
EvatrUtils.checkVatIdSyntaxForCountry('DE123456789', 'DE'); // true
// Get country information
EvatrUtils.getCountryName('DE'); // 'Germany'
EvatrUtils.isEUMemberState('DE'); // true
// Check validation capability
EvatrUtils.canValidate('DE123456789', 'ATU12345678'); // true
EvatrUtils.canValidate('DE123456789', 'DE987654321'); // false (can't validate DE->DE)
// Get test VAT-IDs for development
const testIds = EvatrUtils.getTestVatIds();Migration Helper (Backward Compatibility)
For users migrating from the evatr library, we provide a migration helper that maintains API compatibility.
[!IMPORTANT] The migration helper was introduced because the German Federal Central Tax Office is sunsetting the XML-RPC API on November 30th, 2025. This helper allows existing code to work with minimal changes while using the new REST API under the hood.
Why the Migration Helper?
The new REST API has several differences from the XML-RPC API:
- JSON responses instead of XML
- Different parameter names
- Different response structure
- Different error codes and messages
- There is no standard yet on English naming conventions for request and response parameters in context of VAT-ID validation
Usage
import { EvatrMigrationHelper as evatr } from 'evatr-api';
// Simple validation (matches original evatr API)
const result = await evatr.checkSimple({
ownVatNumber: 'DE123456789',
validateVatNumber: 'ATU12345678'
});
// Qualified validation (matches original evatr API)
const qualifiedResult = await evatr.checkQualified({
ownVatNumber: 'DE123456789',
validateVatNumber: 'ATU12345678',
companyName: 'Musterhaus GmbH & Co KG',
street: 'Musterstrasse 22',
zip: '12345',
city: 'musterort',
});Breaking Changes
While the migration helper tries to maintain API compatibility, there are some unavoidable breaking changes:
| Change | evatr | evatr-api |
|---|---|---|
| Raw data parameter | includeRawXml |
includeRaw |
| Raw data response | rawXml (XML string) |
raw (JSON string) |
| Error codes | XML-RPC specific codes | Mapped to legacy codes (best effort) |
| Error descriptions | Based on error code | Based on REST API status messages |
| Additional field | - | status (new REST API status code) |
[!NOTE] API status codes have been mapped to legacy codes to the best of our knowledge. If an API status does not correspond to a legacy code, the 999 legacy code is being returned. We recommend to relay on API status.
[!TIP] See the migration helper example for a complete usage demonstration.
Mapping
The following tables show the parameter naming mapping between evatr and evatr-api:
Request
| evatr | evatr-api |
|---|---|
ownVatNumber |
vatIdOwn |
validateVatNumber |
vatIdForeign |
companyName |
company |
city |
location |
street |
street |
zip |
zip |
includeRaw |
includeRaw |
Response
| evatr | evatr-api |
|---|---|
raw (XML) |
raw (JSON) |
date |
timestamp {0, 10} (format YYYY-MM-DD) |
time |
timestamp {11, 8} (format HH:MM:SS) |
errorCode |
- (replaced by status) |
errorDescription |
- (use getStatusMessage() or message in ExtendedResponse) |
| - (exists in migration helper) | status |
ownVatNumber |
vatIdOwn |
validatedVatNumber |
vatIdForeign |
validFrom |
validFrom |
validTill |
validTill |
valid |
valid |
resultName |
company |
resultCity |
location |
resultStreet |
street |
resultZip |
zip |
resultNameDescription |
- (use explainQualifiedResultCode()) |
resultCityDescription |
- (use explainQualifiedResultCode()) |
resultStreetDescription |
- (use explainQualifiedResultCode()) |
resultZipDescription |
- (use explainQualifiedResultCode()) |
Error Handling
The library throws EvatrApiError for API-related errors:
try {
const result = await client.validateSimple({
anfragendeUstid: 'DE123456789',
angefragteUstid: 'INVALID'
});
} catch (error) {
if (error.name === 'EvatrApiError') {
console.log('Status:', error.status);
console.log('HTTP Code:', error.http);
console.log('Field:', error.field);
console.log('Message:', error.message);
}
}API Updates
The library includes utilities to check for API updates:
# Check for all updates
npm run update:api check
# Check only API documentation
npm run update:api api-docs
# Check only status messages
npm run update:api status-messagesUpdate Workflow
- Check for updates: Run
npm run update:api checkto see if there are new versions - Inspect output: Status message changes are displayed with added, removed, and modified messages
- Compare differences: Compare current file with updated versions using for example
diff, New files are saved with timestamps (e.g.,statusmeldungen-2025-08-01.json) - Update constants: Update the TypeScript constants file with new messages:
npm run update:api update-constants ./docs/statusmeldungen-2025-08-01.jsonRate Limits and Best Practices
- The BZSt API has rate limits for qualified validation requests
- Add delays between requests when validating multiple VAT-IDs
- Cache results when possible to avoid unnecessary API calls (for example for 12 hours)
- Handle errors gracefully and provide meaningful feedback to users
Testing
npm testDummy data
The library includes test VAT-IDs and information that can be used for testing. These are official test VAT-IDs provided by the API documentation:
const testRequest = {
anfragendeUstid: 'DE123456789',
angefragteUstid: 'ATU12345678',
};
const qualifiedTestRequest = {
anfragendeUstid: 'DE123456789',
angefragteUstid: 'ATU12345678',
firmenname: 'Musterhaus GmbH & Co KG',
strasse: 'Musterstrasse 22',
plz: '12345',
ort: 'musterort',
};Changelog
Please see Release Notes for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
If you discover any security-related issues, please email open-source@rechtlogisch.de instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.