# EU Invoice Extractor with VIES VAT Validation (`n1ckyta/eu-invoice-vat-extractor`) Actor

Extract validated data from EU invoices and receipts. Returns seller, buyer, VAT numbers, invoice number, dates, net/VAT/gross totals, IBAN and line items as JSON. Checks VAT against the official VIES registry, validates IBAN, OCRs scans. Never billed for a failure.

- **URL**: https://apify.com/n1ckyta/eu-invoice-vat-extractor.md
- **Developed by:** [Nikita Kubishkin](https://apify.com/n1ckyta) (community)
- **Categories:** Agents, MCP servers, Automation
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## EU Invoice Extractor with VIES VAT Validation

Turn EU invoices and receipts into **validated** structured JSON. Not just text extraction — every VAT number is checked against the official European Commission VIES registry, and every IBAN is verified with the mod-97 checksum.

Built for accounting automation, accounts-payable pipelines and AI agents that need to trust what comes out of a PDF.

### Why this Actor

Most document extractors hand you fields and leave you guessing whether they are real. This one tells you:

- Is this VAT number actually registered, and to whom?
- Does the registered company name match the name printed on the invoice?
- Is this IBAN a real IBAN, or OCR noise?
- Do net + VAT actually add up to the gross total?

That last check alone catches a large share of OCR errors before they reach your ledger.

### You are never billed for a failure

This is enforced in code, not promised in marketing copy:

| Situation | Billed? |
|---|---|
| Document parsed successfully | Yes |
| Download failed, file corrupt, password-protected | **No** |
| Document exceeded the timeout | **No** |
| No text could be extracted | **No** |
| VIES was down or rate-limited | **No** |
| VAT number was not an EU format | **No** |

Every run also writes a `SUMMARY` record to the key-value store with the actual success rate for that run.

### What you get per document

```json
{
  "status": "ok",
  "invoice_number": "INV-2026-0417",
  "issue_date": "2026-03-14",
  "due_date": "2026-03-28",
  "currency": "EUR",
  "total_net": 2450.00,
  "total_vat": 539.00,
  "total_gross": 2989.00,
  "vat_rate": 22.0,
  "totals_reconcile": true,
  "seller_name": "ACME Software OÜ",
  "seller_vat": "EE101584055",
  "seller_vat_valid": true,
  "seller_registered_address": "Tartu mnt 84a, 10112 Tallinn",
  "buyer_name": "Northwind Trading SIA",
  "buyer_vat": "LV40003032949",
  "buyer_vat_valid": true,
  "iban": "LV80BANK0000435195001",
  "iban_valid": true,
  "line_items": [
    { "description": "Annual licence", "quantity": 5, "unit_price": 490.0, "amount": 2450.0 }
  ],
  "confidence": 1.0,
  "extraction_method": "text_layer",
  "billed": true
}
```

`confidence` is a transparent 0–1 score. Route anything below 0.6 to human review.

### Languages

Field labels are recognised in English, German, French, Spanish, Italian, Dutch, Polish, Czech, Latvian, Lithuanian, Estonian and more. Both European (`1.234,56`) and Anglo (`1,234.56`) number formats are handled, along with parenthesised negatives and space-separated thousands.

Scanned documents are OCR'd on-box with Tesseract in 22 languages. **No external AI API is called**, so your invoices never leave the Apify platform — which matters if you are processing documents under GDPR.

### Input

| Field | Type | Description |
|---|---|---|
| `documentUrls` | array | Public URLs of PDFs or images. Up to 100 per run. |
| `documentsBase64` | array | `{"filename": "...", "data": "<base64>"}` for private files. |
| `validateVat` | boolean | Check VAT numbers against VIES. Default `true`. |
| `validateIban` | boolean | Validate IBAN checksums. Free. Default `true`. |
| `forceOcr` | boolean | OCR even when a text layer exists. Default `false`. |
| `ocrLanguages` | array | Tesseract codes, priority order. Default `["eng","deu"]`. |
| `extractLineItems` | boolean | Return the invoice table rows. Default `true`. |
| `includeRawText` | boolean | Attach full extracted text. Default `false`. |
| `perDocumentTimeoutSecs` | integer | Hard per-document limit. Default `90`. |

### Use with AI agents (MCP)

This Actor is exposed as an MCP tool, so an agent can call it directly:

```
https://mcp.apify.com/?actors=YOUR_USERNAME/eu-invoice-vat-extractor
```

Typical agent prompt: *"Extract this supplier invoice and confirm the seller's VAT number is currently registered."*

### Pricing

Pay per event — you pay for results, not for runtime.

| Event | What triggers it |
|---|---|
| `invoice-parsed` | One document turned into a usable record |
| `ocr-page` | One page actually rasterised and OCR'd (scanned documents only) |
| `vat-validated` | One VIES lookup that actually returned an answer |

Repeated VAT numbers within a run are cached and charged once.

### Limits

- 100 documents per run, 25 MB per file, first 40 pages of a PDF
- Password-protected PDFs are reported as failed, not billed
- VIES is operated by the European Commission; individual member states go offline periodically. When that happens you get `status: "unavailable"` and no charge
- Party names are read from the layout and are best-effort; where VIES returns a registered name, that authoritative value replaces the guess

### Development

```bash
apify login
apify run --purge          # local run
apify push                 # build on the platform
```

Parsing logic is deterministic and unit-tested:

```bash
python -m pytest tests/ -q
```

# Actor input Schema

## `documentUrls` (type: `array`):

Public URLs of invoices or receipts. PDF, PNG, JPG, TIFF and WEBP are supported. Up to 100 documents per run.

## `documentsBase64` (type: `array`):

For files that are not publicly reachable. Each item: {"filename": "invoice.pdf", "data": "<base64>"}.

## `validateVat` (type: `boolean`):

Check every detected EU VAT number against the official European Commission VIES registry and return the registered name and address. Billed separately, never billed when VIES is unreachable.

## `validateIban` (type: `boolean`):

Verify detected IBANs with the mod-97 checksum. Free.

## `forceOcr` (type: `boolean`):

Run OCR even when the PDF already has a text layer. Slower, billed per page, helps with broken text layers.

## `ocrLanguages` (type: `array`):

Tesseract language codes for scanned documents, in priority order.

## `extractLineItems` (type: `boolean`):

Detect the invoice table and return line items with description, quantity, unit price and amount.

## `includeRawText` (type: `boolean`):

Add the full extracted text to each record. Useful for debugging, makes output much larger.

## `perDocumentTimeoutSecs` (type: `integer`):

Hard limit for one document. Exceeding it returns status "timeout" and is not billed, instead of hanging the run.

## Actor input object example

```json
{
  "validateVat": true,
  "validateIban": true,
  "forceOcr": false,
  "ocrLanguages": [
    "eng",
    "deu"
  ],
  "extractLineItems": true,
  "includeRawText": false,
  "perDocumentTimeoutSecs": 90
}
```

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("n1ckyta/eu-invoice-vat-extractor").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("n1ckyta/eu-invoice-vat-extractor").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 '{}' |
apify call n1ckyta/eu-invoice-vat-extractor --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

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