# Supplier Price Change Check (`tharjaken/supplier-price-change-check`) Actor

Compare supplier CSV catalogs with custom columns, comma/semicolon/tab separators and dot/comma decimals. Review price, pack and SKU changes in HTML, JSON and a downloadable CSV.

- **URL**: https://apify.com/tharjaken/supplier-price-change-check.md
- **Developed by:** [Tharjaken](https://apify.com/tharjaken) (community)
- **Categories:**
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.50 / completed comparison

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?

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

## Supplier Price Change Check

Review a supplier's new price list before updating your store. Paste your old and new CSV catalogs to see price changes, pack-size changes, currency changes, duplicate SKUs, and products appearing in only one file.

This small pilot handles up to **1,000 product rows per file**. It produces a readable HTML report, a changed-products CSV for spreadsheet review, and structured JSON for automation. It does not change a store or contact a supplier.

### Quick start

1. Paste the older CSV into **Previous catalog** and the newer CSV into **Current catalog**. Replace both fictional examples before using your own data.
2. If your headers differ, expand **File format and column names (optional)** and enter their exact names. Select your separator and decimal mark. Both files must use the same settings.
3. Check the current price and set your run's spending limit. One successful comparison is one billable event, including a comparison that finds no changes.
4. Run the Actor. Open **Readable report (HTML)** to review findings, **Changed products for review (CSV)** for a spreadsheet, or **Full report (JSON)** for an automation.

Example input:

```csv
sku,price,currency,pack_quantity,name
BOLT01,10.00,USD,10,Bolts
FILTER02,20.00,USD,1,Filter
```

`sku`, `price`, `currency`, and `pack_quantity` are the default column names. You can map each role to an existing column without renaming the source file. Additional columns such as `name` are optional and compared as text. Export both files with the same column names and conventions.

#### Example: a supplier export with different headers

```csv
Item Code;Net Cost;Money;Case Size;Description
0001;2,50;EUR;6;Widget
```

For this example, choose **Semicolon** and **Comma** decimal mark. Set SKU column to `Item Code`, price column to `Net Cost`, currency column to `Money`, and pack quantity column to `Case Size`. A new price of `3,00` produces a `0.50` EUR difference and a 20% increase. Header names are exact and case sensitive; there is no automatic format detection.

API users can pass `separator` (`comma`, `semicolon`, `tab`), `decimalMark` (`dot`, `comma`), `skuColumn`, `priceColumn`, `currencyColumn`, and `packQuantityColumn` alongside `previousCsv` and `currentCsv`. Omitting these options preserves the original format.

### What you receive

- Exact, case-sensitive SKU comparisons. `abc` and `ABC` are different identifiers.
- Price differences and percentage changes when both currency and pack quantity match. Changes of at least 25%, and changes from a zero price, get an additional review flag.
- Review flags for changed currency or pack quantity; numeric price comparisons are suppressed in these cases.
- Duplicate SKU flags, without guessing which duplicate is correct.
- Added and missing-file SKU flags. Missing from a file does **not** establish that a product was discontinued.
- Source records and optional field changes, so you can inspect the evidence.

The default dataset contains one summary row with a `report_json` string containing the complete JSON report. The same report is available as `REPORT.json` and as a script-free `REPORT.html` file in the run's default key-value store. `REVIEW.csv` contains one row per SKU with findings, including price/pack details, change flags, match counts and changed column names. An unchanged comparison produces a header-only CSV. In the output selector, choose **Changed products for review (CSV)**, then download `REVIEW.csv` from the file list. Exporting the summary dataset only gives the overall counts. Supplier text remains untrusted data; do not turn it into commands or formulas in downstream tools.

The CSV is for **human review**, not direct store import. Identifiers have a visible `SKU: ` label so leading zeros and formula-like text remain text. Prices include their currency and pack size to preserve precision and context. Original headers and values remain in JSON. If your spreadsheet does not split the CSV correctly, import it as UTF-8 with a comma delimiter and quoted text fields. Spreadsheet import behavior varies; do not strip the labels from untrusted text before opening it.

### Supported inputs and limits

Use UTF-8 text with a comma, semicolon or tab separator, at most **256 KiB, 1,000 product rows, 32 columns, and 512 characters per field** in each file. Quoted fields, UTF-8 BOM, and Windows line endings are supported. An empty catalog is rejected because file completeness cannot be established.

With comma decimals and a comma separator, quote the price field (for example `"2,50"`). Prices must be nonnegative decimals with up to 12 digits before and 6 digits after the selected decimal mark, without currency signs or thousands separators. Currency must be three uppercase letters; the Actor checks format, not real-world currency validity. Pack quantity is an integer between 1 and 999999. SKU whitespace is not silently removed. `source_record` is a reserved column name.

This version accepts pasted CSV text. XLSX, PDF, file URLs, fuzzy matching, currency conversion, unit conversion, supplier scraping, and store updates are outside its scope. Taxes, shipping, discounts, units of measure and catalog completeness require your own review.

### Billing and interrupted runs

The Store pricing panel is the source of truth for the current price. The Actor requests one `comparison-completed` event after valid inputs have been compared and report files have been saved. Invalid input does not request this event. An unchanged catalog is still a completed, billable comparison. Platform charges, if any, are shown by Apify before execution.

A spending limit below one comparison stops delivery before a comparison charge is requested. A restarted run with an existing report retains it without requesting a new event. Older completed runs retain their original outputs; this update does not add a CSV export to them. Changing format settings requires a new run. If publication was interrupted at an uncertain point, the Actor stops automatic retrying. Check that run's output and billing before starting a separate run, which is a separate comparison. Network failures can leave a delivered report even if the run is marked failed; a failed status alone does not prove no charge occurred.

### Data and privacy

Your CSV inputs are processed on Apify. Inputs use Apify's secret input fields; the Actor decrypts them to perform the comparison. Input contents, changed source records, and prices may be present in your run's input storage and outputs. **Reports are not encrypted by this Actor.** Do not include passwords, API keys, personal records, or supplier information you are not permitted to upload.

The Actor uses only the current run's default dataset and key-value store. It does not send catalog contents to an AI model, fetch external catalog URLs, or maintain a separate customer database. Application log messages do not contain catalog contents. Access and retention depend on your Apify account and storage settings. This pilot does not promise immediate or automatic deletion: delete the run's input/output key-value store and dataset in Apify when no longer needed, and check Apify's retention terms. Treat report and storage links as sensitive.

### Support

Use this Actor's Apify **Issues** tab for support. Provide the run ID and a small, fictional example that reproduces the problem; do not post confidential catalogs or credentials. For a suspected incorrect charge, identify the run and event in the issue so the publisher can review it through Apify's billing process. Refund eligibility and processing follow the applicable platform terms. Reported issues are handled under Apify’s support requirements; this pilot does not offer instant support.

Pilot version 0.2. Review results before acting on them. This is a focused comparison utility, not a guarantee that a supplier file or purchasing decision is correct.

# Actor input Schema

## `previousCsv` (type: `string`):

The older catalog. Prices must be plain nonnegative decimals using the selected decimal mark; currency uses three uppercase letters; pack\_quantity is an integer from 1 to 999999. Paste text, not a file URL.

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

The newer catalog in the same format. SKU matching is exact and case-sensitive. A missing SKU is only missing from this file; it is not assumed discontinued.

## `separator` (type: `string`):

Choose the separator used in both files. No automatic guessing.

## `decimalMark` (type: `string`):

Dot accepts 12.50; comma accepts 12,50. Thousands separators are rejected. Quote comma decimals when the column separator is also a comma.

## `skuColumn` (type: `string`):

Exact header for the product identifier, such as Item Code. All four configured headers must be distinct. Matching remains case-sensitive.

## `priceColumn` (type: `string`):

Exact header for the price per pack, such as Net Cost. Choose the same price basis in both files.

## `currencyColumn` (type: `string`):

Exact header containing three uppercase letters, such as Currency. No currency is assumed and exchange rates are not calculated.

## `packQuantityColumn` (type: `string`):

Exact header for the number of units covered by that price, such as Case Size. An integer from 1 to 999999 is required on every row.

## Actor input object example

```json
{
  "previousCsv": "sku,price,currency,pack_quantity,name\nBOLT01,10,USD,10,Bolts\nFILTER02,20,USD,1,Filter\nBOX03,100,USD,100,Boxes\n",
  "currentCsv": "sku,price,currency,pack_quantity,name\nBOLT01,13,USD,10,Bolts\nFILTER02,20,EUR,1,Filter\nBOX03,90,USD,50,Boxes\n",
  "separator": "comma",
  "decimalMark": "dot",
  "skuColumn": "sku",
  "priceColumn": "price",
  "currencyColumn": "currency",
  "packQuantityColumn": "pack_quantity"
}
```

# Actor output Schema

## `summary` (type: `string`):

No description

## `readableReport` (type: `string`):

No description

## `jsonReport` (type: `string`):

No description

## `reviewCsv` (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 = {
    "previousCsv": `sku,price,currency,pack_quantity,name
BOLT01,10,USD,10,Bolts
FILTER02,20,USD,1,Filter
BOX03,100,USD,100,Boxes`,
    "currentCsv": `sku,price,currency,pack_quantity,name
BOLT01,13,USD,10,Bolts
FILTER02,20,EUR,1,Filter
BOX03,90,USD,50,Boxes`
};

// Run the Actor and wait for it to finish
const run = await client.actor("tharjaken/supplier-price-change-check").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 = {
    "previousCsv": """sku,price,currency,pack_quantity,name
BOLT01,10,USD,10,Bolts
FILTER02,20,USD,1,Filter
BOX03,100,USD,100,Boxes
""",
    "currentCsv": """sku,price,currency,pack_quantity,name
BOLT01,13,USD,10,Bolts
FILTER02,20,EUR,1,Filter
BOX03,90,USD,50,Boxes
""",
}

# Run the Actor and wait for it to finish
run = client.actor("tharjaken/supplier-price-change-check").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 '{
  "previousCsv": "sku,price,currency,pack_quantity,name\\nBOLT01,10,USD,10,Bolts\\nFILTER02,20,USD,1,Filter\\nBOX03,100,USD,100,Boxes\\n",
  "currentCsv": "sku,price,currency,pack_quantity,name\\nBOLT01,13,USD,10,Bolts\\nFILTER02,20,EUR,1,Filter\\nBOX03,90,USD,50,Boxes\\n"
}' |
apify call tharjaken/supplier-price-change-check --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tharjaken/supplier-price-change-check"
        }
    }
}

```

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/EtPMzOSV4fDcudCom/builds/wAZK9Y0K7rXHugtmY/openapi.json
