VIES API — EU VAT Validation for Developers
Built for developers integrating EU VAT validation into ERPs, e-commerce platforms, accounting systems and invoicing software. Designed around the realities of the official VIES service: rate limits, MS_UNAVAILABLE errors and the legal value of consultation IDs.
Why use our API instead of the official EU SOAP service
The official EU VIES SOAP/REST endpoint is free and publicly available — you can use it directly. But for production systems you'll want: retry logic for the frequent MS_UNAVAILABLE responses (15–60 min outages of specific country registries), result caching to respect EU's soft rate limit (~10 queries/second), batch endpoints to verify hundreds of numbers in one call, webhooks for status change alerts, ready-made SDKs, and 7-year archival of consultation IDs for audit purposes. Building all that in-house typically costs more than our paid plans.
Endpoints
Main endpoint: <code>GET /api/v1/check?country=DE&vat=123456789</code>. Authentication via Bearer token in the Authorization header. Response: JSON with fields valid (boolean), name (string), address (string), requestDate (ISO 8601), consultationNumber (string), countryCode (string), latencyMs (number). For batch validation: <code>POST /api/v1/batch</code> with an array of up to 1,000 VAT numbers. Result delivered via webhook callback or polling on <code>GET /api/v1/batch/{batchId}</code>. Sandbox endpoint <code>/api/v1/sandbox/check</code> returns deterministic test data without consuming VIES quota.
Authentication and keys
Get your API key from the customer panel after registration. The key is a long opaque string (do not embed in client-side code). Send it as <code>Authorization: Bearer YOUR_KEY</code>. Each key can be scoped to specific environments (production, staging) and projects, with separate quotas. Rotate keys via the panel — old keys stay valid for 24 hours after rotation to allow zero-downtime deployment. Suspected key leaks — immediate revocation via panel button.
Error handling and retries
We classify errors into recoverable and permanent. Recoverable: MS_UNAVAILABLE (target country registry down) and TIMEOUT — handled automatically by our infrastructure with exponential backoff (1 min, 5 min, 30 min). You get the final result via webhook or you can poll. Permanent: INVALID_INPUT (bad format) and VAT_BLOCKED (number blocked by EU anti-fraud system) — returned immediately, no retry. Recommendation: always implement timeout in your client (10 seconds), handle 503 (recoverable) and 400 (permanent) distinctly.
Rate limits and quotas
Plan limits: Free 100 queries/month, Pro 10,000/month, Business unlimited within fair-use SLA, Enterprise custom. Within plan: maximum 10 queries/second per key (we throttle to respect EU's soft limit). Batch endpoint counts each VAT in batch as one query against quota. Overage on Pro and Business: 0.005 EUR per query above quota, billed monthly. No overage on Free — extra queries return 429 (Too Many Requests).
SDKs and libraries
Official SDKs maintained on our GitHub: PHP (Composer: viesvat/php-sdk, compatible with Laravel and Symfony), Python (PyPI: viesvat, async client based on aiohttp), Node.js (npm: @viesvat/sdk, TypeScript types included), .NET (NuGet: ViesVAT.Sdk, .NET 6+), Java (Maven Central: pl.viesvat:sdk, Java 11+). All SDKs implement automatic retry, response caching (24h per EU recommendation), and helper methods for common patterns (e.g. validateBeforeInvoice that throws if VAT is not active).
Webhooks
Configure webhook URLs in the customer panel. Three event types: <code>statusChanged</code> (one of your tracked customers' VAT became invalid — sent daily based on automated re-checks), <code>batchCompleted</code> (a POST /batch finished), and <code>registryDown</code> (a country registry your customers are in went down — sent within 5 minutes of detection). Webhooks include HMAC-SHA256 signature for verification. Delivery retry: 1 min, 5 min, 30 min, 2 h, then dead-letter queue you can inspect in panel.
GDPR and data handling
We process only the data required to perform the VIES query: country code, VAT number, optional requester ID for qualified consultations. Results stored according to plan retention. Servers exclusively in EU (Frankfurt, Warsaw). DPA available on request, GDPR-compliant by default. We never share data with third parties except the EU VIES service itself (which is the entire purpose of the query). Right to erasure honored within 30 days, except for legally-required retention of accounting records.
API versioning and stability guarantees
Our REST API uses semantic versioning: major.minor.patch. Current stable version: v1. Endpoints under /api/v1/* are guaranteed stable until at least 2030. New features will go into v2 (planned 2027) with at least 24 months of v1 deprecation notice before any v1 endpoint is removed. Breaking changes within v1 are forbidden — we only add new optional fields, new endpoints, new query parameters. SDK versioning follows the API: SDK v1.x supports API v1.x. SDK v2.x will support API v2.x. We provide deprecation warnings in API responses (X-Deprecation header) at least 6 months before any non-breaking removals. Production SLA covers v1 endpoints; preview features (under /api/preview/*) may change without notice and have no SLA. For customers building long-term integrations: pin to a specific minor version in your SDK requirements to guarantee no surprises. For agile teams: track latest minor versions for new features (we don't break existing functionality).
Webhook signatures and replay protection
All webhooks include an X-Signature header with HMAC-SHA256 of the request body, computed using your webhook secret (configured in customer portal, separate from API key). Verification example in PHP: $expected = hash_hmac('sha256', file_get_contents('php://input'), $webhook_secret); if (hash_equals($expected, $_SERVER['HTTP_X_SIGNATURE'])) { /* valid */ }. Python: hmac.new(secret.encode(), body, hashlib.sha256).hexdigest(). Node.js: crypto.createHmac('sha256', secret).update(body).digest('hex'). Replay protection: every webhook includes X-Timestamp header (Unix seconds) and X-Idempotency-Key (UUID v4). Reject webhooks where timestamp is more than 5 minutes old. Deduplicate by idempotency key (store last 7 days of received keys). These protections together prevent attacker replay and ensure exactly-once processing. Our webhook retry policy: 1 min, 5 min, 30 min, 2h, 6h. After 5 failures, the webhook moves to your dead-letter queue (visible in customer portal). You can manually retry from there.
Performance benchmarks — real numbers
Production performance metrics (measured October 2025 across 5 million requests): p50 latency 800ms (median request), p95 3.0s, p99 8.0s. Cache hit performance: p50 50ms (40× faster than uncached). Cache hit ratio: 65% for typical customer with stable contractor base. Throughput: 1000 requests/second sustained across our infrastructure; bursts to 5000 req/s tolerated. Per-key rate limit: 10 req/s (configurable up to 50 req/s on Business plan). Concurrent batch jobs: 5 simultaneous batches of 1000 numbers (configurable up). Geographic performance: Frankfurt-hosted requests p50 600ms, US-East requests p50 950ms (transatlantic latency), Asia-Pacific p50 1200ms. We recommend US/Asia customers to use our CDN endpoints (Cloudflare Workers) for cached responses — p50 drops to 200ms globally. Status page (status.viesvat.com) shows current performance metrics in real time, updated every 30 seconds.
Error code reference — production error handling
Comprehensive error code reference for the REST API. HTTP 200 with valid:true means a successful verification with a valid VAT number. HTTP 200 with valid:false means a successful query that returned an invalid VAT number (this is a normal business result, not a technical error). HTTP 400 INVALID_INPUT means the request was malformed (wrong country code format, missing required field). HTTP 400 INVALID_REQUESTER_INFO means your own VAT number provided as requester is invalid or inactive. HTTP 401 UNAUTHORIZED means your API key is missing or invalid. HTTP 403 FORBIDDEN means your plan does not support this endpoint (e.g., batch on Free plan). HTTP 429 TOO_MANY_REQUESTS means you've exceeded the rate limit or monthly quota. HTTP 503 MS_UNAVAILABLE means the destination country's tax registry is temporarily down (typically Germany, Italy, or Spain). HTTP 503 SERVICE_UNAVAILABLE means our service itself is down (rare; see status page). HTTP 504 GATEWAY_TIMEOUT means the upstream EU VIES service timed out (>30 seconds). For each error code, the response body includes details: error.code (string), error.message (human-readable), error.retry_after (seconds, for 429 and 503), error.documentation_url (link to relevant docs). Best practice: implement retry with exponential backoff for 503 and 504; immediately fail (no retry) for 400, 401, 403; respect retry_after for 429.
Migration guide from official EU VIES SOAP
If you're currently using the official EU VIES SOAP service directly and considering migration to ViesVAT REST, here's a comprehensive guide. Step 1: register at viesvat.com, obtain your API key (svies_pk_...). Step 2: update your endpoint from https://ec.europa.eu/taxation_customs/vies/services/checkVatService to https://api.viesvat.com/v1/check. Step 3: replace SOAP envelope with simple GET request. SOAP request body had countryCode, vatNumber, requesterCountryCode, requesterVatNumber. REST equivalent: GET /api/v1/check?country=DE&vat=123456789. Authentication: add Authorization: Bearer svies_pk_... header. Step 4: parse JSON response (we return same fields as SOAP but in JSON: valid, name, address, requestDate, consultationNumber). Step 5: update error handling. SOAP returned SoapFault with faultstring; REST returns HTTP status codes with JSON error body. Step 6: leverage features official SOAP doesn't have: automatic retry, 24h caching, batch endpoints, webhooks. Average migration time: 1-2 developer days. Our SDK in your language can reduce this to a few hours — replace import vies-soap-php with composer require viesvat/sdk and rewrite ~20 lines. Migration support: free 1-hour consultation with our developer for any paying plan, included in Business plan onboarding.
Batch validation — patterns and limits
Batch endpoints let you validate up to 1000 VAT numbers in a single request, asynchronously. POST /api/v1/batch with a JSON body containing an array of {country, vat} objects returns immediately with a batchId. The actual validation runs in the background; results delivered via webhook (configured in customer portal) or polled via GET /api/v1/batch/{batchId}. Typical batch processing time: 30-90 seconds for 1000 numbers, depending on country distribution (more German numbers = slower due to BZSt delays). Rate limits for batch: 5 concurrent batches per API key, configurable up to 20 on Business plan. Each batch counts each VAT number as one quota query. Common use cases: monthly recheck of your contractor base (10K-100K numbers), one-time database migration cleanup, audit preparation. For very large datasets (>10K numbers), we recommend splitting into multiple batches and using webhook notifications to coordinate processing. Sample PHP code: $batch = $client->batchSubmit([['country' => 'DE', 'vat' => '123456789'], ...]); $client->onBatchComplete($batch->id, function($results) { foreach ($results as $r) { /* process */ } });.
Self-hosted deployment for enterprise customers
Enterprise plan customers can deploy ViesVAT on their own infrastructure (on-premise or private cloud) for maximum data sovereignty and compliance. Deployment options: Docker Compose for small deployments (single VM, up to 100K verifications/day), Kubernetes (Helm chart) for production-scale, Terraform modules for AWS/Azure/GCP. Self-hosted version includes: full API REST and SOAP gateway, caching layer (Redis), database (PostgreSQL), background workers for retry handling, monitoring (Prometheus + Grafana), all SDKs. Customer responsibilities: infrastructure provisioning and maintenance, OS patching, SSL certificates, network configuration. Our responsibilities: software updates (monthly releases), security patches (within 24h of CVE disclosure), 24/7 incident response, dedicated TAM (Technical Account Manager). Customer infrastructure must meet minimum specs: 4 vCPU, 16GB RAM, 100GB SSD per node; minimum 3 nodes for HA. Typical deployment time: 1-2 weeks including testing. Pricing: from 4,999 EUR/month plus your infrastructure costs. Bank and government customers favor this deployment model due to strict data residency requirements.
Frequently Asked Questions
Do I need a paid plan to test the API?
No — Free plan gives 100 queries/month and full SDK access. The sandbox endpoint returns test data without consuming quota and lets you build integrations end-to-end before paying.
How does pricing scale?
Free: 0 EUR. Pro: 49 EUR/month for 10,000 queries + webhooks + SLA 99.5%. Business: 199 EUR/month, unlimited queries within fair use + SLA 99.9% + dedicated support. Enterprise: from 999 EUR/month, custom SLA, on-premise option, dedicated account manager. Annual billing -15%.
Which language SDK should I use?
Pick the one matching your stack. All SDKs are feature-equivalent. PHP and Python see the most use among our customers (accounting and e-commerce sectors). For high-throughput integrations, Node.js and Java offer better concurrency.
Can I host the API on-premise?
Yes — Enterprise plan includes on-premise option. We deliver Docker images that run in your infrastructure, with optional pass-through to our cloud for failover. Pricing custom per scale.
Is there a status page?
Yes — status.viesvat.com shows real-time service status, recent incidents, and (importantly) status of the underlying EU VIES service per country. Subscribe to incident notifications by email or RSS.
How fast are queries?
p50 latency: 800ms (cached results 50ms). p95: 3 seconds. p99: 8 seconds (when the underlying country registry is slow). Batch endpoints process up to 1,000 numbers in 30–60 seconds depending on country distribution.