# EU VIES VAT & Company Registry Bulk Verifier (MCP-Ready) (`creatortsv/eu-vies-vat-bulk-validator-mcp`) Actor

Bulk EU + Northern Ireland (XI) VAT number validator and company address extractor powered by the official European Commission VIES REST API with automatic SOAP 1.1 XML fallback.

- **URL**: https://apify.com/creatortsv/eu-vies-vat-bulk-validator-mcp.md
- **Developed by:** [Vladimir Tsaplin](https://apify.com/creatortsv) (community)
- **Categories:** Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## EU VIES VAT & Company Registry Bulk Verifier — Self-Healing Apify Actor & MCP Server (`eu-vies-vat-bulk-validator-mcp`)

```json
{
  "id": "vies:IE6388047V",
  "normalized_vat": "IE6388047V",
  "syntax_valid": true,
  "valid": true,
  "company_name": "GOOGLE IRELAND LIMITED",
  "parsed_address": {
    "street": "1ST & 2ND FLOOR, GORDON HOUSE, BARROW STREET",
    "postal_code": "DUBLIN 4",
    "city": "DUBLIN 4"
  },
  "consultation_number": "WAPIAAAAZ1B2C3D4",
  "healing_tiers": {"vies_lookup": "tier1_rest_json"},
  "ppe_event": "item_scraped"
}
```

**Keywords**: `eu-vies-vat-validator`, `vies-rest-soap-api`, `eu-reverse-charge-kyb`, `apify-mcp-server`, `bulk-vat-number-check`

***

### Why FinOps, ERP & Tax Compliance Teams Use This Actor (ROI vs. DIY)

When invoicing B2B customers across the European Union under the **EU VAT Reverse-Charge mechanism (Article 196 of Directive 2006/112/EC)**, finance teams must verify that every buyer's VAT identification number is actively valid in the European Commission VIES registry and retain the registered company name, address, and consultation identifier (`requestIdentifier`) for tax audit defense.

| Approach | Setup & Maintenance Effort | Member State Outage Resilience | MCP / AI Agent Ready | Cost Structure |
|---|---|---|---|---|
| **In-House Script (DIY)** | 16–24 hrs (REST + SOAP 1.1 XML parser + 28 regexes) | Breaks when REST gateway returns `503` or `MS_UNAVAILABLE` | Manual wrapper required | €800+ engineering setup |
| **Enterprise KYB Platforms** | Annual procurement & sales onboarding | High | Proprietary REST API | €400–€1,500/mo minimum |
| **This Actor (`eu-vies-vat-bulk-validator-mcp`)** | **0 hrs (Instant Apify API, CLI, or MCP)** | **3-Tier Self-Healing (Pre-flight Regex + REST + SOAP 1.1 Fallback)** | **Native JSON & MCP Schema** | **Pay-Per-Event (`item_scraped`)** |

***

### 30-Second Copy-Paste Quickstart

Validate a batch of EU + Northern Ireland (`XI`) VAT numbers directly from the CLI:

```bash
python3 workspaces/actors/eu-vies-vat-bulk-validator-mcp/main.py --vat "IE6388047V,SE556703748501,GR094014201"
```

Or run with an explicit JSON configuration payload (including optional requester VAT for official VIES consultation numbers):

```bash
python3 workspaces/actors/eu-vies-vat-bulk-validator-mcp/main.py --input-json '{"vatNumbers":["IE6388047V","SE556703748501"],"requesterCountryCode":"DE","requesterVatNumber":"DE123456789"}'
```

Run the zero-dependency unit and self-healing regression test suite:

```bash
python3 -m unittest discover -s workspaces/actors/eu-vies-vat-bulk-validator-mcp -p "test_*.py" -v
```

***

### 3-Tier Self-Healing VIES Verification Architecture

1. **Pre-Flight Normalization & 28-State Syntax Guard (`normalize_and_validate_vat_syntax`)**:
   - Strips spaces, dots, slashes, and hyphens from messy ERP/CRM exports.
   - Automatically maps Greece's ISO-3166 alpha-2 prefix (`GR`) to its mandatory VIES prefix (`EL`), and normalizes 9-digit Belgian numbers to 10-digit leading-zero format.
   - Validates against official regular expressions for all 27 EU Member States (`AT`, `BE`, `BG`, `CY`, `CZ`, `DE`, `DK`, `EE`, `EL`, `ES`, `FI`, `FR`, `HR`, `HU`, `IE`, `IT`, `LT`, `LU`, `LV`, `MT`, `NL`, `PL`, `PT`, `RO`, `SE`, `SI`, `SK`) plus Northern Ireland (`XI`).
   - Invalid syntax is rejected locally (`ppe_event: "syntax_rejected"`) in `<1ms` without wasting VIES rate limits or billing events.
2. **Tier 1 Primary — Official EC VIES REST API**:
   - Queries `POST https://ec.europa.eu/taxation_customs/vies/rest-api/check-vat-number` with exponential backoff on transient Member State concurrency limits (`MS_MAX_CONCURRENT_REQ`, `MS_UNAVAILABLE`).
3. **Tier 2 Fallback — Official EC VIES SOAP 1.1 XML Endpoint**:
   - If the VIES REST gateway returns HTTP `5xx` or an unparseable response, the Actor automatically constructs a standards-compliant SOAP 1.1 `<urn:checkVat>` (or `<urn:checkVatApprox>`) XML envelope and queries `POST https://ec.europa.eu/taxation_customs/vies/services/checkVatService`.
4. **Structured European Address Parser (`parse_vies_address`)**:
   - Splits multi-line VIES registry addresses into structured `street`, `postal_code`, `city`, and `raw_address` fields across continental, Irish, and Nordic postal formats.

***

### Input & Output Schema Reference

#### Input Parameters (`INPUT_SCHEMA.json`)

- `vatNumbers` *(array of strings, required)*: List of EU or `XI` VAT numbers to verify (e.g. `["IE6388047V", "SE556703748501"]`).
- `requesterCountryCode` *(string, optional)*: Two-letter VIES country code of your company to request an official consultation number (`requestIdentifier`).
- `requesterVatNumber` *(string, optional)*: Your company's VAT number for `checkVatApprox` audit trail generation.
- `maxRetries` *(integer, optional, default `3`)*: Maximum retry attempts per tier on transient Member State unavailability.

#### Output Record Fields

- `id`: Canonical identifier (`vies:<country_code><vat_number>`).
- `vat_input`: Raw input string supplied by the caller.
- `country_code`: Normalized 2-letter VIES jurisdiction code (`AT`..`SK`, `EL`, `XI`).
- `vat_number`: Normalized numeric/alphanumeric VAT body without prefix.
- `normalized_vat`: Combined canonical VAT number (`<country_code><vat_number>`).
- `syntax_valid`: Boolean indicating whether the number passed 28-prefix pre-flight regex validation.
- `valid`: Official VIES registry active status (`true` / `false`).
- `company_name`: Registered legal entity name returned by the national tax authority.
- `address`: Raw multi-line address returned by VIES.
- `parsed_address`: Structured object containing `street`, `postal_code`, `city`, and `raw_address`.
- `request_date`: Official timestamp of the VIES verification.
- `consultation_number`: Official VIES `requestIdentifier` when requester credentials are provided.
- `healing_tiers`: Audit map showing which tier (`tier1_rest_json`, `tier2_soap_xml`, or `preflight_syntax_guard`) resolved the query.
- `ppe_event`: `"item_scraped"` for verified records or `"syntax_rejected"` for malformed inputs.

***

### Scope & Compatibility (What's Included / What's Not Included)

- **What's Included**:
  - Zero-dependency Python 3.9+ Apify Actor (`main.py`) with 28-jurisdiction EU/XI regex pre-flight validation, official EC VIES REST Tier 1 client, and SOAP 1.1 XML Tier 2 fallback.
  - Structured multi-line European address parser (`street`, `postal_code`, `city`).
  - Apify Cloud Key-Value Store input loader, Dataset item pusher, `Dockerfile`, `.actor/actor.json`, and automated unit test suite (`test_actor.py`).
- **What's Not Included (Anti-Refund Warranty Boundary)**:
  - Does not override national tax authority databases that do not publicly disclose trader names/addresses via VIES (e.g., German `DE` or Spanish `ES` VIES endpoints return `valid: true/false` without trader name/address unless queried through national portals).
  - Does not verify non-EU VAT/GST numbers outside the 27 EU Member States + Northern Ireland (`XI`) (e.g., Great Britain `GB`, Switzerland `CHE`, Norway `NO` are not part of the EC VIES system and are rejected at the pre-flight syntax stage).
  - Does not constitute formal legal or tax advisory services; provided as an automated B2B data verification utility.

# Actor input Schema

## `vatNumbers` (type: `array`):

List of EU Member State or Northern Ireland (XI) VAT numbers to validate (e.g. IE6388047V, SE556703748501, DE123456789). Supports raw strings with spaces, dots, or hyphens and automatically maps GR to EL.

## `requesterCountryCode` (type: `string`):

Two-letter EU VIES country code of the requesting company (e.g. IE, DE, SE) to obtain an official VIES consultation number (requestIdentifier) for tax audit proof.

## `requesterVatNumber` (type: `string`):

VAT number of the requesting company (without country prefix) to generate an official VIES consultation identifier.

## `maxRetries` (type: `integer`):

Maximum retry attempts on transient VIES Member State errors (MS_UNAVAILABLE, MS_MAX_CONCURRENT_REQ, HTTP 503) before switching to Tier 2 SOAP fallback.

## `targetUrl` (type: `string`):

Official European Commission VIES REST endpoint

## `maxItems` (type: `integer`):

Maximum number of VAT numbers to verify in a single run

## Actor input object example

```json
{
  "vatNumbers": [
    "IE6388047V",
    "SE556703748501"
  ],
  "requesterCountryCode": "",
  "requesterVatNumber": "",
  "maxRetries": 3,
  "targetUrl": "https://ec.europa.eu/taxation_customs/vies/rest-api/check-vat-number",
  "maxItems": 1000
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset containing verified EU/XI VAT registration statuses, legal names, parsed addresses, and VIES consultation numbers.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "vatNumbers": [
        "IE6388047V",
        "SE556703748501"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("creatortsv/eu-vies-vat-bulk-validator-mcp").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "vatNumbers": [
        "IE6388047V",
        "SE556703748501",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("creatortsv/eu-vies-vat-bulk-validator-mcp").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "vatNumbers": [
    "IE6388047V",
    "SE556703748501"
  ]
}' |
apify call creatortsv/eu-vies-vat-bulk-validator-mcp --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,creatortsv/eu-vies-vat-bulk-validator-mcp"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/S76EdeNtz3rhFaqC5/builds/Qo4fvDmAvw76Yf7dZ/openapi.json
