# Dataset Schema Guard — Validate & Quarantine Records (`orangepinlabs/dataset-schema-guard`) Actor

Validate any Apify dataset with required fields, types, ranges, regex, allowed values, lengths, uniqueness, and unexpected-field checks. Separate valid records from rejected records with exact failure reasons.

- **URL**: https://apify.com/orangepinlabs/dataset-schema-guard.md
- **Developed by:** [Orange Pin Labs](https://apify.com/orangepinlabs) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.02 / 1,000 validated records

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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

## Dataset Schema Guard

Stop malformed scraper output before it reaches automations, APIs, customers, or databases.

Dataset Schema Guard validates every record in an existing Apify dataset—or a pasted inline sample—against explicit field rules. Clean records are copied unchanged into a valid dataset. Failed records go to a separate rejected dataset with the original source index, the untouched record, and an exact list of errors.

### What it checks

- Required nested fields using dot paths such as `contact.email`
- JSON-compatible types: string, number, integer, boolean, array, and object
- Empty strings, arrays, and objects
- Numeric minimum and maximum values
- String and array length limits
- JavaScript regular expressions
- Exact allowed-value lists
- Duplicate values within the source dataset
- Unexpected top-level fields when strict mode is enabled

The source dataset is read-only and is never modified.

Leave **Source dataset** blank to validate the inline records shown in the input form. When a source dataset is selected, it takes precedence and the inline demo records are ignored.

### Example input

```json
{
  "sourceDatasetId": "YOUR_DATASET_ID",
  "rules": [
    {
      "field": "id",
      "required": true,
      "type": "string",
      "allowEmpty": false,
      "unique": true
    },
    {
      "field": "contact.email",
      "required": true,
      "type": "string",
      "pattern": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$"
    },
    {
      "field": "score",
      "required": false,
      "type": "number",
      "min": 0,
      "max": 100
    },
    {
      "field": "status",
      "type": "string",
      "allowedValues": ["new", "approved", "rejected"]
    }
  ],
  "rejectUnknownTopLevelFields": false,
  "maxErrorsPerRecord": 20,
  "maxItems": 100000
}
````

### Outputs

Each run produces:

- **Valid dataset** — original records that passed every rule, unchanged and ready for downstream use.
- **Rejected dataset** — wrappers containing `sourceIndex`, `errorCount`, `errors`, and the original `record`.
- **Result manifest** — dataset IDs, API URLs, and item counts for both result datasets.
- **OUTPUT summary** — processed, valid, rejected, total-error, completion, and per-error-code totals.

Each validation error includes the field, stable error code, human-readable message, expected value, and actual value when useful. Duplicate errors also point to the first source index where the value appeared.

### Uniqueness behavior

For a rule with `unique: true`, the first appearance of a value is accepted. Later appearances are rejected and reference the first record's zero-based source index. Missing optional values do not participate in uniqueness checks.

### Pricing

Pay per source record validated:

- Actor start: Apify's standard low-cost start event
- `validated-record`: **$0.00002 per record** ($0.02 per 1,000)

One source record creates at most one validation charge, regardless of the number of field rules or errors. The Actor stops cleanly before processing unpaid records when the run's spending limit is reached.

### Limits and safety

- Up to 100 field rules per run
- Up to 1,000,000 source records, controlled by `maxItems`
- Up to 100 recorded errors per rejected record
- Regular expressions are compiled before dataset processing begins
- No proxy, browser, LLM, or external API is used
- Runs under Apify limited permissions and accesses only the selected source dataset plus its own run storages

### Local development

```bash
npm install
npm test
npm start
```

Built by [Orange Pin Labs](https://orangepinlabs.vercel.app/): practical plugins, APIs, and applications for stubborn operational problems.

# Actor input Schema

## `sourceDatasetId` (type: `string`):

Dataset ID or name containing the records to validate. The source is read-only.

## `records` (type: `array`):

Optional JSON records for instant testing. Used only when Source dataset is blank.

## `rules` (type: `array`):

Schema rules for nested dot-path fields. Use the JSON editor to add required fields, types, ranges, patterns, allowed values, and uniqueness checks.

## `rejectUnknownTopLevelFields` (type: `boolean`):

When enabled, a record is rejected if it contains a top-level field not represented by any rule.

## `maxErrorsPerRecord` (type: `integer`):

Caps the error list for badly malformed records while continuing validation.

## `maxItems` (type: `integer`):

Safety limit. The run fails before validation if the source dataset is larger.

## Actor input object example

```json
{
  "records": [
    {
      "id": "lead-001",
      "contact": {
        "email": "ada@example.com"
      },
      "score": 92
    },
    {
      "id": "lead-002",
      "contact": {
        "email": "grace@example.com"
      },
      "score": 78
    },
    {
      "id": "lead-003",
      "contact": {
        "email": "not-an-email"
      },
      "score": 110
    }
  ],
  "rules": [
    {
      "field": "id",
      "required": true,
      "type": "string",
      "allowEmpty": false,
      "unique": true
    },
    {
      "field": "contact.email",
      "required": true,
      "type": "string",
      "pattern": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$"
    },
    {
      "field": "score",
      "required": false,
      "type": "number",
      "min": 0,
      "max": 100
    }
  ],
  "rejectUnknownTopLevelFields": false,
  "maxErrorsPerRecord": 20,
  "maxItems": 100000
}
```

# Actor output Schema

## `manifest` (type: `string`):

No description

## `valid` (type: `string`):

No description

## `rejected` (type: `string`):

No description

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

// Run the Actor and wait for it to finish
const run = await client.actor("orangepinlabs/dataset-schema-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("orangepinlabs/dataset-schema-guard").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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 orangepinlabs/dataset-schema-guard --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=orangepinlabs/dataset-schema-guard",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Dataset Schema Guard — Validate & Quarantine Records",
        "description": "Validate any Apify dataset with required fields, types, ranges, regex, allowed values, lengths, uniqueness, and unexpected-field checks. Separate valid records from rejected records with exact failure reasons.",
        "version": "0.1",
        "x-build-id": "WLDweUtsa3QgZtOgK"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/orangepinlabs~dataset-schema-guard/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-orangepinlabs-dataset-schema-guard",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/orangepinlabs~dataset-schema-guard/runs": {
            "post": {
                "operationId": "runs-sync-orangepinlabs-dataset-schema-guard",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/orangepinlabs~dataset-schema-guard/run-sync": {
            "post": {
                "operationId": "run-sync-orangepinlabs-dataset-schema-guard",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "rules"
                ],
                "properties": {
                    "sourceDatasetId": {
                        "title": "Source dataset",
                        "type": "string",
                        "description": "Dataset ID or name containing the records to validate. The source is read-only."
                    },
                    "records": {
                        "title": "Inline records",
                        "maxItems": 10000,
                        "type": "array",
                        "description": "Optional JSON records for instant testing. Used only when Source dataset is blank.",
                        "items": {
                            "type": "object"
                        },
                        "default": [
                            {
                                "id": "lead-001",
                                "contact": {
                                    "email": "ada@example.com"
                                },
                                "score": 92
                            },
                            {
                                "id": "lead-002",
                                "contact": {
                                    "email": "grace@example.com"
                                },
                                "score": 78
                            },
                            {
                                "id": "lead-003",
                                "contact": {
                                    "email": "not-an-email"
                                },
                                "score": 110
                            }
                        ]
                    },
                    "rules": {
                        "title": "Field rules",
                        "minItems": 1,
                        "maxItems": 100,
                        "type": "array",
                        "description": "Schema rules for nested dot-path fields. Use the JSON editor to add required fields, types, ranges, patterns, allowed values, and uniqueness checks.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "field": {
                                    "title": "Field path",
                                    "type": "string",
                                    "description": "Dot path such as contact.email or product.price."
                                },
                                "required": {
                                    "title": "Required",
                                    "type": "boolean",
                                    "description": "Reject the record when this field is missing, null, or undefined.",
                                    "default": true
                                },
                                "type": {
                                    "title": "Data type",
                                    "type": "string",
                                    "description": "Expected JSON-compatible type.",
                                    "enum": [
                                        "any",
                                        "string",
                                        "number",
                                        "integer",
                                        "boolean",
                                        "array",
                                        "object"
                                    ],
                                    "default": "any"
                                },
                                "allowEmpty": {
                                    "title": "Allow empty values",
                                    "type": "boolean",
                                    "description": "Allow empty strings, arrays, and objects.",
                                    "default": true
                                },
                                "min": {
                                    "title": "Minimum number",
                                    "type": "number",
                                    "description": "Inclusive minimum for numeric fields."
                                },
                                "max": {
                                    "title": "Maximum number",
                                    "type": "number",
                                    "description": "Inclusive maximum for numeric fields."
                                },
                                "minLength": {
                                    "title": "Minimum length",
                                    "type": "integer",
                                    "description": "Inclusive minimum length for strings and arrays.",
                                    "minimum": 0
                                },
                                "maxLength": {
                                    "title": "Maximum length",
                                    "type": "integer",
                                    "description": "Inclusive maximum length for strings and arrays.",
                                    "minimum": 0
                                },
                                "pattern": {
                                    "title": "Regular expression",
                                    "type": "string",
                                    "description": "JavaScript regular expression applied to string fields."
                                },
                                "allowedValues": {
                                    "title": "Allowed values",
                                    "type": "array",
                                    "description": "Exact string values accepted for the field.",
                                    "editor": "stringList",
                                    "items": {
                                        "type": "string"
                                    }
                                },
                                "unique": {
                                    "title": "Require unique values",
                                    "type": "boolean",
                                    "description": "Reject later records that repeat this value.",
                                    "default": false
                                }
                            },
                            "required": [
                                "field"
                            ]
                        },
                        "default": [
                            {
                                "field": "id",
                                "required": true,
                                "type": "string",
                                "allowEmpty": false,
                                "unique": true
                            },
                            {
                                "field": "contact.email",
                                "required": true,
                                "type": "string",
                                "pattern": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$"
                            },
                            {
                                "field": "score",
                                "required": false,
                                "type": "number",
                                "min": 0,
                                "max": 100
                            }
                        ]
                    },
                    "rejectUnknownTopLevelFields": {
                        "title": "Reject unexpected top-level fields",
                        "type": "boolean",
                        "description": "When enabled, a record is rejected if it contains a top-level field not represented by any rule.",
                        "default": false
                    },
                    "maxErrorsPerRecord": {
                        "title": "Maximum errors per rejected record",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Caps the error list for badly malformed records while continuing validation.",
                        "default": 20
                    },
                    "maxItems": {
                        "title": "Maximum source records",
                        "minimum": 1,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Safety limit. The run fails before validation if the source dataset is larger.",
                        "default": 100000
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
