# Inventory CSV Diff & Stock Change Checker (`overbifrost/inventory-csv-diff-stock-change-checker`) Actor

Compare two inventory CSV files by SKU or SKU + warehouse. Find stock drops, items going to zero, added or removed SKUs, and duplicate entries before a stock update. Try the built-in example without files; get an HTML report, CSV findings, and JSON.

- **URL**: https://apify.com/overbifrost/inventory-csv-diff-stock-change-checker.md
- **Developed by:** [Lasse](https://apify.com/overbifrost) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.007 / comparison completed

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

Compare your current inventory CSV with the next supplier or warehouse snapshot. **Find stock drops, items going to zero, added or removed SKUs, and duplicate entries before applying the update.** Download an HTML review report, CSV findings, and JSON for your automation.

**Try it without preparing files:** click [Try for free](https://console.apify.com/actors/lXpy82nw4OAz88f9v?addFromActorId=lXpy82nw4OAz88f9v), leave **Try the built-in example** checked, and press **Start**. Open **Review report (HTML)** when the run finishes. The three-row example costs **$0.01008 on the Free plan** at up to 1 GB of memory under the rates below. Normal event pricing applies to the example.

### See what the example finds

| SKU | Current stock | Proposed stock | Result |
|---|---:|---:|---|
| DEMO-COF-001 | 12 | 0 | 100% stock drop and stock going to zero |
| DEMO-MUG-002 | 5 | 5 | Unchanged; no finding |
| DEMO-TEE-003 | Absent | 8 | Added SKU |

The report returns **Review required**, **3 evaluated rows**, and **3 findings**. One row can trigger several findings without extra row charges. The example is labeled as built-in sample data in the report.

Use this for supplier feeds, warehouse exports, or an inventory workflow where you already have two snapshots. It **compares your files and leaves the stock update to you**. No store or ERP credentials are needed.

### Compare your own inventory CSV files

1. Turn **Try the built-in example** off.
2. Choose **SKU + Stock columns** if both files have those exact headers. Choose **Custom columns / multiple warehouses** if headers differ or each SKU has separate warehouse quantities.
3. Upload the **Current inventory CSV** and **Next inventory CSV**.
4. Check **Both snapshots cover the same complete scope**. Both files must describe the same supplier, warehouse, or other declared scope; a partial update file is unsuitable for inferring additions and removals.
5. Keep the default review rules or change the thresholds, then press **Start**.
6. Open **Review report (HTML)**. Download **Findings (CSV)** for a spreadsheet or **Comparison report (JSON)** for your workflow.

For the standard profile, use these headers. This is the example current snapshot:

```csv
SKU,Stock
DEMO-COF-001,12
DEMO-MUG-002,5
```

The example next snapshot is:

```csv
SKU,Stock
DEMO-COF-001,0
DEMO-MUG-002,5
DEMO-TEE-003,8
```

Paste CSV text, use public HTTPS CSV URLs, or select Apify datasets under the alternative-source sections. Choose exactly one source for each side.

### Pricing

Pay per event, with platform usage included. **All prices below are USD per event**, not per 1,000 events.

| Event | Free | Starter | Scale | Business |
|---|---:|---:|---:|---:|
| `comparison-completed` | $0.01 | $0.009 | $0.008 | $0.007 |
| `row-evaluated` | $0.00001 | $0.00001 | $0.00001 | $0.00001 |
| `apify-actor-start` | $0.00005 | $0.00005 | $0.00005 | $0.00005 |

- **Comparison:** charged once when a completed report evaluates at least one proposed row.
- **Rows:** one event per evaluated proposed row, including unchanged rows and valid additions. Multiple findings on one row still count as one row event. Removed rows and uncheckable rows do not add row events.
- **Start:** charged by Apify, including failed runs. One event at up to 1 GB; higher memory adds start events.

| Example, at up to 1 GB | Free | Starter | Scale | Business |
|---|---:|---:|---:|---:|
| Built-in example: 3 evaluated rows | $0.01008 | $0.00908 | $0.00808 | $0.00708 |
| Comparison: 1,000 evaluated rows | $0.02005 | $0.01905 | $0.01805 | $0.01705 |

**Maximum cost per run is a spending cap, not a minimum bill.** The minimum allowed cap is $0.011. That covers the built-in example at up to 1 GB; a 1,000-row comparison on Free needs at least $0.02005, so use $0.021 or more.

The Actor checks the complete comparison cost before delivering and charging the custom events. Insufficient-budget runs incur no custom comparison or row charges; the Apify start event still applies. The [Pricing tab](https://apify.com/overbifrost/inventory-csv-diff-stock-change-checker/pricing) is authoritative.

### What is checked

| Check | Default behavior |
|---|---|
| Stock drop | Flag a decrease strictly over 50% from a positive current quantity |
| Stock increase | Flag an increase strictly over 200% from a positive current quantity |
| Stock goes to zero | Flag a positive quantity changing to zero |
| Added or removed identity | Flag entries present in only one complete snapshot |
| Duplicates or invalid rows | Report them as uncheckable; do not choose a matching row |
| Warehouse identity | With location mapping, compare SKU + location separately |

SKU matching is exact and case-sensitive. Quantities must be signed whole numbers in the supported 32-bit range. Blank quantities, decimal quantities, and stock-status words are uncheckable. Percentage checks require a positive current quantity.

A generic spreadsheet diff lists changed cells. This Actor matches inventory identities and applies your stock-review rules.

#### Custom columns and multiple warehouses

Choose **Custom columns / multiple warehouses** and map **SKU**, **Quantity**, and optional **Warehouse / location** independently for each file. For example, the current file can use `item_code`, `available`, and `warehouse`, while the next file uses `sku`, `qty`, and `warehouse_id`.

Map location on **both sides or neither**. The same SKU in Oslo and Bergen is then two separate inventory identities. Quantities are not added together across warehouses.

### Reports and result status

| Output | Use |
|---|---|
| **Review report (HTML)** | Read the status, coverage, counts, and individual findings |
| **Findings (CSV)** | Open the retained findings in a spreadsheet |
| **Comparison report (JSON)** | Use the canonical report in an integration |
| **Dataset report** | Read the same JSON report through Apify datasets |
| **Run metadata** | Inspect execution and billing details |

| Status | Meaning |
|---|---|
| `review_required` | The checks found changes to review |
| `no_findings` | The supported checks found no review items |
| `incomplete` | Rows were uncheckable or finding details were capped |
| `no_changes` | Both snapshots contained no data rows |

Up to **100,000 data records per file** are supported within the size limits. Uploaded and remote files are limited to **10 MB** each; pasted CSV to **512 KB** each. The finding list retains at most 1,000 entries while keeping the total counts.

The Actor does not synchronize stock, connect to live inventory, repair files, or approve updates. A report with no findings does not guarantee that a later update is safe.

### API and recurring checks

The published Actor name is **`overbifrost/inventory-csv-diff-stock-change-checker`**. Keep **Try the built-in example** off when providing your own sources.

#### JavaScript example

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client
  .actor('overbifrost/inventory-csv-diff-stock-change-checker')
  .call({ demoMode: true }, { maxTotalChargeUsd: 0.011, memory: 512 });

if (run.status !== 'SUCCEEDED') {
  throw new Error(`Comparison failed: ${run.status}`);
}

const result = await client
  .keyValueStore(run.defaultKeyValueStoreId)
  .getRecord('OUTPUT');

console.log(result.value);
```

#### n8n and Make

Use an HTTP request to:

```text
POST https://api.apify.com/v2/acts/overbifrost~inventory-csv-diff-stock-change-checker/run-sync-get-dataset-items?maxTotalChargeUsd=0.011&memory=512
```

Authenticate with an **Authorization: Bearer** header using your Apify token, set `Content-Type: application/json`, and use `{"demoMode":true}` as the first request body. For real comparisons, send the two snapshots and required confirmation, and increase the cost cap for the expected evaluated rows.

A successful response contains an array with one comparison report. Route `review_required` and `incomplete` to a human review step before your separate stock-update process.

#### Saved snapshots and scheduled runs

Save a named baseline to reuse a validated current snapshot. Save comparison input as an Apify Task and use an Apify Schedule for recurring checks. Comparing does not automatically advance the saved baseline. An optional webhook can send a small summary for selected result statuses.

### FAQ and support

#### Can I compare a partial update with a full inventory export?

Additions and removals require both files to cover the same complete scope. Do not check the confirmation for a partial delta feed.

#### Do I need to write code or provide store credentials?

For uploads, use the Apify input form. No store login or ERP connection is used. API integrations need an Apify token.

#### Why does my first run use example data?

**Try the built-in example** is preselected so you can inspect a report before preparing files. Turn it off before using your own sources; example mode and customer sources cannot be combined.

#### What should I check if the comparison fails?

Turn the example off for real files, choose one source per side, check the complete-snapshot confirmation, and verify the selected headers or mappings. Also check the CSV delimiter and run cost cap. Open the error record for the exact error code.

#### Where can I get help?

Use the Actor's [Issues tab](https://apify.com/overbifrost/inventory-csv-diff-stock-change-checker/issues). Include the run ID and error code when available; you do not need to include private inventory files in a public issue.

This Actor is part of **SKUFuse — Stock Keeping Unit Fuse**. For product-catalog imports, see [Shopify CSV Import Checker & Catalog Diff](https://apify.com/overbifrost/shopify-csv-import-checker-catalog-diff) and [WooCommerce CSV Import Checker & Catalog Diff](https://apify.com/overbifrost/woocommerce-csv-import-checker-catalog-diff).

# Changelog

This Actor's version history is a separate document: https://apify.com/overbifrost/inventory-csv-diff-stock-change-checker/changelog.md

# Actor input Schema

## `demoMode` (type: `boolean`):

No files needed. The three-row example shows stock dropping from 12 to zero, one unchanged item, and one added SKU. Turn this off before supplying your own data. The example uses normal event pricing.

## `schemaVersion` (type: `string`):

Choose SKU + Stock columns when both files use those exact headers. Choose Custom columns / multiple warehouses to map other headers or compare each SKU separately by warehouse.

## `currentCsvFile` (type: `string`):

Upload the snapshot you currently use, up to 10 MB. For the standard profile, headers must include SKU and Stock. Use exactly one current source; turn the example off first.

## `proposedCsvFile` (type: `string`):

Upload the next complete snapshot you want to check, up to 10 MB. Use the same inventory scope as the current file and exactly one proposed source.

## `confirmCompleteSnapshots` (type: `boolean`):

Required for your own data. Both snapshots must cover the same complete supplier, warehouse, or other scope. Do not check this for a partial update feed: absence would be mistaken for an addition or removal.

## `rules` (type: `object`):

Control which stock changes, additions, and removals are highlighted for review.

## `maxFindings` (type: `integer`):

Limit the retained finding list to 1–1000 entries. SKUFuse still counts all findings when the list is capped.

## `currentMapping` (type: `object`):

Mapping profile only. Map logical inventory fields to the current source's exact CSV headers or dataset field paths.

## `proposedMapping` (type: `object`):

Mapping profile only. Map logical inventory fields to the proposed source's exact CSV headers or dataset field paths.

## `currentCsv` (type: `string`):

Alternative to file upload: paste the current inventory CSV as text (max 512 KB). Use exactly one current source.

## `proposedCsv` (type: `string`):

Alternative to file upload: paste the proposed inventory CSV as text (max 512 KB). Use exactly one proposed source.

## `currentCsvUrl` (type: `string`):

Public HTTPS URL returning the current CSV (max 10 MB). HTTPS port 443 only; redirects and URL credentials are rejected.

## `proposedCsvUrl` (type: `string`):

Public HTTPS URL returning the proposed CSV (max 10 MB). HTTPS port 443 only; redirects and URL credentials are rejected.

## `csvDelimiter` (type: `string`):

Delimiter used by uploaded, pasted, or URL CSV files. Dataset and saved-baseline sources use canonical comma CSV.

## `currentDataset` (type: `string`):

Alternative current source: select an Apify dataset containing inventory records. SKUFuse requests READ-only access.

## `proposedDataset` (type: `string`):

Alternative proposed source: select an Apify dataset containing the planned inventory snapshot. SKUFuse requests READ-only access.

## `currentDatasetMapping` (type: `object`):

Default profile only. Optional visual mapping for a dataset whose fields are not named SKU and Stock.

## `proposedDatasetMapping` (type: `object`):

Default profile only. Optional visual mapping for a proposed dataset whose fields are not named SKU and Stock.

## `baseline` (type: `object`):

Reuse a named, validated current snapshot for recurring comparisons. A comparison never automatically replaces it with the next snapshot. No baseline settings are needed for an ordinary two-file comparison.

## `reviewWebhook` (type: `object`):

Optional encrypted webhook configuration for API or Task input. Hidden from the Form view so customers are never asked to enter JSON.

## `payload` (type: `object`):

Platform-provided integration envelope for chained Apify runs.

## Actor input object example

```json
{
  "demoMode": true,
  "schemaVersion": "inventory_snapshot_single_location_v1",
  "maxFindings": 1000,
  "currentCsvUrl": "https://example.com/exports/current-inventory.csv",
  "proposedCsvUrl": "https://example.com/exports/proposed-inventory.csv"
}
```

# Actor output Schema

## `reviewHtml` (type: `string`):

No description

## `findingsCsv` (type: `string`):

No description

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

No description

## `datasetItem` (type: `string`):

No description

## `runMetadata` (type: `string`):

No description

## `errorRecord` (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 = {
    "demoMode": true,
    "schemaVersion": "inventory_snapshot_single_location_v1"
};

// Run the Actor and wait for it to finish
const run = await client.actor("overbifrost/inventory-csv-diff-stock-change-checker").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 = {
    "demoMode": True,
    "schemaVersion": "inventory_snapshot_single_location_v1",
}

# Run the Actor and wait for it to finish
run = client.actor("overbifrost/inventory-csv-diff-stock-change-checker").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 '{
  "demoMode": true,
  "schemaVersion": "inventory_snapshot_single_location_v1"
}' |
apify call overbifrost/inventory-csv-diff-stock-change-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,overbifrost/inventory-csv-diff-stock-change-checker"
        }
    }
}
```

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/lXpy82nw4OAz88f9v/builds/gEt2zR5iG7GvRls1g/openapi.json
