# Romania e-Factura Validator (CIUS-RO, Peppol, EN 16931) (`switchertheone/efactura-validator`) Actor

Validate UBL invoices before uploading to ANAF SPV: official CIUS-RO 1.0.9, EN 16931 and Peppol BIS 3.0 rules, the fix for every error in plain words, and optional auto-repair of codes, dates and totals.

- **URL**: https://apify.com/switchertheone/efactura-validator.md
- **Developed by:** [Alex Constantin](https://apify.com/switchertheone) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 invoice validateds

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/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

## Romania e-Factura Validator (CIUS-RO, Peppol BIS 3.0, EN 16931)

Check UBL 2.1 invoices **before you upload them to ANAF SPV** (or send them over Peppol) and get every error with
the fix in plain words. Optionally the Actor **repairs** what can be fixed without guessing and returns the
corrected XML.

Built for accountants, ERP and invoicing developers, and AI agents that produce e-Factura XML.

### What it checks

- **UBL 2.1 schema** (XSD) for Invoice and CreditNote
- **EN 16931** business rules (CEN), the European core
- **CIUS-RO 1.0.9**, the Romanian rules ANAF applies to e-Factura (BR-RO-xxx)
- **Peppol BIS Billing 3.0**
- `auto` picks the rule set from the invoice's `CustomizationID`

Every finding has the rule id, severity, the official message, a short title and the fix, the UBL path of the
field, and for calculation errors (BR-CO-10…17, BR-S-09) **the correct value computed from the invoice itself**.

### Auto-fix (optional)

With `autofix: true`, invoices whose errors can be repaired get a corrected XML, re-validated:

- county codes → ISO 3166-2:RO (`Cluj` → `RO-CJ`), Bucharest `Sector 3` → `SECTOR3`
- country, currency (`LEI` → `RON`) and unit codes (`buc` → `H87`), dates → `YYYY-MM-DD`
- VAT id country prefix, CIUS-RO `CustomizationID`
- decimals, then **all totals and VAT amounts recomputed from the lines**, in dependency order

Every change is listed (rule, field, path, old value, new value).

### Input

```json
{
  "xmlUrls": ["https://example.com/invoices/FCT-0001.xml"],
  "profile": "auto",
  "autofix": true
}
```

Or send one invoice as text in `xml` (handy for AI agents). Up to 2 MB per invoice.

### Output (one dataset row per invoice)

```json
{
  "source": "https://example.com/invoices/FCT-0001.xml",
  "valid": false,
  "profile": "ro",
  "errors": 1,
  "warnings": 0,
  "autofix_rules": ["BR-CO-15"],
  "findings": [{
    "rule": "BR-CO-15", "severity": "error", "title": "Total with VAT is wrong",
    "fix": "Set it to: total without VAT + total VAT.",
    "ubl": "cac:LegalMonetaryTotal/cbc:TaxInclusiveAmount",
    "expected": {"field": "BT-112", "value": "1210.00", "found": "1190.00", "currency": "RON"}
  }],
  "fixed_xml": "<?xml version='1.0' encoding='UTF-8'?><Invoice …>",
  "valid_after_fix": true
}
```

### Pricing (pay per event)

| Event | Price | When |
|---|---|---|
| Invoice validated | $0.01 | an UBL Invoice/CreditNote was checked (valid or not) |
| Invoice fixed | $0.05 | `autofix` is on and something was actually repaired |

Not charged: files that are not UBL invoices, unreadable links, or when the service is unavailable.

### Use it from an AI agent

Add Apify's MCP server (`https://mcp.apify.com`) to Claude, Cursor or VS Code and ask, for example,
*"validate this e-Factura before I upload it to SPV"*: the agent can find and run this Actor. Through the Apify
API it is a single call to `run-sync-get-dataset-items`.

### Data

Invoices are sent over HTTPS to the validation service run by the author in the EU, checked in memory and not
stored. Results stay in your Apify storage. Each rule is explained at
[einvoice.alexhub.uk/en/rules/](https://einvoice.alexhub.uk/en/rules/) (Romanian:
[/ro/erori/](https://einvoice.alexhub.uk/ro/erori/)).

### FAQ

**Is this the ANAF validator?** It applies the same official rule sets (the CIUS-RO and EN 16931 Schematron
published by the Ministry of Finance and CEN), so an invoice that passes here passes those checks at ANAF.
SPV also checks things that need its own data (for example that your CUI may upload).

**Romanian error text?** CIUS-RO rules include `message_ro`.

**Related:** e-Factura Generator (JSON → valid CIUS-RO XML), Romanian Company Lookup by CUI (ANAF),
SAF-T D406 Validator.

# Actor input Schema

## `xmlUrls` (type: `array`):

Links to UBL invoice XML files, e.g. files in an Apify key-value store, S3 or any public URL. Each one is validated separately.

## `xml` (type: `string`):

A single invoice pasted as XML (\<Invoice …> or \<CreditNote …>). Handy for AI agents: send the XML directly.

## `profile` (type: `string`):

Which rule set to apply. auto picks it from the invoice's CustomizationID (CIUS-RO for ANAF e-Factura, Peppol BIS 3.0, or plain EN 16931).

## `autofix` (type: `boolean`):

When the report has errors that can be repaired without guessing (county and unit codes, dates, decimals, totals and VAT recomputed from the lines), also return the corrected XML. Charged as a separate event, only when something was fixed.

## Actor input object example

```json
{
  "xmlUrls": [
    "https://einvoice.alexhub.uk/sample.xml"
  ],
  "profile": "auto",
  "autofix": false
}
```

# Actor output Schema

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

No description

# 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 = {
    "xmlUrls": [
        "https://einvoice.alexhub.uk/sample.xml"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("switchertheone/efactura-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 = { "xmlUrls": ["https://einvoice.alexhub.uk/sample.xml"] }

# Run the Actor and wait for it to finish
run = client.actor("switchertheone/efactura-validator").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 '{
  "xmlUrls": [
    "https://einvoice.alexhub.uk/sample.xml"
  ]
}' |
apify call switchertheone/efactura-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,switchertheone/efactura-validator"
        }
    }
}
```

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/fWYPlXjSxTMWSgAAb/builds/jjnYMZV8txzW07rCK/openapi.json
