# JSON Content Checker & Validator - API Testing Tool (`maximedupre/api-testing-tool`) Actor

Check public JSON API endpoints with structural, JSON Schema, or path-based content rules. Get a dataset row for each readable endpoint with pass or fail status, response time, and actionable findings.

- **URL**: https://apify.com/maximedupre/api-testing-tool.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Developer tools, Automation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 1,000 endpoint validations

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

### 🧪 Check your JSON API responses

For developers, QA engineers, and API teams, this Actor checks public HTTP or HTTPS endpoints that return JSON. It saves a structured dataset row for each endpoint that yields readable JSON, including pass or fail status, HTTP status, response time, and findings. One shared validation setup lets you check multiple endpoints in one run.

- Use [**API testing tools**](https://apify.com/maximedupre/api-testing-tool/examples/api-testing-tools) to check public JSON endpoints with one shared validation setup.
- Try the prefilled public URL with [**Sample API for testing**](https://apify.com/maximedupre/api-testing-tool/examples/sample-api-for-testing) before adding your own endpoint.
- Check one or more public URLs with [**Test API endpoint**](https://apify.com/maximedupre/api-testing-tool/examples/test-api-endpoint) and review each pass or fail row.
- Compare HTTP status and response times across public services with [**REST API tools**](https://apify.com/maximedupre/api-testing-tool/examples/rest-api-tools) and inspect each finding.
- Check required paths and response values with [**API response validation**](https://apify.com/maximedupre/api-testing-tool/examples/api-response-validation) before a client depends on them.

#### 📋 JSON validation rows

The `dataset` output field opens the default Apify dataset. Each saved row describes one endpoint that returned readable JSON and includes its HTTP status, response time, pass or fail status, and validation findings.

#### ▶️ Run endpoint checks

1. Add one or more public HTTP or HTTPS URLs that return JSON.
2. Choose Structural checks, JSON Schema checks, Path-based content rules, or Combined checks. One choice and its settings apply to every submitted endpoint.
3. Add required paths, a JSON Schema, or path-based content rules when the selected checks use them.
4. Set an optional response-time threshold in milliseconds. A response above that value gets a response-time finding in every choice.
5. Run the Actor and open the dataset link in the output.

If one endpoint cannot be read or validated, the remaining endpoints can still be processed. A validation row is returned for each endpoint that yields readable JSON.

#### ⚙️ Input

Add at least one public HTTP or HTTPS endpoint. The same validation setup is used for every endpoint in the list.

| Field | Type | What it does |
|---|---|---|
| `endpoints` | array of objects | Required. Lists the public JSON endpoints to check. Submit at least one endpoint. |
| `endpoints[].url` | string | Required in each endpoint object. A public HTTP or HTTPS URL that returns a JSON response. |
| `validationMode` | string | Required. Chooses `structural`, `jsonSchema`, `content`, or `combined` checks. |
| `validationSettings` | object, optional | Sets structural checks and an optional response-time threshold. One settings object applies to the whole endpoint list. |
| `validationSettings.requiredFieldPaths` | array of strings, optional | Adds dot paths that must be present in each response. This check runs in Structural checks and Combined checks. |
| `validationSettings.checkNullValues` | boolean | Flags null values found anywhere in each response during Structural checks and Combined checks. The default is `true`. |
| `validationSettings.checkEmptyStrings` | boolean | Flags empty string values found anywhere in each response during Structural checks and Combined checks. The default is `true`. |
| `validationSettings.checkDuplicateArrayEntries` | boolean | Flags duplicate entries within JSON arrays during Structural checks and Combined checks. The default is `true`. |
| `validationSettings.responseTimeThresholdMs` | integer, optional | Sets the maximum response time in milliseconds. A response above the value gets a finding in every validation mode. The value must be at least `1`; the schema does not set an upper bound. |
| `jsonSchema` | object, optional | Supplies a JSON Schema for JSON Schema checks or Combined checks. Other choices ignore this field. |
| `contentRules` | array of objects, optional | Adds path-based value checks for Path-based content rules or Combined checks. Other choices ignore this field. |
| `contentRules[].path` | string | Required in each rule. The dot path to the value in the JSON response. |
| `contentRules[].operator` | string | Required in each rule. Uses `equals`, `notEquals`, `contains`, `notContains`, `greaterThan`, or `lessThan`. |
| `contentRules[].expectedValue` | string | Required in each rule. One JSON value written as text, such as `"active"` or `200`. |

The `structural` mode checks required paths, null values, empty strings, and duplicate array entries. The `jsonSchema` mode compares each response with `jsonSchema`. The `content` mode applies `contentRules`. The `combined` mode runs the structural, JSON Schema, and path-based content checks together.

**Input example**

This is the smallest successful current-beta structural input:

```json
{
  "endpoints": [
    {
      "url": "https://jsonplaceholder.typicode.com/todos/1"
    }
  ],
  "validationMode": "structural",
  "validationSettings": {
    "checkNullValues": true,
    "checkEmptyStrings": true,
    "checkDuplicateArrayEntries": true
  }
}
```

#### 🧾 Output

**Run output**

| Field | Type | What it does |
|---|---|---|
| `dataset` | string | Links to the default dataset view with API endpoint validation rows. |

**Dataset row**

| Field | Type | What it does |
|---|---|---|
| `endpointUrl` | string (URI) | The public URL that returned the JSON response. |
| `httpStatus` | integer | The HTTP status code returned by the endpoint. |
| `responseTimeMs` | number | The time from the request to the response, in milliseconds. |
| `passed` | boolean | Whether the response passed all checks selected for this run. |
| `findings` | array of objects | Errors and warnings found while checking the response. |
| `findings[].check` | string | The check that produced the finding: `requiredField`, `nullValue`, `emptyString`, `duplicateArrayEntry`, `jsonSchema`, `contentRule`, or `responseTime`. |
| `findings[].severity` | string | Whether the finding is an `error` or a `warning`. |
| `findings[].path` | string, optional | The dot path or array path where the finding occurred, when it applies. |
| `findings[].message` | string | A clear explanation of the finding. |
| `findings[].expected` | string, number, boolean, object, array, or null, optional | The value or condition the response was expected to meet, when it applies. |
| `findings[].observed` | string, number, boolean, object, array, or null, optional | The value found at the response path, when it applies. |

**Example validation row**

This complete row comes from a successful current-beta run. It shows response-time, empty-string, null-value, and duplicate-entry findings:

```json
{
  "endpointUrl": "https://httpbin.org/anything?value=one&value=one",
  "httpStatus": 200,
  "responseTimeMs": 722.4323049999998,
  "passed": false,
  "findings": [
    {
      "check": "emptyString",
      "severity": "warning",
      "path": "$.data",
      "message": "An empty string was found in the JSON response.",
      "expected": "a non-empty string",
      "observed": ""
    },
    {
      "check": "nullValue",
      "severity": "warning",
      "path": "$.json",
      "message": "A null value was found in the JSON response.",
      "expected": "a non-null value",
      "observed": null
    },
    {
      "check": "duplicateArrayEntry",
      "severity": "warning",
      "path": "$.args.value[1]",
      "message": "Array entry duplicates the value at index 0.",
      "expected": "unique array entries",
      "observed": "one"
    },
    {
      "check": "responseTime",
      "severity": "warning",
      "path": "$responseTimeMs",
      "message": "The response exceeded the configured response-time threshold.",
      "expected": 1,
      "observed": 722.4323049999998
    }
  ]
}
```

#### 💳 Pricing

This Actor uses pay-per-event pricing. Each completed validation report for a readable JSON endpoint costs $0.005. A run with multiple readable endpoints can create one chargeable event per endpoint. An endpoint that cannot produce a completed validation report is not described by this chargeable event.

#### 🔌 Integrations

Results are available in the Apify dataset linked from the `dataset` output field. You can use that dataset in the Apify platform and its API.

For a guide to using the Apify API, see:

https://www.youtube.com/watch?v=bNACk1\_S\_6w\&list=PLObrtcm1Kw6MUrlLNDbK9QRg8VDJg0gOW\&index=4

#### ❓ FAQ

##### Can I test a private or authenticated API?

No. Submit public HTTP or HTTPS URLs that return JSON. This Actor does not provide fields for credentials, request bodies, or private network access.

##### Can one run use different checks for different endpoints?

No. One validation mode and one set of validation settings apply to every endpoint submitted in the run.

##### What is the difference between the four validation modes?

Structural checks look for required paths, null values, empty strings, and duplicate array entries. JSON Schema checks compare each response with the schema you provide. Path-based content rules compare selected values. Combined checks run all three groups.

##### How do required paths and content rules differ?

Required paths check whether a path is present. Content rules check the value at a path with an operator such as `equals`, `contains`, `greaterThan`, or `lessThan`.

##### What happens when an endpoint does not return readable JSON?

The remaining endpoints can still be processed. The dataset contains a validation row for each endpoint that yields readable JSON.

##### How does the response-time threshold work?

Set `responseTimeThresholdMs` to a positive number of milliseconds. A response above that value gets a `responseTime` finding, and the threshold applies in every validation mode.

##### What does `passed` mean in a dataset row?

It shows whether that response passed all checks selected for the run. Use `findings` to see the severity, path, message, expected value, and observed value for each finding.

##### Can I start with a sample API for testing?

Yes. The form includes a public JSONPlaceholder URL, and you can replace it with any public HTTP or HTTPS endpoint that returns JSON.

### 📝 Changelog

**v0.0** (20-09-2026)

- Initial release.

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~api-testing-tool/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Related Actors

- [Schema Markup & JSON-LD Validator](https://apify.com/maximedupre/schema-markup-validator): Check JSON-LD, Microdata, and RDFa on public pages.
- [YAML Validator & Converter](https://apify.com/maximedupre/yaml-validator-converter): Check JSON, YAML, and TOML syntax when you need to validate document data.
- [Redirect Chain Checker](https://apify.com/maximedupre/redirect-checker): Trace public HTTP/HTTPS URLs and review status, timing, and redirect issues.
- [SSL Certificate Checker](https://apify.com/maximedupre/ssl-certificate-checker): Check public HTTPS certificates, hostname matches, and expiry details.
- [DNS Propagation Checker](https://apify.com/maximedupre/dns-propagation-checker): Compare public resolver answers after a DNS change.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `endpoints` (type: `array`):

Add one or more public HTTP or HTTPS URLs that return JSON. The same validation setup is used for every endpoint.

## `validationMode` (type: `string`):

Choose which checks to run. Structural checks look for missing paths, nulls, empty strings, and duplicate array entries. JSON Schema checks compare each response with your schema. Path-based content rules check selected values. Combined checks run structural, JSON Schema, and content checks.

## `validationSettings` (type: `object`):

Set structural checks and an optional response-time threshold. Required paths, null checks, empty-string checks, and duplicate-entry checks apply in Structural checks and Combined checks. The threshold applies to every choice.

## `jsonSchema` (type: `object`):

Add a JSON Schema when you choose JSON Schema checks or Combined checks. Other choices ignore this field. Example: {"type":"object","required":\["id"]}.

## `contentRules` (type: `array`):

Add one or more rules when you choose Path-based content rules or Combined checks. Each rule has a response path, a condition, and a JSON value written as text. Other choices ignore this field.

## Actor input object example

```json
{
  "endpoints": [
    {
      "url": "https://jsonplaceholder.typicode.com/todos/1"
    }
  ],
  "validationMode": "structural",
  "validationSettings": {
    "requiredFieldPaths": [
      "data.id"
    ],
    "checkNullValues": true,
    "checkEmptyStrings": true,
    "checkDuplicateArrayEntries": true,
    "responseTimeThresholdMs": 1000
  },
  "jsonSchema": {
    "type": "object",
    "properties": {
      "id": {
        "type": "string"
      }
    },
    "required": [
      "id"
    ]
  },
  "contentRules": [
    {
      "path": "data.status",
      "operator": "equals",
      "expectedValue": "\"active\""
    }
  ]
}
```

# Actor output Schema

## `dataset` (type: `string`):

A link to the API endpoint test results.

# 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 = {
    "endpoints": [
        {
            "url": "https://jsonplaceholder.typicode.com/todos/1"
        }
    ],
    "validationMode": "structural",
    "validationSettings": {
        "requiredFieldPaths": [
            "data.id"
        ],
        "checkNullValues": true,
        "checkEmptyStrings": true,
        "checkDuplicateArrayEntries": true,
        "responseTimeThresholdMs": 1000
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/api-testing-tool").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 = {
    "endpoints": [{ "url": "https://jsonplaceholder.typicode.com/todos/1" }],
    "validationMode": "structural",
    "validationSettings": {
        "requiredFieldPaths": ["data.id"],
        "checkNullValues": True,
        "checkEmptyStrings": True,
        "checkDuplicateArrayEntries": True,
        "responseTimeThresholdMs": 1000,
    },
}

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/api-testing-tool").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 '{
  "endpoints": [
    {
      "url": "https://jsonplaceholder.typicode.com/todos/1"
    }
  ],
  "validationMode": "structural",
  "validationSettings": {
    "requiredFieldPaths": [
      "data.id"
    ],
    "checkNullValues": true,
    "checkEmptyStrings": true,
    "checkDuplicateArrayEntries": true,
    "responseTimeThresholdMs": 1000
  }
}' |
apify call maximedupre/api-testing-tool --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maximedupre/api-testing-tool"
        }
    }
}
```

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/ccFvXEh6zgYIGgUXc/builds/aXNO5dwTasYQWl1Zx/openapi.json
