# VIES EU VAT Batch Validator + Audit Evidence (`burly_bat/vies-eu-vat-batch-validator`) Actor

Batch-validate EU VAT numbers via the official European Commission VIES REST API. Returns VALID / INVALID / retry status, the VIES consultation number and a snapshot date as audit evidence for intra-EU B2B (reverse charge / WDT).

- **URL**: https://apify.com/burly\_bat/vies-eu-vat-batch-validator.md
- **Developed by:** [Burly Bat](https://apify.com/burly_bat) (community)
- **Categories:** Developer tools, Automation, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## VIES EU VAT Batch Validator + Audit Evidence

Batch-validate EU VAT numbers against the official European Commission **VIES**
(VAT Information Exchange System) REST API, and export **due-diligence evidence** for
intra-EU B2B: the VIES **consultation number** plus a **snapshot date** ("valid on
date X"). Built for accounting, compliance, ERP/e-commerce integrators and exporters
who want to document that a counterparty's VAT number was checked before applying 0%
intra-community supply (WDT) or reverse charge.

This is an independent tool, **not affiliated with or endorsed by the European
Commission**.

Ręczne sprawdzanie na stronie VIES robi się jeden numer na raz i bez trwałego dowodu.
Ten Actor robi to wsadowo i zwraca trwały materiał dowodowy.

### Two modes

- **validate** - one-off batch check of a supplier / customer list.
- **monitor** - scheduled re-validation of a saved contractor list (run it on an
  Apify Schedule); a status flip to `INVALID` means a partner is no longer an active
  EU VAT payer - a direct risk signal for purchasing / accounting.

### Input

```json
{
  "verificationDate": "2026-07-03",
  "mode": "validate",
  "requesterVatNumber": "PL5260001246",
  "maxChecks": 200,
  "requestDelayMs": 400,
  "records": [
    { "reference": "invoice-001", "vatNumber": "PL5260001246" },
    { "reference": "invoice-002", "countryCode": "DE", "number": "811569869" }
  ]
}
````

- Each record takes either a full `vatNumber` (with country prefix) or a
  `countryCode` + `number` pair. `rowId` / `reference` are optional and echoed back.
- `requesterVatNumber` (optional): **your own valid EU VAT number**. When present,
  VIES returns a **consultation number** (`requestIdentifier`) as proof you checked
  the counterparty. Without it, you still get VALID/INVALID but no consultation number.
- `useTestService: true` routes to the VIES test endpoint (demo numbers, safe for
  smoke tests). `sourceMode: "offline"` uses local fixtures (no network).

### Output

One dataset item per VAT number:

- `status` - `VALID` / `INVALID` / `UNAVAILABLE_RETRY`
- `countryCode`, `vatNumber`
- `name`, `address` - when the member state exposes them (else `null`)
- `requestIdentifier` - VIES consultation number, or `null`
- `checkedOn` - your snapshot date (audit evidence)
- `requestDate` - timestamp returned by VIES
- `valid`, `mode`, `source`, `sourceMethod`, `viesUserError`, `error`

Only resolved records (`VALID` / `INVALID`) are written to the **default dataset**.
Records VIES could not resolve go to a separate **`unresolved`** dataset:

- `UNAVAILABLE_RETRY` - member-state database down, timeout, or rate limit. Retried
  with exponential backoff; if still unresolved, re-run just those rows.
- `INVALID_INPUT` - VIES rejected the request format (e.g. malformed number).

This split means pay-per-event billing only ever covers resolved checks - you are
never charged for a VIES outage or a malformed input.

### Source, limits and throttling

Official source: `https://ec.europa.eu/taxation_customs/vies/`. VIES rate limits are
undisclosed and enforced by blocking floods, so this Actor sends requests sequentially
with a configurable delay and backoff. See `docs/source_and_limits.md`.

### Related Actor

Complementary to **Polish VAT Whitelist & Bank Account Validator** (checks the Polish
domestic bank account / Biała Lista): that one validates the domestic PL bank account,
this one validates cross-border **EU VAT status**.

### Disclaimer

This Actor is **not** an official service of the European Commission and does **not**
provide tax or legal advice. It calls the public VIES REST API and returns its
response for automation convenience.

The consultation number and snapshot are **due-diligence documentation - they do NOT
constitute a guarantee of acceptance by any tax authority or a defence in a tax
audit.** Treatment of VIES evidence is decided by the competent authority under
applicable national law. Always keep the returned consultation number and snapshot
for your own records and consult a tax advisor for your specific case.

# Actor input Schema

## `records` (type: `array`):

Each record needs a full EU VAT number (e.g. "PL5260001246") or a countryCode + number pair. Optional rowId/reference are echoed back for mapping.

## `verificationDate` (type: `string`):

Date recorded as the audit snapshot ("valid on date X") in YYYY-MM-DD. Defaults to today. VIES always answers for the current day.

## `mode` (type: `string`):

validate = one-off batch check. monitor = scheduled re-validation of a contractor list (same checks, monitoring framing).

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

Optional. Your own valid EU VAT number (e.g. "PL5260001246"). When provided, VIES returns a consultation number (requestIdentifier) as proof you checked the counterparty.

## `maxChecks` (type: `integer`):

Hard cap on records validated in one run.

## `requestDelayMs` (type: `integer`):

Gentle throttling between VIES requests. VIES has undisclosed, strict rate limits and blocks floods. Keep this conservative.

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

Retry attempts with exponential backoff for UNAVAILABLE\_RETRY outcomes (MS\_UNAVAILABLE / SERVICE\_UNAVAILABLE / TIMEOUT / concurrency limits).

## `useTestService` (type: `boolean`):

Route checks to the VIES test endpoint (special demo numbers, e.g. 100 = valid, 200 = invalid). Use for safe smoke tests without hitting real data / rate limits.

## `sourceMode` (type: `string`):

Use offline for local fixture-based checks (no network).

## Actor input object example

```json
{
  "records": [
    {
      "reference": "invoice-001",
      "vatNumber": "PL5260001246"
    },
    {
      "reference": "invoice-002",
      "countryCode": "DE",
      "number": "811569869"
    }
  ],
  "mode": "validate",
  "requesterVatNumber": "",
  "maxChecks": 200,
  "requestDelayMs": 400,
  "maxRetries": 3,
  "useTestService": false,
  "sourceMode": "live"
}
```

# Actor output Schema

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

Default dataset: only records VIES resolved as VALID or INVALID. Each item has country code, VAT number, name/address if VIES returns them, consultation number (requestIdentifier), snapshot date and VIES request date. Unresolved records (VIES outage / rate limit / malformed input) are NOT written here, so pay-per-event never bills for them.

## `summary` (type: `string`):

Run summary stored in the default key-value store under the OUTPUT key, incl. resolved vs unresolved counts. Unresolved records live in the named 'unresolved' dataset.

# 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 = {
    "records": [
        {
            "reference": "invoice-001",
            "vatNumber": "PL5260001246"
        },
        {
            "reference": "invoice-002",
            "countryCode": "DE",
            "number": "811569869"
        }
    ],
    "requesterVatNumber": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("burly_bat/vies-eu-vat-batch-validator").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 = {
    "records": [
        {
            "reference": "invoice-001",
            "vatNumber": "PL5260001246",
        },
        {
            "reference": "invoice-002",
            "countryCode": "DE",
            "number": "811569869",
        },
    ],
    "requesterVatNumber": "",
}

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

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

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

```

## CLI example

```bash
echo '{
  "records": [
    {
      "reference": "invoice-001",
      "vatNumber": "PL5260001246"
    },
    {
      "reference": "invoice-002",
      "countryCode": "DE",
      "number": "811569869"
    }
  ],
  "requesterVatNumber": ""
}' |
apify call burly_bat/vies-eu-vat-batch-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=burly_bat/vies-eu-vat-batch-validator",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "VIES EU VAT Batch Validator + Audit Evidence",
        "description": "Batch-validate EU VAT numbers via the official European Commission VIES REST API. Returns VALID / INVALID / retry status, the VIES consultation number and a snapshot date as audit evidence for intra-EU B2B (reverse charge / WDT).",
        "version": "0.1",
        "x-build-id": "mK0NluAVkNRCed4Rr"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/burly_bat~vies-eu-vat-batch-validator/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-burly_bat-vies-eu-vat-batch-validator",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/burly_bat~vies-eu-vat-batch-validator/runs": {
            "post": {
                "operationId": "runs-sync-burly_bat-vies-eu-vat-batch-validator",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/burly_bat~vies-eu-vat-batch-validator/run-sync": {
            "post": {
                "operationId": "run-sync-burly_bat-vies-eu-vat-batch-validator",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "records"
                ],
                "properties": {
                    "records": {
                        "title": "VAT numbers to validate",
                        "type": "array",
                        "description": "Each record needs a full EU VAT number (e.g. \"PL5260001246\") or a countryCode + number pair. Optional rowId/reference are echoed back for mapping."
                    },
                    "verificationDate": {
                        "title": "Verification (snapshot) date",
                        "type": "string",
                        "description": "Date recorded as the audit snapshot (\"valid on date X\") in YYYY-MM-DD. Defaults to today. VIES always answers for the current day."
                    },
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "validate",
                            "monitor"
                        ],
                        "type": "string",
                        "description": "validate = one-off batch check. monitor = scheduled re-validation of a contractor list (same checks, monitoring framing).",
                        "default": "validate"
                    },
                    "requesterVatNumber": {
                        "title": "Your EU VAT number (for consultation number)",
                        "type": "string",
                        "description": "Optional. Your own valid EU VAT number (e.g. \"PL5260001246\"). When provided, VIES returns a consultation number (requestIdentifier) as proof you checked the counterparty.",
                        "default": ""
                    },
                    "maxChecks": {
                        "title": "Maximum checks",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Hard cap on records validated in one run.",
                        "default": 200
                    },
                    "requestDelayMs": {
                        "title": "Delay between requests (ms)",
                        "minimum": 0,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Gentle throttling between VIES requests. VIES has undisclosed, strict rate limits and blocks floods. Keep this conservative.",
                        "default": 400
                    },
                    "maxRetries": {
                        "title": "Retries for temporary failures",
                        "minimum": 0,
                        "maximum": 8,
                        "type": "integer",
                        "description": "Retry attempts with exponential backoff for UNAVAILABLE_RETRY outcomes (MS_UNAVAILABLE / SERVICE_UNAVAILABLE / TIMEOUT / concurrency limits).",
                        "default": 3
                    },
                    "useTestService": {
                        "title": "Use VIES test service",
                        "type": "boolean",
                        "description": "Route checks to the VIES test endpoint (special demo numbers, e.g. 100 = valid, 200 = invalid). Use for safe smoke tests without hitting real data / rate limits.",
                        "default": false
                    },
                    "sourceMode": {
                        "title": "Source mode",
                        "enum": [
                            "live",
                            "offline"
                        ],
                        "type": "string",
                        "description": "Use offline for local fixture-based checks (no network).",
                        "default": "live"
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
