# Dataset Audit — what you actually paid for (`ledgerworks/dataset-audit`) Actor

Audit any Actor run: duplicates, unmet criteria, and the real cost per usable record. Live Excel receipt included.

- **URL**: https://apify.com/ledgerworks/dataset-audit.md
- **Developed by:** [Alessandro Bonzio](https://apify.com/ledgerworks) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 1 total users, 0 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/platform/actors/running/actors-in-store#pay-per-usage

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

## Dataset Audit — what you actually paid for

You paid per result. This tells you what you got.

Point it at the dataset of any run — from any Actor — and it returns the receipt:
how many records were duplicates, how many ignored the filters you asked for,
and **what a usable record really cost you**.

### Why

Across the Apify Store the same complaint keeps coming back, in the reviews of
tools that otherwise work fine:

> *"I expected 2,000 results for $10. I got 748 unique ones. That's $0.01337 per
> unique job, not the $0.005 advertised — 2.67 times the price."*

That user did the arithmetic by hand, in a review box. This Actor does it for
anyone, in about a second.

### What it gives you

- **Duplicates** — how many, and exactly which keys repeat
- **Unmet criteria** — records that ignored the filters you set (date windows,
  minimum thresholds, required fields)
- **Empty fields** — how often each field came back blank
- **Cost per usable record** — what you paid divided by what you can actually use
- **A live Excel receipt** — input cell at the top, real formulas underneath.
  Change the amount you paid and every figure recalculates. It is a working
  model, not a screenshot.

### Input

| Field | Meaning |
|---|---|
| `datasetId` | The dataset to audit. Pick it from the list — that grants read access to that dataset only. |
| `dedupeKeys` | Fields that identify one record, e.g. `["jobId"]`. Empty compares whole rows. |
| `filters` | What you had asked for, e.g. `[{"field":"postedAt","op":"after","value":"2026-07-01"}]` |
| `amountPaidUsd` | What that run cost you, from your Apify console |
| `locale` | `en` or `it` — the language of the Excel receipt |

Operators: `nonEmpty`, `equals`, `oneOf`, `min`, `max`, `after`, `before`, `matches`.

A field that is **missing counts as a failure**, not as a case to skip: that is
precisely the record you believed you had excluded when you paid.

### What it does NOT do

Said plainly, because the absence of this section is why tools get 3 stars:

- **It does not read your account.** It runs with limited permissions and can
  only see the one dataset you select. Not your other runs, not your other
  storages, not your billing.
- **It cannot read the run's cost by itself.** Apify does not expose that to a
  limited-permission Actor, so you type the amount in. If you leave it out, you
  still get duplicates and unmet criteria — just no cost per record.
- **It does not judge whether the data is true.** It checks the data against the
  criteria you declare. If a scraper invents a plausible email, this will not
  know — it will only tell you the field was not empty.
- **It does not compare across runs.** Duplicates are counted inside one dataset.
  If the same record was sold to you in two separate runs, that is not caught yet.
- **It does not store anything.** Your rows are read, counted, and dropped. The
  only output is on your own account.

### Cost

Free. If it ever stops being free you will read about it here first, with the
notice period the platform requires.

***

Built by [ledgerworks](https://apify.com/ledgerworks) — financial tools that get
the numbers right. Same workshop as
[13-Week Cash Flow](https://apify.com/ledgerworks/cashflow13).

# Actor input Schema

## `datasetId` (type: `string`):

The dataset produced by the run you want to check. It is read only — this Actor never writes to it, and has no access to anything else in your account.

## `dedupeKeys` (type: `array`):

Two rows with the same values in these fields are the same record. Example: \["jobId"] or \["name","city"]. Leave empty to compare whole rows. Dotted paths work: "author.name".

## `filters` (type: `array`):

The criteria you set on the original run, so they can be checked against what was delivered. Each entry: {"field":"postedAt","op":"after","value":"2026-07-01"}. Operators: nonEmpty, equals, oneOf, min, max, after, before, matches.

## `amountPaidUsd` (type: `number`):

What the run cost you, taken from your Apify console. Optional: without it the audit still reports duplicates and unmet criteria, but cannot compute cost per usable record.

## `locale` (type: `string`):

Language used for the labels in the generated workbook.

## Actor input object example

```json
{
  "dedupeKeys": [],
  "filters": [],
  "locale": "en"
}
```

# 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("ledgerworks/dataset-audit").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("ledgerworks/dataset-audit").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 ledgerworks/dataset-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=ledgerworks/dataset-audit",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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