# OpenAPI Spec Diff Auditor (`junipr/openapi-spec-diff-auditor`) Actor

Diff OpenAPI specs for breaking changes, added or removed endpoints, required parameters, response drift, and schema compatibility.  by default.

- **URL**: https://apify.com/junipr/openapi-spec-diff-auditor.md
- **Developed by:** [junipr](https://apify.com/junipr) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $9.80 / 1,000 target auditeds

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.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.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/platform/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

## OpenAPI Spec Diff Auditor

<!-- FIXED_INCLUSIVE_PPE_20260707_START -->
### Store Positioning

**Store title:** OpenAPI Spec Diff Auditor

**Short description:** Diff OpenAPI specs for breaking changes, added or removed endpoints, required parameters, response drift, and schema compatibility.  by default.

**SEO title:** OpenAPI Spec Diff Auditor — API, schema, and developer QA

**SEO description:** Diff OpenAPI specs for breaking changes, added or removed endpoints, required parameters, response drift, and schema compatibility.  by default. Use it to catch contract drift, schema mistakes, unsafe endpoint assumptions, and developer-tool quality issues before release.

**Categories:** SEO_TOOLS, DEVELOPER_TOOLS, AUTOMATION

**Keywords:** openapi, spec, diff, auditor, schema, change monitor, api testing, api/developer qa

### Fixed-Inclusive PPE Pricing

This actor uses pay-per-event pricing. Event prices include Apify platform usage; users are not expected to pay a separate platform-usage pass-through charge for the configured pricing model.

- Tier: A1 — API/developer QA
- Primary event: `schema-validated` at $0.00650 base
- Default max charge: $10.00
- Store discounts: FREE/BRONZE base, SILVER discounted, GOLD deepest approved discount

Event set:

- `actor-start`: base $0.00500, GOLD $0.00400. Openapi Spec Diff Auditor: charged when actor start is completed. The price includes Apify platform usage; no separate usage pass-through is intended.
- `schema-validated`: base $0.00650, GOLD $0.00520. Openapi Spec Diff Auditor: charged when schema validated is completed. The price includes Apify platform usage; no separate usage pass-through is intended.
- `contract-rule-checked`: base $0.00390, GOLD $0.00312. Openapi Spec Diff Auditor: charged when contract rule checked is completed. The price includes Apify platform usage; no separate usage pass-through is intended.
- `report-generated`: base $0.05000, GOLD $0.04000. Openapi Spec Diff Auditor: charged when report generated is completed. The price includes Apify platform usage; no separate usage pass-through is intended.

### Public Task Concepts

- Compare previous and current OpenAPI Spec Diff snapshots
- Monitor OpenAPI Spec Diff changes for a capped watchlist
- Build an OpenAPI Spec Diff change digest from supplied evidence
- Prioritize high-impact OpenAPI Spec Diff changes
- Export OpenAPI Spec Diff change rows for client review
<!-- FIXED_INCLUSIVE_PPE_20260707_END -->

### What does OpenAPI Spec Diff Auditor do?

OpenAPI Spec Diff Auditor compares two OpenAPI specifications and returns structured compatibility findings for API teams, SDK maintainers, and integration owners. It is fixture-first and makes no network calls by default, so the default Apify quality run is deterministic, fast, and safe.

It detects:

- Added and removed endpoints by method and path
- Operation-level drift across summaries, parameters, request bodies, responses, and deprecation flags
- Newly required request parameters that can break existing clients
- Removed response codes and response schema fields
- Response field type changes and newly required response fields
- Invalid OpenAPI inputs before trusting diff output

### Why Use This Actor

| Capability | OpenAPI Spec Diff Auditor | Manual JSON diff | General API changelog monitor |
| --- | --- | --- | --- |
| OpenAPI-aware endpoint matching | Yes, by HTTP method and path | No | Usually partial |
| Breaking-change severity | Built in | No | Usually text-only |
| Fixture-first defaults | Yes | Depends on setup | Often network-first |
| Dataset rows for automation | Yes | No | Varies |
| KVS summary report | Yes | No | Varies |
| Cost per 1K audited targets | $9.80 | Staff time | Varies |

Use this actor when you need a clear compatibility signal, not a raw line-by-line diff. It is designed for release gates, SDK update reviews, partner API monitoring, and support delivery summaries.

### How to Use

Start with the default input to see a tiny fixture diff:

```json
{
  "sourceId": "example-billing-api",
  "includeReport": true,
  "allowUrlFetch": false,
  "maxTargets": 1,
  "maxChanges": 25
}
````

1. Paste the previous OpenAPI JSON or YAML text into `previousSpec`.
2. Paste the current OpenAPI JSON or YAML text into `currentSpec`.
3. Keep `allowUrlFetch` disabled unless you explicitly want capped URL fetching.
4. Run the actor and review dataset rows sorted by severity.
5. Open `OPENAPI_DIFF_REPORT.md` in the key-value store for a compact release summary.

#### Release Gate Review

Use one target with your last published spec and the release candidate spec. Set `maxChanges` high enough to capture all compatibility findings, then fail your downstream workflow if any `critical` row appears.

#### Multi-Spec Partner Audit

#### URL Fetch Opt-In

Set `allowUrlFetch` to `true` only when you want the actor to fetch `previousSpecUrl` and `currentSpecUrl`. Fetching is capped by timeout and byte size. Inline spec text remains the safest default.

### Input Configuration

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `sourceId` | string | `example-billing-api` | Stable label for a single top-level spec pair. |
| `previousLabel` | string | `previous` | Label for the older spec. |
| `currentLabel` | string | `current` | Label for the newer spec. |
| `previousSpec` | string | tiny fixture | Older OpenAPI JSON or simple YAML text. |
| `currentSpec` | string | tiny fixture | Newer OpenAPI JSON or simple YAML text. |
| `previousSpecUrl` | string | empty | Optional older spec URL, fetched only when enabled and spec text is blank. |
| `currentSpecUrl` | string | empty | Optional newer spec URL, fetched only when enabled and spec text is blank. |
| `targets` | array | `[]` | Optional list of spec pairs that overrides top-level fields. |
| `maxTargets` | integer | `1` | Maximum spec pairs audited per run. |
| `maxChanges` | integer | `100` | Maximum dataset rows emitted per target after severity sorting. |
| `includeReport` | boolean | `true` | Write JSON and Markdown report artifacts to the key-value store. |
| `allowUrlFetch` | boolean | `false` | Explicit opt-in for capped network fetches. |
| `debug` | boolean | `false` | Enable additional debug logs. |

### Output Format

Each dataset row is one compatibility finding:

```json
{
  "changeId": "d9b77a3d18c67f21",
  "sourceId": "example-billing-api",
  "previousLabel": "previous",
  "currentLabel": "current",
  "status": "changed",
  "changeType": "removed",
  "category": "endpoint",
  "severity": "critical",
  "method": "GET",
  "path": "/v1/legacy-invoices",
  "identifier": "GET /v1/legacy-invoices",
  "previousValue": "operation fingerprint",
  "currentValue": null,
  "previousSpecUrl": null,
  "currentSpecUrl": null,
  "auditedAt": "2026-07-02T00:00:00.000Z",
  "recommendation": "Confirm GET /v1/legacy-invoices is intentionally removed and identify affected consumers before release."
}
```

Report artifacts:

- `OPENAPI_DIFF_RESULTS.json`: full structured result array
- `OPENAPI_DIFF_SUMMARY.json`: run counts, target summaries, and severity totals
- `OPENAPI_DIFF_REPORT.md`: concise Markdown report for release review

### Integration Examples

#### Node.js

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('junipr/openapi-spec-diff-auditor').call({
  previousSpec: JSON.stringify(previousOpenApi),
  currentSpec: JSON.stringify(currentOpenApi),
  maxChanges: 500
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
const critical = items.filter((item) => item.severity === 'critical');
if (critical.length) {
  throw new Error(`OpenAPI release has ${critical.length} critical compatibility changes`);
}
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("APIFY_TOKEN")
run = client.actor("junipr/openapi-spec-diff-auditor").call(run_input={
    "previousSpec": previous_spec_text,
    "currentSpec": current_spec_text,
    "maxChanges": 500,
})

items = client.dataset(run["defaultDatasetId"]).list_items().items
critical = [item for item in items if item["severity"] == "critical"]
print(f"critical changes: {len(critical)}")
```

### Tips and Advanced Usage

#### Performance Optimization

Keep specs inline for the most deterministic runs. Use `maxTargets` and `maxChanges` to bound work and output volume. The actor is designed for text parsing and does not need a browser, proxy, or external API.

#### URL Fetch Safety

Network access is disabled by default. If enabled, the actor uses a timeout and byte cap for each spec URL. Prefer pinned spec artifacts over mutable documentation URLs when using this in CI.

#### Interpreting Severity

`critical` means a change is likely breaking or blocks reliable diffing, such as removed endpoints, newly required parameters, removed response codes, removed response fields, type changes, or invalid specs. `warning` means compatibility drift should be reviewed. `info` is usually additive.

### Limitations

- This actor focuses on practical breaking-change evidence and does not replace a full OpenAPI conformance validator.
- URL fetching is optional and capped; pinned JSON or YAML spec artifacts are the recommended input for reliable CI use.
- Complex `$ref` graphs, vendor-specific extensions, and every possible schema constraint are not expanded with full compiler-level semantics.
- Results are compatibility triage rows and should be reviewed before production release decisions.

### FAQ

#### Does the actor fetch URLs by default?

No. It is local-first and fixture-first. URL fetching requires `allowUrlFetch: true`.

#### Does it support YAML?

It supports JSON and a simple YAML shape suitable for common OpenAPI path/method structures. For maximum fidelity, pass JSON.

#### Is this a full OpenAPI semantic validator?

No. It includes a lightweight validation helper to catch missing version and paths. Use a dedicated OpenAPI validator in CI if you need full specification compliance.

#### What counts as breaking?

Removed endpoints, newly required request parameters, removed response codes, removed response fields, response type changes, request body compatibility changes, and invalid specs are treated as critical.

#### Can I audit multiple APIs in one run?

#### Does this need a proxy?

No proxy is required for inline specs. URL fetching is optional and intended for simple spec files, not anti-bot pages.

### Related Actors

- API Docs Changelog Diff Monitor
- Security Headers Auditor
- TLS Certificate Monitor
- Broken Link Redirect Map
- Structured Data Monitor for AI Search

# Actor input Schema

## `sourceId` (type: `string`):

Stable label for this OpenAPI specification pair.

## `previousLabel` (type: `string`):

Label for the older specification.

## `currentLabel` (type: `string`):

Label for the newer specification.

## `previousSpec` (type: `string`):

Older OpenAPI document as JSON or simple YAML text. Leave blank only when URL fetch is explicitly enabled.

## `currentSpec` (type: `string`):

Newer OpenAPI document as JSON or simple YAML text. Leave blank only when URL fetch is explicitly enabled.

## `previousSpecUrl` (type: `string`):

Optional URL for the older spec. Fetched only when Allow URL Fetch is enabled and previousSpec is blank.

## `currentSpecUrl` (type: `string`):

Optional URL for the newer spec. Fetched only when Allow URL Fetch is enabled and currentSpec is blank.

## `targets` (type: `array`):

Optional list of OpenAPI spec pairs. When provided, these override the top-level spec fields.

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

Alias for Max Targets/Maximum Records used by the Junipr actor baseline. When both are provided, actor-specific limits still apply.

## `maxTargets` (type: `integer`):

Maximum spec pairs to audit in one run.

## `maxChanges` (type: `integer`):

Maximum structured diff rows emitted per target after sorting by severity.

## `includeReport` (type: `boolean`):

Store diff rows, summary JSON, and a Markdown report in the default key-value store.

## `allowUrlFetch` (type: `boolean`):

Disabled by default. When enabled, the actor may fetch previous/current spec URLs with a strict byte and timeout cap.

## `dryRun` (type: `boolean`):

Validate input and write a dry-run summary without PPE charges or dataset output.

## `debug` (type: `boolean`):

Enable additional logs for spec normalization and diff extraction.

## Actor input object example

```json
{
  "sourceId": "example-billing-api",
  "previousLabel": "previous",
  "currentLabel": "current",
  "previousSpec": "{\n  \"openapi\": \"3.1.0\",\n  \"info\": { \"title\": \"Example Billing API\", \"version\": \"2026-06-01\" },\n  \"paths\": {\n    \"/v1/customers\": {\n      \"get\": {\n        \"summary\": \"List customers\",\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Customer list\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"type\": \"object\",\n                  \"required\": [\"data\"],\n                  \"properties\": {\n                    \"data\": { \"type\": \"array\" },\n                    \"next_cursor\": { \"type\": \"string\" }\n                  }\n                }\n              }\n            }\n          }\n        }\n      }\n    },\n    \"/v1/legacy-invoices\": {\n      \"get\": {\n        \"deprecated\": true,\n        \"responses\": { \"200\": { \"description\": \"Legacy invoice list\" } }\n      }\n    }\n  }\n}",
  "currentSpec": "{\n  \"openapi\": \"3.1.0\",\n  \"info\": { \"title\": \"Example Billing API\", \"version\": \"2026-07-01\" },\n  \"paths\": {\n    \"/v1/customers\": {\n      \"get\": {\n        \"summary\": \"List customers\",\n        \"parameters\": [\n          { \"name\": \"X-API-Version\", \"in\": \"header\", \"required\": true, \"schema\": { \"type\": \"string\" } }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Customer list\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"type\": \"object\",\n                  \"required\": [\"data\", \"has_more\"],\n                  \"properties\": {\n                    \"data\": { \"type\": \"array\" },\n                    \"has_more\": { \"type\": \"boolean\" }\n                  }\n                }\n              }\n            }\n          }\n        }\n      }\n    },\n    \"/v1/invoices\": {\n      \"get\": {\n        \"responses\": { \"200\": { \"description\": \"Invoice list\" } }\n      }\n    }\n  }\n}",
  "previousSpecUrl": "",
  "currentSpecUrl": "",
  "targets": [],
  "maxItems": 1,
  "maxTargets": 1,
  "maxChanges": 100,
  "includeReport": true,
  "allowUrlFetch": false,
  "dryRun": false,
  "debug": false
}
```

# Actor output Schema

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

Each dataset row is one added, removed, or changed OpenAPI compatibility signal with severity and recommendation.

## `diffResultsJson` (type: `string`):

Full JSON array of structured OpenAPI diff rows.

## `summaryJson` (type: `string`):

Run-level counts by target, change type, category, and severity.

## `summaryReport` (type: `string`):

Markdown report describing the most important OpenAPI compatibility changes.

# 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("junipr/openapi-spec-diff-auditor").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("junipr/openapi-spec-diff-auditor").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 junipr/openapi-spec-diff-auditor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=junipr/openapi-spec-diff-auditor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "OpenAPI Spec Diff Auditor",
        "description": "Diff OpenAPI specs for breaking changes, added or removed endpoints, required parameters, response drift, and schema compatibility.  by default.",
        "version": "1.0",
        "x-build-id": "nWj3ivbA1OJ8edzkB"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/junipr~openapi-spec-diff-auditor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-junipr-openapi-spec-diff-auditor",
                "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/junipr~openapi-spec-diff-auditor/runs": {
            "post": {
                "operationId": "runs-sync-junipr-openapi-spec-diff-auditor",
                "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/junipr~openapi-spec-diff-auditor/run-sync": {
            "post": {
                "operationId": "run-sync-junipr-openapi-spec-diff-auditor",
                "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",
                "properties": {
                    "sourceId": {
                        "title": "Source ID",
                        "type": "string",
                        "description": "Stable label for this OpenAPI specification pair.",
                        "default": "example-billing-api"
                    },
                    "previousLabel": {
                        "title": "Previous Label",
                        "type": "string",
                        "description": "Label for the older specification.",
                        "default": "previous"
                    },
                    "currentLabel": {
                        "title": "Current Label",
                        "type": "string",
                        "description": "Label for the newer specification.",
                        "default": "current"
                    },
                    "previousSpec": {
                        "title": "Previous OpenAPI Spec",
                        "type": "string",
                        "description": "Older OpenAPI document as JSON or simple YAML text. Leave blank only when URL fetch is explicitly enabled.",
                        "default": "{\n  \"openapi\": \"3.1.0\",\n  \"info\": { \"title\": \"Example Billing API\", \"version\": \"2026-06-01\" },\n  \"paths\": {\n    \"/v1/customers\": {\n      \"get\": {\n        \"summary\": \"List customers\",\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Customer list\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"type\": \"object\",\n                  \"required\": [\"data\"],\n                  \"properties\": {\n                    \"data\": { \"type\": \"array\" },\n                    \"next_cursor\": { \"type\": \"string\" }\n                  }\n                }\n              }\n            }\n          }\n        }\n      }\n    },\n    \"/v1/legacy-invoices\": {\n      \"get\": {\n        \"deprecated\": true,\n        \"responses\": { \"200\": { \"description\": \"Legacy invoice list\" } }\n      }\n    }\n  }\n}"
                    },
                    "currentSpec": {
                        "title": "Current OpenAPI Spec",
                        "type": "string",
                        "description": "Newer OpenAPI document as JSON or simple YAML text. Leave blank only when URL fetch is explicitly enabled.",
                        "default": "{\n  \"openapi\": \"3.1.0\",\n  \"info\": { \"title\": \"Example Billing API\", \"version\": \"2026-07-01\" },\n  \"paths\": {\n    \"/v1/customers\": {\n      \"get\": {\n        \"summary\": \"List customers\",\n        \"parameters\": [\n          { \"name\": \"X-API-Version\", \"in\": \"header\", \"required\": true, \"schema\": { \"type\": \"string\" } }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Customer list\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"type\": \"object\",\n                  \"required\": [\"data\", \"has_more\"],\n                  \"properties\": {\n                    \"data\": { \"type\": \"array\" },\n                    \"has_more\": { \"type\": \"boolean\" }\n                  }\n                }\n              }\n            }\n          }\n        }\n      }\n    },\n    \"/v1/invoices\": {\n      \"get\": {\n        \"responses\": { \"200\": { \"description\": \"Invoice list\" } }\n      }\n    }\n  }\n}"
                    },
                    "previousSpecUrl": {
                        "title": "Previous Spec URL",
                        "type": "string",
                        "description": "Optional URL for the older spec. Fetched only when Allow URL Fetch is enabled and previousSpec is blank.",
                        "default": ""
                    },
                    "currentSpecUrl": {
                        "title": "Current Spec URL",
                        "type": "string",
                        "description": "Optional URL for the newer spec. Fetched only when Allow URL Fetch is enabled and currentSpec is blank.",
                        "default": ""
                    },
                    "targets": {
                        "title": "Spec Targets",
                        "type": "array",
                        "description": "Optional list of OpenAPI spec pairs. When provided, these override the top-level spec fields.",
                        "items": {
                            "type": "object"
                        },
                        "default": []
                    },
                    "maxItems": {
                        "title": "Max Items",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Alias for Max Targets/Maximum Records used by the Junipr actor baseline. When both are provided, actor-specific limits still apply.",
                        "default": 1
                    },
                    "maxTargets": {
                        "title": "Maximum Targets",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Maximum spec pairs to audit in one run.",
                        "default": 1
                    },
                    "maxChanges": {
                        "title": "Maximum Changes Per Target",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Maximum structured diff rows emitted per target after sorting by severity.",
                        "default": 100
                    },
                    "includeReport": {
                        "title": "Generate Summary Report",
                        "type": "boolean",
                        "description": "Store diff rows, summary JSON, and a Markdown report in the default key-value store.",
                        "default": true
                    },
                    "allowUrlFetch": {
                        "title": "Allow URL Fetch",
                        "type": "boolean",
                        "description": "Disabled by default. When enabled, the actor may fetch previous/current spec URLs with a strict byte and timeout cap.",
                        "default": false
                    },
                    "dryRun": {
                        "title": "Dry Run",
                        "type": "boolean",
                        "description": "Validate input and write a dry-run summary without PPE charges or dataset output.",
                        "default": false
                    },
                    "debug": {
                        "title": "Debug Logging",
                        "type": "boolean",
                        "description": "Enable additional logs for spec normalization and diff extraction.",
                        "default": false
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
