Supplier Catalog Price Change Audit
Pricing
$0.25 / completed catalog audit
Supplier Catalog Price Change Audit
Compare supplier CSV or JSON catalogs by SKU. Find exact price changes, added/removed products and duplicate warnings. The dataset is a summary; get full SKU details from the run's key-value store record OUTPUT.
Pricing
$0.25 / completed catalog audit
Rating
0.0
(0)
Developer
Anthony Rosas
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
13 hours ago
Last modified
Categories
Share
Compare two supplier catalog exports by SKU and review price increases, price decreases, added products, removed products, and records that need attention.
This tool is designed for a recurring task: a supplier sends an updated price list, and you need to understand what changed before updating your own catalog. It uses explicit identifiers and decimal arithmetic. It does not guess product matches or update your store.
$0.25 per completed audit, including platform usage. See the live Pricing tab.
A completed audit is charged once when paid pricing is enabled, including audits that report data-quality issues or exclude all supplied records. An input-validation failure that prevents an audit from being produced does not emit a completed-audit charge. Review the issues and excluded-record totals alongside the changes.
Quick start
Supply the previous and current CSV contents, including a header row. The default column names are sku and price.
{"beforeCsv": "sku,price\n00123,12.50\n00456,8.00\nOLD-1,5.00\nDUP-1,1.00\nDUP-1,2.00\n","afterCsv": "sku,price\n00123,13.25\n00456,7.50\nNEW-1,4.00\nDUP-1,1.50\n","currency": "USD"}
This example contains:
- SKU
00123: price increases by0.75, or 6%. - SKU
00456: price decreases by0.50, or 6.25%. NEW-1: added to the current file.OLD-1: absent from the current file.DUP-1: ambiguous because the previous file contains two rows with that SKU. Its records need review; the audit does not select a price arbitrarily.
Leading zeros in 00123 and 00456 are part of the identifiers.
You can also supply arrays of objects. Use strings for identifiers and prices so earlier software does not remove leading zeros or round decimal amounts.
{"beforeRows": [{ "sku": "00123", "price": "12.50" },{ "sku": "00456", "price": "8.00" }],"afterRows": [{ "sku": "00123", "price": "13.25" },{ "sku": "00456", "price": "7.50" }],"currency": "USD"}
Provide exactly one previous source (beforeCsv or beforeRows) and exactly one current source (afterCsv or afterRows). You can mix formats between the two sides. The first release accepts pasted or programmatically supplied contents. It does not fetch URLs, download files, or connect to supplier accounts.
Column mapping
If both files use different names from the defaults:
{"beforeCsv": "Product Code,Unit Cost\nA-100,19.95\n","afterCsv": "Product Code,Unit Cost\nA-100,20.45\n","skuColumn": "Product Code","priceColumn": "Unit Cost","currency": "USD"}
If names differ between the two exports, use the corresponding overrides:
| Input | Purpose | Default |
|---|---|---|
skuColumn | Shared identifier column | sku |
priceColumn | Shared price column | price |
beforeSkuColumn, afterSkuColumn | Identifier column for one side | Shared identifier column |
beforePriceColumn, afterPriceColumn | Price column for one side | Shared price column |
currency | Currency label attached to the audit; does not convert values | USD |
delimiter | CSV separator: ,, ;, or a tab character (\t in JSON) | , |
decimalSeparator | Decimal point convention: . or , | . |
trimSkus | Ignore leading and trailing whitespace around identifiers | true |
caseSensitiveSkus | Treat uppercase and lowercase identifiers as distinct | true |
Trimming or ignoring case can make two previously distinct identifiers collide. Such collisions are reported as duplicate identifiers rather than silently merged. Header names must match the column mapping you provide.
Reading the audit
The run's key-value store contains:
| Record | Contents |
|---|---|
OUTPUT | JSON object with summary, changes, and issues. |
changes.csv | Downloadable product comparison report. |
issues.csv | Downloadable issues report. |
The Actor also writes an audit summary row to the default dataset, including when no prices changed or all records need review. The complete JSON and CSV reports remain in the key-value store. Downloadable CSV reports are intended for review in spreadsheet applications; formula-like text, including negative delta strings, receives a leading apostrophe. Use the canonical JSON values for numeric processing.
When importing a CSV into a spreadsheet, set the SKU column to text so the spreadsheet preserves leading zeros. The JSON report retains SKU strings without relying on spreadsheet import settings.
Each change record contains status, sku, oldPrice, newPrice, deltaAmount, deltaPercent, beforeRow, afterRow, and currency. Added and removed records have null deltas. Monetary values are strings with unnecessary trailing zeros removed. For example, a change from 12.50 to 13.25 has deltaAmount equal to "0.75".
The summary reports beforeRows, afterRows, beforeValidRows, afterValidRows, comparedSkus, unchanged, increased, decreased, added, removed, excludedSkus, excludedRows, issueCount, and hasIssues, plus currency and priceScale. comparedSkus includes valid matches whose prices are unchanged. excludedSkus counts identifiable excluded keys; missing identifiers contribute to excludedRows only.
Issues include a code, severity, source, sku, row, rows, and message. Issue codes are MISSING_SKU, INVALID_PRICE, DUPLICATE_SKU, and ZERO_BASELINE. Row numbers refer to logical data records with a header offset: the first data record is row 2 for both CSV and arrays. They are not physical line numbers when a CSV contains blank lines or quoted multiline values.
Price differences use exact decimal amounts with up to six fractional digits. Percentage changes are derived from the previous price and rounded to two decimal places, with halves rounded up in magnitude. When that price is zero, deltaPercent is null and a ZERO_BASELINE warning explains why.
Duplicate or missing identifiers cannot be confidently matched. Invalid prices are reported as issues rather than treated as zero. Check the issues and excluded-record counts alongside the price report before acting on the results.
An item missing from the new export is absent from that export. It is not proof that the supplier discontinued it; an incomplete export can produce the same result.
Repeat the workflow
- Keep the previous complete supplier export.
- Obtain the current export using the same scope and price convention.
- Submit both contents with the saved column mapping.
- Review issues and price changes before making downstream changes.
- Save the new export as the baseline for the next comparison.
The Actor does not retain a managed baseline between runs. Your existing automation supplies both versions each time. Reports stay in the run's Apify storage and follow that account's storage and retention settings.
Run from an automation or AI agent
Use the Actor name anthonyyrosas/supplier-catalog-price-audit. Supply both complete snapshots on every call; rerunning unchanged saved input compares the same files again. Set a maximum run cost of $0.25 and wait for the run to succeed before retrieving its reports.
For a Node.js workflow using the official apify-client package, set your own APIFY_TOKEN environment variable and read the two local CSV files:
import { readFile } from 'node:fs/promises';import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const input = {beforeCsv: await readFile('previous.csv', 'utf8'),afterCsv: await readFile('current.csv', 'utf8'),currency: 'USD',};const run = await client.actor('anthonyyrosas/supplier-catalog-price-audit').call(input, { build: 'latest', memory: 512, timeout: 60,maxTotalChargeUsd: 0.25 });if (run.status !== 'SUCCEEDED') throw new Error(`Audit ${run.id}: ${run.status}`);const report = await client.keyValueStore(run.defaultKeyValueStoreId).getRecord('OUTPUT');if (!report) throw new Error(`Audit ${run.id}: report unavailable`);const { summary, changes, issues } = report.value;console.log(JSON.stringify({ summary, changes, issues }, null, 2));
The default dataset contains summary counts only. To answer which SKUs changed, retrieve OUTPUT from that run's default key-value store. AI clients using Apify MCP can inspect the Actor with fetch-actor-details and execute it with call-actor. With the relevant run and storage tools enabled, use get-actor-run to obtain defaultKeyValueStoreId, then get-key-value-store-record for OUTPUT. A dataset-only preview is insufficient for individual SKU details. Authentication, supplier data access and spending permission come from the caller's own account.
Keep your API token in your automation's secret settings. Schedule the surrounding workflow at the supplier's actual update cadence, then review exclusions before making changes to a store.
Scope and limits
- Maximum 10,000 combined data records across the previous and current inputs, subject to the 5 MiB combined input limit (5,242,880 UTF-8 bytes). Arrays are measured as their JSON representation.
- At most 200 columns per row and 65,536 characters per header or text field.
- UTF-8 CSV contents or arrays of flat objects; no Excel workbooks, PDFs, OCR, URLs, or external API connections.
- One currency and one price basis per audit. Compare equivalent units, tax treatment, and pack sizes. The currency field labels values and does not verify or convert them.
- Nonnegative plain decimal prices, at most six fractional digits and 24 integer digits. Surrounding whitespace and a leading
+are accepted. Use the declared decimal separator for text prices; JSON numeric prices use the standard dot. Remove currency symbols, thousands separators and exponent notation in the source export. - Matching by one explicitly selected identifier, with no fuzzy matching or cross-supplier product reconciliation.
- Reports explain the supplied data. They do not certify Shopify import compatibility or write changes to any store.
For a useful issue report, provide a small synthetic or redacted example and the input settings. Avoid publishing a private supplier price list in a public support thread.