# GTIN Catalog Guard — Barcode Checks & SKU Conflicts (`brandgard/gtin-catalog-guard`) Actor

Check catalog CSV barcodes in bulk: GTIN/EAN/UPC check digits, damaged formats, missing codes and cross-SKU barcode reuse. JSON, CSV and HTML reports. Structure only; no GS1 registry lookup. $0.10 per completed batch; fixed demo free.

- **URL**: https://apify.com/brandgard/gtin-catalog-guard.md
- **Developed by:** [Brandon Gardner](https://apify.com/brandgard) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.10 / completed catalog check

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?

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

## GTIN Catalog Guard

Check product barcode columns before importing or reconciling a catalog. Find missing identifiers, unsupported lengths, damaged spreadsheet formats, bad check digits and checksum-passing barcodes shared across different SKUs.

**Structure and checksum checking only.** A passing checksum does not prove that a barcode was assigned by GS1, belongs to your brand, identifies the stated product, or will be accepted by a marketplace. This independent utility does not query GS1 and is not affiliated with GS1.

### Try the free demo

Run `{"demo":true}` or use the prefilled form. The fixed synthetic sample includes eight catalog records: three pass the checksum, one is missing, and four are structurally invalid. Two different SKUs share the same barcode represented at different lengths. Seven records need review. Demo accepts no other input fields and never triggers the completed-check fee.

### Check your catalog

Disable **Run fixed demonstration**, paste CSV text including headers, and choose column names if they differ from `sku` and `gtin`.

```json
{
  "demo": false,
  "csvText": "sku,gtin\nITEM-A,036000291452\nITEM-B,0036000291452\nITEM-C,4006381333932\n"
}
```

Optional `skuColumn` and `gtinColumn` select exact header names. Omit these fields in the demo. No URLs, account credentials, images or downloads are accepted. Input records may contain errors: those errors are the report, so a completed batch with invalid barcodes is still charged.

### What is checked

- ASCII digits and lengths 8, 12, 13 or 14; checksum arithmetic for GTIN-8, GTIN-12/UPC-A, GTIN-13/EAN-13 and GTIN-14.
- Missing identifiers, all-zero placeholders, numeric/exponent or punctuation formats, and outer whitespace.
- Checksum-passing identifiers padded to 14 digits for grouping, preserving leading zeros. This can reveal the same identifier stored as UPC-A and EAN-13.
- Repeated barcode groups, cross-SKU barcode reuse, repeated exact SKU text and missing SKUs. These are review signals: legitimate catalog relationships can produce duplicates.

Eight-digit input is interpreted as GTIN-8. **UPC-E expansion is unsupported.** No missing digit or stripped leading zero is guessed. Interior spaces, dashes, currency symbols and scientific notation are rejected. Outer whitespace is trimmed for checking but reported. SKUs remain exact case-sensitive strings. Expected check digits are arithmetic evidence, not replacement product identifiers.

### Reports

The Output tab displays an HTML report with the first 200 records. Storage → Key-value store contains `OUTPUT` (full JSON), `REPORT-CSV` (all records) and `REPORT-HTML`. The default dataset contains one summary for automation, including record counts and cross-SKU group counts. Source record numbers count non-blank data records after the header, not physical lines.

CSV identifier cells are prefixed with an apostrophe to protect spreadsheet formulas and leading zeros. Use JSON when exact raw text is needed. HTML escapes all input and loads no scripts or outside resources. Only selected SKU and GTIN columns are returned; other source columns are not exported or logged.

### Limits and pricing

**$0.10 per completed batch**, platform usage included. Up to 5,000 non-blank records, 2 MB UTF-8 CSV, 200 distinct headers, 16,384 characters per field and 256 characters per selected SKU/GTIN cell. Each export is limited to 8 MB. Header-only CSV, malformed CSV, missing selected headers, ragged rows and oversized inputs fail without a completion event. Split an oversized catalog into batches. The active Pricing tab is authoritative.

There is no separate startup or per-row fee. A successful no-issue check is charged too. Set maximum run cost to at least $0.10 for custom input. Reports and summary are saved before charging. Retries in the same run use a stable billing key; resurrection can append another summary, but does not charge a second completed-check event in that run. A new run is a new purchase.

This is a stateless, on-demand checker. Your own workflow supplies each catalog through Console, a saved task or the Apify API. It does not monitor stores or change listings. Inputs and reports remain in the caller's Apify storage under the caller's access and retention settings. The Actor does not delete them or send them to outside services.

For registered ownership and product information, consult [Verified by GS1](https://support.gs1.org/support/solutions/articles/43000734070/). Arithmetic follows the [GS1 check digit method](https://www.gs1.org/services/how-calculate-check-digit-manually); shorter identifiers are padded only for comparison as described in [GS1's format guidance](https://support.gs1.org/support/solutions/articles/43000734355-what-is-the-required-format-of-gtin-in-gs1-edi-standards-).

For support, open an Actor issue with a run ID and a small synthetic example. Never post private source catalogs publicly.

# Actor input Schema

## `demo` (type: `boolean`):

Free synthetic sample. Disable before adding custom fields.

## `csvText` (type: `string`):

CSV text with headers. Up to 5,000 records / 2 MB UTF-8. Omit in demo.

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

Exact header name. Defaults to sku when omitted. Omit in demo.

## `gtinColumn` (type: `string`):

Exact header name. Defaults to gtin when omitted. Omit in demo.

## Actor input object example

```json
{
  "demo": true
}
```

# Actor output Schema

## `html` (type: `string`):

No description

## `csv` (type: `string`):

No description

## `report` (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 = {
    "demo": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("brandgard/gtin-catalog-guard").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 = { "demo": True }

# Run the Actor and wait for it to finish
run = client.actor("brandgard/gtin-catalog-guard").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 '{
  "demo": true
}' |
apify call brandgard/gtin-catalog-guard --silent --output-dataset

```

## MCP server setup

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

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/mti7Dhkp1zw51eOLI/builds/Wr1NOQbUiZWZ8OzcO/openapi.json
