{
  "openapi": "3.0.1",
  "info": {
    "title": "Dataset Diff: See What Changed & Why",
    "description": "Compare two datasets by key and get only what changed: new, removed and changed records with before/after values, numeric deltas and alert rules. Pure compute, no scraping.",
    "version": "0.1",
    "x-build-id": "CJVfyIfJ4UpMAdPjp"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/hiredhandai~dataset-diff-explainer/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-hiredhandai-dataset-diff-explainer",
        "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/hiredhandai~dataset-diff-explainer/runs": {
      "post": {
        "operationId": "runs-sync-hiredhandai-dataset-diff-explainer",
        "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/hiredhandai~dataset-diff-explainer/run-sync": {
      "post": {
        "operationId": "run-sync-hiredhandai-dataset-diff-explainer",
        "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": {
          "currentDatasetId": {
            "title": "Current dataset (after)",
            "type": "string",
            "description": "The newer dataset, for example the output of today's scraper run. Pick it from your datasets, or pass its ID through the API. Leave empty if you paste records below."
          },
          "currentRecords": {
            "title": "Current records (inline)",
            "type": "array",
            "description": "Up to 10,000 records as a JSON array. Handy for trying the Actor or for small API calls. Use the dataset field for bigger jobs."
          },
          "baselineDatasetId": {
            "title": "Baseline dataset (before)",
            "type": "string",
            "description": "The older dataset to compare against, for example yesterday's run. Use exactly one of: baseline dataset, baseline records or snapshot name."
          },
          "baselineRecords": {
            "title": "Baseline records (inline)",
            "type": "array",
            "description": "Up to 10,000 records as a JSON array. Use exactly one of: baseline dataset, baseline records or snapshot name."
          },
          "snapshotName": {
            "title": "Snapshot name (compare with last run)",
            "type": "string",
            "description": "Compare the current data with the snapshot saved by the last run under this name, then save the current data as the new snapshot. The first run only creates the snapshot and costs nothing. Schedule the Actor and you get a change feed. Snapshots are stored in your own key-value store named dataset-diff-snapshots."
          },
          "updateSnapshot": {
            "title": "Update snapshot after the run",
            "type": "boolean",
            "description": "Save the current data as the new snapshot when the run completes. Turn off for a dry run. Ignored when you do not use a snapshot name.",
            "default": true
          },
          "keyFields": {
            "title": "Key fields",
            "type": "array",
            "description": "Field(s) that identify a record, for example [\"url\"] or [\"shopId\",\"sku\"]. Leave empty to let the Actor choose a key; it tells you why in the run summary, and stops with an explanation if it cannot find a reliable one.",
            "items": {
              "type": "string"
            }
          },
          "keyNormalization": {
            "title": "Key normalization",
            "enum": [
              "auto",
              "text",
              "url",
              "none"
            ],
            "type": "string",
            "description": "How key values are compared. Auto treats web addresses as URLs (ignores http/https, www, tracking parameters, trailing slash) and other values as text (ignores case and spacing).",
            "default": "auto"
          },
          "keyCaseSensitive": {
            "title": "Case-sensitive keys",
            "type": "boolean",
            "description": "Treat \"ABC\" and \"abc\" as different keys.",
            "default": false
          },
          "fallbackKeyFields": {
            "title": "Fallback key fields",
            "type": "array",
            "description": "Used for records that are missing a part of the key, for example [\"url\"] when some records have no sku.",
            "items": {
              "type": "string"
            }
          },
          "duplicateKeyPolicy": {
            "title": "Duplicate keys",
            "enum": [
              "occurrence",
              "first",
              "last",
              "fail"
            ],
            "type": "string",
            "description": "What to do when several records share a key. Occurrence matches the first with the first, the second with the second (reordered duplicates can look like changes).",
            "default": "occurrence"
          },
          "missingKeyPolicy": {
            "title": "Records without a key",
            "enum": [
              "wholeRecord",
              "skip",
              "fail"
            ],
            "type": "string",
            "description": "Whole record: identical records still match, but a record that changed shows up as removed plus added. Skip: ignore them. Stop: fail the run.",
            "default": "wholeRecord"
          },
          "fuzzyMatch": {
            "title": "Re-pair renamed records (optional)",
            "type": "object",
            "description": "Example: {\"enabled\": true, \"fields\": [\"title\"], \"threshold\": 0.92}. Pairs a removed and a new record that are almost the same text (\"same product, new URL\") and reports them as one changed record with the confidence. Numbers inside the text must match exactly."
          },
          "compareFields": {
            "title": "Only compare these fields",
            "type": "array",
            "description": "Dot paths, for example [\"price\",\"stock\"]. Empty means every field. Wildcards: * is one level, ** is any depth.",
            "items": {
              "type": "string"
            }
          },
          "ignoreFields": {
            "title": "Ignore these fields",
            "type": "array",
            "description": "Dot paths or wildcards, for example [\"meta.*\",\"**.updatedAt\"]. Ignored fields never create changes.",
            "items": {
              "type": "string"
            }
          },
          "ignoreVolatileFields": {
            "title": "Ignore timestamps and run metadata",
            "type": "boolean",
            "description": "Skips fields that change on every scrape without meaning anything, such as scrapedAt, crawledAt, timestamp, requestId and #debug. The list used is echoed in the run summary.",
            "default": true
          },
          "arrayKeys": {
            "title": "Match list items by key",
            "type": "object",
            "description": "Example: {\"variants\": \"sku\", \"offers\": [\"seller\",\"currency\"]}. Items in those lists are matched by the key instead of by position, so changes are reported like variants[sku=B2].stock."
          },
          "arrayMode": {
            "title": "Lists without a key",
            "enum": [
              "set",
              "ordered"
            ],
            "type": "string",
            "description": "Set: ignore order, report added and removed items. Ordered: compare position by position.",
            "default": "set"
          },
          "normalize": {
            "title": "Noise control",
            "type": "object",
            "description": "All default to on except caseInsensitive: trim, collapseWhitespace, unicodeNfkc, caseInsensitive, emptyEqualsMissing (null, empty text, [] and {} equal missing), parseNumericStrings (\"$1,299.00\" equals 1299), parseDates. Example: {\"caseInsensitive\": true}."
          },
          "numericTolerance": {
            "title": "Numeric tolerance",
            "type": "object",
            "description": "Ignore tiny numeric movements. Example: {\"rel\": 0.01, \"perField\": {\"rating\": {\"abs\": 0.05}}} ignores moves under 1% and rating moves under 0.05. The summary says how many were ignored."
          },
          "rules": {
            "title": "Alert rules",
            "type": "array",
            "description": "Example: [{\"id\":\"price-drop\",\"field\":\"price\",\"when\":\"decreased\",\"minPercent\":10,\"severity\":\"high\"},{\"field\":\"stock\",\"when\":\"became\",\"value\":0}]. when: changed, increased, decreased, became, became_empty, became_nonempty, added, removed, matches (pattern), crossed (threshold, direction). Use field $record with when added or removed for new and gone records. Matching records get alerts and a severity you can filter on in Zapier, Make or n8n."
          },
          "watchFields": {
            "title": "Watch fields",
            "type": "array",
            "description": "Fields listed first in each summary line, for example [\"price\",\"stock\"]. Other changed fields are still reported.",
            "items": {
              "type": "string"
            }
          },
          "emit": {
            "title": "Report these change types",
            "type": "array",
            "description": "Any of: added, removed, changed. Default is all three. You are charged for the changes returned, so this also controls cost.",
            "default": [
              "added",
              "removed",
              "changed"
            ],
            "items": {
              "type": "string"
            }
          },
          "alertsOnly": {
            "title": "Only records with alerts",
            "type": "boolean",
            "description": "Return only records that triggered at least one alert rule. Detected-but-skipped changes are not charged.",
            "default": false
          },
          "outputMode": {
            "title": "Output shape",
            "enum": [
              "records",
              "fieldChanges"
            ],
            "type": "string",
            "description": "One item per changed record, or one item per changed field (easier for spreadsheets). You are charged per changed record either way.",
            "default": "records"
          },
          "includeRecords": {
            "title": "Include before/after values",
            "enum": [
              "changedFields",
              "full",
              "none"
            ],
            "type": "string",
            "description": "Changed fields only (default), the full records, or none.",
            "default": "changedFields"
          },
          "includeSuppressed": {
            "title": "Explain what was ignored",
            "type": "boolean",
            "description": "Adds a note to changed records about differences that were suppressed, such as numeric moves within tolerance.",
            "default": false
          },
          "abortIfShrinksPercent": {
            "title": "Stop if the new dataset shrank by (%)",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "Protects against a failed scrape showing every record as removed. Example: 50 stops the run if the current dataset has more than 50% fewer records than the baseline. 0 turns it off; a warning is always given below 50%.",
            "default": 0
          },
          "strategy": {
            "title": "Memory strategy",
            "enum": [
              "auto",
              "memory",
              "low-memory"
            ],
            "type": "string",
            "description": "Auto uses memory for small datasets and a multi-pass low-memory method for large ones. Results are identical.",
            "default": "auto"
          },
          "maxRecordsPerSide": {
            "title": "Max records per dataset",
            "minimum": 1,
            "type": "integer",
            "description": "Safety limit for each side. Default 500,000.",
            "default": 500000
          },
          "maxChangesReported": {
            "title": "Max changes reported",
            "minimum": 1,
            "type": "integer",
            "description": "Hard cap on the changes returned (and charged) in one run. Default 100,000.",
            "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}