{
  "openapi": "3.0.1",
  "info": {
    "title": "Merge Datasets & Dedupe: Combine, Filter, Export CSV & Excel",
    "description": "Merge datasets API and dataset merge tool: combine datasets from any Apify run, merge CSV, JSON, JSONL and Excel files into one clean dataset. Dedupe by key or full row, dataset filter rules, flatten, rename, sort, limit, export CSV, XLSX, JSON with public links.",
    "version": "0.1",
    "x-build-id": "nGdevs9XU55HMjGss"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/data-done-right~merge-datasets/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-data-done-right-merge-datasets",
        "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/data-done-right~merge-datasets/runs": {
      "post": {
        "operationId": "runs-sync-data-done-right-merge-datasets",
        "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/data-done-right~merge-datasets/run-sync": {
      "post": {
        "operationId": "run-sync-data-done-right-merge-datasets",
        "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": {
          "datasetIds": {
            "title": "Datasets to merge",
            "type": "array",
            "description": "Apify datasets to merge, in this order. Pick them from the list, or paste dataset IDs. Reads go through your run, so datasets of other Actors and other runs that you can read all work. Example: [\"aBcD1234eFgH5678i\", \"username~my-named-dataset\"]. Leave empty to use only files and pasted text."
          },
          "datasetUrls": {
            "title": "Dataset links or IDs",
            "type": "array",
            "description": "Dataset IDs, \"username~name\" names or Apify links, one per line. Example: https://console.apify.com/storage/datasets/aBcD1234eFgH5678i or https://api.apify.com/v2/datasets/aBcD1234eFgH5678i/items. A dataset that is only given here may be unreadable when the run has limited permissions: pick it in \"Datasets to merge\" instead.",
            "items": {
              "type": "string"
            }
          },
          "fileUrls": {
            "title": "File URLs (CSV, JSON, JSONL, Excel)",
            "type": "array",
            "description": "Direct links to .csv, .tsv, .json, .jsonl or .xlsx files, one per line. The type is detected from the extension or the content. Example: https://example.com/export/leads.csv. Links to localhost and private networks are blocked.",
            "items": {
              "type": "string"
            }
          },
          "inlineSources": {
            "title": "Pasted data (inline sources)",
            "type": "array",
            "description": "CSV, JSON or JSONL text pasted straight into the input. Each item is {\"name\": ..., \"format\": \"csv\" | \"json\" | \"jsonl\", \"text\": ...}. The name is shown in the source column. Works offline, so it is a good way to try the Actor."
          },
          "sourceField": {
            "title": "Source column name",
            "type": "string",
            "description": "Add a column with the name of the source each row came from (the dataset ID, file name or inline name). Leave empty for no extra column. Example: source."
          },
          "dedupeMode": {
            "title": "Remove duplicates",
            "enum": [
              "keys",
              "fullRow",
              "off"
            ],
            "type": "string",
            "description": "keys: rows with the same value in all Dedupe key fields are duplicates. fullRow: only identical rows are duplicates. off: keep everything.",
            "default": "keys"
          },
          "dedupeKeys": {
            "title": "Dedupe key fields",
            "type": "array",
            "description": "Fields that identify a row, e.g. [\"email\"] or [\"firstName\", \"lastName\"]. Dots reach nested fields: \"author.id\". Values are trimmed; a number and the same number as text count as equal. A row where all key fields are empty is only removed when it is an exact copy of another row.",
            "items": {
              "type": "string"
            }
          },
          "dedupeKeep": {
            "title": "Which duplicate wins",
            "enum": [
              "first",
              "last"
            ],
            "type": "string",
            "description": "first keeps the earliest row (streams, uses little memory). last keeps the latest row and puts it where its last copy appeared (the surviving rows are held in memory).",
            "default": "first"
          },
          "dedupeCaseInsensitive": {
            "title": "Ignore upper/lower case in keys",
            "type": "boolean",
            "description": "Treat ANNA@example.com and anna@example.com as the same key. Applies to key fields (or the whole row in full-row mode).",
            "default": false
          },
          "filters": {
            "title": "Filter rules",
            "type": "array",
            "description": "Keep only rows that match. Each rule is {\"field\": ..., \"op\": ..., \"value\": ...}. Operators: equals, notEquals, contains, notContains, startsWith, endsWith, regex, gt, gte, lt, lte, between (value [min, max], inclusive, dates or numbers), in (value is a list), exists, notExists, empty, notEmpty. Example: [{\"field\": \"plan\", \"op\": \"notEquals\", \"value\": \"free\"}, {\"field\": \"price\", \"op\": \"between\", \"value\": [10, 100]}]. Filters run before dedupe."
          },
          "filterMode": {
            "title": "Combine filter rules with",
            "enum": [
              "and",
              "or"
            ],
            "type": "string",
            "description": "and: a row must match every rule. or: matching any one rule is enough.",
            "default": "and"
          },
          "filterCaseSensitive": {
            "title": "Case-sensitive filters",
            "type": "boolean",
            "description": "Make equals, contains, startsWith, endsWith, in and regex respect upper/lower case. Off by default.",
            "default": false
          },
          "flatten": {
            "title": "Flatten nested fields",
            "type": "boolean",
            "description": "Turn nested objects into dotted columns, e.g. {\"address\": {\"city\": \"Oslo\"}} becomes address.city. Lists are kept as lists (they become JSON text in CSV and Excel).",
            "default": false
          },
          "fields": {
            "title": "Columns to keep (in order)",
            "type": "array",
            "description": "Only these columns, in this order. Dots reach nested fields. Leave empty to keep all columns. Filter, dedupe and sort use the original names; this step comes last. Example: email, name, address.city.",
            "items": {
              "type": "string"
            }
          },
          "renameFields": {
            "title": "Rename columns",
            "type": "object",
            "description": "Rename columns in the output, as {\"old name\": \"new name\"}. Example: {\"address.city\": \"city\", \"emailAddress\": \"email\"}."
          },
          "sortBy": {
            "title": "Sort by",
            "type": "array",
            "description": "Sort the output by one or more fields, one per line, with :desc for descending. Numbers sort as numbers, ISO dates as dates, text without regard to case, empty values last. Example: signup:desc. Sorting holds the surviving rows in memory.",
            "items": {
              "type": "string"
            }
          },
          "limit": {
            "title": "Max output rows",
            "minimum": 1,
            "maximum": 5000000,
            "type": "integer",
            "description": "Stop after this many output rows (after sorting). Leave empty for no limit. You are charged per output row."
          },
          "exports": {
            "title": "Export files",
            "type": "array",
            "description": "Also write the result as downloadable files in the key-value store, each with a public link in the SUMMARY record. Every file is charged once. Leave empty for the dataset only.",
            "items": {
              "type": "string",
              "enum": [
                "csv",
                "xlsx",
                "json",
                "jsonl"
              ],
              "enumTitles": [
                "CSV (UTF-8, opens in Excel)",
                "Excel (.xlsx)",
                "JSON array",
                "JSON Lines"
              ]
            },
            "default": []
          },
          "exportName": {
            "title": "Export file name",
            "type": "string",
            "description": "Base name of the export files, e.g. merged gives merged.csv and merged.xlsx.",
            "default": "merged"
          },
          "escapeFormulas": {
            "title": "Protect CSV from spreadsheet formulas",
            "type": "boolean",
            "description": "In the CSV export, text that starts with = + - or @ gets a leading apostrophe so Excel and Sheets cannot run it as a formula. Excel files always store such text as plain text. Turn off only if you need the raw values.",
            "default": true
          },
          "maxItems": {
            "title": "Max rows to read",
            "minimum": 1,
            "maximum": 2000000,
            "type": "integer",
            "description": "Hard cap on rows read across all sources. Reading stops at the cap and the run still succeeds. It also bounds memory when sorting or keeping the last duplicate.",
            "default": 100000
          },
          "maxItemsPerSource": {
            "title": "Max rows per source",
            "minimum": 1,
            "maximum": 2000000,
            "type": "integer",
            "description": "Optional cap on rows taken from each source, so one huge source cannot use up the whole budget. Leave empty for no per-source cap."
          },
          "maxFileSizeMb": {
            "title": "Max file size (MB)",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "Files larger than this are rejected (that source fails, the others continue). A JSON array file is loaded whole and is limited to 100 MB; use JSONL or CSV for bigger files.",
            "default": 50
          },
          "csvInferTypes": {
            "title": "Detect numbers and booleans in CSV",
            "type": "boolean",
            "description": "Turn CSV text like 42, 3.5 or true into numbers and booleans. Values with leading zeros (007), plus signs or very long digit strings stay text.",
            "default": true
          },
          "xlsxSheet": {
            "title": "Excel sheet",
            "type": "string",
            "description": "Sheet name or number (1 = first) to read from every Excel file. Leave empty for the first sheet."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}