# ONIX 3 Feed Checker (Book Metadata) (`madrasco/onix-feed-checker`) Actor

Checks ONIX for Books 3.0/3.1 XML feeds against EDItEUR's schema and code lists, plus rules the schema misses (ISBN-13 check digits, real dates, price, currency, territory, contributor). One row per issue with record, field path and line, plus an HTML/Markdown report.

- **URL**: https://apify.com/madrasco/onix-feed-checker.md
- **Developed by:** [Madrasco](https://apify.com/madrasco) (community)
- **Categories:** Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## 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

## ONIX 3 Feed Checker (Book Metadata)

Check ONIX for Books **3.0 and 3.1** XML feeds before you send them. Give the actor one or more file URLs; it returns **one row per problem** with the record reference, field path, line number, severity, rule and a plain-English message, plus a readable **HTML and Markdown report**.

### What it checks

1. **Well-formed XML** and the right ONIX root element and namespace (reference names or short tags, detected automatically).
2. **Schema validity** against EDItEUR's published ONIX for Books XSD (3.0.8 or 3.1.3) — elements missing, misplaced or not allowed.
3. **Code-list values** (EDItEUR code lists Issue 74) — e.g. an unknown ProductForm or currency code.
4. **Rules the schema cannot check**, each with its source shown in the output:

| Rule | Severity | Source |
|---|---|---|
| ISBN-13 / GTIN-13 check digit | error | GS1 check-digit method; ISBN Users' Manual |
| ISBN-13 is 13 digits starting 978/979, no hyphens | error | ISBN Users' Manual |
| ISBN-13 sent without the matching GTIN-13 (type 03) | warning | ONIX 3.0 spec P.2 |
| No ISBN-13 or GTIN-13 at all | warning | ONIX 3.0 spec P.2 |
| Duplicate RecordReference in one message | error | ONIX 3.0 spec P.1 |
| DescriptiveDetail / PublishingDetail missing from a full record | error | ONIX 3.0 spec Blocks 1 and 4 |
| No distinctive title (TitleType 01) | warning | ONIX 3.0 spec P.6 |
| No Contributor, ContributorStatement or NoContributor | warning | ONIX 3.0 spec P.7.52 |
| ProductForm 00 (undefined) | warning | ONIX 3.0 spec P.3.2, List 150 |
| No publishing status, globally or per market | error | ONIX 3.0 spec P.20.1 |
| No publication date, globally or per market | warning | ONIX 3.0 spec P.20 / P.25 |
| No ProductSupply block, or no price in any market | warning | ONIX 3.0 spec Block 6, P.26 |
| Price with no currency and no DefaultCurrencyCode | error | ONIX 3.0 spec P.26.71 |
| Market territory with no countries or regions included | warning | ONIX 3.0 spec P.24 |
| Dates that are not real dates in their stated format (e.g. 20260231) | error | ONIX 3.0 spec, List 55 |

EDItEUR's own best-practice guide points out that a conventional schema cannot check things such as the check digits of identifiers, so schema validation alone is not enough; the rules above cover some of that gap.

### What it does not do

- It does **not** guarantee that Amazon, Apple, Kobo, Ingram or any other recipient will accept your feed. Each recipient has its own extra requirements; this checks the ONIX standard and the rules listed above only.
- No EDItEUR "strict" (XSD 1.1) co-occurrence checks beyond the rules listed.
- ONIX 2.1 files are not supported.

### Input

- **ONIX file URLs** (required): direct links to `.xml`, `.xml.gz`, or a `.zip` holding one or more `.xml` files (each checked and reported separately as `URL#name`, up to 50 per zip). Up to 50 URLs per run. Files must be reachable from the internet (e.g. a signed link from your storage).
  The form comes prefilled with a small demo file written by Madrasco (a fictional publisher and books, with deliberate errors), so a first run shows what the issues look like.
- **Include warnings** (default on), **Maximum issues per file** (default 5,000), **Maximum file size** (default 200 MB; as a rough guide, give the run about 10x the file size in memory).

### Output

**Dataset**, one row per issue:

```json
{"fileUrl": "https://example.com/feed.xml", "recordReference": "example.press.0001", "productIndex": 1,
 "line": 13, "fieldPath": "/ONIXMessage/Product[1]/ProductIdentifier[2]/IDValue", "severity": "error",
 "rule": "gtin13-check-digit", "message": "ISBN-13 '9780000000018' has a wrong check digit.",
 "source": "GS1, How to calculate a check digit manually, ...; International ISBN Agency, ISBN Users' Manual ..."}
```

A clean file gives a single `no-issues` row; a file that cannot be downloaded gives a `fetch-failed` row.

**Key-value store**: `REPORT.html` and `REPORT.md` (summary per file, issues by rule, issue table, sources), `OUTPUT` (JSON totals).

### Privacy

Your file is downloaded into the run, checked, and not kept by us beyond your own Apify storage. Nothing is sent anywhere else.

### Support

Open an issue on the actor's Issues tab. This actor is built and maintained with AI assistance by Madrasco; a human owner can be reached on request through the Issues tab.

ONIX is a standard published by EDItEUR. This actor is independent and not affiliated with or endorsed by EDItEUR.

ONIX for Books, its schemas and code lists are © EDItEUR (https://www.editeur.org/), used unmodified under the EDItEUR licence (https://doi.org/10.4400/nwgj).

# Actor input Schema

## `urls` (type: `array`):

Direct links to ONIX 3.0 or 3.1 XML files (reference names or short tags). Plain .xml, .xml.gz, or a .zip holding one or more .xml files (each checked separately, up to 50 per zip). Up to 50 URLs per run.

## `includeWarnings` (type: `boolean`):

Also report recommended-practice gaps (missing publication date, contributor, price...). Turn off to see only errors.

## `maxIssuesPerFile` (type: `integer`):

Stop listing issues for a file after this many (the totals in OUTPUT still count all).

## `maxFileSizeMb` (type: `integer`):

Files larger than this are reported as a download failure. Large files need more run memory (about 10x the file size).

## Actor input object example

```json
{
  "urls": [
    "https://api.apify.com/v2/key-value-stores/sQTsKf70UcAc4U4uT/records/demo_errors.xml"
  ],
  "includeWarnings": true,
  "maxIssuesPerFile": 5000,
  "maxFileSizeMb": 200
}
```

# Actor output Schema

## `issues` (type: `string`):

One dataset row per issue: file, record, field path, line, severity, rule and message.

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

Readable report of all checked files (a Markdown copy is stored as REPORT.md).

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

Totals per file and severity.

# 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 = {
    "urls": [
        "https://api.apify.com/v2/key-value-stores/sQTsKf70UcAc4U4uT/records/demo_errors.xml"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("madrasco/onix-feed-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 = { "urls": ["https://api.apify.com/v2/key-value-stores/sQTsKf70UcAc4U4uT/records/demo_errors.xml"] }

# Run the Actor and wait for it to finish
run = client.actor("madrasco/onix-feed-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 '{
  "urls": [
    "https://api.apify.com/v2/key-value-stores/sQTsKf70UcAc4U4uT/records/demo_errors.xml"
  ]
}' |
apify call madrasco/onix-feed-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,madrasco/onix-feed-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/seurBMqfVdXKbBEjR/builds/cBNlaqzkytgTuwz2H/openapi.json
