# JSON Schema Checker and Schema Inference (`brightwater-tools/json-schema-validator-generator`) Actor

Validate a JSON document against a JSON Schema and list each failing path with its message, or infer a draft 2020-12 schema from JSON samples. Unsupported keywords are reported, not enforced. Makes no outside requests in its own code.

- **URL**: https://apify.com/brightwater-tools/json-schema-validator-generator.md
- **Developed by:** [Brightwater Tools](https://apify.com/brightwater-tools) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 successful validation or inferences

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

## JSON Schema Checker and Schema Inference

Check one JSON document against a JSON Schema and get every failing path with its message, or infer a JSON Schema (draft 2020-12) from one document or several samples. Paste your JSON, pick a mode, get the result. Each run does one mode.

**$0.005 per successful run (UNCONFIRMED against the live Store).** Failed runs are not charged.

### What you can do with it

- **Check an API payload or config file** against the schema your team agreed on, and see every field that breaks it, with its JSON Pointer path such as `/items/2/sku`.
- **Start a schema from examples.** Paste a few sample records and get a draft 2020-12 schema with the types, the properties, and the properties that appear in every sample as `required`.
- **Use it as a step** in your Apify integrations, Make, Zapier or n8n workflows, or call it from the **Apify API**.

### How to use it

1. Choose a **mode**: `validate` to check data against a schema, or `infer` to build a schema from data.
2. Fill in the fields for that mode (see below).
3. Click **Start**. The result appears in the **Output** tab and the dataset.

#### Mode: validate

| Field | What to enter |
|---|---|
| `data` | The JSON document to check (required) |
| `schema` | The JSON Schema to check it against |
| `max_input_bytes` | Optional size limit for `schema` and for `data`, each checked separately (default 1,000,000; up to 5,000,000) |

Example input:

```json
{
  "mode": "validate",
  "schema": "{\"type\": \"object\", \"required\": [\"part\", \"qty\"], \"properties\": {\"part\": {\"type\": \"string\"}, \"qty\": {\"type\": \"integer\", \"minimum\": 1}}}",
  "data": "{\"part\": \"Bolt M6\", \"qty\": 0}"
}
```

Output (one dataset item):

```json
{
  "mode": "validate",
  "valid": false,
  "error_count": 1,
  "errors": [
    { "path": "/qty", "message": "must be at least 1, found 0", "keyword": "minimum" }
  ],
  "unsupported_keywords": [],
  "sample_count": null,
  "schema": null
}
```

Each error has a `path` (a JSON Pointer; an empty string means the whole document), a `message` and the `keyword` that failed. Every error is listed, not only the first.

#### Mode: infer

| Field | What to enter |
|---|---|
| `data` | One JSON document, or a JSON array of samples (required). Any value in the `schema` field is ignored. |
| `max_input_bytes` | Optional size limit for the data (same rules as above) |

In infer mode a top-level array is read as a list of samples, one per item. A single object or value is read as one document. To infer the schema of an array value itself, wrap it in another array. An empty array is refused.

Example input:

```json
{
  "mode": "infer",
  "data": "[{\"part\": \"Bolt M6\", \"qty\": 4}, {\"part\": \"Nut M6\"}]"
}
```

Output (one dataset item):

```json
{
  "mode": "infer",
  "valid": null,
  "error_count": 0,
  "errors": [],
  "unsupported_keywords": [],
  "sample_count": 2,
  "schema": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "properties": {
      "part": { "type": "string" },
      "qty": { "type": "integer" }
    },
    "required": ["part"]
  }
}
```

How the schema is built:

- A key that appears in every object sample is `required`. A key missing from some samples is optional.
- Numbers written without a decimal point give `integer`. A mix of whole and decimal numbers gives `number`.
- Mixed kinds give a list of types, for example `["null", "string"]` when a value is sometimes `null`.
- Items of all arrays are merged into one `items` schema.
- The inferred schema does not include `enum`, `format`, length limits or ranges.

### Keywords the validator enforces

Validation covers a subset of JSON Schema, not a full validator for any draft. In validate mode these 24 keywords are enforced. Keywords next to `$ref` are applied too.

| Group | Keywords |
|---|---|
| Types and fixed values | `type`, `enum`, `const` |
| Strings | `minLength`, `maxLength`, `pattern` |
| Numbers | `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`, `multipleOf` |
| Objects | `required`, `properties`, `additionalProperties` |
| Arrays | `items`, `prefixItems`, `minItems`, `maxItems`, `uniqueItems` |
| Combining schemas | `allOf`, `anyOf`, `oneOf`, `not` |
| References | `$ref` (local only: it must point into `$defs` or `definitions`) |

Notes on the rules:

- `pattern` uses Python's regular expression syntax and matches anywhere in the string. A pattern written for another validator may behave slightly differently.
- `minLength` and `maxLength` count Unicode code points.
- `multipleOf` compares the decimal values as written, so `0.3` is a multiple of `0.1`.
- `integer` accepts `2.0`. `true` is not a number, and `1` does not equal `true` in `const`, `enum` or `uniqueItems`.

### Keywords that are reported, not enforced

Any other keyword in the schema is **not enforced**. It is listed in `unsupported_keywords` with its schema path, so you can see what was skipped. The result is still based only on the supported keywords. Examples: `format`, `contains`, `minProperties`, `maxProperties`, `patternProperties`, `propertyNames`, `if`, `then`, `else`, `dependentRequired`, `dependentSchemas`, `unevaluatedProperties` and `unevaluatedItems`. Keywords nested inside an unsupported keyword are not read and are not listed.

Annotation keywords (`$schema`, `$id`, `$comment`, `title`, `description`, `default`, `examples`) are ignored and not listed.

A schema is **refused** with a message, and the run is not charged, when:

- a supported keyword has the wrong shape (for example `"required": "a"` or `"minimum": "1"`),
- a `$ref` points outside `$defs` or `definitions`, or to a target that does not exist,
- `items` is given as an array of schemas (the draft-07 tuple form). Use `prefixItems` for that.

The draft named in the schema's `$schema` is not used to choose the rules in validate mode. The draft 2020-12 name applies only to the schema that infer mode writes.

### Pricing

- **$0.005 per successful run**, in either mode (UNCONFIRMED against the live Store).
- **Failed runs are not charged**: bad input, a refused schema, or data too large.

### Good to know

- **Size limit:** the schema and the data are each limited to 1 MB by default (`max_input_bytes`, up to 5 MB).
- **Only JSON is accepted.** `NaN`, `Infinity` and numbers too large for a standard floating-point value are refused.
- **Nesting depth:** Nesting deeper than 200 levels is rejected with a clear error.

### FAQ

**Does it send my data anywhere?** No. The actor's own code makes no outside requests. Results are saved to your run's dataset on Apify, as with any Apify actor.

**Which schema draft does validation follow?** None is selected. The same keyword set applies whatever `$schema` the schema names. Keywords outside the set are listed as unsupported.

**Can I call it from code?** Yes, through the Apify API or the Apify client for JavaScript or Python, like any Apify actor.

**I found a bug or need a keyword.** Open an issue on this actor's Issues tab.

### AI use

This actor was written with the help of AI coding tools. The rules above describe exactly what the validation and inference do.

***

Made by Brightwater Tools.

# Actor input Schema

## `mode` (type: `string`):

'validate' checks the JSON in 'JSON data' against the schema in 'JSON Schema' for a listed subset of keywords and lists every error they find. Keywords outside that subset are reported, not enforced. 'infer' builds a draft 2020-12 schema from the JSON in 'JSON data' and ignores 'JSON Schema'.

## `schema` (type: `string`):

The JSON Schema to check the data against. Used only in validate mode. Only the supported keywords are enforced; any other keyword is reported in the output as unsupported and is not enforced. Local references must point into $defs or definitions.

## `data` (type: `string`):

The JSON text to check (validate mode), or the JSON to infer a schema from (infer mode). In infer mode a top-level array is read as a list of samples, one per item, and a single object or value is read as one document. To infer the schema of an array value itself, wrap it in another array.

## `max_input_bytes` (type: `integer`):

The schema text and the data text are each refused if they are larger than this. The hard ceiling is 5,000,000 bytes.

## Actor input object example

```json
{
  "mode": "validate",
  "schema": "{\n  \"type\": \"object\",\n  \"required\": [\"part_name\", \"qty\"],\n  \"properties\": {\n    \"part_name\": { \"type\": \"string\", \"minLength\": 1 },\n    \"qty\": { \"type\": \"integer\", \"minimum\": 1 }\n  },\n  \"additionalProperties\": false\n}",
  "data": "{\n  \"part_name\": \"Bolt M6\",\n  \"qty\": 1\n}",
  "max_input_bytes": 1000000
}
```

# Actor output Schema

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

One item per run: in validate mode, 'valid', every error with its path, keyword and message, and any unsupported schema keywords; in infer mode, the inferred 'schema' and the sample count.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("brightwater-tools/json-schema-validator-generator").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("brightwater-tools/json-schema-validator-generator").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 '{}' |
apify call brightwater-tools/json-schema-validator-generator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,brightwater-tools/json-schema-validator-generator"
        }
    }
}
```

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/Xfe5jm96tNIbrYgHb/builds/tjxbafxszwBut4VwB/openapi.json
