# Supplier Price List vs Catalog: CSV Comparison (`royal_paddle/catalog-reconcile-csv`) Actor

Compare supplier prices with your catalog by SKU before a bulk update. Export proposed price changes and exceptions for conflicting prices, invalid values and unknown SKUs. Preserves leading-zero SKUs and Hebrew text. Includes a synthetic demo; does not update Shopify.

- **URL**: https://apify.com/royal\_paddle/catalog-reconcile-csv.md
- **Developed by:** [Shay](https://apify.com/royal_paddle) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.20 / 1,000 supplier row processeds

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

## Catalog CSV Reconcile — Supplier Prices vs Current (Shopify / Matrixify / Google Shopping Prep)

**Pay-per-event (PPE) Actor** for ecommerce ops: compare a **supplier price-update CSV** against your **current catalog CSV** and emit a reviewable change set.

**Outputs in one run:**

1. **Proposed changes** — matched SKUs with a clear old → new price delta
2. **Exceptions** — withheld rows (conflicting duplicates, invalid prices, unmapped new SKUs, missing SKUs)
3. **SUMMARY JSON** — key-value store record with counts, reason tallies, and disclosures

This is a **reviewable change proposal**, not an unattended Shopify, Matrixify, or Google Merchant Center import.

**Store:** https://apify.com/royal\_paddle/catalog-reconcile-csv\
**Try with empty input:** schema defaults + bundled samples run the synthetic demo successfully (no files required).

### Who this is for

- **Shopify** merchants / agencies preparing price updates before admin CSV or **Matrixify** import
- **Google Shopping / Merchant Center** ops reconciling supplier files against an existing product feed (`id` / `price` style columns via overrides)
- Teams that need a **safe reconcile**: proposals + explicit exceptions — **no silent guesses**

If you only need a one-off VLOOKUP, a spreadsheet may be enough. Use this Actor when you want repeatable runs, structured exceptions, and leading-zero / UTF-8-safe SKUs.

### Honest disclosures (please read)

| Claim | Reality |
| --- | --- |
| Demo data | Logic and samples come from a **synthetic** pilot pack (invented products). **Not prior client results.** |
| Who built it | **AI coding agent** (disclosed). Not billed as human engineering hours. |
| What it does **not** do | Does **not** log into Shopify/GMC, does **not** push live imports, does **not** invent product mappings for new SKUs. |
| Currency | Sample assumes **ILS**, period decimals, comma thousands. Agree currency, tax, and separators with your buyer before production use. |

If you need a human-reviewed agency engagement with destination Matrixify / GMC headers, scope that separately.

### Features

- Preserves **leading-zero SKUs as strings** (e.g. `001`)
- Preserves **Hebrew / UTF-8** titles from the catalog
- **Withholds** conflicting duplicate supplier prices (does not pick one silently)
- **Withholds** invalid / negative prices, empty SKUs, and **unmapped** new SKUs
- Accepts common price shapes (`₪99.00`, `99.00 USD`) — strips symbols/codes; **no FX conversion**
- Optional `currencyNote` recorded in SUMMARY
- One paid event: `row_processed`; proposed changes and exception records are included

### How to reconcile supplier CSV with catalog

1. Paste or upload your **current catalog** CSV (`sku` + `title` + `price` / `price_ils` — or set column overrides).
2. Paste or upload the **supplier update** CSV (`sku` + `price` / `price_ils`).
3. Run the Actor — review **proposed changes** and **exceptions** in the dataset; open `SUMMARY` in the key-value store.
4. Map accepted proposals into your **Matrixify / Shopify / Google Shopping** template offline (this Actor does not push live).

#### Try in one run (synthetic demo)

Leave inputs empty or keep the prefilled defaults. Expected synthetic outcome is under **Sample I/O** — invented products, not production catalogs.

### Input

Provide CSVs as **text fields** and/or **file uploads** (file wins if both set). **All fields optional** — empty runs use bundled demo CSVs.

| Field | Required | Description |
| --- | --- | --- |
| `currentCatalogCsv` / `currentCatalogFile` | no (demo if empty) | Columns: `sku`, `title`, `price_ils` (or `price`) |
| `supplierUpdateCsv` / `supplierUpdateFile` | no (demo if empty) | Columns: `sku`, `price_ils` (or `price`); symbols/`USD`/`ILS` codes stripped |
| `currencyNote` | no | Free-text note stored in summary |
| `skuColumn` / `titleColumn` / `priceColumn` | no | Override defaults — e.g. Shopify `Variant SKU` / `Variant Price`, GMC `id` / `price` |

#### Sample I/O

**Catalog (input)**

```csv
sku,title,price_ils
001,כוס כחולה,89.00
002,כוס אדומה,99.00
003,מגבת פשתן,129.00
```

**Supplier update (input)**

```csv
sku,price_ils
001,₪99.00
002,99.00
003,119.00
003,125.00
004,79.00
005,-5.00
,49.00
```

**Expected synthetic outcome (demo)**

| Result | Count | Treatment |
| --- | ---: | --- |
| Proposed price change | 1 | SKU `001`: 89.00 → 99.00 |
| Unchanged | 1 | SKU `002` stays 99.00 |
| Conflicting duplicates | 2 | Both `003` prices withheld |
| Unmapped new SKU | 1 | `004` needs mapping |
| Invalid price | 1 | Negative withheld |
| Missing SKU | 1 | Row withheld |

**Dataset items (shape)**

- `proposed_change` — `sku`, `title`, `oldPrice`, `proposedPrice`, `difference`, `sourceLine`
- `exception` — `sku`, `sourceLine`, `originalPrice`, `reason`\
  Reasons: `duplicate_sku_requires_resolution`, `new_sku_requires_mapping`, `invalid_price`, `missing_sku`

**Key-value store:** `SUMMARY` — counts, exception tallies, full lists, disclosure flags.

### Pricing

**$0.20 per 1,000 supplier CSV data rows processed** ($0.0002 per row). Catalog lookup, proposed changes, exception records and platform usage are included. There is no separate startup or output charge. The live Pricing tab is authoritative.

For example, 1,000 supplier rows cost $0.20 whether they produce 50 changes, 20 exceptions or no price changes. This is the customer price, not the developer profit.

A synthetic test on build 0.2.1 with 1,000 catalog rows and 1,000 supplier rows completed in 52 seconds at 256 MB. Larger files and different data may take longer. Set a run spending limit and review the final status and output counts before using results.

For scheduled workflows, supply both fresh CSV files explicitly. Missing input can fall back to demonstration data. Require a SUCCEEDED run and verify that dataset item count equals SUMMARY.proposedChangeCount + SUMMARY.exceptionCount before producing an import proposal.

### FAQ

#### Empty run / “Just try it” — will it succeed?

Yes. If both catalog and supplier inputs are empty, the Actor loads bundled `samples/` (or inline fallbacks) and completes with the synthetic demo outcome above. Useful for Store QA and first-look buyers.

#### Is this legal / what are the disclaimers?

You supply your own CSVs. The Actor only compares files you provide; it does not scrape sites or access Shopify/GMC accounts. Review disclosures: synthetic demo, AI-built, no live push, agree currency/tax with your buyer. Output is a proposal for human review.

#### How is this different from Excel VLOOKUP / XLOOKUP?

A spreadsheet can perform this comparison with suitable formulas and validation. This Actor provides a repeatable API run with structured proposals, exceptions and SUMMARY JSON.

#### Shopify / Matrixify / Google Shopping — what does “prep” mean?

**Prep only, unofficial.** Shopify admin CSV, Matrixify, and Google Merchant Center are separate tools. This Actor does **not** emit a finished Matrixify template or GMC feed and does **not** upload anywhere. Typical flow: reconcile here → review → map accepted rows into your destination columns offline → import under your process. Brand names describe common prep destinations only.

#### Which column names should I use?

Defaults: `sku`, `title`, `price_ils` (fallback `price` / `variant_price`). For Shopify Matrixify-style exports, set overrides (e.g. `skuColumn` = `Variant SKU`, `priceColumn` = `Variant Price`). For Google Shopping–style feeds, try `skuColumn` = `id` and `priceColumn` = `price`.

#### Currency, tax, and separators?

No FX conversion and no tax logic. Samples assume ILS-style amounts with period decimals. Confirm currency, VAT/tax, and thousand/decimal separators before production. Optional `currencyNote` is stored in `SUMMARY` only.

#### Will it create new products for unknown SKUs?

No. Unmapped new SKUs → `new_sku_requires_mapping`. Conflicting duplicates → `duplicate_sku_requires_resolution`. Invalid/missing → withheld. Nothing is silently guessed.

### Limitations

- No FX conversion; no tax logic
- New SKUs are never auto-created
- Duplicate conflicting prices are never auto-resolved
- Output is **not** Matrixify/GMC-ready until you map columns with the buyer
- Sample CSVs are synthetic

### Operator

Published by royal\_paddle. Use the Actor Issues tab for reproducible problems. Samples are synthetic and the implementation is AI-assisted.

# Actor input Schema

## `currentCatalogCsv` (type: `string`):

Full current catalog as CSV text. Default columns: sku, title, price (or price\_ils). SKU/title/price aliases (Variant SKU, id, Variant Price, etc.) are auto-tried when overrides are blank. Leading zeros preserved; UTF-8 / Hebrew titles supported. Leave empty to run the bundled synthetic demo.

## `supplierUpdateCsv` (type: `string`):

Supplier price update as CSV text. Default columns: sku, price (or price\_ils). Currency symbols and codes (₪, $, USD, ILS) are stripped when parsing — no FX conversion. Duplicate SKUs with conflicting prices are withheld. Leave empty to run the bundled synthetic demo.

## `currentCatalogFile` (type: `string`):

Optional file upload alternative to currentCatalogCsv text. If both are set, the file wins.

## `supplierUpdateFile` (type: `string`):

Optional file upload alternative to supplierUpdateCsv text. If both are set, the file wins.

## `currencyNote` (type: `string`):

Free-text note recorded in SUMMARY (e.g. ILS, tax-included, Google Shopping feed currency). Does not convert currencies — agree rules with your buyer before production use.

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

Preferred SKU column (case-insensitive). Fallbacks include sku, Variant SKU, id, item\_id, handle.

## `titleColumn` (type: `string`):

Preferred title column in the catalog CSV. Fallbacks include title, name, product\_title.

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

Preferred price column. Fallbacks include price\_ils, price, Variant Price. Accepts values like 99.00, ₪99.00, or 99.00 USD.

## Actor input object example

```json
{
  "currentCatalogCsv": "sku,title,price_ils\n001,כוס כחולה,89.00\n002,כוס אדומה,99.00\n003,מגבת פשתן,129.00",
  "supplierUpdateCsv": "sku,price_ils\n001,₪99.00\n002,99.00\n003,119.00\n003,125.00\n004,79.00\n005,-5.00\n,49.00",
  "currencyNote": "ILS (period decimals; currency symbols stripped from supplier prices)",
  "skuColumn": "sku",
  "titleColumn": "title",
  "priceColumn": "price_ils"
}
```

# Actor output Schema

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

Proposed changes, unchanged SKUs, and exception rows.

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

Counts and currency note written to KEY-VALUE SUMMARY.

# 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 = {
    "currentCatalogCsv": `sku,title,price_ils
001,כוס כחולה,89.00
002,כוס אדומה,99.00
003,מגבת פשתן,129.00`,
    "supplierUpdateCsv": `sku,price_ils
001,₪99.00
002,99.00
003,119.00
003,125.00
004,79.00
005,-5.00
,49.00`
};

// Run the Actor and wait for it to finish
const run = await client.actor("royal_paddle/catalog-reconcile-csv").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 = {
    "currentCatalogCsv": """sku,title,price_ils
001,כוס כחולה,89.00
002,כוס אדומה,99.00
003,מגבת פשתן,129.00""",
    "supplierUpdateCsv": """sku,price_ils
001,₪99.00
002,99.00
003,119.00
003,125.00
004,79.00
005,-5.00
,49.00""",
}

# Run the Actor and wait for it to finish
run = client.actor("royal_paddle/catalog-reconcile-csv").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 '{
  "currentCatalogCsv": "sku,title,price_ils\\n001,כוס כחולה,89.00\\n002,כוס אדומה,99.00\\n003,מגבת פשתן,129.00",
  "supplierUpdateCsv": "sku,price_ils\\n001,₪99.00\\n002,99.00\\n003,119.00\\n003,125.00\\n004,79.00\\n005,-5.00\\n,49.00"
}' |
apify call royal_paddle/catalog-reconcile-csv --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,royal_paddle/catalog-reconcile-csv"
        }
    }
}

```

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/tRdlBE0OKaMgenKyq/builds/qQkiujufzsTJUu2qb/openapi.json
