# Document Data Cleaner (`freddy.universe/document-data-cleaner`) Actor

Cleans, normalizes, validates and deduplicates commercial CSV files before import into ERPs and e-commerce. Deterministic, no LLM, no external network.

- **URL**: https://apify.com/freddy.universe/document-data-cleaner.md
- **Developed by:** [Stefano Musarra](https://apify.com/freddy.universe) (community)
- **Stats:** 2 total users, 1 monthly users, 0.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/actors/running/actors-in-store.md#pay-per-usage

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

## Document Data Cleaner

Microsoftware deterministico per pulire, normalizzare, validare e deduplicare file CSV commerciali prima dell'import in gestionali ed e-commerce. Nessun LLM, nessuna rete, nessuna dipendenza: solo Node.js stdlib. Primo artefatto dell'esperimento "Strada C" del Money Engine (budget 0).

### Cosa fa

- Parser CSV robusto (campi quotati, virgole e newline dentro le virgolette, quote escapate).
- Normalizzazione automatica per colonna:
  - tutte le colonne: trim + collapse degli spazi multipli;
  - colonne email (header contenente "email"/"e-mail"/"mail"): lowercase + validazione formato;
  - colonne telefono (header contenente phone/tel/cellulare/telefono/mobile): solo cifre con eventuale "+" iniziale;
  - colonne importo (header contenente importo/prezzo/amount/price/total/totale/value/valore/costo/cost): decimale canonico con punto (accetta `1.234,56`, `1234,56`, `1,234.56`, `€ 1.234,56`, spazi).
- Deduplica per colonne chiave (default: intera riga normalizzata, confronto case-insensitive), tenendo la prima occorrenza.
- Validazione: campi obbligatori mancanti, email non valide, importi non numerici, righe con numero di campi diverso dall'header.
- Report JSON versionato con conteggi e dettaglio per riga.

### Uso

```sh
node main.js --in input.csv --out cleaned.csv
node main.js --in input.csv --out cleaned.csv --report report.json
node main.js --in input.csv --out cleaned.csv --key email --required email,name
node main.js --in input.csv --out cleaned.csv --on-invalid drop
node main.js --in - --out cleaned.csv        # legge da stdin
```

Opzioni: `--in`, `--out`, `--report`, `--key col1,col2`, `--required col1,...`, `--on-invalid keep|drop`, `--delimiter ,`, `--bom`, `--help`.

Exit code: 0 elaborazione riuscita (anche con problemi segnalati), 1 errore d'uso, 2 errore di input/output.

### Esempio end-to-end

```sh
node main.js --in demo/input.csv --out demo/output.csv --report demo/report.json --key email --required email,name
```

### Limiti onesti

- Non fa scraping, non recupera dati da fonti esterne: lavora solo su file forniti dal cliente o sintetici.
- Non pubblica nulla e non crea account: la pubblicazione su Apify Store richiede account e approvazione esplicita di Stefano.
- Non è ancora venduto: è un artefatto pronto e testato in locale, non un prodotto con clienti.
- Le righe con problemi restano nell'output di default (`--on-invalid keep`): scelta prudente, non si buttano righe di lavoro senza ordine esplicito.

### Calcolo del margine (numeri Apify verificati)

Fonti: docs.apify.com (monetizzazione Actor, pricing e costi), lette il 2026-10-19.

- Formula verificata: utile = 0,8 × ricavi − costi piattaforma.
- Compute unit (FREE tier): 0,20 USD / CU.
- Modello: pay-per-event (prezzo per evento/run).
- Gli utenti del piano free di Apify sono esclusi dal profitto (non generano ricavi per l'Actor).

Scenari IPOTETICI (i prezzi sono esempi, non previsioni né promesse; il volume reale di run a pagamento è sconosciuto):

| Prezzo evento (USD) | Eventi | Ricavi lordi (USD) | Quota piattaforma 20% (USD) | Utile prima compute (USD) |
|---|---:|---:|---:|---:|
| 0,01 | 100 | 1,00 | 0,20 | 0,80 |
| 0,01 | 1.000 | 10,00 | 2,00 | 8,00 |
| 0,05 | 100 | 5,00 | 1,00 | 4,00 |
| 0,05 | 1.000 | 50,00 | 10,00 | 40,00 |
| 0,10 | 100 | 10,00 | 2,00 | 8,00 |
| 0,10 | 1.000 | 100,00 | 20,00 | 80,00 |

Il costo compute si sottrae dall'utile prima compute: con il FREE tier il costo è 0 fino al limite gratuito, poi 0,20 USD/CU. Se il costo per run supera l'80% del prezzo evento, il prodotto va fermato (stop condition del Money Engine).

### Test

```sh
node test/run-tests.js
```

Tutti i test devono passare (exit 0). I dataset in `test/datasets/` e `demo/` sono sintetici: nessun dato reale di persone o clienti.

# Actor input Schema

## `inputFile` (type: `string`):

URL pubblico (http/https) del CSV da pulire, oppure chiave del key-value store Apify. Se vuoto, legge la chiave INPUT del default store.

## `csvContent` (type: `string`):

Contenuto CSV da pulire, incollato direttamente. Ha priorità su inputFile. Utile per test rapidi.

## `keyColumns` (type: `string`):

Nomi di colonna separati da virgola. Se vuoto deduplica sull'intera riga normalizzata.

## `requiredColumns` (type: `string`):

Nomi di colonna separati da virgola che non possono essere vuote.

## `onInvalid` (type: `string`):

keep = mantieni e segnala nel report; drop = rimuovi dall'output.

## `delimiter` (type: `string`):

Carattere separatore del CSV.

## `bom` (type: `boolean`):

Prependi il BOM UTF-8 all'output.

## Actor input object example

```json
{
  "inputFile": "",
  "csvContent": "",
  "keyColumns": "",
  "requiredColumns": "",
  "onInvalid": "keep",
  "delimiter": ",",
  "bom": false
}
```

# Actor output Schema

## `cleanedRows` (type: `string`):

Cleaned CSV output (text).

## `report` (type: `string`):

JSON report with duplicates and issues.

# 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("freddy.universe/document-data-cleaner").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("freddy.universe/document-data-cleaner").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 '{}' |
apify call freddy.universe/document-data-cleaner --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,freddy.universe/document-data-cleaner"
        }
    }
}
```

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/KdbKjUe232ibuWUfZ/builds/n1yYDp3J9oO08HoIz/openapi.json
